From c5ab5e785a380e8300bfbe3498a65e02fd49e4e2 Mon Sep 17 00:00:00 2001 From: Donald Ball Date: Fri, 5 Dec 2025 12:48:02 -0500 Subject: [PATCH] day2 --- day2/main.go | 201 +++++++++++++++++++++++++++++++++++++++++++++++++ day2/part0.txt | 1 + day2/part1.txt | 1 + 3 files changed, 203 insertions(+) create mode 100644 day2/main.go create mode 100644 day2/part0.txt create mode 100644 day2/part1.txt diff --git a/day2/main.go b/day2/main.go new file mode 100644 index 0000000..cb08050 --- /dev/null +++ b/day2/main.go @@ -0,0 +1,201 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +func readLines(filename string) []string { + raw, err := os.ReadFile(filename) + if err != nil { + panic(err) + } + return strings.Split(string(raw), "\n") +} + +type id struct { + value uint64 + length uint8 +} + +func (x id) isSilly() bool { + c := uint64(1) + for range x.length / 2 { + c *= 10 + } + return x.value/c == x.value%c +} + +type pattern struct { + length uint8 + repeats uint8 +} + +var patterns = map[uint8][]pattern{ + 1: {}, + 2: {pattern{length: 1, repeats: 2}}, + 3: {pattern{length: 1, repeats: 3}}, + 4: {pattern{length: 1, repeats: 4}, pattern{length: 2, repeats: 2}}, + 5: {pattern{length: 1, repeats: 5}}, + 6: {pattern{length: 1, repeats: 6}, pattern{length: 2, repeats: 3}, pattern{length: 3, repeats: 2}}, + 7: {pattern{length: 1, repeats: 7}}, + 8: {pattern{length: 1, repeats: 8}, pattern{length: 2, repeats: 4}, pattern{length: 4, repeats: 2}}, + 9: {pattern{length: 1, repeats: 9}, pattern{length: 3, repeats: 3}}, + 10: {pattern{length: 1, repeats: 10}, pattern{length: 5, repeats: 2}, pattern{length: 2, repeats: 5}}, + 11: {pattern{length: 1, repeats: 11}}, +} + +func (x id) isVerySilly() bool { + ps := patterns[x.length] + if ps == nil { + panic(x.length) + } +PATTERNS: + for _, pattern := range ps { + mod := uint64(1) + for range pattern.length { + mod *= 10 + } + value := x.value + candidate := value % mod + if candidate == 0 { + continue + } + for range pattern.repeats - 1 { + value /= mod + if value%mod != candidate { + continue PATTERNS + } + } + return true + } + return false +} + +type seq struct { + start id + stop id +} + +func parseLine(line string) ([]seq, error) { + parts := strings.Split(line, ",") + seqs := make([]seq, len(parts)) + for i, part := range strings.Split(line, ",") { + pieces := strings.Split(part, "-") + if len(pieces) != 2 { + return seqs, fmt.Errorf("invalid part") + } + var err error + s := seq{ + start: id{length: uint8(len(pieces[0]))}, + stop: id{length: uint8(len(pieces[1]))}, + } + s.start.value, err = strconv.ParseUint(pieces[0], 10, 64) + if err != nil { + return seqs, err + } + s.stop.value, err = strconv.ParseUint(pieces[1], 10, 64) + if err != nil { + return seqs, err + } + if s.stop.value < s.start.value { + return seqs, fmt.Errorf("invalid range") + } + if !(s.stop.length == s.start.length || s.stop.length == s.start.length+1) { + return seqs, fmt.Errorf("unexpectedly large range %v", s) + } + seqs[i] = s + } + return seqs, nil +} + +func findSillyPatterns(s seq) []uint64 { + sillies := []uint64{} + oddStart := s.start.length%2 == 1 + oddStop := s.stop.length%2 == 1 + if oddStart && oddStop { + return sillies + } + if oddStart { + s.start.value = 1 + s.start.length++ + for range s.start.length - 1 { + s.start.value *= 10 + } + } + if oddStop { + s.stop.value = 0 + s.stop.length-- + c := 1 + for range s.stop.length { + s.stop.value += uint64(9 * c) + c *= 10 + } + } + if s.stop.value < s.start.value { + return sillies + } + for { + if s.start.value > s.stop.value { + break + } + if s.start.isSilly() { + sillies = append(sillies, s.start.value) + } + s.start.value++ + } + return sillies +} + +func findVerySillyPatterns(s seq) []uint64 { + sillies := []uint64{} + pivot := uint64(1) + for range s.stop.length - 1 { + pivot *= 10 + } + for { + if s.start.value > s.stop.value { + break + } + if s.start.isVerySilly() { + sillies = append(sillies, s.start.value) + } + s.start.value++ + if s.start.value == pivot { + s.start.length++ + } + } + return sillies +} + +func main() { + filename := "part0.txt" + if len(os.Args) > 1 { + filename = os.Args[1] + } + lines := readLines(filename) + if len(lines) != 1 { + panic("Invalid lines") + } + seqs, err := parseLine(lines[0]) + if err != nil { + panic(err) + } + total := uint64(0) + for _, seq := range seqs { + for _, value := range findSillyPatterns(seq) { + total += value + } + } + fmt.Printf("%v\n", total) + + total = uint64(0) + for _, seq := range seqs { + for _, value := range findVerySillyPatterns(seq) { + total += value + } + } + fmt.Printf("%v\n", total) +} diff --git a/day2/part0.txt b/day2/part0.txt new file mode 100644 index 0000000..bd04584 --- /dev/null +++ b/day2/part0.txt @@ -0,0 +1 @@ +11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 \ No newline at end of file diff --git a/day2/part1.txt b/day2/part1.txt new file mode 100644 index 0000000..5531ea6 --- /dev/null +++ b/day2/part1.txt @@ -0,0 +1 @@ +16100064-16192119,2117697596-2117933551,1-21,9999936269-10000072423,1770-2452,389429-427594,46633-66991,877764826-877930156,880869-991984,18943-26512,7216-9427,825-1162,581490-647864,2736-3909,39327886-39455605,430759-454012,1178-1741,219779-244138,77641-97923,1975994465-1976192503,3486612-3602532,277-378,418-690,74704280-74781349,3915-5717,665312-740273,69386294-69487574,2176846-2268755,26-45,372340114-372408052,7996502103-7996658803,7762107-7787125,48-64,4432420-4462711,130854-178173,87-115,244511-360206,69-86 \ No newline at end of file