package year25 import ( "bufio" "fmt" "io" "iter" "log" "strconv" ) func Day1Part1(r io.Reader, l *log.Logger) (any, error) { dial := 50 solution := 0 for pair := range day1GetPairs(r) { dial += pair.MustValue() dial %= 100 if dial < 0 { dial = 100 + dial } if dial == 0 { solution += 1 } l.Printf("The dial is rotated %s(%d) to point at 0 `once` \n", pair, pair.MustValue()) } return solution, nil } func Day1Part2Slow(r io.Reader, l *log.Logger) (any, error) { dial := 50 solution := 0 for pair := range day1GetPairs(r) { nextDial, count := day1AdvanceSimulation(dial, pair.MustValue()) dial = nextDial solution += count if count > 0 { l.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count) } else { l.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial) } } return solution, nil } func Day1Part2Fast(r io.Reader, l *log.Logger) (any, error) { dial := 50 solution := 0 for pair := range day1GetPairs(r) { value := pair.MustValue() nextDial, count := day1Advance(dial, value) dial = nextDial solution += count if count > 0 { l.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count) } else { l.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial) } } return solution, nil } func day1GetPairs(r io.Reader) iter.Seq[Day1Pair] { return func(yield func(Day1Pair) bool) { scanner := bufio.NewScanner(r) scanner.Split(bufio.ScanLines) for scanner.Scan() { pair := Day1Pair(scanner.Text()) if !yield(pair) { return } } if err := scanner.Err(); err != nil { panic(err) } } } type Day1Pair string func (p Day1Pair) Value() (int, error) { valueStr := string(p[1:]) v, err := strconv.Atoi(valueStr) if err != nil { return 0, fmt.Errorf("failed to convert action value to int") } switch p[0] { case 'L': return -v, nil case 'R': return v, nil default: return 0, fmt.Errorf("unknown action value %q", p[0]) } } func (p Day1Pair) MustValue() int { v, err := p.Value() if err != nil { panic(err) } return v } func day1AdvanceSimulation(dial int, value int) (int, int) { solution := 0 for value < 0 { value += 1 dial -= 1 if dial == 0 { solution += 1 } if dial == -1 { dial = 99 } } for value > 0 { value -= 1 dial += 1 if dial == 100 { dial = 0 solution += 1 } } return dial, solution } func day1Advance(dial, step int) (next int, count int) { next = dial + step count += next / 100 if count < 0 { count = -count } next = next % 100 if dial != 0 && step < 0 && next <= 0 { count += 1 } if next < 0 { next += 100 } return }