Last active
December 3, 2019 06:38
-
-
Save mgwidmann/bd4f2411d447dd627add22aaefb7e0d8 to your computer and use it in GitHub Desktop.
2019 AOC - golang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
var allMasses []int = []int{ | |
147308, 51605, 71317, 110882, 92545, 126856, 104937, 92433, 107850, 119538, 82733, 52216, 105704, 123682, 105919, 136265, 100540, 84245, 72006, 111652, 85116, 85841, 71374, 144196, 125493, 113529, 64637, 87489, 138161, 120897, 53384, 83310, | |
120672, 126144, 107681, 101369, 77469, 141056, 140426, 114920, 124454, 130867, 64611, 104813, 138808, 114234, 148654, 59031, 91367, 83316, 106192, 127495, 139980, 119024, 149567, 57007, 61075, 65637, 75293, 61670, 104044, 77230, 80201, | |
137094, 99733, 50801, 68922, 148404, 79980, 62716, 67666, 72694, 81951, 108427, 111721, 55532, 94442, 88562, 101088, 111656, 111649, 92085, 91730, 114744, 59355, 55842, 100926, 146370, 147829, 62160, 91447, 115745, 141815, 106837, 68151, | |
89077, 60357, 89856, 75040, 139131, | |
} | |
func fuelRequired(mass int) int { | |
return (mass / 3) - 2 | |
} | |
func mainFirstStar() int { | |
sum := 0 | |
for _, mass := range allMasses { | |
sum += fuelRequired(mass) | |
} | |
return sum | |
} | |
func fuelForFuel(fuel int) int { | |
if fuel <= 0 { | |
return 0 | |
} else { | |
extraFuel := fuelRequired(fuel) | |
f2 := fuelForFuel(extraFuel) | |
return fuel + f2 | |
} | |
} | |
func mainSecondStar() int { | |
sum := 0 | |
for _, mass := range allMasses { | |
fuel := fuelRequired(mass) | |
extraFuel := fuelForFuel(fuel) | |
sum += extraFuel | |
} | |
return sum | |
} | |
func main() { | |
basicSum := mainFirstStar() | |
fmt.Println("(Basic) Sum fuel required:", basicSum) | |
extraFuel := mainSecondStar() | |
fmt.Println("Full Sum fuel required:", extraFuel) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"strings" | |
) | |
var instructions []int = []int{ | |
1, 12, 2, 3, // Original was 1, 0, 0, 3, | |
1, 1, 2, 3, | |
1, 3, 4, 3, | |
1, 5, 0, 3, | |
2, 6, 1, 19, | |
2, 19, 9, 23, | |
1, 23, 5, 27, | |
2, 6, 27, 31, | |
1, 31, 5, 35, | |
1, 35, 5, 39, | |
2, 39, 6, 43, | |
2, 43, 10, 47, | |
1, 47, 6, 51, | |
1, 51, 6, 55, | |
2, 55, 6, 59, | |
1, 10, 59, 63, | |
1, 5, 63, 67, | |
2, 10, 67, 71, | |
1, 6, 71, 75, | |
1, 5, 75, 79, | |
1, 10, 79, 83, | |
2, 83, 10, 87, | |
1, 87, 9, 91, | |
1, 91, 10, 95, | |
2, 6, 95, 99, | |
1, 5, 99, 103, | |
1, 103, 13, 107, | |
1, 107, 10, 111, | |
2, 9, 111, 115, | |
1, 115, 6, 119, | |
2, 13, 119, 123, | |
1, 123, 6, 127, | |
1, 5, 127, 131, | |
2, 6, 131, 135, | |
2, 6, 135, 139, | |
1, 139, 5, 143, | |
1, 143, 10, 147, | |
1, 147, 2, 151, | |
1, 151, 13, 0, | |
99, | |
2, 0, 14, 0, | |
} | |
type InstructionType int | |
const ( | |
Add InstructionType = iota + 1 | |
Multiply | |
End InstructionType = 99 | |
) | |
// Can't make real enum :( | |
// Making const gives the following error | |
// const initializer []InstructionType literal is not a constant | |
var Action []InstructionType = []InstructionType{Add, Multiply, End} | |
func (t InstructionType) String() string { | |
if t == 99 { | |
return "End" | |
} | |
if t < Add || t > Multiply { | |
return "INVALID" | |
} | |
return [...]string{"Add", "Multiply"}[t-1] | |
} | |
func printProgram(program []int) string { | |
var prog []string | |
for i := 0; i < len(program); i += 4 { | |
switch instruction := program[i]; InstructionType(instruction) { | |
case End: | |
prog = append(prog, fmt.Sprintf("%d: %v", i, program[i:i+1])) | |
i -= 3 | |
default: | |
if i+4 >= len(program) { | |
prog = append(prog, fmt.Sprintf("%d: %v", i, program[i:])) | |
} else { | |
prog = append(prog, fmt.Sprintf("%d: %v", i, program[i:i+4])) | |
} | |
} | |
} | |
return strings.Join(prog, "\n") | |
} | |
type Instruction struct { | |
Action []InstructionType | |
Pos1 int | |
Pos2 int | |
StoreAt int | |
} | |
func executeInstruction(program []int, i int) int { | |
switch instruction := program[i]; InstructionType(instruction) { | |
case Add: | |
pos1 := program[i+1] | |
pos2 := program[i+2] | |
storeAt := program[i+3] | |
// fmt.Println("Adding", program[pos1], "(idx "+strconv.Itoa(pos1)+")", program[pos2], "(idx "+strconv.Itoa(pos2)+")", "and storing at", storeAt, "(before "+strconv.Itoa(program[storeAt])+" after "+strconv.Itoa(program[pos1]+program[pos2])+")") | |
program[storeAt] = program[pos1] + program[pos2] | |
return i + 4 | |
case Multiply: | |
pos1 := program[i+1] | |
pos2 := program[i+2] | |
storeAt := program[i+3] | |
// fmt.Println("Multiplying", program[pos1], "(idx "+strconv.Itoa(pos1)+")", program[pos2], "(idx "+strconv.Itoa(pos2)+")", "and storing at", storeAt, "(before "+strconv.Itoa(program[storeAt])+" after "+strconv.Itoa(program[pos1]*program[pos2])+")") | |
program[storeAt] = program[pos1] * program[pos2] | |
return i + 4 | |
case End: | |
return -1 | |
default: | |
var fullInstruction []int | |
if i+4 >= len(program) { | |
fullInstruction = program[i:] | |
} else { | |
fullInstruction = program[i : i+4] | |
} | |
message := fmt.Sprintf("Unknown instruction %v at position %v (%v)\nCurrent program: \n%v", instruction, i, fullInstruction, printProgram(program)) | |
panic(message) | |
} | |
} | |
func executeProgram(program []int) []int { | |
for i := 0; i < len(program); { | |
// if i+4 >= len(program) { | |
// fmt.Printf("Executing %v (%v)\n", i, program[i:]) | |
// } else { | |
// fmt.Printf("Executing %v (%v)\n", i, program[i:i+4]) | |
// } | |
i = executeInstruction(program, i) | |
if i == -1 { | |
// fmt.Println("BREAKING!!") | |
break | |
} | |
// fmt.Println("Next instruction:", i, "("+InstructionType(program[i]).String()+")") | |
// fmt.Println(printProgram(program)) | |
} | |
return program | |
} | |
const NOUN_AND_VERB_ANSWER = 19690720 | |
func findNounAndVerb() (int, int) { | |
for i := 0; i <= 99; i++ { | |
for j := 0; j <= 99; j++ { | |
newProgram := make([]int, len(instructions)) | |
copy(newProgram, instructions) | |
newProgram[1] = i | |
newProgram[2] = j | |
modifiedInstructions := executeProgram(newProgram) | |
if modifiedInstructions[0] == NOUN_AND_VERB_ANSWER { | |
return i, j | |
} | |
} | |
} | |
return -1, -1 | |
} | |
func main() { | |
program := make([]int, len(instructions)) | |
copy(program, instructions) | |
modifiedInstructions := executeProgram(program) | |
fmt.Println("New program:", printProgram(modifiedInstructions)) | |
noun, verb := findNounAndVerb() | |
fmt.Println("Found noun", noun, "and verb", verb, "(final answer is:", noun*100+verb, ")") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"reflect" | |
"testing" | |
) | |
func TestExecuteInstructionHalt(t *testing.T) { | |
program := []int{ | |
1, 2, 3, 3, | |
1, 4, 5, 7, | |
99, | |
} | |
runTestExample(t, program, 8, -1, -1, 0) | |
} | |
func TestExecuteInstructionAdd(t *testing.T) { | |
program := []int{ | |
1, 2, 3, 3, // Overwrites last 3 with 6 (3 + 3) | |
1, 4, 5, 7, | |
99, | |
} | |
runTestExample(t, program, 0, 4, 3, 6) | |
} | |
func TestExecuteInstructionMultiply(t *testing.T) { | |
program := []int{ | |
2, 2, 3, 3, // Overwrites last 3 with 9 (3 * 3) | |
1, 4, 5, 7, | |
99, | |
} | |
runTestExample(t, program, 0, 4, 3, 9) | |
} | |
func TestExecuteProgram1(t *testing.T) { | |
program := []int{ | |
2, 4, 4, 5, | |
99, | |
0, | |
} | |
originalProgram := make([]int, len(program)) | |
copy(originalProgram, program) | |
got := executeProgram(program) | |
expected := []int{ | |
2, 4, 4, 5, | |
99, | |
9801, | |
} | |
if !reflect.DeepEqual(expected, got) { | |
fmt.Println("Original Program:\n" + printProgram(originalProgram)) | |
t.Errorf("Expected program:\n%s\nGot:\n%s", printProgram(expected), printProgram(got)) | |
} | |
} | |
func runTestExample(t *testing.T, program []int, instruction int, expectedNextInstruction int, modifiedIndex int, modifiedValue int) { | |
currentInstruction := make([]int, 4) | |
if instruction+4 >= len(program) { | |
copy(currentInstruction, program[instruction:]) | |
} else { | |
copy(currentInstruction, program[instruction:instruction+4]) | |
} | |
nextInstruction := executeInstruction(program, instruction) | |
if nextInstruction != expectedNextInstruction { | |
fmt.Println(printProgram(program)) | |
t.Errorf("Executing %v returned %d; want %v", currentInstruction, nextInstruction, expectedNextInstruction) | |
} | |
if modifiedIndex != -1 { | |
if program[modifiedIndex] != modifiedValue { | |
fmt.Println(printProgram(program)) | |
t.Errorf("Executing %v did not modify index %d to set value to %d (was %d)", currentInstruction, modifiedIndex, modifiedValue, program[modifiedIndex]) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment