main.go (2492B)
1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "os" 8 "sort" 9 "strings" 10 ) 11 12 type Packets []any 13 14 func (p Packets) Len() int { return len(p) } 15 func (p Packets) Swap(i, j int) { 16 p[i], p[j] = p[j], p[i] 17 } 18 func (p Packets) Less(i, j int) bool { 19 cmp, _ := Compare(p[i], p[j]) 20 return cmp 21 } 22 23 func main() { 24 if len(os.Args) > 1 { 25 day13(os.Args[1]) 26 } else if len(os.Args) == 1 { 27 fmt.Printf("usage: %s inputfile.txt\n", os.Args[0]) 28 } else { 29 fmt.Println("No input data") 30 } 31 } 32 33 func day13(input_file string) { 34 fmt.Printf("day 13 input filename: %s\n", input_file) 35 input, err := os.ReadFile(input_file) 36 if err != nil { 37 log.Fatal(err) 38 } 39 pairs := strings.Split(string(input), "\n\n") 40 sum := 0 41 var packets Packets 42 for i, p := range pairs { 43 pair := strings.Split(p, "\n") 44 if len(pair) < 2 { 45 log.Fatal("Invalid pair", pair) 46 } 47 var p1, p2 any 48 if err = json.Unmarshal([]byte(pair[0]), &p1); err != nil { 49 log.Fatal(err) 50 } 51 if err = json.Unmarshal([]byte(pair[1]), &p2); err != nil { 52 log.Fatal(err) 53 } 54 res, _ := Compare(p1, p2) 55 if res { 56 sum += i + 1 57 } 58 packets = append(packets, p1, p2) 59 } 60 m1, m2 := "[[2]]", "[[6]]" 61 var marker1, marker2 any 62 json.Unmarshal([]byte(m1), &marker1) 63 json.Unmarshal([]byte(m2), &marker2) 64 packets = append(packets, marker1, marker2) 65 66 sort.Sort(packets) 67 68 v1, v2 := 0, 0 69 for i, p := range packets { 70 j, err := json.Marshal(p) 71 if err != nil { 72 log.Fatal(err) 73 } 74 if string(j) == m1 { 75 v1 = i + 1 76 } 77 if string(j) == m2 { 78 v2 = i + 1 79 } 80 } 81 82 fmt.Println("Part 1:", sum) 83 fmt.Println("Part 2:", v1*v2) 84 } 85 86 // returns (result, continue) 87 func Compare(p1, p2 any) (bool, bool) { 88 p1ar, p2ar := IsArray(p1), IsArray(p2) 89 if !p1ar && !p2ar { 90 p1n, p2n := int(p1.(float64)), int(p2.(float64)) 91 return p1n < p2n, p1n == p2n 92 } else if p1ar && p2ar { 93 return CompareArrays(p1.([]any), p2.([]any)) 94 } else if p1ar { 95 return CompareArrays(p1.([]any), []any{p2}) 96 } else if p2ar { 97 return CompareArrays([]any{p1}, p2.([]any)) 98 } 99 log.Fatal("Invalid something") 100 return false, false 101 } 102 103 func CompareArrays(p1, p2 []any) (bool, bool) { 104 for i := 0; i < len(p1); i++ { 105 if i >= len(p2) { 106 return false, false 107 } 108 res, cont := Compare(p1[i], p2[i]) 109 if !cont { 110 return res, false 111 } 112 } 113 return len(p1) < len(p2), len(p1) >= len(p2) 114 } 115 116 func IsArray(v any) bool { 117 switch v.(type) { 118 case float64: 119 return false 120 case []any: 121 return true 122 default: 123 log.Fatal("unknown value", v) 124 //return true 125 } 126 return false 127 }