120 lines
2.2 KiB
Go
120 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("# Day 14")
|
|
inp := h.StdinToStringSlice()
|
|
vsn := h.Atoi(h.OptArgNumber(1, "1"))
|
|
if vsn == 1 {
|
|
part1(inp)
|
|
} else {
|
|
part2(inp)
|
|
}
|
|
}
|
|
|
|
func part1(inp []string) {
|
|
memory := make(map[int]uint)
|
|
var mask map[int]uint
|
|
for _, v := range inp {
|
|
pts := strings.Split(v, " = ")
|
|
if pts[0] == "mask" {
|
|
mask = make(map[int]uint)
|
|
parsemask := pts[1]
|
|
for k := range parsemask {
|
|
if parsemask[k] != 'X' {
|
|
place := (len(parsemask) - k - 1)
|
|
if parsemask[k] == '0' {
|
|
mask[place] = 0
|
|
} else {
|
|
mask[place] = 1
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
var reg int
|
|
fmt.Sscanf(pts[0], "mem[%d]", ®)
|
|
val := uint(h.Atoi(pts[1]))
|
|
store := applyMask(val, mask)
|
|
memory[reg] = store
|
|
}
|
|
}
|
|
|
|
var res uint
|
|
for _, v := range memory {
|
|
res = res + v
|
|
}
|
|
fmt.Println("## Part 1")
|
|
fmt.Println("Sum:", res)
|
|
}
|
|
|
|
func applyMask(val uint, mask map[int]uint) uint {
|
|
for k, v := range mask {
|
|
if v == 0 {
|
|
val = val &^ (1 << k)
|
|
} else if v == 1 {
|
|
val = val | (1 << k)
|
|
}
|
|
}
|
|
return val
|
|
}
|
|
|
|
func part2(inp []string) {
|
|
memory := make(map[uint]uint)
|
|
var mask string
|
|
for _, v := range inp {
|
|
pts := strings.Split(v, " = ")
|
|
if pts[0] == "mask" {
|
|
mask = pts[1]
|
|
} else {
|
|
var reg int
|
|
fmt.Sscanf(pts[0], "mem[%d]", ®)
|
|
val := uint(h.Atoi(pts[1]))
|
|
stores := []uint{uint(reg)}
|
|
for k := range mask {
|
|
bit := len(mask) - k - 1
|
|
var wrk []uint
|
|
for i := range stores {
|
|
switch mask[k] {
|
|
case '0':
|
|
wrk = append(wrk, stores[i])
|
|
case '1':
|
|
wrk = append(wrk, setBitTo(stores[i], bit, true))
|
|
case 'X':
|
|
wrk = append(wrk, floatBit(stores[i], bit)...)
|
|
}
|
|
}
|
|
stores = append([]uint{}, wrk...)
|
|
}
|
|
for k := range stores {
|
|
memory[stores[k]] = val
|
|
}
|
|
}
|
|
}
|
|
var sum uint
|
|
for k := range memory {
|
|
sum = sum + memory[k]
|
|
}
|
|
fmt.Println("## Part 2")
|
|
fmt.Println("Sum:", sum)
|
|
}
|
|
|
|
func setBitTo(addr uint, pos int, val bool) uint {
|
|
if val {
|
|
return addr | (1 << pos)
|
|
} else {
|
|
return addr &^ (1 << pos)
|
|
}
|
|
}
|
|
func floatBit(addr uint, pos int) []uint {
|
|
var ret []uint
|
|
ret = append(ret, addr|(1<<pos))
|
|
ret = append(ret, addr&^(1<<pos))
|
|
return ret
|
|
}
|