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 }