adventofcode/2020/day14/main.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]", &reg)
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]", &reg)
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
}