|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "fmt" |
| 6 | + "os" |
| 7 | + "reflect" |
| 8 | + "sort" |
| 9 | + "strings" |
| 10 | +) |
| 11 | + |
| 12 | +func main() { |
| 13 | + input, _ := os.ReadFile("../../input/day13.txt") |
| 14 | + pairs := readPairs(string(input)) |
| 15 | + |
| 16 | + packets := [][]any{} |
| 17 | + sum := 0 |
| 18 | + for i, pair := range pairs { |
| 19 | + if less(pair[0], pair[1]) { |
| 20 | + sum += i + 1 |
| 21 | + } |
| 22 | + packets = append(packets, pair[0], pair[1]) |
| 23 | + } |
| 24 | + fmt.Printf("part1: %v\n", sum) |
| 25 | + |
| 26 | + packets = append(packets, dividers...) |
| 27 | + sort.Sort(ByPacket(packets)) |
| 28 | + var key int |
| 29 | + for i, p := range packets { |
| 30 | + if reflect.DeepEqual(p, dividers[0]) { |
| 31 | + key = i + 1 |
| 32 | + } else if reflect.DeepEqual(p, dividers[1]) { |
| 33 | + key = key * (i + 1) |
| 34 | + } |
| 35 | + } |
| 36 | + fmt.Printf("part2: %v\n", key) |
| 37 | +} |
| 38 | + |
| 39 | +func less(left []any, right []any) (less bool) { |
| 40 | + return compare(left, right, 0) <= 0 |
| 41 | +} |
| 42 | + |
| 43 | +func compare(left []any, right []any, i int) (res int) { |
| 44 | + if i >= len(left) && i >= len(right) { |
| 45 | + return 0 // end of both lists |
| 46 | + } else if i >= len(left) { |
| 47 | + return -1 // left ended first |
| 48 | + } else if i >= len(right) { |
| 49 | + return 1 // right shorter |
| 50 | + } |
| 51 | + |
| 52 | + // number comparison |
| 53 | + li, ri := left[i], right[i] |
| 54 | + ln, isln := li.(float64) |
| 55 | + rn, isrn := ri.(float64) |
| 56 | + if isln && isrn && ln == rn { |
| 57 | + return compare(left, right, i+1) // same, continue to next item |
| 58 | + } else if isln && isrn { |
| 59 | + return int(ln - rn) // different numbers |
| 60 | + } |
| 61 | + |
| 62 | + // list comparison |
| 63 | + llist, isllist := li.([]any) |
| 64 | + rlist, isrlist := ri.([]any) |
| 65 | + if !isllist { |
| 66 | + llist = []any{ln} // mixed, convert to list |
| 67 | + } |
| 68 | + if !isrlist { |
| 69 | + rlist = []any{rn} // mixed, convert to list |
| 70 | + } |
| 71 | + res = compare(llist, rlist, 0) |
| 72 | + if res == 0 { // tie, continue to next item |
| 73 | + return compare(left, right, i+1) |
| 74 | + } |
| 75 | + return res |
| 76 | +} |
| 77 | + |
| 78 | +var dividers = [][]any{{[]any{float64(2)}}, {[]any{float64(6)}}} |
| 79 | + |
| 80 | +type ByPacket [][]any |
| 81 | + |
| 82 | +func (p ByPacket) Len() int { return len(p) } |
| 83 | +func (p ByPacket) Swap(i, j int) { p[i], p[j] = p[j], p[i] } |
| 84 | +func (p ByPacket) Less(i, j int) bool { return less(p[i], p[j]) } |
| 85 | + |
| 86 | +func readPairs(input string) (res [][2][]any) { |
| 87 | + pairs := strings.Split(input, "\n\n") |
| 88 | + for _, pair := range pairs { |
| 89 | + part := strings.Split(pair, "\n") |
| 90 | + var left, right []any |
| 91 | + json.Unmarshal([]byte(part[0]), &left) |
| 92 | + json.Unmarshal([]byte(part[1]), &right) |
| 93 | + pair := [2][]any{left, right} |
| 94 | + res = append(res, pair) |
| 95 | + } |
| 96 | + return res |
| 97 | +} |
0 commit comments