package main import ( "flag" "fmt" "log" "math" "os" "slices" ) func main() { debug := flag.Bool("debug", false, "Debug.") flag.Parse() ranges, err := readRanges(os.Stdin) if err != nil { log.Fatal(err) } var sum1, sum2 uint for _, r := range ranges { invalid1 := handleRange(r, scanPart1) invalid2 := handleRange(r, scanPart2) if *debug { fmt.Printf("range: %d-%d\n", r.from, r.to) } if *debug && len(invalid1) > 0 { fmt.Println("invalid (part 1):") for _, id := range invalid1 { fmt.Printf(" %d\n", id) } } if *debug && len(invalid2) > 0 { fmt.Println("invalid (part 2):") for _, id := range invalid2 { fmt.Printf(" %d\n", id) } } for _, id := range invalid1 { sum1 += id } for _, id := range invalid2 { sum2 += id } } fmt.Println("sum (part 1):", sum1) fmt.Println("sum (part 2):", sum2) } func handleRange(r idRange, scan func(id uint) (advance uint, ok bool)) []uint { var invalid []uint for id := r.from; id <= r.to; { advance, ok := scan(id) if !ok { invalid = append(invalid, id) } id += advance } return invalid } func scanPart1(id uint) (advance uint, ok bool) { digits := digits(id) if len(digits)%2 == 1 { // odd is always valid nextSmallestEven := uint(math.Pow10(len(digits))) return nextSmallestEven - id, true } var ( x = uint(math.Pow10(len(digits) / 2)) left = id / x right = id % x ) return 1, left != right } func scanPart2(id uint) (advance uint, ok bool) { digits := digits(id) if len(digits) <= 1 { return 1, true } loop: for i := 1; i <= len(digits)/2; i++ { ref := digits[:i] for chunk := range slices.Chunk(digits, i) { if !slices.Equal(chunk, ref) { continue loop } } return 1, false } return 1, true }