AoC2020/day14/day14.go
Karl Spickermann f2e83bc7d2 Day14
2020-12-14 17:18:16 +01:00

139 lines
3.1 KiB
Go

package main
import (
"AoC2020/helper"
"fmt"
"os"
"strconv"
"strings"
)
var Mem = make(map[int]int64)
var Mask string
func main() {
args := os.Args[1:]
input, err := helper.GetInput(args[0])
if err != nil {
fmt.Println(err)
}
execute(input, run)
Mem = make(map[int]int64)
execute(input, runPart2)
}
func execute(input []string, f func(a string)) {
for _, val := range input {
f(val)
}
count := 0
for _, value := range Mem {
count = count + int(value)
}
fmt.Println(count)
}
func run(row string) {
command := strings.Split(row," = ")
if command[0] == "mask" {
Mask = command[1]
} else {
location, _ := strconv.Atoi(command[0][4:len(command[0])-1])
number, _ := strconv.Atoi(command[1])
save(number, Mask, location)
}
}
func save(number int, mask string, location int) {
bitNumber := strconv.FormatInt(int64(number), 2)
bitNumber = addPrecedingZeroes(bitNumber)
bitNumber = applyMask(bitNumber,mask)
saveToM(bitNumber, location)
}
func applyMask(number string, mask string) string{
var newNumber string
for i, val := range mask {
switch val {
case 'X': newNumber = newNumber + string(number[i])
case '1': newNumber = newNumber + "1"
case '0': newNumber = newNumber + "0"
}
}
return newNumber
}
func runPart2(row string) {
command := strings.Split(row," = ")
if command[0] == "mask" {
Mask = command[1]
} else {
location, _ := strconv.Atoi(command[0][4:len(command[0])-1])
number, _ := strconv.Atoi(command[1])
savePart2(number, Mask, location)
}
}
func savePart2(number int, mask string, location int) {
bitNumber := strconv.FormatInt(int64(location), 2)
bitNumber = addPrecedingZeroes(bitNumber)
bitNumbers := applyMaskPart2(bitNumber,mask)
for _,val := range bitNumbers {
Mem[int(getIntFromBitNumber(val))] = int64(number)
}
}
func saveToM(bitNumber string, location int) {
Mem[location] = getIntFromBitNumber(bitNumber)
}
func getIntFromBitNumber(bitNumber string) int64 {
if i, err := strconv.ParseInt(bitNumber, 2, 64); err != nil {
fmt.Println(err)
} else {
return i
}
return -1
}
func applyMaskPart2(number string, mask string) []string{
var newNumber string
for i, val := range mask {
switch val {
case 'X': newNumber = newNumber + "X"
case '1': newNumber = newNumber + "1"
case '0': newNumber = newNumber + string(number[i])
}
}
return getVariations(0,newNumber)
}
func getVariations(pointer int ,number string) []string{
var variations []string
for i := pointer; i < len(number); i++ {
if number[i] == 'X' {
number1 := number + ""
number1 = replaceAtIndex(number1,'0',i)
number2 := number + ""
number2 = replaceAtIndex(number1,'1',i)
variations = append(variations, getVariations(i, number1) ...)
variations = append(variations, getVariations(i, number2) ...)
}
}
if strings.Index(number, "X") == -1 {
variations = append(variations, number)
}
return variations
}
func addPrecedingZeroes(number string) string {
return strings.Repeat("0", 36-len(number)) + number
}
func replaceAtIndex(in string, r rune, i int) string {
out := []rune(in)
out[i] = r
return string(out)
}