Skip to content

Instantly share code, notes, and snippets.

Created April 21, 2023 11:42
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
package main
import (
// Course struct
type Course struct {
name string
capacity int
regCounter int
regStudents []int
// CourseSystem struct
// to access this struct you need to acquire a lock
type CourseSystem struct {
courses map[string]*Course
mutex sync.Mutex
// Registers a dummy student for a course.
func (c *Course) Register(studentID int) bool {
if c.regCounter < c.capacity {
c.regStudents = append(c.regStudents, studentID)
return true
return false
// GetCourse returns a course from the course system.
func (cs *CourseSystem) GetCourse(courseName string) *Course {
defer cs.mutex.Unlock()
// AddCourse adds a course to the course system.
func (cs *CourseSystem) AddCourse(course *Course) {
defer cs.mutex.Unlock()[] = course
// registerStudentWithFallback tries to register a student for a course until it succeeds, if not then no course is registered.
func registerStudentWithFallback(studentID int, courseNames []string, cs *CourseSystem) {
remainingCourses := courseNames
for len(remainingCourses) > 0 {
// Randomly select a course to register for from the remaining courses.
courseIndex := rand.Intn(len(remainingCourses))
courseName := remainingCourses[courseIndex]
// Try to register for the course.
success := registerStudent(studentID, courseName, cs)
if success {
fmt.Printf("Student %d registered for %s.\n", studentID, courseName)
// If the registration was not successful, remove the course from the list of remaining courses.
remainingCourses = append(remainingCourses[:courseIndex], remainingCourses[courseIndex+1:]...)
fmt.Printf("Student %d could not register for any course.\n", studentID)
// selectNewCourse selects a new course randomly from the remaining courses.
func selectNewCourse(courseNames []string, currentCourse string) string {
remainingCourses := make([]string, 0, len(courseNames)-1)
for _, c := range courseNames {
// We don't want to try the same course again.
if c != currentCourse {
remainingCourses = append(remainingCourses, c)
if len(remainingCourses) == 0 {
// If there are no more courses to try, give up.
return ""
return remainingCourses[rand.Intn(len(remainingCourses))]
// registerStudent tries to register a student for a course.
// Returns true if successful, false otherwise.
func registerStudent(studentID int, courseName string, cs *CourseSystem) bool {
c := cs.GetCourse(courseName)
if c == nil {
fmt.Printf("Course %s not found.\n", courseName)
return false
if c.Register(studentID) {
return true
fmt.Printf("Student %d could not register for %s (course full).\n", studentID, courseName)
return false
func main() {
cs := &CourseSystem{
courses: make(map[string]*Course),
totalStudents := 25
allotedStudents := 0
cs.AddCourse(&Course{name: "Diaster Management", capacity: 10})
cs.AddCourse(&Course{name: "System Engineering", capacity: 10})
cs.AddCourse(&Course{name: "Mathematical Modelling", capacity: 2})
simulateRegistration(totalStudents, []string{"Diaster Management", "System Engineering", "Mathematical Modelling"}, cs)
for _, c := range {
fmt.Printf("Total Students registeted for %s: %d\n",, len(c.regStudents))
allotedStudents += len(c.regStudents)
fmt.Printf("Total Students alloted / Total Students: %d/%d\n", allotedStudents, totalStudents)
func simulateRegistration(numStudents int, courseNames []string, cs *CourseSystem) {
var wg sync.WaitGroup
for i := 1; i <= numStudents; i++ {
go func(n int) {
defer wg.Done()
registerStudentWithFallback(n, courseNames, cs)
time.Sleep(10 * time.Millisecond) // introduce a small delay to simulate concurrent requests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment