77 "io"
88 "regexp"
99 "strconv"
10+ "sync"
1011
1112 "github.com/obalunenko/advent-of-code/internal/puzzles"
1213)
@@ -59,7 +60,7 @@ const (
5960func part1 (in io.Reader ) (string , error ) {
6061 scanner := bufio .NewScanner (in )
6162
62- var curfreq int
63+ fdevice := newDevice ()
6364
6465 for scanner .Scan () {
6566 line := scanner .Text ()
@@ -69,19 +70,14 @@ func part1(in io.Reader) (string, error) {
6970 return "" , err
7071 }
7172
72- switch delta .sign {
73- case "+" :
74- curfreq += delta .d
75- case "-" :
76- curfreq -= delta .d
77- }
73+ fdevice .Apply (delta )
7874 }
7975
8076 if err := scanner .Err (); err != nil {
8177 return "" , fmt .Errorf ("scanner error: %w" , err )
8278 }
8379
84- return strconv .Itoa (curfreq ), nil
80+ return strconv .Itoa (fdevice . CurFreq () ), nil
8581}
8682
8783func part2 (in io.Reader ) (string , error ) {
@@ -93,43 +89,31 @@ func part2(in io.Reader) (string, error) {
9389
9490 b := buf .Bytes ()
9591
96- seenfreqs := make (map [int ]bool )
97-
9892 var (
99- curfreq int
100- loops int
101- found bool
93+ loops int
94+ found bool
10295 )
10396
104- for ! found {
105- if len (seenfreqs ) == 0 {
106- seenfreqs [curfreq ] = true
107- }
97+ fdevice := newDevice ()
10898
99+ for ! found {
109100 scanner := bufio .NewScanner (bytes .NewReader (b ))
110101
111102 for scanner .Scan () {
112103 line := scanner .Text ()
113104
114105 delta , err := getFreqDelta (line )
115106 if err != nil {
116- return "" , err
107+ return "" , fmt . Errorf ( "get frequency delta: %w" , err )
117108 }
118109
119- switch delta .sign {
120- case "+" :
121- curfreq += delta .d
122- case "-" :
123- curfreq -= delta .d
124- }
110+ fdevice .Apply (delta )
125111
126- if seenfreqs [ curfreq ] {
112+ if fdevice . SeenFreq ( fdevice . CurFreq ()) {
127113 found = true
128114
129115 break
130116 }
131-
132- seenfreqs [curfreq ] = true
133117 }
134118
135119 if err := scanner .Err (); err != nil {
@@ -139,7 +123,50 @@ func part2(in io.Reader) (string, error) {
139123 loops ++
140124 }
141125
142- return strconv .Itoa (curfreq ), nil
126+ return strconv .Itoa (fdevice .CurFreq ()), nil
127+ }
128+
129+ type device struct {
130+ frequency int
131+ mu sync.Mutex
132+ seen map [int ]int
133+ }
134+
135+ func newDevice () * device {
136+ d := device {
137+ frequency : 0 ,
138+ mu : sync.Mutex {},
139+ seen : make (map [int ]int ),
140+ }
141+
142+ d .seen [0 ] = 1
143+
144+ return & d
145+ }
146+
147+ func (d * device ) Apply (delta freqDelta ) {
148+ switch delta .sign {
149+ case "+" :
150+ d .frequency += delta .d
151+ case "-" :
152+ d .frequency -= delta .d
153+ }
154+
155+ d .mu .Lock ()
156+ defer d .mu .Unlock ()
157+
158+ d .seen [d .frequency ] = d .seen [d .frequency ] + 1
159+ }
160+
161+ func (d * device ) CurFreq () int {
162+ return d .frequency
163+ }
164+
165+ func (d * device ) SeenFreq (freq int ) bool {
166+ d .mu .Lock ()
167+ defer d .mu .Unlock ()
168+
169+ return d .seen [freq ] > 1
143170}
144171
145172type freqDelta struct {
0 commit comments