11package main
22
33import (
4+ "math/rand"
5+ "strings"
46 "time"
57
68 ext "github.com/reugn/go-streams/extension"
@@ -10,61 +12,76 @@ import (
1012type Move int
1113
1214const (
13- LEFT Move = iota
14- RIGHT
15+ left Move = iota
16+ right
1517)
1618
17- // Simulate waling through a maze
18- var MAZE = "------"
19- var MOVES = []Move {RIGHT , RIGHT , LEFT , RIGHT , LEFT , LEFT , RIGHT , RIGHT , RIGHT , LEFT }
19+ const (
20+ mazeLength = 10
21+ movesNumber = 20
22+ )
23+
24+ var maze = strings .Repeat ("-" , mazeLength )
25+
26+ // Simulate walking through a maze.
27+ func main () {
28+ source := ext .NewChanSource (moveChan (500 * time .Millisecond , movesNumber ))
29+ positionFlow := flow .NewFold (mazeLength / 2 , move )
30+ formatFlow := flow .NewMap (format , 1 )
31+ sink := ext .NewStdoutSink ()
32+
33+ source .
34+ Via (positionFlow ).
35+ Via (formatFlow ).
36+ To (sink )
37+ }
2038
39+ // move calculates the next position given the current position and a Move.
40+ // If the move is invalid (out of bounds), the original position is returned.
2141func move (m Move , pos int ) int {
22- if m == RIGHT {
42+ switch {
43+ case m == left && pos > 0 :
44+ return pos - 1
45+ case m == right && pos < len (maze )- 1 :
2346 return pos + 1
47+ default :
48+ return pos
2449 }
25-
26- return pos - 1
2750}
2851
52+ // format marks the position with an X.
2953func format (pos int ) string {
30- // Mark the position with an X
31- positionInMaze := MAZE [:pos ] + "X" + MAZE [pos + 1 :]
32- return positionInMaze
54+ return maze [:pos ] + "X" + maze [pos + 1 :]
3355}
3456
35- // Make a move every interval
36- func moveChan (interval time.Duration ) chan any {
37- // Create a sequence of moves
57+ // moveChan creates a channel that emits n random moves at the specified interval.
58+ func moveChan (interval time.Duration , n int ) chan any {
3859 outChan := make (chan any )
3960
4061 go func () {
41- ticker := time .NewTicker (interval )
42- // Start at position 0
43- pos := 0
44- for _ = range ticker .C {
45- // Send the next move
46- outChan <- MOVES [pos ]
47- // Move to the next position
48- pos = (pos + 1 )
49- if pos >= len (MOVES ) {
50- // Stop
51- close (outChan )
52- break
53- }
62+ defer close (outChan )
63+ // generate a sequence of moves
64+ moves := generateRandomMoves (n )
65+ for i := 0 ; i < n ; i ++ {
66+ time .Sleep (interval )
67+ // send the next move
68+ outChan <- moves [i ]
5469 }
5570 }()
5671
5772 return outChan
5873}
5974
60- func main () {
61- source := ext . NewChanSource ( moveChan ( time . Second ))
62- positionFlow := flow . NewFold ( 0 , move )
63- formatFlow := flow . NewMap ( format , 1 )
64- sink := ext . NewStdoutSink ()
75+ // generateRandomMoves creates a random sequence of moves with length n.
76+ func generateRandomMoves ( n int ) [] Move {
77+ if n <= 0 {
78+ return [] Move {}
79+ }
6580
66- source .
67- Via (positionFlow ).
68- Via (formatFlow ).
69- To (sink )
81+ moves := make ([]Move , n )
82+ for i := 0 ; i < n ; i ++ {
83+ moves [i ] = Move (rand .Intn (2 )) //nolint:gosec
84+ }
85+
86+ return moves
7087}
0 commit comments