main.go (2350B)
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "regexp" 8 "strconv" 9 ) 10 11 const ( 12 MASK = iota 13 MEM 14 ) 15 16 type program struct { 17 len int 18 ops []int 19 args1 []int64 20 args2 []int64 21 } 22 23 func (this program) get(i int) (int, int64, int64) { 24 return this.ops[i], this.args1[i], this.args2[i] 25 } 26 27 func readInput(filename string) (res program) { 28 file, _ := os.Open(filename) 29 defer file.Close() 30 31 scanner := bufio.NewScanner(file) 32 matcher := regexp.MustCompile(`(mask|mem)\[?([0-9]*)\]? = ([X10]{36}|[0-9]+)`) 33 for scanner.Scan() { 34 matches := matcher.FindAllStringSubmatch(scanner.Text(), -1) 35 switch matches[0][1] { 36 case "mask": 37 res.ops = append(res.ops, MASK) 38 mask0 := int64(0) 39 mask1 := int64(0) 40 for _, ch := range matches[0][3] { 41 mask0 <<= 1 42 mask1 <<= 1 43 switch ch { 44 case '0': 45 mask0 += 1 46 case '1': 47 mask1 += 1 48 } 49 } 50 res.args1 = append(res.args1, mask0) 51 res.args2 = append(res.args2, mask1) 52 case "mem": 53 res.ops = append(res.ops, MEM) 54 args1, _ := strconv.ParseInt(matches[0][2], 10, 64) 55 res.args1 = append(res.args1, args1) 56 args2, _ := strconv.ParseInt(matches[0][3], 10, 64) 57 res.args2 = append(res.args2, args2) 58 } 59 res.len += 1 60 } 61 return 62 } 63 64 func main() { 65 input := readInput("./input.txt") 66 // 4297467072083 67 fmt.Println(part1(input)) 68 // 5030603328768 69 fmt.Println(part2(input)) 70 } 71 72 func part1(input program) (res int64) { 73 var ( 74 mask0 int64 75 mask1 int64 76 mem = map[int64]int64{} 77 ) 78 for i := 0; i < input.len; i++ { 79 op, arg1, arg2 := input.get(i) 80 switch op { 81 case MASK: 82 mask0, mask1 = arg1, arg2 83 case MEM: 84 mem[arg1] = (arg2 &^ mask0) | mask1 85 } 86 } 87 for _, v := range mem { 88 res += v 89 } 90 return 91 } 92 93 func part2(input program) (res int64) { 94 var ( 95 mask1 int64 96 maskX int64 97 mem = map[int64]int64{} 98 ) 99 for i := 0; i < input.len; i++ { 100 op, arg1, arg2 := input.get(i) 101 switch op { 102 case MASK: 103 mask1, maskX = arg2, 0xFFFFFFFFF&^(arg1|arg2) 104 case MEM: 105 addrs := []int64{arg1 | mask1} 106 for i := int64(1); i <= (1 << 36); i <<= 1 { 107 if i&maskX > 0 { 108 addrsNew := []int64{} 109 for _, addr := range addrs { 110 addrsNew = append(addrsNew, addr|i) 111 addrsNew = append(addrsNew, addr&^i) 112 } 113 addrs = addrsNew 114 } 115 } 116 for _, addr := range addrs { 117 mem[addr] = arg2 118 } 119 } 120 } 121 for _, v := range mem { 122 res += v 123 } 124 return 125 }