commit a1b380717c8431dd3598481d47c5db316c3c0295 Author: george Date: Tue Jun 18 15:06:38 2024 +0100 add day 1 and 2 solutions diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fdf18b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +input diff --git a/day01/Cargo.lock b/day01/Cargo.lock new file mode 100644 index 0000000..683c0b9 --- /dev/null +++ b/day01/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day01" +version = "0.1.0" diff --git a/day01/Cargo.toml b/day01/Cargo.toml new file mode 100644 index 0000000..5a61072 --- /dev/null +++ b/day01/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day01" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day01/src/main.rs b/day01/src/main.rs new file mode 100644 index 0000000..bcd6d65 --- /dev/null +++ b/day01/src/main.rs @@ -0,0 +1,30 @@ +use std::io::{self, BufRead}; + +fn main() { + let nums: Vec = io::stdin() + .lock() + .lines() + .map(|line| line.unwrap().parse::().unwrap()) + .collect(); + + let p1: u64 = nums.iter().map(|&num| mass_to_fuel(num)).sum(); + let p2: u64 = nums.iter().map(|&num| fuel_for_fuel(num)).sum(); + + println!("P1: {}, P2: {}", p1, p2); +} + +fn mass_to_fuel(mass: u64) -> u64 { + (mass / 3).saturating_sub(2) +} + +fn fuel_for_fuel(fuel: u64) -> u64 { + let mut tot = 0; + let mut fuel = fuel; + + while fuel > 0 { + fuel = mass_to_fuel(fuel); + tot += fuel; + } + + tot +} diff --git a/day02/Makefile b/day02/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/day02/cmd/main.go b/day02/cmd/main.go new file mode 100644 index 0000000..e1e705a --- /dev/null +++ b/day02/cmd/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "intcode/internal/interpreter" + "intcode/internal/parser" +) + +func main() { + sourceProgram, err := parser.ParseFile(nil) + + if err != nil { + panic(err) + } + + runProgram := make([]int, len(sourceProgram)) + + for x := 0; x < 100; x++ { + for y := 0; y < 100; y++ { + copy(runProgram, sourceProgram) + + runProgram[1], runProgram[2] = x, y + + interpreter := interpreter.Init(runProgram) + + for !interpreter.Next() {} + + if x == 12 && y == 2 { + fmt.Printf("Part 1: %v\n", runProgram[0]) + } + if runProgram[0] == 19690720 { + fmt.Printf("Part 2: %02d%02d\n", x, y) + } + } + } +} diff --git a/day02/go.mod b/day02/go.mod new file mode 100644 index 0000000..e902907 --- /dev/null +++ b/day02/go.mod @@ -0,0 +1,3 @@ +module intcode + +go 1.22.4 diff --git a/day02/internal/debugger/debugger.go b/day02/internal/debugger/debugger.go new file mode 100644 index 0000000..fca119c --- /dev/null +++ b/day02/internal/debugger/debugger.go @@ -0,0 +1 @@ +package debugger diff --git a/day02/internal/interpreter/interpreter.go b/day02/internal/interpreter/interpreter.go new file mode 100644 index 0000000..96b0dec --- /dev/null +++ b/day02/internal/interpreter/interpreter.go @@ -0,0 +1,61 @@ +package interpreter + +import "fmt" + +type Interpreter struct { + program []int + instructionPointer int +} + +func Init(program []int) *Interpreter { + return &Interpreter { + program: program, + instructionPointer: 0, + } +} + +func (i *Interpreter) Next() bool { + opcode := i.getValueAtIndex(i.instructionPointer) + ipIncrement := 1 + + switch opcode { + case 1: + i.add() + ipIncrement = 4 + case 2: + i.mul() + ipIncrement = 4 + case 99: + return true + default: + panic(fmt.Sprintf("unhandled opcode %v at IP %v", opcode, i.instructionPointer)) + } + + i.instructionPointer += ipIncrement + + return false +} + +func (i *Interpreter) getValueAtIndex(index int) int { + return i.program[index] +} + +func (i *Interpreter) setValueAtIndex(index, value int) { + i.program[index] = value +} + +func (i *Interpreter) add() { + resIndex := i.getValueAtIndex(i.instructionPointer + 3) + arg1Index := i.getValueAtIndex(i.instructionPointer + 1) + arg2Index := i.getValueAtIndex(i.instructionPointer + 2) + + i.setValueAtIndex(resIndex, i.getValueAtIndex(arg1Index) + i.getValueAtIndex(arg2Index)) +} + +func (i *Interpreter) mul() { + resIndex := i.getValueAtIndex(i.instructionPointer + 3) + arg1Index := i.getValueAtIndex(i.instructionPointer + 1) + arg2Index := i.getValueAtIndex(i.instructionPointer + 2) + + i.setValueAtIndex(resIndex, i.getValueAtIndex(arg1Index) * i.getValueAtIndex(arg2Index)) +} diff --git a/day02/internal/interpreter/interpreter_test.go b/day02/internal/interpreter/interpreter_test.go new file mode 100644 index 0000000..3576853 --- /dev/null +++ b/day02/internal/interpreter/interpreter_test.go @@ -0,0 +1 @@ +package interpreter diff --git a/day02/internal/parser/parser.go b/day02/internal/parser/parser.go new file mode 100644 index 0000000..9edffd6 --- /dev/null +++ b/day02/internal/parser/parser.go @@ -0,0 +1,48 @@ +package parser + +import ( + "fmt" + "io" + "os" + "strconv" + "strings" +) + +const DefaultFile = "input" + +func ParseFile(input *string) ([]int, error) { + if input == nil { + + file := DefaultFile + + if len(os.Args) == 2 { + file = os.Args[1] + } + + inputFile, err := os.Open(file) + if err != nil { + return nil, fmt.Errorf("could not parse input file: %v", err) + } + + fileData, err := io.ReadAll(inputFile) + if err != nil { + return nil, fmt.Errorf("could not read input file: %v", err) + } + + fileStr := strings.TrimSpace(string(fileData)) + input = &fileStr + } + + strNums := strings.Split(*input, ",") + opcodes := make([]int, len(strNums)) + + for i, v := range strNums { + num, err := strconv.Atoi(v) + if err != nil { + fmt.Fprintf(os.Stderr, "WARNING: error parsing int from input, substring was %v", v) + } + opcodes[i] = num + } + + return opcodes, nil +}