139 lines
3.1 KiB
Go
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)
|
||
|
}
|
||
|
|