AdventOfCode2020/14/main.go

149 lines
2.9 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"time"
)
func main() {
start := time.Now()
partOne()
duration := time.Since(start)
partTwo()
duration2 := time.Since(start)
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
}
type bitset struct {
bits []string
}
func newBitset(i int) bitset {
b := strings.Split(fmt.Sprintf("%036b", i), "")
bs := bitset{
bits: strings.Split("000000000000000000000000000000000000", ""),
}
for i, bt := range b {
if bt != "0" {
bs.bits[i] = bt
}
}
return bs
}
func (b bitset) ToInt() int {
i, _ := strconv.ParseInt(strings.Join(b.bits, ""), 2, 64)
return int(i)
}
func parseMask(s string) string {
return strings.Split(s, " = ")[1]
}
func parseMemoryToAddrAndBitset(s string) (int, bitset) {
a := strings.Split(s, " = ")
addr, _ := strconv.Atoi(strings.TrimFunc(a[0], func(r rune) bool {
if r == 'm' || r == 'e' || r == '[' || r == ']' {
return true
}
return false
}))
i, _ := strconv.Atoi(a[1])
return addr, newBitset(i)
}
func parseMemoryToBitsetAndValue(s string) (bitset, int) {
a := strings.Split(s, " = ")
addr, _ := strconv.Atoi(strings.TrimFunc(a[0], func(r rune) bool {
if r == 'm' || r == 'e' || r == '[' || r == ']' {
return true
}
return false
}))
i, _ := strconv.Atoi(a[1])
return newBitset(addr), i
}
func applyMaskToValue(m string, b bitset) int {
for i, r := range m {
if r == '0' {
b.bits[i] = "0"
}
if r == '1' {
b.bits[i] = "1"
}
}
return b.ToInt()
}
func applyMaskToAddr(prefix []string, m string, attr bitset) []bitset {
if len(m) == 0 {
return []bitset{{bits: prefix}}
}
res := []bitset{}
for _, r := range m {
if r == '0' || r == 'X' {
res = append(res, applyMaskToAddr(append(prefix[:], "0"), m[1:], attr)...)
}
if r == '1' || r == 'X' {
res = append(res, applyMaskToAddr(append(prefix[:], "1"), m[1:], attr)...)
}
}
return res
}
func partOne() {
f, _ := os.Open("input")
reader := bufio.NewReader(f)
scanner := bufio.NewScanner(reader)
mem := map[int]int{}
var currentMask string
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "mask") {
currentMask = parseMask(line)
} else {
addr, value := parseMemoryToAddrAndBitset(line)
mem[addr] = applyMaskToValue(currentMask, value)
}
}
sum := 0
for _, v := range mem {
sum = sum + v
}
fmt.Println(sum)
}
func partTwo() {
f, _ := os.Open("testinput")
reader := bufio.NewReader(f)
scanner := bufio.NewScanner(reader)
mem := map[int]int{}
var currentMask string
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "mask") {
currentMask = parseMask(line)
} else {
addr, value := parseMemoryToBitsetAndValue(line)
for _, b := range applyMaskToAddr([]string{}, currentMask, addr) {
mem[b.ToInt()] = value
}
}
}
sum := 0
for _, v := range mem {
sum = sum + v
}
fmt.Println(sum)
}