package main import ( "fmt" "math/rand" "time" ) const ( BoatCapacity = 4 HalfCapacity = BoatCapacity / 2 MaxDelay = 250 ) type ( Hacker struct{} Serf struct{} ) func sleep() { time.Sleep(time.Duration(rand.Intn(MaxDelay)) * time.Millisecond) } func genHackers(ch chan<- Hacker) { for { ch <- Hacker{} sleep() } } func genSerfs(ch chan<- Serf) { for { ch <- Serf{} sleep() } } func main() { hackerCh := make(chan Hacker) serfCh := make(chan Serf) go genHackers(hackerCh) go genSerfs(serfCh) for { hackers, serfs := 0, 0 hackerCh, serfCh := hackerCh, serfCh for hackers+serfs < BoatCapacity { select { case <-hackerCh: hackers++ case <-serfCh: serfs++ } if hackers+serfs == HalfCapacity+1 { switch { case hackers == HalfCapacity || serfs == HalfCapacity+1: hackerCh = nil case hackers == HalfCapacity+1 || serfs == HalfCapacity: serfCh = nil } } } fmt.Printf("Crossing river with %d hackers and %d serfs\n", hackers, serfs) } }