[ADD] Added day 17 solution

This commit is contained in:
Mika 2024-12-18 14:46:02 +01:00
parent f8fbc4531d
commit ff3010e617
3 changed files with 319 additions and 0 deletions

5
17/input.txt Normal file
View file

@ -0,0 +1,5 @@
Register A: 64012472
Register B: 0
Register C: 0
Program: 2,4,1,7,7,5,0,3,1,7,4,1,5,5,3,0

309
17/main.go Normal file
View file

@ -0,0 +1,309 @@
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
"time"
)
const FILE_PATH = "./input.txt"
//const FILE_PATH = "./sample.txt"
func LoadInput(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
type ComputerParams struct {
startA int
startB int
startC int
program []int
}
type structuredInput = ComputerParams
func TransformInput(lines []string) structuredInput {
var startA int
var startB int
var startC int
var numb int
var numbs []string
var program = make([]int, 0)
startA, _ = strconv.Atoi(lines[0][len("Register A: "):])
startB, _ = strconv.Atoi(lines[1][len("Register B: "):])
startC, _ = strconv.Atoi(lines[2][len("Register C: "):])
numbs = strings.Split(lines[4][len("Program: "):], ",")
for _, temp := range numbs {
numb, _ = strconv.Atoi(temp)
program = append(program, numb)
}
return ComputerParams{startA, startB, startC, program}
}
type Program struct {
a int
b int
c int
i int
out []int
}
const (
ADV = iota
BXL = iota
BST = iota
JNZ = iota
BXC = iota
OUT = iota
BDV = iota
CDV = iota
)
func getCombo(program Program, operand int) int {
if operand >= 0 && operand <= 3 {
return operand
}
if operand == 4 {
return program.a
}
if operand == 5 {
return program.b
}
if operand == 6 {
return program.c
}
return 0
}
func executeProgram(params ComputerParams) Program {
var program = Program{params.startA, params.startB, params.startC, 0, make([]int, 0)}
var opcode int
var operand int
var value int
for program.i < len(params.program) {
opcode = params.program[program.i]
operand = params.program[program.i+1]
switch opcode {
case ADV:
{
value = getCombo(program, operand)
program.a = int(float64(program.a) / math.Pow(2, float64(value)))
program.i += 2
}
case BXL:
{
program.b = program.b ^ operand
program.i += 2
}
case BST:
{
value = getCombo(program, operand)
program.b = value % 8
program.i += 2
}
case JNZ:
{
if program.a != 0 {
program.i = operand
} else {
program.i += 2
}
}
case BXC:
{
program.b = program.b ^ program.c
program.i += 2
}
case OUT:
{
program.out = append(program.out, getCombo(program, operand)%8)
program.i += 2
}
case BDV:
{
value = getCombo(program, operand)
program.b = int(float64(program.a) / math.Pow(2, float64(value)))
program.i += 2
}
case CDV:
{
value = getCombo(program, operand)
program.c = int(float64(program.a) / math.Pow(2, float64(value)))
program.i += 2
}
}
}
return program
}
func Part1(input structuredInput) int {
var result int = 0
input.startA = 265652340990877
var program = executeProgram(input)
for i := 0; i < len(program.out); i++ {
fmt.Printf("%d,", program.out[i])
}
fmt.Println()
return result
}
var numbs = [][]int{
[]int{0, 0, 0},
[]int{0, 0, 1},
[]int{0, 1, 0},
[]int{0, 1, 1},
[]int{1, 0, 0},
[]int{1, 0, 1},
[]int{1, 1, 0},
[]int{1, 1, 1},
}
func clone(input []int) []int {
var result = make([]int, len(input))
for i, numb := range input {
result[i] = numb
}
return result
}
func insert(numbers []int, numb []int, position int) ([]int, bool) {
var result = clone(numbers)
for i := 0; i < len(numb); i++ {
if position+i < 0 && numb[i] == 0 {
continue
}
if numbers[position+i] != -1 && numbers[position+i] != numb[i] {
return []int{}, true
}
result[position+i] = numb[i]
}
return result, false
}
func invs(is []int, should []int) []int {
var result = []int{0, 0, 0}
for i := 0; i < 3; i++ {
if should[i] == 1 && is[i] == 0 || should[i] == 0 && is[i] == 1 {
result[i] = 1
}
}
return result
}
func bToi(numbers []int) int {
var result = 0
var pow = math.Pow(2, float64(len(numbers)-1))
for i := 0; i < len(numbers); i++ {
result += numbers[i] * int(pow)
pow = pow / 2
}
return result
}
func Part2(input structuredInput) int {
var result int = 0
var poss [][]int = make([][]int, 1)
var next [][]int = make([][]int, 0)
var number []int = make([]int, 3*16)
var error bool
var position int
var temp []int
var work []int
for i := 0; i < len(number); i++ {
number[i] = -1
}
poss[0] = number
for j := 15; j >= 0; j-- {
next = make([][]int, 0)
for i := 0; i < len(poss); i++ {
work = poss[i]
position = j * 3
for m := 0; m < len(numbs); m++ {
temp, error = insert(work, numbs[m], position)
if error {
continue
}
temp, error = insert(temp, invs(numbs[m], numbs[input.program[len(input.program)-j-1]]), position-(7-m))
if error {
continue
}
next = append(next, temp)
}
}
poss = next
}
var lowest int = -1
var dec int
for i := 0; i < len(poss); i++ {
dec = bToi(poss[i])
if lowest == -1 || lowest > dec {
lowest = dec
}
}
result = lowest
return result
}
func main() {
var start time.Time
var elapsed time.Duration = 0
input, err := LoadInput(FILE_PATH)
if err != nil {
fmt.Println("Error loading input:", err)
return
}
structuredInput := TransformInput(input)
fmt.Println("Structured Input:", structuredInput)
start = time.Now()
fmt.Println("Solution Part 1: ", Part1(structuredInput))
elapsed = time.Since(start)
fmt.Printf("Part 1 took %s\n", elapsed)
start = time.Now()
fmt.Println("Solution Part 2: ", Part2(structuredInput))
elapsed = time.Since(start)
fmt.Printf("Part 2 took %s\n", elapsed)
}

5
17/sample.txt Normal file
View file

@ -0,0 +1,5 @@
Register A: 2024
Register B: 0
Register C: 0
Program: 0,3,5,4,3,0