-
Notifications
You must be signed in to change notification settings - Fork 0
/
day14.go
162 lines (154 loc) · 3.69 KB
/
day14.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
func main() {
i, err := ioutil.ReadFile("input.txt")
if err != nil {
os.Exit(1)
}
input := string(i)
fmt.Printf("Part 1: %v\n", SolveDay14Part1(stringListToSlice(input)))
fmt.Printf("Part 2: %v\n", SolveDay14Part2(stringListToSlice(input)))
}
//SolveDay14Part1 returns the sum of all addresses after mask the values
func SolveDay14Part1(input []string) (sum int64) {
var curMask string
curValues := make(map[int64]int64)
for _, line := range input {
if strings.HasPrefix(line, "mask") {
curMask = strings.TrimPrefix(line, "mask = ")
} else {
address, value := getMaskValues(line)
curValues[address] = applyMaskOnValue(curMask, value)
}
}
for _, value := range curValues {
sum += value
}
return
}
//SolveDay14Part2 returns the sum of all addresses after mask the addresses
func SolveDay14Part2(input []string) (sum int64) {
var curMask string
curValues := make(map[int64]int64)
for _, line := range input {
if strings.HasPrefix(line, "mask") {
curMask = strings.TrimPrefix(line, "mask = ")
} else {
address, value := getMaskValues(line)
for _, add := range applyMaskOnAddress(curMask, address) {
curValues[add] = value
}
}
}
for _, value := range curValues {
sum += value
}
return
}
//getMaskValues returns the mem address and the value
func getMaskValues(input string) (address, value int64) {
split := strings.Split(input, " = ")
if len(split) != 2 {
return 0, 0
}
addressInt, err := strconv.Atoi(strings.Trim(split[0], "mem[]"))
if err != nil {
return 0, 0
}
valueInt, err := strconv.Atoi(split[1])
if err != nil {
return 0, 0
}
return int64(addressInt), int64(valueInt)
}
//applyMaskOnValue returns the new value of the given value after apply the mask
func applyMaskOnValue(mask string, value int64) (newValue int64) {
if len(mask) != 36 {
return 0
}
curBit := int64(34359738368)
for _, maskChar := range mask {
newValue <<= 1
switch maskChar {
// 1
case 49:
newValue++
// 0
case 48:
// X
case 88:
if (value & curBit) != 0 {
newValue++
}
default:
return 0
}
curBit /= 2
}
return newValue
}
//applyMaskOnAddress apply the mask to the address and returns a list of new addresses
func applyMaskOnAddress(mask string, address int64) (addressesInt []int64) {
if len(mask) != 36 {
return nil
}
//apply mask to address
var maskedAddress string
curBit := int64(34359738368)
for _, maskChar := range mask {
switch maskChar {
// 1 == 49
case 49:
maskedAddress = maskedAddress + "1"
// X == 88
case 88:
maskedAddress = maskedAddress + "X"
// 0 == 48
case 48:
if (address & curBit) == 0 {
maskedAddress = maskedAddress + "0"
} else {
maskedAddress = maskedAddress + "1"
}
default:
return nil
}
curBit /= 2
}
//generate address list by inserting 0 and 1 for each X
addressList := []string{maskedAddress}
for i, bit := range mask {
// 48 == 0 / 49 == 1
if bit == 48 || bit == 49 {
continue
}
var tempAddressList []string
for _, runMask := range addressList {
tempAddressList = append(tempAddressList, runMask[:i]+"0"+runMask[i+1:], runMask[:i]+"1"+runMask[i+1:])
}
addressList = tempAddressList
}
//calculate the numbers of the addresses
for _, address := range addressList {
tmpAddressInt, err := strconv.ParseInt(address, 2, 64)
if err != nil {
return nil
}
addressesInt = append(addressesInt, tmpAddressInt)
}
return
}
//Helper functions
//stringListToSlice converts the list of strings (each string one row) to a slice
func stringListToSlice(list string) (s []string) {
for _, line := range strings.Split(strings.TrimSuffix(list, "\n"), "\n") {
s = append(s, line)
}
return
}