149 lines
2.9 KiB
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)
|
|
}
|