Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
ce6e63b5b6
|
|||
d41aa6cfa5
|
|||
b5202b28c5
|
|||
0a249b85fc
|
|||
f03184d4c4
|
|||
c15d206b8b
|
|||
43d9a77d62
|
|||
b903417c06
|
|||
9dd39aa193
|
|||
3b3c805997
|
|||
3ca7312e2c
|
|||
bb00808f99
|
|||
11b73ba5bc
|
|||
d7db069031
|
|||
870abdf579
|
28
days/02.go
28
days/02.go
@ -18,19 +18,20 @@ func (d Day02) Num() int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day02) getProgramWithParams(param1, param2 int64) utilities.IntcodeProgram {
|
func (d *Day02) setParams(param1, param2 int64) {
|
||||||
program := make(utilities.IntcodeProgram, len(d.program))
|
d.program.Reset()
|
||||||
copy(program, d.program)
|
d.program.SetMemory(1, param1)
|
||||||
program[1] = param1
|
d.program.SetMemory(2, param2)
|
||||||
program[2] = param2
|
|
||||||
return program
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day02) Part1() string {
|
func (d *Day02) Part1() string {
|
||||||
program := d.getProgramWithParams(12, 2)
|
d.setParams(12, 2)
|
||||||
program.Run()
|
d.program.Run()
|
||||||
|
|
||||||
return fmt.Sprintf("Position 0 = %s%d%s", utilities.TextBold, program[0], utilities.TextReset)
|
if d.program.GetMemory(0) != 4138658 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Position 0 = %s%d%s", utilities.TextBold, d.program.GetMemory(0), utilities.TextReset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day02) Part2() string {
|
func (d *Day02) Part2() string {
|
||||||
@ -41,10 +42,10 @@ func (d *Day02) Part2() string {
|
|||||||
found := false
|
found := false
|
||||||
for noun = 0; noun <= 99; noun++ {
|
for noun = 0; noun <= 99; noun++ {
|
||||||
for verb = 0; verb <= 99; verb++ {
|
for verb = 0; verb <= 99; verb++ {
|
||||||
program := d.getProgramWithParams(noun, verb)
|
d.setParams(noun, verb)
|
||||||
program.Run()
|
d.program.Run()
|
||||||
|
|
||||||
if program[0] == sentinel {
|
if d.program.GetMemory(0) == sentinel {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -58,6 +59,9 @@ func (d *Day02) Part2() string {
|
|||||||
if !found {
|
if !found {
|
||||||
panic("!found")
|
panic("!found")
|
||||||
}
|
}
|
||||||
|
if noun != 72 || verb != 64 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%d created by noun=%d, verb=%d. 100 * noun + verb = %s%d%s",
|
return fmt.Sprintf("%d created by noun=%d, verb=%d. 100 * noun + verb = %s%d%s",
|
||||||
sentinel,
|
sentinel,
|
||||||
|
99
days/03.go
99
days/03.go
@ -6,29 +6,24 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"parnic.com/aoc2019/utilities"
|
u "parnic.com/aoc2019/utilities"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pair[T, U any] struct {
|
|
||||||
a T
|
|
||||||
b U
|
|
||||||
}
|
|
||||||
|
|
||||||
type Day03 struct {
|
type Day03 struct {
|
||||||
line1 []Pair[byte, int]
|
line1 []u.Pair[byte, int]
|
||||||
line2 []Pair[byte, int]
|
line2 []u.Pair[byte, int]
|
||||||
visited map[Pair[int, int]]int
|
visited map[u.Pair[int, int]]int
|
||||||
overlaps []Pair[Pair[int, int], int]
|
overlaps []u.Pair[u.Pair[int, int], int]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day03) Parse() {
|
func (d *Day03) Parse() {
|
||||||
lines := utilities.GetStringLines("03p")
|
lines := u.GetStringLines("03p")
|
||||||
|
|
||||||
line1data := strings.Split(lines[0], ",")
|
line1data := strings.Split(lines[0], ",")
|
||||||
line2data := strings.Split(lines[1], ",")
|
line2data := strings.Split(lines[1], ",")
|
||||||
|
|
||||||
d.line1 = make([]Pair[byte, int], len(line1data))
|
d.line1 = make([]u.Pair[byte, int], len(line1data))
|
||||||
d.line2 = make([]Pair[byte, int], len(line2data))
|
d.line2 = make([]u.Pair[byte, int], len(line2data))
|
||||||
|
|
||||||
for idx, instr := range line1data {
|
for idx, instr := range line1data {
|
||||||
dir := instr[0]
|
dir := instr[0]
|
||||||
@ -38,7 +33,7 @@ func (d *Day03) Parse() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.line1[idx] = Pair[byte, int]{a: dir, b: iAmt}
|
d.line1[idx] = u.Pair[byte, int]{First: dir, Second: iAmt}
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, instr := range line2data {
|
for idx, instr := range line2data {
|
||||||
@ -49,7 +44,7 @@ func (d *Day03) Parse() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.line2[idx] = Pair[byte, int]{a: dir, b: iAmt}
|
d.line2[idx] = u.Pair[byte, int]{First: dir, Second: iAmt}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,96 +53,96 @@ func (d Day03) Num() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day03) Part1() string {
|
func (d *Day03) Part1() string {
|
||||||
d.visited = make(map[Pair[int, int]]int)
|
d.visited = make(map[u.Pair[int, int]]int)
|
||||||
var x int
|
var x int
|
||||||
var y int
|
var y int
|
||||||
var steps int
|
var steps int
|
||||||
for _, inst := range d.line1 {
|
for _, inst := range d.line1 {
|
||||||
switch inst.a {
|
switch inst.First {
|
||||||
case 'R':
|
case 'R':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
d.visited[Pair[int, int]{a: x + i, b: y}] = steps
|
d.visited[u.Pair[int, int]{First: x + i, Second: y}] = steps
|
||||||
}
|
}
|
||||||
x += inst.b
|
x += inst.Second
|
||||||
case 'U':
|
case 'U':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
d.visited[Pair[int, int]{a: x, b: y + i}] = steps
|
d.visited[u.Pair[int, int]{First: x, Second: y + i}] = steps
|
||||||
}
|
}
|
||||||
y += inst.b
|
y += inst.Second
|
||||||
case 'L':
|
case 'L':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
d.visited[Pair[int, int]{a: x - i, b: y}] = steps
|
d.visited[u.Pair[int, int]{First: x - i, Second: y}] = steps
|
||||||
}
|
}
|
||||||
x -= inst.b
|
x -= inst.Second
|
||||||
case 'D':
|
case 'D':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
d.visited[Pair[int, int]{a: x, b: y - i}] = steps
|
d.visited[u.Pair[int, int]{First: x, Second: y - i}] = steps
|
||||||
}
|
}
|
||||||
y -= inst.b
|
y -= inst.Second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x = 0
|
x = 0
|
||||||
y = 0
|
y = 0
|
||||||
steps = 0
|
steps = 0
|
||||||
d.overlaps = make([]Pair[Pair[int, int], int], 0)
|
d.overlaps = make([]u.Pair[u.Pair[int, int], int], 0)
|
||||||
for _, inst := range d.line2 {
|
for _, inst := range d.line2 {
|
||||||
switch inst.a {
|
switch inst.First {
|
||||||
case 'R':
|
case 'R':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
if _, exists := d.visited[Pair[int, int]{x + i, y}]; exists {
|
if _, exists := d.visited[u.Pair[int, int]{First: x + i, Second: y}]; exists {
|
||||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x + i, y}, b: steps})
|
d.overlaps = append(d.overlaps, u.Pair[u.Pair[int, int], int]{First: u.Pair[int, int]{First: x + i, Second: y}, Second: steps})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x += inst.b
|
x += inst.Second
|
||||||
case 'U':
|
case 'U':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
if _, exists := d.visited[Pair[int, int]{x, y + i}]; exists {
|
if _, exists := d.visited[u.Pair[int, int]{First: x, Second: y + i}]; exists {
|
||||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x, y + i}, b: steps})
|
d.overlaps = append(d.overlaps, u.Pair[u.Pair[int, int], int]{First: u.Pair[int, int]{First: x, Second: y + i}, Second: steps})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y += inst.b
|
y += inst.Second
|
||||||
case 'L':
|
case 'L':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
if _, exists := d.visited[Pair[int, int]{x - i, y}]; exists {
|
if _, exists := d.visited[u.Pair[int, int]{First: x - i, Second: y}]; exists {
|
||||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x - i, y}, b: steps})
|
d.overlaps = append(d.overlaps, u.Pair[u.Pair[int, int], int]{First: u.Pair[int, int]{First: x - i, Second: y}, Second: steps})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x -= inst.b
|
x -= inst.Second
|
||||||
case 'D':
|
case 'D':
|
||||||
for i := 1; i <= inst.b; i++ {
|
for i := 1; i <= inst.Second; i++ {
|
||||||
steps++
|
steps++
|
||||||
if _, exists := d.visited[Pair[int, int]{x, y - i}]; exists {
|
if _, exists := d.visited[u.Pair[int, int]{First: x, Second: y - i}]; exists {
|
||||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x, y - i}, b: steps})
|
d.overlaps = append(d.overlaps, u.Pair[u.Pair[int, int], int]{First: u.Pair[int, int]{First: x, Second: y - i}, Second: steps})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y -= inst.b
|
y -= inst.Second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
minDist := math.MaxInt
|
minDist := math.MaxInt
|
||||||
for _, overlap := range d.overlaps {
|
for _, overlap := range d.overlaps {
|
||||||
dist := int(math.Abs(float64(overlap.a.a))) + int(math.Abs(float64(overlap.a.b)))
|
dist := int(math.Abs(float64(overlap.First.First))) + int(math.Abs(float64(overlap.First.Second)))
|
||||||
if dist < minDist {
|
if dist < minDist {
|
||||||
minDist = dist
|
minDist = dist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("Closest overlap manhattan distance = %s%d%s", utilities.TextBold, minDist, utilities.TextReset)
|
return fmt.Sprintf("Closest overlap manhattan distance = %s%d%s", u.TextBold, minDist, u.TextReset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day03) Part2() string {
|
func (d *Day03) Part2() string {
|
||||||
minOverlap := math.MaxInt
|
minOverlap := math.MaxInt
|
||||||
for _, overlap := range d.overlaps {
|
for _, overlap := range d.overlaps {
|
||||||
line1Steps := d.visited[overlap.a]
|
line1Steps := d.visited[overlap.First]
|
||||||
line2Steps := overlap.b
|
line2Steps := overlap.Second
|
||||||
|
|
||||||
totalSteps := line1Steps + line2Steps
|
totalSteps := line1Steps + line2Steps
|
||||||
if totalSteps < minOverlap {
|
if totalSteps < minOverlap {
|
||||||
@ -155,5 +150,5 @@ func (d *Day03) Part2() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("Minimum steps to overlap = %s%d%s", utilities.TextBold, minOverlap, utilities.TextReset)
|
return fmt.Sprintf("Minimum steps to overlap = %s%d%s", u.TextBold, minOverlap, u.TextReset)
|
||||||
}
|
}
|
||||||
|
188
days/05.go
Normal file
188
days/05.go
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day05 struct {
|
||||||
|
program utilities.IntcodeProgram
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day05) Parse() {
|
||||||
|
d.program = utilities.LoadIntcodeProgram("05p")
|
||||||
|
d.test()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day05) Num() int {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day05) test() {
|
||||||
|
// Using position mode, consider whether the input is equal to 8; output 1 (if it is) or 0 (if it is not).
|
||||||
|
program := utilities.ParseIntcodeProgram("3,9,8,9,10,9,4,9,99,-1,8")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Using position mode, consider whether the input is less than 8; output 1 (if it is) or 0 (if it is not).
|
||||||
|
program = utilities.ParseIntcodeProgram("3,9,7,9,10,9,4,9,99,-1,8")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Using immediate mode, consider whether the input is equal to 8; output 1 (if it is) or 0 (if it is not).
|
||||||
|
program = utilities.ParseIntcodeProgram("3,3,1108,-1,8,3,4,3,99")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Using immediate mode, consider whether the input is less than 8; output 1 (if it is) or 0 (if it is not).
|
||||||
|
program = utilities.ParseIntcodeProgram("3,3,1107,-1,8,3,4,3,99")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// jump tests that take an input, then output 0 if the input was zero or 1 if the input was non-zero
|
||||||
|
// position mode
|
||||||
|
program = utilities.ParseIntcodeProgram("3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// jump tests that take an input, then output 0 if the input was zero or 1 if the input was non-zero
|
||||||
|
// immediate mode
|
||||||
|
program = utilities.ParseIntcodeProgram("3,3,1105,-1,9,1101,0,0,12,4,12,99,1")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 0 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// uses an input instruction to ask for a single number. The program will then output 999 if the input value is below 8, output 1000 if the input value is equal to 8, or output 1001 if the input value is greater than 8.
|
||||||
|
program = utilities.ParseIntcodeProgram("3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99")
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 999 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 8
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1000 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
program.Reset()
|
||||||
|
program.RunIn(func(int) int64 {
|
||||||
|
return 9
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if val != 1001 {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day05) Part1() string {
|
||||||
|
diagCode := int64(-1)
|
||||||
|
d.program.RunIn(func(int) int64 {
|
||||||
|
return 1
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if state.IsHalting() {
|
||||||
|
diagCode = val
|
||||||
|
} else if val != 0 {
|
||||||
|
panic("test failed")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("Diagnostic code: %d", diagCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day05) Part2() string {
|
||||||
|
d.program.Reset()
|
||||||
|
diagCode := int64(-1)
|
||||||
|
d.program.RunIn(func(int) int64 {
|
||||||
|
return 5
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
if !state.IsHalting() {
|
||||||
|
panic("unexpected output received")
|
||||||
|
}
|
||||||
|
diagCode = val
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("Diagnostic code: %d", diagCode)
|
||||||
|
}
|
114
days/06.go
Normal file
114
days/06.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type body struct {
|
||||||
|
orbits *body
|
||||||
|
obj string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day06 struct {
|
||||||
|
allBodies []*body
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day06) Parse() {
|
||||||
|
d.allBodies = make([]*body, 0)
|
||||||
|
|
||||||
|
getOrAddBody := func(obj string) *body {
|
||||||
|
target := d.findBody(obj)
|
||||||
|
if target == nil {
|
||||||
|
target = &body{
|
||||||
|
obj: obj,
|
||||||
|
}
|
||||||
|
d.allBodies = append(d.allBodies, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := utilities.GetStringLines("06p")
|
||||||
|
for _, line := range lines {
|
||||||
|
bodies := strings.Split(line, ")")
|
||||||
|
newBody := getOrAddBody(bodies[1])
|
||||||
|
|
||||||
|
target := getOrAddBody(bodies[0])
|
||||||
|
newBody.orbits = target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day06) findBody(obj string) *body {
|
||||||
|
for _, checkBody := range d.allBodies {
|
||||||
|
if checkBody.obj == obj {
|
||||||
|
return checkBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day06) Num() int {
|
||||||
|
return 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day06) Part1() string {
|
||||||
|
orbits := 0
|
||||||
|
for _, obj := range d.allBodies {
|
||||||
|
next := obj.orbits
|
||||||
|
for next != nil {
|
||||||
|
next = next.orbits
|
||||||
|
orbits++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Total orbits: %s%d%s", utilities.TextBold, orbits, utilities.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day06) Part2() string {
|
||||||
|
you := d.findBody("YOU")
|
||||||
|
san := d.findBody("SAN")
|
||||||
|
|
||||||
|
youChildren := make([]*body, 0)
|
||||||
|
next := you.orbits
|
||||||
|
for next != nil {
|
||||||
|
youChildren = append(youChildren, next)
|
||||||
|
next = next.orbits
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkingNode *body
|
||||||
|
next = san.orbits
|
||||||
|
for next != nil {
|
||||||
|
if utilities.ArrayContains(youChildren, next) {
|
||||||
|
linkingNode = next
|
||||||
|
break
|
||||||
|
}
|
||||||
|
next = next.orbits
|
||||||
|
}
|
||||||
|
|
||||||
|
if linkingNode == nil {
|
||||||
|
panic("")
|
||||||
|
}
|
||||||
|
|
||||||
|
getDistToLinking := func(start *body) int {
|
||||||
|
dist := 0
|
||||||
|
next = start.orbits
|
||||||
|
for next != nil {
|
||||||
|
if next == linkingNode {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dist++
|
||||||
|
next = next.orbits
|
||||||
|
}
|
||||||
|
|
||||||
|
return dist
|
||||||
|
}
|
||||||
|
|
||||||
|
distYouToLinking := getDistToLinking(you)
|
||||||
|
distSanToLinking := getDistToLinking(san)
|
||||||
|
|
||||||
|
return fmt.Sprintf("Transfers to get to Santa: %s%d%s", utilities.TextBold, distYouToLinking+distSanToLinking, utilities.TextReset)
|
||||||
|
}
|
116
days/07.go
Normal file
116
days/07.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day07 struct {
|
||||||
|
program utilities.IntcodeProgram
|
||||||
|
amps []utilities.IntcodeProgram
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day07) Parse() {
|
||||||
|
d.program = utilities.LoadIntcodeProgram("07p")
|
||||||
|
d.amps = make([]utilities.IntcodeProgram, 5)
|
||||||
|
for i := range d.amps {
|
||||||
|
d.amps[i] = d.program.Copy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day07) Num() int {
|
||||||
|
return 7
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day07) Part1() string {
|
||||||
|
var highestVal int64
|
||||||
|
var highestSequence []int64
|
||||||
|
|
||||||
|
allSequences := utilities.GetPermutations([]int64{0, 1, 2, 3, 4}...)
|
||||||
|
for _, sequence := range allSequences {
|
||||||
|
if len(sequence) != len(d.amps) {
|
||||||
|
panic("input sequence does not match up to number of amplifiers")
|
||||||
|
}
|
||||||
|
|
||||||
|
input := int64(0)
|
||||||
|
var output int64
|
||||||
|
for i, amp := range d.amps {
|
||||||
|
amp.RunIn(func(step int) int64 {
|
||||||
|
if step == 1 {
|
||||||
|
return sequence[i]
|
||||||
|
} else if step == 2 {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("hit more input instructions than expected")
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
output = val
|
||||||
|
})
|
||||||
|
|
||||||
|
input = output
|
||||||
|
}
|
||||||
|
|
||||||
|
if output > highestVal {
|
||||||
|
highestVal = output
|
||||||
|
if highestSequence == nil {
|
||||||
|
highestSequence = make([]int64, len(sequence))
|
||||||
|
}
|
||||||
|
copy(highestSequence, sequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Max thruster signal: %s%d%s (produced by %v)", utilities.TextBold, highestVal, utilities.TextReset, highestSequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day07) Part2() string {
|
||||||
|
var highestVal int64
|
||||||
|
var highestSequence []int64
|
||||||
|
|
||||||
|
allSequences := utilities.GetPermutations([]int64{5, 6, 7, 8, 9}...)
|
||||||
|
for _, sequence := range allSequences {
|
||||||
|
if len(sequence) != len(d.amps) {
|
||||||
|
panic("input sequence does not match up to number of amplifiers")
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs := make([]chan int64, len(d.amps))
|
||||||
|
for i := range d.amps {
|
||||||
|
d.amps[i].Reset()
|
||||||
|
inputs[i] = make(chan int64, 1)
|
||||||
|
inputs[i] <- sequence[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
var finalOutput int64
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := range d.amps {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(idx int) {
|
||||||
|
d.amps[idx].RunIn(func(step int) int64 {
|
||||||
|
input := <-inputs[idx]
|
||||||
|
return input
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
finalOutput = val
|
||||||
|
inputIdx := idx + 1
|
||||||
|
if inputIdx == len(inputs) {
|
||||||
|
inputIdx = 0
|
||||||
|
}
|
||||||
|
inputs[inputIdx] <- val
|
||||||
|
})
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
inputs[0] <- 0
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if finalOutput > highestVal {
|
||||||
|
highestVal = finalOutput
|
||||||
|
if highestSequence == nil {
|
||||||
|
highestSequence = make([]int64, len(sequence))
|
||||||
|
}
|
||||||
|
copy(highestSequence, sequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Max thruster signal: %s%d%s (produced by %v)", utilities.TextBold, highestVal, utilities.TextReset, highestSequence)
|
||||||
|
}
|
100
days/08.go
Normal file
100
days/08.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day08 struct {
|
||||||
|
img [][]int
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
imgWidth = 25
|
||||||
|
imgHeight = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *Day08) Parse() {
|
||||||
|
contents := utilities.GetStringContents("08p")
|
||||||
|
imgSize := imgWidth * imgHeight
|
||||||
|
layers := len(contents) / imgSize
|
||||||
|
d.img = make([][]int, layers)
|
||||||
|
for layer := 0; layer < layers; layer++ {
|
||||||
|
d.img[layer] = make([]int, imgSize)
|
||||||
|
for i := 0; i < imgSize; i++ {
|
||||||
|
d.img[layer][i] = int(contents[(layer*imgSize)+i] - '0')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day08) Num() int {
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day08) Part1() string {
|
||||||
|
fewestZeroes := math.MaxInt
|
||||||
|
var layerFewestZeroes int
|
||||||
|
for layer := range d.img {
|
||||||
|
zeroes := 0
|
||||||
|
for i := range d.img[layer] {
|
||||||
|
if d.img[layer][i] == 0 {
|
||||||
|
zeroes++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if zeroes < fewestZeroes {
|
||||||
|
fewestZeroes = zeroes
|
||||||
|
layerFewestZeroes = layer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
numOne := 0
|
||||||
|
numTwo := 0
|
||||||
|
for i := range d.img[layerFewestZeroes] {
|
||||||
|
if d.img[layerFewestZeroes][i] == 1 {
|
||||||
|
numOne++
|
||||||
|
} else if d.img[layerFewestZeroes][i] == 2 {
|
||||||
|
numTwo++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Fewest zeroes on layer %d, #1s * #2s = %d * %d = %s%d%s",
|
||||||
|
layerFewestZeroes,
|
||||||
|
numOne,
|
||||||
|
numTwo,
|
||||||
|
utilities.TextBold,
|
||||||
|
numOne*numTwo,
|
||||||
|
utilities.TextReset,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day08) Part2() string {
|
||||||
|
imgSize := imgWidth * imgHeight
|
||||||
|
finalImg := make([]int, imgSize)
|
||||||
|
for i := 0; i < imgSize; i++ {
|
||||||
|
for layer := 0; layer < len(d.img); layer++ {
|
||||||
|
if d.img[layer][i] != 2 {
|
||||||
|
finalImg[i] = d.img[layer][i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outStr := strings.Builder{}
|
||||||
|
outStr.WriteRune('\n')
|
||||||
|
for y := 0; y < imgHeight; y++ {
|
||||||
|
for x := 0; x < imgWidth; x++ {
|
||||||
|
if finalImg[(y*imgWidth)+x] == 0 {
|
||||||
|
outStr.WriteRune(' ')
|
||||||
|
} else {
|
||||||
|
outStr.WriteRune('█')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outStr.WriteRune('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
return outStr.String()
|
||||||
|
}
|
42
days/09.go
Normal file
42
days/09.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day09 struct {
|
||||||
|
program utilities.IntcodeProgram
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day09) Parse() {
|
||||||
|
d.program = utilities.LoadIntcodeProgram("09p")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day09) Num() int {
|
||||||
|
return 9
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day09) Part1() string {
|
||||||
|
var code int64
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
return 1
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
code = val
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("BOOST keycode: %s%d%s", utilities.TextBold, code, utilities.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day09) Part2() string {
|
||||||
|
var coordinates int64
|
||||||
|
d.program.Reset()
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
return 2
|
||||||
|
}, func(val int64, state utilities.IntcodeProgramState) {
|
||||||
|
coordinates = val
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("Coordinates: %s%d%s", utilities.TextBold, coordinates, utilities.TextReset)
|
||||||
|
}
|
171
days/10.go
Normal file
171
days/10.go
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day10 struct {
|
||||||
|
asteroids [][]bool
|
||||||
|
idealLocation u.Vec2[int]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day10) Parse() {
|
||||||
|
lines := u.GetStringLines("10p")
|
||||||
|
d.asteroids = make([][]bool, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
d.asteroids[i] = make([]bool, len(line))
|
||||||
|
for j, ch := range line {
|
||||||
|
d.asteroids[i][j] = ch == '#'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day10) Num() int {
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (d Day10) draw() {
|
||||||
|
// for i := range d.asteroids {
|
||||||
|
// for j := range d.asteroids[i] {
|
||||||
|
// if !d.asteroids[i][j].First {
|
||||||
|
// fmt.Print(".")
|
||||||
|
// } else {
|
||||||
|
// num := d.asteroids[i][j].Second
|
||||||
|
// ch := rune('0') + rune(num)
|
||||||
|
// if num >= 10 {
|
||||||
|
// ch = '+'
|
||||||
|
// }
|
||||||
|
// fmt.Printf("%c", ch)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fmt.Println()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (d Day10) getVisibleAsteroids(i1, j1 int) []u.Vec2[int] {
|
||||||
|
visited := make([]u.Vec2[int], 0)
|
||||||
|
foundAsteroids := make([]u.Vec2[int], 0)
|
||||||
|
|
||||||
|
findNext := func(startX, startY, incX, incY int) *u.Vec2[int] {
|
||||||
|
var found *u.Vec2[int]
|
||||||
|
if incX == 0 && incY == 0 {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
x := startX + incX
|
||||||
|
y := startY + incY
|
||||||
|
for x < len(d.asteroids) && x >= 0 && y < len(d.asteroids[x]) && y >= 0 {
|
||||||
|
currPair := u.Vec2[int]{X: x, Y: y}
|
||||||
|
if !u.ArrayContains(visited, currPair) {
|
||||||
|
visited = append(visited, currPair)
|
||||||
|
|
||||||
|
if d.asteroids[x][y] {
|
||||||
|
if found == nil {
|
||||||
|
found = &currPair
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += incX
|
||||||
|
y += incY
|
||||||
|
}
|
||||||
|
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
for incX := 0; ; {
|
||||||
|
plusXValid := i1+incX < len(d.asteroids)
|
||||||
|
minusXValid := i1-incX >= 0
|
||||||
|
if !plusXValid && !minusXValid {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for incY := 0; ; {
|
||||||
|
plusYValid := j1+incY < len(d.asteroids[0])
|
||||||
|
minusYValid := j1-incY >= 0
|
||||||
|
if !plusYValid && !minusYValid {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if found := findNext(i1, j1, incX, incY); found != nil {
|
||||||
|
foundAsteroids = append(foundAsteroids, *found)
|
||||||
|
}
|
||||||
|
if found := findNext(i1, j1, incX, -incY); found != nil {
|
||||||
|
foundAsteroids = append(foundAsteroids, *found)
|
||||||
|
}
|
||||||
|
if found := findNext(i1, j1, -incX, incY); found != nil {
|
||||||
|
foundAsteroids = append(foundAsteroids, *found)
|
||||||
|
}
|
||||||
|
if found := findNext(i1, j1, -incX, -incY); found != nil {
|
||||||
|
foundAsteroids = append(foundAsteroids, *found)
|
||||||
|
}
|
||||||
|
|
||||||
|
incY++
|
||||||
|
}
|
||||||
|
|
||||||
|
incX++
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundAsteroids
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day10) numVisibleAsteroids(i1, j1 int) int {
|
||||||
|
return len(d.getVisibleAsteroids(i1, j1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day10) removeAsteroids(locs ...u.Vec2[int]) {
|
||||||
|
for _, loc := range locs {
|
||||||
|
if !d.asteroids[loc.X][loc.Y] {
|
||||||
|
panic("tried to remove non-asteroid")
|
||||||
|
}
|
||||||
|
|
||||||
|
d.asteroids[loc.X][loc.Y] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day10) Part1() string {
|
||||||
|
mostAsteroids := 0
|
||||||
|
for i := range d.asteroids {
|
||||||
|
for j := range d.asteroids[i] {
|
||||||
|
if d.asteroids[i][j] {
|
||||||
|
numVisible := d.numVisibleAsteroids(i, j)
|
||||||
|
if numVisible > mostAsteroids {
|
||||||
|
mostAsteroids = numVisible
|
||||||
|
d.idealLocation = u.Vec2[int]{X: i, Y: j}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Most visible asteroids: %s%d%s at (%d,%d)", u.TextBold, mostAsteroids, u.TextReset, d.idealLocation.Y, d.idealLocation.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day10) Part2() string {
|
||||||
|
findNumVaporized := 200
|
||||||
|
var targetLocation u.Vec2[int]
|
||||||
|
|
||||||
|
vaporized := 0
|
||||||
|
for vaporized < findNumVaporized {
|
||||||
|
visibleAsteroids := d.getVisibleAsteroids(d.idealLocation.X, d.idealLocation.Y)
|
||||||
|
if len(visibleAsteroids) == 0 {
|
||||||
|
panic("no more asteroids to vaporize")
|
||||||
|
}
|
||||||
|
|
||||||
|
if vaporized+len(visibleAsteroids) < findNumVaporized {
|
||||||
|
vaporized += len(visibleAsteroids)
|
||||||
|
d.removeAsteroids(visibleAsteroids...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(visibleAsteroids, func(i, j int) bool {
|
||||||
|
return d.idealLocation.AngleBetween(visibleAsteroids[i]) > d.idealLocation.AngleBetween(visibleAsteroids[j])
|
||||||
|
})
|
||||||
|
targetLocation = visibleAsteroids[findNumVaporized-1-vaporized]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("#%d asteroid to be vaporized is at (%d,%d), transformed: %s%d%s", findNumVaporized, targetLocation.Y, targetLocation.X, u.TextBold, (targetLocation.Y*100)+targetLocation.X, u.TextReset)
|
||||||
|
}
|
116
days/11.go
Normal file
116
days/11.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day11 struct {
|
||||||
|
program u.IntcodeProgram
|
||||||
|
painted map[u.Pair[int, int]]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day11) Parse() {
|
||||||
|
d.program = u.LoadIntcodeProgram("11p")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day11) Num() int {
|
||||||
|
return 11
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day11) paintHull() (int, u.Pair[int, int], u.Pair[int, int]) {
|
||||||
|
pos := u.Pair[int, int]{First: 0, Second: 0}
|
||||||
|
facing := 0
|
||||||
|
|
||||||
|
min := pos
|
||||||
|
max := pos
|
||||||
|
|
||||||
|
outputState := 0
|
||||||
|
numPainted := 1
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
return int64(d.painted[pos])
|
||||||
|
}, func(val int64, state u.IntcodeProgramState) {
|
||||||
|
if outputState == 0 {
|
||||||
|
outputState++
|
||||||
|
color := int(val)
|
||||||
|
if _, exists := d.painted[pos]; !exists {
|
||||||
|
numPainted++
|
||||||
|
}
|
||||||
|
d.painted[pos] = color
|
||||||
|
} else {
|
||||||
|
outputState = 0
|
||||||
|
direction := val
|
||||||
|
|
||||||
|
if direction == 0 {
|
||||||
|
facing--
|
||||||
|
if facing == -1 {
|
||||||
|
facing = 3
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
facing++
|
||||||
|
if facing == 4 {
|
||||||
|
facing = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch facing {
|
||||||
|
case 0:
|
||||||
|
pos.First--
|
||||||
|
if pos.First < min.First {
|
||||||
|
min.First = pos.First
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
pos.Second++
|
||||||
|
if pos.Second > max.Second {
|
||||||
|
max.Second = pos.Second
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
pos.First++
|
||||||
|
if pos.First > max.First {
|
||||||
|
max.First = pos.First
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
pos.Second--
|
||||||
|
if pos.Second < min.Second {
|
||||||
|
min.Second = pos.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return numPainted, min, max
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day11) Part1() string {
|
||||||
|
d.painted = map[u.Pair[int, int]]int{
|
||||||
|
{First: 0, Second: 0}: 0,
|
||||||
|
}
|
||||||
|
numPainted, _, _ := d.paintHull()
|
||||||
|
|
||||||
|
return fmt.Sprintf("Unique panels painted: %s%d%s", u.TextBold, numPainted, u.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day11) Part2() string {
|
||||||
|
d.painted = map[u.Pair[int, int]]int{
|
||||||
|
{First: 0, Second: 0}: 1,
|
||||||
|
}
|
||||||
|
_, min, max := d.paintHull()
|
||||||
|
|
||||||
|
outStr := strings.Builder{}
|
||||||
|
outStr.WriteRune('\n')
|
||||||
|
for x := min.First; x <= max.First; x++ {
|
||||||
|
for y := min.Second; y <= max.Second; y++ {
|
||||||
|
val, exists := d.painted[u.Pair[int, int]{First: x, Second: y}]
|
||||||
|
if exists && val == 1 {
|
||||||
|
outStr.WriteRune('█')
|
||||||
|
} else {
|
||||||
|
outStr.WriteRune(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outStr.WriteRune('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
return outStr.String()
|
||||||
|
}
|
156
days/12.go
Normal file
156
days/12.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type moonData struct {
|
||||||
|
pos u.Vec3[int]
|
||||||
|
vel u.Vec3[int]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *moonData) applyGravity(other *moonData) {
|
||||||
|
applyGravityAxis := func(pos1, pos2, vel1, vel2 *int) {
|
||||||
|
if *pos1 < *pos2 {
|
||||||
|
*vel1++
|
||||||
|
*vel2--
|
||||||
|
} else if *pos1 > *pos2 {
|
||||||
|
*vel1--
|
||||||
|
*vel2++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyGravityAxis(&m.pos.X, &other.pos.X, &m.vel.X, &other.vel.X)
|
||||||
|
applyGravityAxis(&m.pos.Y, &other.pos.Y, &m.vel.Y, &other.vel.Y)
|
||||||
|
applyGravityAxis(&m.pos.Z, &other.pos.Z, &m.vel.Z, &other.vel.Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *moonData) applyVelocity() {
|
||||||
|
m.pos.Add(m.vel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m moonData) getPotentialEnergy() int {
|
||||||
|
return int(math.Abs(float64(m.pos.X))) +
|
||||||
|
int(math.Abs(float64(m.pos.Y))) +
|
||||||
|
int(math.Abs(float64(m.pos.Z)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m moonData) getKineticEnergy() int {
|
||||||
|
return int(math.Abs(float64(m.vel.X))) +
|
||||||
|
int(math.Abs(float64(m.vel.Y))) +
|
||||||
|
int(math.Abs(float64(m.vel.Z)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m moonData) getTotalEnergy() int {
|
||||||
|
return m.getPotentialEnergy() * m.getKineticEnergy()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day12 struct {
|
||||||
|
moons []*moonData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day12) Parse() {
|
||||||
|
lines := u.GetStringLines("12p")
|
||||||
|
d.moons = make([]*moonData, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
trimmed := line[1 : len(line)-1]
|
||||||
|
vals := strings.Split(trimmed, ", ")
|
||||||
|
x, _ := strconv.Atoi(vals[0][2:])
|
||||||
|
y, _ := strconv.Atoi(vals[1][2:])
|
||||||
|
z, _ := strconv.Atoi(vals[2][2:])
|
||||||
|
d.moons[i] = &moonData{
|
||||||
|
pos: u.Vec3[int]{X: x, Y: y, Z: z},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day12) Num() int {
|
||||||
|
return 12
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day12) copyMoons() []*moonData {
|
||||||
|
moons := make([]*moonData, len(d.moons))
|
||||||
|
for i, moon := range d.moons {
|
||||||
|
moonCopy := *moon
|
||||||
|
moons[i] = &moonCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
return moons
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllEnergy(moons ...*moonData) int {
|
||||||
|
energy := 0
|
||||||
|
for _, moon := range moons {
|
||||||
|
energy += moon.getTotalEnergy()
|
||||||
|
}
|
||||||
|
return energy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day12) Part1() string {
|
||||||
|
moons := d.copyMoons()
|
||||||
|
|
||||||
|
numSteps := 1000
|
||||||
|
|
||||||
|
for i := 0; i < numSteps; i++ {
|
||||||
|
for i, moon1 := range moons {
|
||||||
|
for _, moon2 := range moons[i+1:] {
|
||||||
|
moon1.applyGravity(moon2)
|
||||||
|
}
|
||||||
|
|
||||||
|
moon1.applyVelocity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Total energy after %d steps: %s%d%s", numSteps, u.TextBold, getAllEnergy(moons...), u.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day12) Part2() string {
|
||||||
|
moons := d.copyMoons()
|
||||||
|
|
||||||
|
orig := make([]u.Vec3[int], len(moons))
|
||||||
|
for i, moon := range moons {
|
||||||
|
orig[i] = moon.pos
|
||||||
|
}
|
||||||
|
period := u.Vec3[int]{}
|
||||||
|
|
||||||
|
for loops := 0; period.X == 0 || period.Y == 0 || period.Z == 0; loops++ {
|
||||||
|
for i, moon1 := range moons {
|
||||||
|
for _, moon2 := range moons[i+1:] {
|
||||||
|
moon1.applyGravity(moon2)
|
||||||
|
}
|
||||||
|
moon1.applyVelocity()
|
||||||
|
}
|
||||||
|
|
||||||
|
foundX := true
|
||||||
|
foundY := true
|
||||||
|
foundZ := true
|
||||||
|
for i, moon := range moons {
|
||||||
|
if moon.pos.X != orig[i].X || moon.vel.X != 0 {
|
||||||
|
foundX = false
|
||||||
|
}
|
||||||
|
if moon.pos.Y != orig[i].Y || moon.vel.Y != 0 {
|
||||||
|
foundY = false
|
||||||
|
}
|
||||||
|
if moon.pos.Z != orig[i].Z || moon.vel.Z != 0 {
|
||||||
|
foundZ = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if foundX && period.X == 0 {
|
||||||
|
period.X = loops + 1
|
||||||
|
}
|
||||||
|
if foundY && period.Y == 0 {
|
||||||
|
period.Y = loops + 1
|
||||||
|
}
|
||||||
|
if foundZ && period.Z == 0 {
|
||||||
|
period.Z = loops + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stepsRequired := u.LCM(period.X, period.Y, period.Z)
|
||||||
|
return fmt.Sprintf("Iterations to reach a previous state: %s%d%s", u.TextBold, stepsRequired, u.TextReset)
|
||||||
|
}
|
147
days/13.go
Normal file
147
days/13.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
tileEmpty = 0
|
||||||
|
tileWall = 1
|
||||||
|
tileBlock = 2
|
||||||
|
tileHPaddle = 3
|
||||||
|
tileBall = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type tile struct {
|
||||||
|
pos u.Vec2[int]
|
||||||
|
id int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day13 struct {
|
||||||
|
program u.IntcodeProgram
|
||||||
|
tiles []tile
|
||||||
|
gameBoard [24][45]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day13) Parse() {
|
||||||
|
d.program = u.LoadIntcodeProgram("13p")
|
||||||
|
d.tiles = make([]tile, 0, 1080)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day13) Num() int {
|
||||||
|
return 13
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day13) getNumBlocks() int {
|
||||||
|
blockTiles := 0
|
||||||
|
for _, tile := range d.tiles {
|
||||||
|
if tile.id == tileBlock {
|
||||||
|
blockTiles++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockTiles
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (d Day13) drawGameBoard() {
|
||||||
|
// s := strings.Builder{}
|
||||||
|
// for x := range d.gameBoard {
|
||||||
|
// for y := range d.gameBoard[x] {
|
||||||
|
// block := d.gameBoard[x][y]
|
||||||
|
// if block == tileBlock {
|
||||||
|
// s.WriteString(u.ColorBlue)
|
||||||
|
// s.WriteRune('█')
|
||||||
|
// s.WriteString(u.TextReset)
|
||||||
|
// } else if block == tileBall {
|
||||||
|
// s.WriteString(u.ColorGreen)
|
||||||
|
// s.WriteRune('█')
|
||||||
|
// s.WriteString(u.TextReset)
|
||||||
|
// } else if block == tileWall {
|
||||||
|
// s.WriteString(u.ColorWhite)
|
||||||
|
// s.WriteRune('█')
|
||||||
|
// s.WriteString(u.TextReset)
|
||||||
|
// } else if block == tileHPaddle {
|
||||||
|
// s.WriteString(u.ColorRed)
|
||||||
|
// s.WriteRune('█')
|
||||||
|
// s.WriteString(u.TextReset)
|
||||||
|
// } else if block == tileEmpty {
|
||||||
|
// s.WriteRune(' ')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// s.WriteRune('\n')
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Print(s.String())
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (d *Day13) Part1() string {
|
||||||
|
outputStep := 0
|
||||||
|
var newTilePos u.Vec2[int]
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state u.IntcodeProgramState) {
|
||||||
|
if outputStep == 0 {
|
||||||
|
newTilePos.X = int(val)
|
||||||
|
outputStep++
|
||||||
|
} else if outputStep == 1 {
|
||||||
|
newTilePos.Y = int(val)
|
||||||
|
outputStep++
|
||||||
|
} else {
|
||||||
|
d.tiles = append(d.tiles, tile{
|
||||||
|
pos: newTilePos,
|
||||||
|
id: int(val),
|
||||||
|
})
|
||||||
|
outputStep = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("# block tiles: %s%d%s (%d total tiles)", u.TextBold, d.getNumBlocks(), u.TextReset, len(d.tiles))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day13) Part2() string {
|
||||||
|
d.program.Reset()
|
||||||
|
d.program.SetMemory(0, 2)
|
||||||
|
|
||||||
|
outputStep := 0
|
||||||
|
newTilePos := u.Vec2[int]{}
|
||||||
|
var ball u.Vec2[int]
|
||||||
|
var paddle u.Vec2[int]
|
||||||
|
var score int64
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
if ball.X < paddle.X {
|
||||||
|
return -1
|
||||||
|
} else if ball.X > paddle.X {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}, func(val int64, state u.IntcodeProgramState) {
|
||||||
|
if outputStep == 0 {
|
||||||
|
newTilePos.X = int(val)
|
||||||
|
outputStep++
|
||||||
|
} else if outputStep == 1 {
|
||||||
|
newTilePos.Y = int(val)
|
||||||
|
outputStep++
|
||||||
|
} else {
|
||||||
|
if newTilePos.Equals(u.Vec2[int]{X: -1, Y: 0}) {
|
||||||
|
score = val
|
||||||
|
} else {
|
||||||
|
d.gameBoard[newTilePos.Y][newTilePos.X] = int(val)
|
||||||
|
|
||||||
|
if val == tileBall {
|
||||||
|
ball = newTilePos
|
||||||
|
} else if val == tileHPaddle {
|
||||||
|
paddle = newTilePos
|
||||||
|
// d.drawGameBoard()
|
||||||
|
// time.Sleep(time.Millisecond * 33)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStep = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return fmt.Sprintf("Game over! Score: %s%d%s", u.TextBold, score, u.TextReset)
|
||||||
|
}
|
129
days/14.go
Normal file
129
days/14.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type reaction struct {
|
||||||
|
inputs map[string]int64
|
||||||
|
output u.Pair[string, int]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day14 struct {
|
||||||
|
reactions []reaction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day14) Parse() {
|
||||||
|
lines := u.GetStringLines("14p")
|
||||||
|
d.reactions = make([]reaction, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
sides := strings.Split(line, " => ")
|
||||||
|
inputs := strings.Split(sides[0], ", ")
|
||||||
|
output := sides[1]
|
||||||
|
|
||||||
|
outPair := strings.Split(output, " ")
|
||||||
|
outAmt, _ := strconv.Atoi(outPair[0])
|
||||||
|
d.reactions[i].output = u.Pair[string, int]{First: outPair[1], Second: outAmt}
|
||||||
|
d.reactions[i].inputs = make(map[string]int64)
|
||||||
|
for _, input := range inputs {
|
||||||
|
pair := strings.Split(input, " ")
|
||||||
|
d.reactions[i].inputs[pair[1]], _ = strconv.ParseInt(pair[0], 10, 64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day14) getReactionProducing(chem string) *reaction {
|
||||||
|
for _, reaction := range d.reactions {
|
||||||
|
if reaction.output.First == chem {
|
||||||
|
return &reaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day14) Num() int {
|
||||||
|
return 14
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day14) getOreRequiredForFuel(qty int64) int64 {
|
||||||
|
oreRequired := int64(0)
|
||||||
|
needs := map[string]int64{
|
||||||
|
"FUEL": qty,
|
||||||
|
}
|
||||||
|
excess := make(map[string]int64)
|
||||||
|
|
||||||
|
getFromExcess := func(qty int64, chemical string) int64 {
|
||||||
|
available := u.Min(excess[chemical], qty)
|
||||||
|
excess[chemical] -= available
|
||||||
|
return available
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(needs) > 0 {
|
||||||
|
keys := u.MapKeys(needs)
|
||||||
|
producing := keys[0]
|
||||||
|
qtyRequired := needs[producing]
|
||||||
|
delete(needs, producing)
|
||||||
|
|
||||||
|
fromExcess := getFromExcess(qtyRequired, producing)
|
||||||
|
if fromExcess == qtyRequired {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
qtyRequired -= fromExcess
|
||||||
|
|
||||||
|
reaction := d.getReactionProducing(producing)
|
||||||
|
|
||||||
|
qtyProduced := int64(reaction.output.Second)
|
||||||
|
reactionsNeeded := int64(math.Ceil(float64(qtyRequired) / float64(qtyProduced)))
|
||||||
|
|
||||||
|
excess[producing] = (qtyProduced * reactionsNeeded) - qtyRequired
|
||||||
|
|
||||||
|
for reagent, inputQty := range reaction.inputs {
|
||||||
|
qtyNeeded := inputQty * reactionsNeeded
|
||||||
|
if reagent == "ORE" {
|
||||||
|
oreRequired += qtyNeeded
|
||||||
|
} else {
|
||||||
|
needs[reagent] += qtyNeeded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oreRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day14) Part1() string {
|
||||||
|
neededOre := d.getOreRequiredForFuel(1)
|
||||||
|
return fmt.Sprintf("%s%d%s", u.TextBold, neededOre, u.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day14) Part2() string {
|
||||||
|
oreAvailable := int64(1000000000000)
|
||||||
|
estimate := oreAvailable / d.getOreRequiredForFuel(1)
|
||||||
|
|
||||||
|
high := estimate * 2
|
||||||
|
low := estimate
|
||||||
|
|
||||||
|
lastSuccess := low
|
||||||
|
lastFailure := high
|
||||||
|
fuelProduced := low
|
||||||
|
|
||||||
|
for math.Abs(float64(lastFailure-lastSuccess)) > 1 {
|
||||||
|
oreConsumed := d.getOreRequiredForFuel(fuelProduced)
|
||||||
|
adjustment := (lastFailure - lastSuccess) / 2
|
||||||
|
if oreConsumed < oreAvailable {
|
||||||
|
lastSuccess = fuelProduced
|
||||||
|
} else {
|
||||||
|
lastFailure = fuelProduced
|
||||||
|
adjustment = -adjustment
|
||||||
|
}
|
||||||
|
|
||||||
|
fuelProduced += adjustment
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%d%s", u.TextBold, lastSuccess, u.TextReset)
|
||||||
|
}
|
332
days/15.go
Normal file
332
days/15.go
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
//go:generate stringer -type=cellStatus,responseType,dirType -output=15_types_string.go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type point u.Pair[int, int]
|
||||||
|
type cellStatus int
|
||||||
|
type responseType int
|
||||||
|
type dirType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
cellStatusUnknown cellStatus = iota
|
||||||
|
cellStatusWall
|
||||||
|
cellStatusOpen
|
||||||
|
cellStatusGoal
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
responseWall responseType = iota
|
||||||
|
responseSuccess
|
||||||
|
responseFoundGoal
|
||||||
|
)
|
||||||
|
|
||||||
|
const maxVisited = 3
|
||||||
|
|
||||||
|
const (
|
||||||
|
dirNorth dirType = iota + 1
|
||||||
|
dirSouth
|
||||||
|
dirWest
|
||||||
|
dirEast
|
||||||
|
|
||||||
|
dirFirst = dirNorth
|
||||||
|
dirLast = dirEast
|
||||||
|
)
|
||||||
|
|
||||||
|
var dirOrders = [][]dirType{
|
||||||
|
{dirNorth, dirSouth, dirWest, dirEast},
|
||||||
|
{dirSouth, dirWest, dirEast, dirNorth},
|
||||||
|
{dirWest, dirEast, dirNorth, dirSouth},
|
||||||
|
{dirEast, dirNorth, dirSouth, dirWest},
|
||||||
|
}
|
||||||
|
|
||||||
|
// turned out to be unnecessary on multiple datasets i tried. increases the iterations 6x
|
||||||
|
// var dirOrders = u.GetPermutations(dirNorth, dirSouth, dirWest, dirEast)
|
||||||
|
|
||||||
|
type visitedStatus struct {
|
||||||
|
timesVisited int
|
||||||
|
distanceFromStart int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day15 struct {
|
||||||
|
program u.IntcodeProgram
|
||||||
|
grid map[point]cellStatus
|
||||||
|
visited map[point]*visitedStatus
|
||||||
|
shortestPath []point
|
||||||
|
pos point
|
||||||
|
goalPos point
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) Parse() {
|
||||||
|
d.program = u.LoadIntcodeProgram("15p")
|
||||||
|
d.grid = map[point]cellStatus{
|
||||||
|
{First: 0, Second: 0}: cellStatusOpen,
|
||||||
|
}
|
||||||
|
d.visited = map[point]*visitedStatus{
|
||||||
|
{First: 0, Second: 0}: {timesVisited: 1},
|
||||||
|
}
|
||||||
|
d.shortestPath = []point{{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day15) Num() int {
|
||||||
|
return 15
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day15) getPointInDirection(pos point, dir dirType) point {
|
||||||
|
target := pos
|
||||||
|
switch dir {
|
||||||
|
case dirNorth:
|
||||||
|
target.First--
|
||||||
|
case dirSouth:
|
||||||
|
target.First++
|
||||||
|
case dirWest:
|
||||||
|
target.Second--
|
||||||
|
case dirEast:
|
||||||
|
target.Second++
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day15) getCellTypeInDirection(pos point, dir dirType) (cellStatus, point) {
|
||||||
|
target := d.getPointInDirection(pos, dir)
|
||||||
|
return d.grid[target], target
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day15) getAdjacentCellsOfType(pos point, cellType cellStatus) []point {
|
||||||
|
points := make([]point, 0, 4)
|
||||||
|
for i := dirFirst; i <= dirLast; i++ {
|
||||||
|
adjacentCell := d.getPointInDirection(pos, i)
|
||||||
|
if d.grid[adjacentCell] == cellType {
|
||||||
|
points = append(points, adjacentCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day15) getDirToNextCellType(pos point, t cellStatus, maxNumVisited int, dirs []dirType) (dirType, point, error) {
|
||||||
|
for _, dir := range dirs {
|
||||||
|
cellInDirection, targetCell := d.getCellTypeInDirection(pos, dir)
|
||||||
|
if cellInDirection == t {
|
||||||
|
_, visitedTargetExists := d.visited[targetCell]
|
||||||
|
foundUnknown := t == cellStatusUnknown && !visitedTargetExists
|
||||||
|
foundOther := t != cellStatusUnknown && visitedTargetExists && d.visited[targetCell].timesVisited <= maxNumVisited
|
||||||
|
if foundUnknown || foundOther {
|
||||||
|
return dir, targetCell, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirFirst, point{}, fmt.Errorf("no %v tiles around %v", t, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) Draw() {
|
||||||
|
min := point{First: math.MaxInt, Second: math.MaxInt}
|
||||||
|
max := point{First: math.MinInt, Second: math.MinInt}
|
||||||
|
for p := range d.grid {
|
||||||
|
if p.First < min.First {
|
||||||
|
min.First = p.First
|
||||||
|
}
|
||||||
|
if p.First > max.First {
|
||||||
|
max.First = p.First
|
||||||
|
}
|
||||||
|
if p.Second < min.Second {
|
||||||
|
min.Second = p.Second
|
||||||
|
}
|
||||||
|
if p.Second > max.Second {
|
||||||
|
max.Second = p.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for x := min.First; x <= max.First; x++ {
|
||||||
|
for y := min.Second; y <= max.Second; y++ {
|
||||||
|
p := point{First: x, Second: y}
|
||||||
|
switch d.grid[p] {
|
||||||
|
case cellStatusGoal:
|
||||||
|
fmt.Printf("%s@%s", u.ColorBrightGreen, u.TextReset)
|
||||||
|
case cellStatusOpen:
|
||||||
|
if p == d.pos {
|
||||||
|
fmt.Print(u.BackgroundBrightRed)
|
||||||
|
} else if x == 0 && y == 0 {
|
||||||
|
fmt.Print(u.BackgroundYellow)
|
||||||
|
} else if u.ArrayContains(d.shortestPath, p) {
|
||||||
|
fmt.Print(u.BackgroundGreen)
|
||||||
|
} else if d.visited[p] != nil && d.visited[p].timesVisited > maxVisited {
|
||||||
|
fmt.Print(u.ColorYellow)
|
||||||
|
fmt.Print(u.BackgroundBlack)
|
||||||
|
} else if d.visited[p] != nil && d.visited[p].timesVisited > 1 {
|
||||||
|
fmt.Print(u.BackgroundMagenta)
|
||||||
|
} else {
|
||||||
|
fmt.Print(u.BackgroundBlue)
|
||||||
|
}
|
||||||
|
fmt.Printf(".%s", u.TextReset)
|
||||||
|
case cellStatusWall:
|
||||||
|
fmt.Print("█")
|
||||||
|
case cellStatusUnknown:
|
||||||
|
fmt.Print(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) markShortestPath() {
|
||||||
|
pos := d.goalPos
|
||||||
|
checkOffsets := []point{
|
||||||
|
{First: -1, Second: 0},
|
||||||
|
{First: 1, Second: 0},
|
||||||
|
{First: 0, Second: -1},
|
||||||
|
{First: 0, Second: 1},
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPt := func(pt point) (bool, int) {
|
||||||
|
if v, exists := d.visited[pt]; exists && d.grid[pt] == cellStatusOpen {
|
||||||
|
return true, v.distanceFromStart
|
||||||
|
}
|
||||||
|
return false, math.MaxInt
|
||||||
|
}
|
||||||
|
|
||||||
|
d.shortestPath = []point{d.goalPos}
|
||||||
|
|
||||||
|
for pos.First != 0 || pos.Second != 0 {
|
||||||
|
lowestDist := math.MaxInt
|
||||||
|
lowestPoint := point{}
|
||||||
|
for _, pt := range checkOffsets {
|
||||||
|
newPt := point{First: pos.First + pt.First, Second: pos.Second + pt.Second}
|
||||||
|
if found, dist := checkPt(newPt); found && dist < lowestDist {
|
||||||
|
lowestDist = dist
|
||||||
|
lowestPoint = newPt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.shortestPath = append(d.shortestPath, lowestPoint)
|
||||||
|
pos = lowestPoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) exploreFullMap() map[point]*visitedStatus {
|
||||||
|
grids := make([]map[point]cellStatus, 0, len(dirOrders))
|
||||||
|
goalVisited := d.visited
|
||||||
|
|
||||||
|
for _, dirOrder := range dirOrders {
|
||||||
|
d.program.Reset()
|
||||||
|
|
||||||
|
targetPos := point{}
|
||||||
|
nextDir := dirFirst
|
||||||
|
distFromStart := 0
|
||||||
|
|
||||||
|
d.pos = point{}
|
||||||
|
d.visited = map[point]*visitedStatus{
|
||||||
|
{First: 0, Second: 0}: {timesVisited: 1},
|
||||||
|
}
|
||||||
|
d.grid = map[point]cellStatus{
|
||||||
|
{First: 0, Second: 0}: cellStatusOpen,
|
||||||
|
}
|
||||||
|
d.program.RunIn(func(inputStep int) int64 {
|
||||||
|
var err error
|
||||||
|
nextDir, targetPos, err = d.getDirToNextCellType(d.pos, cellStatusUnknown, 0, dirOrder)
|
||||||
|
if err != nil {
|
||||||
|
// ensure we never try to go back into the trapped spot
|
||||||
|
d.visited[d.pos].timesVisited = maxVisited + 1
|
||||||
|
for x := 1; x <= maxVisited && err != nil; x++ {
|
||||||
|
nextDir, targetPos, err = d.getDirToNextCellType(d.pos, cellStatusOpen, x, dirOrder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// d.Draw()
|
||||||
|
// panic(err)
|
||||||
|
d.program.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
return int64(nextDir)
|
||||||
|
}, func(val int64, state u.IntcodeProgramState) {
|
||||||
|
rVal := responseType(val)
|
||||||
|
|
||||||
|
p := d.getPointInDirection(d.pos, nextDir)
|
||||||
|
shouldMove := true
|
||||||
|
switch rVal {
|
||||||
|
case responseWall:
|
||||||
|
d.grid[p] = cellStatusWall
|
||||||
|
shouldMove = false
|
||||||
|
case responseSuccess:
|
||||||
|
d.grid[p] = cellStatusOpen
|
||||||
|
case responseFoundGoal:
|
||||||
|
d.grid[p] = cellStatusGoal
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldMove {
|
||||||
|
d.pos = targetPos
|
||||||
|
if d.visited[d.pos] == nil {
|
||||||
|
d.visited[d.pos] = &visitedStatus{}
|
||||||
|
distFromStart++
|
||||||
|
} else {
|
||||||
|
distFromStart--
|
||||||
|
}
|
||||||
|
d.visited[d.pos].timesVisited++
|
||||||
|
d.visited[d.pos].distanceFromStart = distFromStart
|
||||||
|
}
|
||||||
|
|
||||||
|
if rVal == responseFoundGoal {
|
||||||
|
// d.Draw()
|
||||||
|
d.goalPos = targetPos
|
||||||
|
goalVisited = d.visited
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
grids = append(grids, d.grid)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.grid = map[point]cellStatus{
|
||||||
|
{First: 0, Second: 0}: cellStatusOpen,
|
||||||
|
}
|
||||||
|
for _, grid := range grids {
|
||||||
|
keys := u.MapKeys(grid)
|
||||||
|
for _, key := range keys {
|
||||||
|
d.grid[key] = grid[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return goalVisited
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) tagDistanceRecursive(pos, last point, dist int, distances map[point]int) {
|
||||||
|
distances[pos] = dist
|
||||||
|
for _, cell := range d.getAdjacentCellsOfType(pos, cellStatusOpen) {
|
||||||
|
if cell == last {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d.tagDistanceRecursive(cell, pos, dist+1, distances)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) Part1() string {
|
||||||
|
d.visited = d.exploreFullMap()
|
||||||
|
d.markShortestPath()
|
||||||
|
|
||||||
|
for _, visited := range d.visited {
|
||||||
|
visited.timesVisited = 1
|
||||||
|
}
|
||||||
|
d.pos = point{}
|
||||||
|
d.Draw()
|
||||||
|
|
||||||
|
return fmt.Sprintf("Moves required to reach target: %s%d%s", u.TextBold, d.visited[d.goalPos].distanceFromStart, u.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day15) Part2() string {
|
||||||
|
startLoc := d.goalPos
|
||||||
|
distanceMap := map[point]int{startLoc: 0}
|
||||||
|
|
||||||
|
d.tagDistanceRecursive(startLoc, point{}, 0, distanceMap)
|
||||||
|
|
||||||
|
cellDistances := u.MapValues(distanceMap)
|
||||||
|
sort.Slice(cellDistances, func(i, j int) bool { return cellDistances[i] > cellDistances[j] })
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%d%s", u.TextBold, cellDistances[0], u.TextReset)
|
||||||
|
}
|
66
days/15_types_string.go
Normal file
66
days/15_types_string.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Code generated by "stringer -type=cellStatus,responseType,dirType -output=15_types_string.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package days
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[cellStatusUnknown-0]
|
||||||
|
_ = x[cellStatusWall-1]
|
||||||
|
_ = x[cellStatusOpen-2]
|
||||||
|
_ = x[cellStatusGoal-3]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _cellStatus_name = "cellStatusUnknowncellStatusWallcellStatusOpencellStatusGoal"
|
||||||
|
|
||||||
|
var _cellStatus_index = [...]uint8{0, 17, 31, 45, 59}
|
||||||
|
|
||||||
|
func (i cellStatus) String() string {
|
||||||
|
if i < 0 || i >= cellStatus(len(_cellStatus_index)-1) {
|
||||||
|
return "cellStatus(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _cellStatus_name[_cellStatus_index[i]:_cellStatus_index[i+1]]
|
||||||
|
}
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[responseWall-0]
|
||||||
|
_ = x[responseSuccess-1]
|
||||||
|
_ = x[responseFoundGoal-2]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _responseType_name = "responseWallresponseSuccessresponseFoundGoal"
|
||||||
|
|
||||||
|
var _responseType_index = [...]uint8{0, 12, 27, 44}
|
||||||
|
|
||||||
|
func (i responseType) String() string {
|
||||||
|
if i < 0 || i >= responseType(len(_responseType_index)-1) {
|
||||||
|
return "responseType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _responseType_name[_responseType_index[i]:_responseType_index[i+1]]
|
||||||
|
}
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[dirNorth-1]
|
||||||
|
_ = x[dirSouth-2]
|
||||||
|
_ = x[dirWest-3]
|
||||||
|
_ = x[dirEast-4]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _dirType_name = "dirNorthdirSouthdirWestdirEast"
|
||||||
|
|
||||||
|
var _dirType_index = [...]uint8{0, 8, 16, 23, 30}
|
||||||
|
|
||||||
|
func (i dirType) String() string {
|
||||||
|
i -= 1
|
||||||
|
if i < 0 || i >= dirType(len(_dirType_index)-1) {
|
||||||
|
return "dirType(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||||
|
}
|
||||||
|
return _dirType_name[_dirType_index[i]:_dirType_index[i+1]]
|
||||||
|
}
|
1
inputs/05p.txt
Normal file
1
inputs/05p.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,225,1,225,6,6,1100,1,238,225,104,0,1102,78,40,225,1102,52,43,224,1001,224,-2236,224,4,224,102,8,223,223,101,4,224,224,1,224,223,223,1,191,61,224,1001,224,-131,224,4,224,102,8,223,223,101,4,224,224,1,223,224,223,1101,86,74,225,1102,14,76,225,1101,73,83,224,101,-156,224,224,4,224,102,8,223,223,101,6,224,224,1,224,223,223,1102,43,82,225,2,196,13,224,101,-6162,224,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1001,161,51,224,101,-70,224,224,4,224,102,8,223,223,1001,224,1,224,1,224,223,223,102,52,187,224,1001,224,-832,224,4,224,102,8,223,223,101,1,224,224,1,224,223,223,1102,19,79,225,101,65,92,224,1001,224,-147,224,4,224,1002,223,8,223,101,4,224,224,1,223,224,223,1102,16,90,225,1102,45,44,225,1102,92,79,225,1002,65,34,224,101,-476,224,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,107,226,226,224,1002,223,2,223,1005,224,329,1001,223,1,223,1007,226,226,224,102,2,223,223,1005,224,344,101,1,223,223,1008,226,226,224,102,2,223,223,1005,224,359,1001,223,1,223,8,226,677,224,102,2,223,223,1006,224,374,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,389,101,1,223,223,1108,226,677,224,102,2,223,223,1005,224,404,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,419,1001,223,1,223,7,677,226,224,102,2,223,223,1005,224,434,101,1,223,223,1007,677,677,224,102,2,223,223,1005,224,449,1001,223,1,223,108,226,677,224,102,2,223,223,1005,224,464,1001,223,1,223,108,226,226,224,102,2,223,223,1006,224,479,101,1,223,223,107,226,677,224,102,2,223,223,1006,224,494,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,509,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,524,101,1,223,223,1107,677,226,224,102,2,223,223,1005,224,539,101,1,223,223,1008,677,226,224,102,2,223,223,1005,224,554,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,569,101,1,223,223,1107,677,677,224,102,2,223,223,1006,224,584,1001,223,1,223,1108,226,226,224,1002,223,2,223,1006,224,599,101,1,223,223,7,226,677,224,102,2,223,223,1006,224,614,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,629,101,1,223,223,1007,677,226,224,102,2,223,223,1006,224,644,101,1,223,223,8,677,677,224,1002,223,2,223,1006,224,659,101,1,223,223,8,677,226,224,102,2,223,223,1005,224,674,101,1,223,223,4,223,99,226
|
1013
inputs/06p.txt
Normal file
1013
inputs/06p.txt
Normal file
File diff suppressed because it is too large
Load Diff
11
inputs/06s1.txt
Normal file
11
inputs/06s1.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
COM)B
|
||||||
|
B)C
|
||||||
|
C)D
|
||||||
|
D)E
|
||||||
|
E)F
|
||||||
|
B)G
|
||||||
|
G)H
|
||||||
|
D)I
|
||||||
|
E)J
|
||||||
|
J)K
|
||||||
|
K)L
|
13
inputs/06s2.txt
Normal file
13
inputs/06s2.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
COM)B
|
||||||
|
B)C
|
||||||
|
C)D
|
||||||
|
D)E
|
||||||
|
E)F
|
||||||
|
B)G
|
||||||
|
G)H
|
||||||
|
D)I
|
||||||
|
E)J
|
||||||
|
J)K
|
||||||
|
K)L
|
||||||
|
K)YOU
|
||||||
|
I)SAN
|
1
inputs/07p.txt
Normal file
1
inputs/07p.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,8,1001,8,10,8,105,1,0,0,21,38,47,64,85,106,187,268,349,430,99999,3,9,1002,9,4,9,1001,9,4,9,1002,9,4,9,4,9,99,3,9,1002,9,4,9,4,9,99,3,9,1001,9,3,9,102,5,9,9,1001,9,5,9,4,9,99,3,9,101,3,9,9,102,5,9,9,1001,9,4,9,102,4,9,9,4,9,99,3,9,1002,9,3,9,101,2,9,9,102,4,9,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,99
|
1
inputs/07s1.txt
Normal file
1
inputs/07s1.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0
|
1
inputs/07s2.txt
Normal file
1
inputs/07s2.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0
|
1
inputs/07s3.txt
Normal file
1
inputs/07s3.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0
|
1
inputs/07s4.txt
Normal file
1
inputs/07s4.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5
|
1
inputs/07s5.txt
Normal file
1
inputs/07s5.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10
|
1
inputs/08p.txt
Normal file
1
inputs/08p.txt
Normal file
File diff suppressed because one or more lines are too long
1
inputs/08s1.txt
Normal file
1
inputs/08s1.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
123456789012
|
1
inputs/09p.txt
Normal file
1
inputs/09p.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,31,1018,1102,352,1,1023,1101,0,1,1021,1101,0,33,1003,1102,1,36,1007,1102,21,1,1005,1101,359,0,1022,1101,0,787,1024,1102,1,24,1011,1101,30,0,1014,1101,22,0,1016,1101,0,0,1020,1102,1,29,1000,1101,778,0,1025,1102,23,1,1017,1102,1,28,1002,1101,38,0,1019,1102,1,27,1013,1102,1,32,1012,1101,0,37,1006,1101,444,0,1027,1102,1,20,1009,1101,0,447,1026,1101,0,39,1008,1101,35,0,1010,1102,559,1,1028,1102,26,1,1004,1102,1,25,1015,1102,1,34,1001,1101,0,554,1029,109,-3,2101,0,9,63,1008,63,34,63,1005,63,205,1001,64,1,64,1105,1,207,4,187,1002,64,2,64,109,23,21107,40,39,-7,1005,1013,227,1001,64,1,64,1106,0,229,4,213,1002,64,2,64,109,-17,1202,-2,1,63,1008,63,36,63,1005,63,249,1106,0,255,4,235,1001,64,1,64,1002,64,2,64,109,-6,1202,10,1,63,1008,63,36,63,1005,63,277,4,261,1106,0,281,1001,64,1,64,1002,64,2,64,109,-2,1208,9,26,63,1005,63,303,4,287,1001,64,1,64,1106,0,303,1002,64,2,64,109,32,1206,-7,321,4,309,1001,64,1,64,1106,0,321,1002,64,2,64,109,-29,1207,7,20,63,1005,63,337,1105,1,343,4,327,1001,64,1,64,1002,64,2,64,109,27,2105,1,-2,1001,64,1,64,1106,0,361,4,349,1002,64,2,64,109,-25,2108,39,7,63,1005,63,377,1106,0,383,4,367,1001,64,1,64,1002,64,2,64,109,1,1201,6,0,63,1008,63,36,63,1005,63,409,4,389,1001,64,1,64,1105,1,409,1002,64,2,64,109,1,2102,1,1,63,1008,63,33,63,1005,63,435,4,415,1001,64,1,64,1105,1,435,1002,64,2,64,109,28,2106,0,-3,1106,0,453,4,441,1001,64,1,64,1002,64,2,64,109,-13,21101,41,0,1,1008,1018,44,63,1005,63,477,1001,64,1,64,1106,0,479,4,459,1002,64,2,64,109,4,21108,42,42,-2,1005,1019,501,4,485,1001,64,1,64,1106,0,501,1002,64,2,64,109,-21,2101,0,2,63,1008,63,28,63,1005,63,523,4,507,1105,1,527,1001,64,1,64,1002,64,2,64,109,26,1205,-5,545,4,533,1001,64,1,64,1105,1,545,1002,64,2,64,109,3,2106,0,-1,4,551,1106,0,563,1001,64,1,64,1002,64,2,64,109,-33,1201,4,0,63,1008,63,28,63,1005,63,583,1105,1,589,4,569,1001,64,1,64,1002,64,2,64,109,11,2107,27,-3,63,1005,63,609,1001,64,1,64,1106,0,611,4,595,1002,64,2,64,109,8,21102,43,1,3,1008,1018,43,63,1005,63,637,4,617,1001,64,1,64,1105,1,637,1002,64,2,64,109,-5,21108,44,41,0,1005,1010,653,1105,1,659,4,643,1001,64,1,64,1002,64,2,64,109,-13,2108,21,8,63,1005,63,681,4,665,1001,64,1,64,1106,0,681,1002,64,2,64,109,6,1207,0,34,63,1005,63,703,4,687,1001,64,1,64,1105,1,703,1002,64,2,64,109,7,1208,-7,35,63,1005,63,723,1001,64,1,64,1106,0,725,4,709,1002,64,2,64,109,-13,2102,1,7,63,1008,63,23,63,1005,63,745,1105,1,751,4,731,1001,64,1,64,1002,64,2,64,109,13,1205,10,767,1001,64,1,64,1105,1,769,4,757,1002,64,2,64,109,14,2105,1,0,4,775,1001,64,1,64,1106,0,787,1002,64,2,64,109,-20,21107,45,46,7,1005,1011,809,4,793,1001,64,1,64,1105,1,809,1002,64,2,64,109,-3,2107,25,3,63,1005,63,827,4,815,1106,0,831,1001,64,1,64,1002,64,2,64,109,13,1206,7,847,1001,64,1,64,1106,0,849,4,837,1002,64,2,64,109,-11,21101,46,0,7,1008,1010,46,63,1005,63,871,4,855,1106,0,875,1001,64,1,64,1002,64,2,64,109,15,21102,47,1,-4,1008,1014,48,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21102,27,1,1,21101,0,915,0,1106,0,922,21201,1,63208,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1105,1,922,22201,1,-1,-2,1106,0,968,21201,-2,0,-2,109,-3,2106,0,0
|
1
inputs/09s1.txt
Normal file
1
inputs/09s1.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99
|
1
inputs/09s2.txt
Normal file
1
inputs/09s2.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
1102,34915192,34915192,7,4,7,99,0
|
1
inputs/09s3.txt
Normal file
1
inputs/09s3.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
104,1125899906842624,99
|
33
inputs/10p.txt
Normal file
33
inputs/10p.txt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
.#......##.#..#.......#####...#..
|
||||||
|
...#.....##......###....#.##.....
|
||||||
|
..#...#....#....#............###.
|
||||||
|
.....#......#.##......#.#..###.#.
|
||||||
|
#.#..........##.#.#...#.##.#.#.#.
|
||||||
|
..#.##.#...#.......#..##.......##
|
||||||
|
..#....#.....#..##.#..####.#.....
|
||||||
|
#.............#..#.........#.#...
|
||||||
|
........#.##..#..#..#.#.....#.#..
|
||||||
|
.........#...#..##......###.....#
|
||||||
|
##.#.###..#..#.#.....#.........#.
|
||||||
|
.#.###.##..##......#####..#..##..
|
||||||
|
.........#.......#.#......#......
|
||||||
|
..#...#...#...#.#....###.#.......
|
||||||
|
#..#.#....#...#.......#..#.#.##..
|
||||||
|
#.....##...#.###..#..#......#..##
|
||||||
|
...........#...#......#..#....#..
|
||||||
|
#.#.#......#....#..#.....##....##
|
||||||
|
..###...#.#.##..#...#.....#...#.#
|
||||||
|
.......#..##.#..#.............##.
|
||||||
|
..###........##.#................
|
||||||
|
###.#..#...#......###.#........#.
|
||||||
|
.......#....#.#.#..#..#....#..#..
|
||||||
|
.#...#..#...#......#....#.#..#...
|
||||||
|
#.#.........#.....#....#.#.#.....
|
||||||
|
.#....#......##.##....#........#.
|
||||||
|
....#..#..#...#..##.#.#......#.#.
|
||||||
|
..###.##.#.....#....#.#......#...
|
||||||
|
#.##...#............#..#.....#..#
|
||||||
|
.#....##....##...#......#........
|
||||||
|
...#...##...#.......#....##.#....
|
||||||
|
.#....#.#...#.#...##....#..##.#.#
|
||||||
|
.#.#....##.......#.....##.##.#.##
|
5
inputs/10s1.txt
Normal file
5
inputs/10s1.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.#..#
|
||||||
|
.....
|
||||||
|
#####
|
||||||
|
....#
|
||||||
|
...##
|
10
inputs/10s2.txt
Normal file
10
inputs/10s2.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
......#.#.
|
||||||
|
#..#.#....
|
||||||
|
..#######.
|
||||||
|
.#.#.###..
|
||||||
|
.#..#.....
|
||||||
|
..#....#.#
|
||||||
|
#..#....#.
|
||||||
|
.##.#..###
|
||||||
|
##...#..#.
|
||||||
|
.#....####
|
10
inputs/10s3.txt
Normal file
10
inputs/10s3.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#.#...#.#.
|
||||||
|
.###....#.
|
||||||
|
.#....#...
|
||||||
|
##.#.#.#.#
|
||||||
|
....#.#.#.
|
||||||
|
.##..###.#
|
||||||
|
..#...##..
|
||||||
|
..##....##
|
||||||
|
......#...
|
||||||
|
.####.###.
|
10
inputs/10s4.txt
Normal file
10
inputs/10s4.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.#..#..###
|
||||||
|
####.###.#
|
||||||
|
....###.#.
|
||||||
|
..###.##.#
|
||||||
|
##.##.#.#.
|
||||||
|
....###..#
|
||||||
|
..#.#..#.#
|
||||||
|
#..#.#.###
|
||||||
|
.##...##.#
|
||||||
|
.....#.#..
|
20
inputs/10s5.txt
Normal file
20
inputs/10s5.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.#..##.###...#######
|
||||||
|
##.############..##.
|
||||||
|
.#.######.########.#
|
||||||
|
.###.#######.####.#.
|
||||||
|
#####.##.#.##.###.##
|
||||||
|
..#####..#.#########
|
||||||
|
####################
|
||||||
|
#.####....###.#.#.##
|
||||||
|
##.#################
|
||||||
|
#####.##.###..####..
|
||||||
|
..######..##.#######
|
||||||
|
####.##.####...##..#
|
||||||
|
.#####..#.######.###
|
||||||
|
##...#.##########...
|
||||||
|
#.##########.#######
|
||||||
|
.####.#.###.###.#.##
|
||||||
|
....##.##.###..#####
|
||||||
|
.#.#.###########.###
|
||||||
|
#.#.#.#####.####.###
|
||||||
|
###.##.####.##.#..##
|
5
inputs/10s6.txt
Normal file
5
inputs/10s6.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.#....#####...#..
|
||||||
|
##...##.#####..##
|
||||||
|
##...#...#.#####.
|
||||||
|
..#.....#...###..
|
||||||
|
..#.#.....#....##
|
1
inputs/11p.txt
Normal file
1
inputs/11p.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,8,1005,8,330,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,29,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,51,1,1103,2,10,1006,0,94,1006,0,11,1,1106,13,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,87,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,109,2,1105,5,10,2,103,16,10,1,1103,12,10,2,105,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,146,1006,0,49,2,1,12,10,2,1006,6,10,1,1101,4,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,183,1,6,9,10,1006,0,32,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,213,2,1101,9,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,239,1006,0,47,1006,0,4,2,6,0,10,1006,0,58,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,274,2,1005,14,10,1006,0,17,1,104,20,10,1006,0,28,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,309,101,1,9,9,1007,9,928,10,1005,10,15,99,109,652,104,0,104,1,21101,0,937263411860,1,21102,347,1,0,1105,1,451,21101,932440724376,0,1,21102,1,358,0,1105,1,451,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29015167015,1,21101,0,405,0,1106,0,451,21102,1,3422723163,1,21101,0,416,0,1106,0,451,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,868389376360,1,21101,0,439,0,1105,1,451,21102,825544712960,1,1,21102,1,450,0,1106,0,451,99,109,2,21201,-1,0,1,21101,0,40,2,21102,482,1,3,21102,1,472,0,1106,0,515,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,477,478,493,4,0,1001,477,1,477,108,4,477,10,1006,10,509,1101,0,0,477,109,-2,2106,0,0,0,109,4,2101,0,-1,514,1207,-3,0,10,1006,10,532,21102,1,0,-3,22101,0,-3,1,22102,1,-2,2,21102,1,1,3,21101,551,0,0,1106,0,556,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,579,2207,-4,-2,10,1006,10,579,22102,1,-4,-4,1106,0,647,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,598,0,1106,0,556,22101,0,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,617,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,639,21201,-1,0,1,21102,639,1,0,105,1,514,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0
|
4
inputs/12p.txt
Normal file
4
inputs/12p.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=-6, y=-5, z=-8>
|
||||||
|
<x=0, y=-3, z=-13>
|
||||||
|
<x=-15, y=10, z=-11>
|
||||||
|
<x=-3, y=-8, z=3>
|
4
inputs/12s1.txt
Normal file
4
inputs/12s1.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=-1, y=0, z=2>
|
||||||
|
<x=2, y=-10, z=-7>
|
||||||
|
<x=4, y=-8, z=8>
|
||||||
|
<x=3, y=5, z=-1>
|
4
inputs/12s2.txt
Normal file
4
inputs/12s2.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=-8, y=-10, z=0>
|
||||||
|
<x=5, y=5, z=10>
|
||||||
|
<x=2, y=-7, z=3>
|
||||||
|
<x=9, y=-8, z=-3>
|
1
inputs/13p.txt
Normal file
1
inputs/13p.txt
Normal file
File diff suppressed because one or more lines are too long
56
inputs/14p.txt
Normal file
56
inputs/14p.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
6 WBVJ, 16 CDVNK => 2 PJBZT
|
||||||
|
135 ORE => 8 MWDXJ
|
||||||
|
27 NBRHT, 2 NSWK, 2 CMHMQ, 29 NFCB, 11 KNGJ, 12 MGCKC, 56 NHTKL, 7 WNFSV => 1 FUEL
|
||||||
|
1 SFJFX, 3 MXNK => 4 NLSBZ
|
||||||
|
2 PFKRW, 1 VXFRX, 22 QDJCL => 6 GBDG
|
||||||
|
7 TSTF, 4 ZLJN => 7 DMWS
|
||||||
|
5 KPCF, 1 DLMDJ, 1 FNWGH => 6 TSTF
|
||||||
|
8 DTWKS, 1 GBDG => 4 CGZQ
|
||||||
|
26 CNWZM, 4 KPCF => 3 DTWKS
|
||||||
|
1 JVLHM, 7 DTWKS, 7 PJBZT => 8 MRPHV
|
||||||
|
2 MWDXJ => 3 VHFPC
|
||||||
|
1 WXNW, 6 PFKRW => 7 ZVGVP
|
||||||
|
2 ZVGVP => 1 CMHMQ
|
||||||
|
8 JVLHM, 11 XRKN, 1 HCGKZ => 8 CHZLX
|
||||||
|
20 TSTF => 4 XDZMZ
|
||||||
|
3 CMHMQ, 7 ZVGVP, 10 XRKN => 9 FNWGH
|
||||||
|
12 HCGKZ, 4 NLSBZ, 15 RWRDP, 4 MRPHV, 31 KRDV, 6 PMXK, 2 NFVZ => 7 KNGJ
|
||||||
|
1 TXZCM => 9 BMPJ
|
||||||
|
2 ZFXQ => 3 NBRHT
|
||||||
|
13 JVLHM, 1 VHFPC => 3 PBJPZ
|
||||||
|
7 HCGKZ => 7 PMXK
|
||||||
|
2 RWRDP, 3 VSTQ, 12 PMXK => 7 MXNK
|
||||||
|
1 PJBZT, 3 QRSK => 1 KRDV
|
||||||
|
1 MGCKC, 6 CMHMQ => 6 PQTVS
|
||||||
|
1 TNHCS, 24 ZLJN => 4 RWRDP
|
||||||
|
5 MWDXJ, 1 WXNW => 9 QBCLF
|
||||||
|
1 ZFXQ, 1 DLMDJ => 4 DJXRM
|
||||||
|
1 ZFXQ => 2 CNWZM
|
||||||
|
1 KPCF => 6 ZXDVF
|
||||||
|
2 MRPHV => 1 GSTG
|
||||||
|
5 BMPJ, 2 ZLJN => 8 XQJZ
|
||||||
|
1 MWDXJ, 1 ZVGVP => 3 CDVNK
|
||||||
|
3 NFCB, 3 CMHMQ, 1 MWDXJ => 4 XRKN
|
||||||
|
1 WXNW, 1 TXZCM => 5 ZLJN
|
||||||
|
4 ZXDVF => 4 WBVJ
|
||||||
|
2 GBDG => 4 KPCF
|
||||||
|
4 CHZLX, 7 ZFXQ, 14 PQTVS => 9 VSTQ
|
||||||
|
3 TXZCM, 7 ZLJN, 7 ZXDVF => 9 JVLHM
|
||||||
|
1 DMWS, 3 TSTF => 5 HCGKZ
|
||||||
|
2 CGZQ => 4 NFVZ
|
||||||
|
2 PQTVS, 9 VMNJ => 9 TXZCM
|
||||||
|
3 KPCF => 4 DLMDJ
|
||||||
|
7 VMNJ, 24 XQJZ, 7 GSTG, 8 NLSBZ, 10 MGCKC, 2 SFJFX, 18 BMPJ => 1 NSWK
|
||||||
|
41 CNWZM, 5 DJXRM, 1 QRSK, 1 KPCF, 15 XDZMZ, 3 MRPHV, 1 NLSBZ, 9 KRDV => 2 WNFSV
|
||||||
|
10 PBJPZ, 29 BMPJ, 2 PMXK => 7 SFJFX
|
||||||
|
116 ORE => 4 WXNW
|
||||||
|
2 CNWZM => 2 TNHCS
|
||||||
|
10 QBCLF => 7 NFCB
|
||||||
|
1 QBCLF => 2 ZFXQ
|
||||||
|
15 ZLJN => 7 QRSK
|
||||||
|
183 ORE => 3 QDJCL
|
||||||
|
11 GBDG => 5 VMNJ
|
||||||
|
4 DMWS, 3 QRSK => 3 NHTKL
|
||||||
|
124 ORE => 6 VXFRX
|
||||||
|
1 MWDXJ => 6 MGCKC
|
||||||
|
108 ORE => 9 PFKRW
|
6
inputs/14s1.txt
Normal file
6
inputs/14s1.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
10 ORE => 10 A
|
||||||
|
1 ORE => 1 B
|
||||||
|
7 A, 1 B => 1 C
|
||||||
|
7 A, 1 C => 1 D
|
||||||
|
7 A, 1 D => 1 E
|
||||||
|
7 A, 1 E => 1 FUEL
|
7
inputs/14s2.txt
Normal file
7
inputs/14s2.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
9 ORE => 2 A
|
||||||
|
8 ORE => 3 B
|
||||||
|
7 ORE => 5 C
|
||||||
|
3 A, 4 B => 1 AB
|
||||||
|
5 B, 7 C => 1 BC
|
||||||
|
4 C, 1 A => 1 CA
|
||||||
|
2 AB, 3 BC, 4 CA => 1 FUEL
|
9
inputs/14s3.txt
Normal file
9
inputs/14s3.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
157 ORE => 5 NZVS
|
||||||
|
165 ORE => 6 DCFZ
|
||||||
|
44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL
|
||||||
|
12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ
|
||||||
|
179 ORE => 7 PSHF
|
||||||
|
177 ORE => 5 HKGWZ
|
||||||
|
7 DCFZ, 7 PSHF => 2 XJWVT
|
||||||
|
165 ORE => 2 GPVTF
|
||||||
|
3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT
|
12
inputs/14s4.txt
Normal file
12
inputs/14s4.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG
|
||||||
|
17 NVRVD, 3 JNWZP => 8 VPVL
|
||||||
|
53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL
|
||||||
|
22 VJHF, 37 MNCFX => 5 FWMGM
|
||||||
|
139 ORE => 4 NVRVD
|
||||||
|
144 ORE => 7 JNWZP
|
||||||
|
5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC
|
||||||
|
5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV
|
||||||
|
145 ORE => 6 MNCFX
|
||||||
|
1 NVRVD => 8 CXFTF
|
||||||
|
1 VJHF, 6 MNCFX => 4 RFSQX
|
||||||
|
176 ORE => 6 VJHF
|
17
inputs/14s5.txt
Normal file
17
inputs/14s5.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
171 ORE => 8 CNZTR
|
||||||
|
7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL
|
||||||
|
114 ORE => 4 BHXH
|
||||||
|
14 VRPVC => 6 BMBT
|
||||||
|
6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL
|
||||||
|
6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT
|
||||||
|
15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW
|
||||||
|
13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW
|
||||||
|
5 BMBT => 4 WPTQ
|
||||||
|
189 ORE => 9 KTJDG
|
||||||
|
1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP
|
||||||
|
12 VRPVC, 27 CNZTR => 2 XDBXC
|
||||||
|
15 KTJDG, 12 BHXH => 5 XCVML
|
||||||
|
3 BHXH, 2 VRPVC => 7 MZWV
|
||||||
|
121 ORE => 7 VRPVC
|
||||||
|
7 XCVML => 6 RJRHP
|
||||||
|
5 BHXH, 4 VRPVC => 5 LTCX
|
1
inputs/15p.txt
Normal file
1
inputs/15p.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,102,1,1034,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,1002,1035,1,1040,1002,1038,1,1043,101,0,1037,1042,1106,0,124,1001,1034,1,1039,1008,1036,0,1041,101,0,1035,1040,1002,1038,1,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,37,1032,1006,1032,165,1008,1040,9,1032,1006,1032,165,1101,2,0,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1101,1,0,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,50,1044,1106,0,224,1102,0,1,1044,1105,1,224,1006,1044,247,1001,1039,0,1034,102,1,1040,1035,102,1,1041,1036,101,0,1043,1038,102,1,1042,1037,4,1044,1106,0,0,37,22,74,27,37,99,30,8,72,31,49,29,51,32,85,21,39,72,2,2,43,94,31,11,76,43,95,21,38,8,90,13,39,97,54,47,14,6,20,49,5,30,97,9,99,64,71,24,36,87,52,94,36,18,52,42,83,38,98,53,26,87,69,32,18,94,2,93,97,15,65,65,21,40,99,19,91,13,4,89,38,70,65,41,73,49,62,54,37,46,14,49,88,86,13,89,23,89,10,3,48,57,92,43,65,4,35,97,48,10,19,64,3,79,38,87,6,13,71,49,74,43,92,8,4,71,6,35,85,98,94,6,38,59,80,65,46,62,63,62,49,61,68,6,7,64,66,40,56,82,59,30,85,45,57,36,86,70,25,83,31,96,65,19,16,67,55,36,49,54,29,75,69,3,3,37,75,49,23,65,22,6,52,75,31,7,87,85,19,48,97,65,51,78,10,35,40,59,54,14,85,6,30,94,68,42,87,46,75,26,82,36,21,65,90,16,59,14,76,55,37,41,99,80,9,79,12,59,17,75,2,40,52,45,76,45,16,82,13,55,61,14,11,49,97,81,99,38,35,20,98,51,64,13,24,85,94,38,25,87,1,42,89,18,32,54,55,17,15,84,98,25,31,21,55,44,57,59,11,78,49,72,87,20,7,33,91,80,75,18,33,37,52,7,26,87,65,36,52,92,6,8,95,89,37,38,57,25,23,71,75,47,20,87,90,37,54,38,77,32,39,67,16,69,62,15,96,47,91,95,18,96,24,45,21,64,9,72,2,54,65,39,36,54,23,71,74,18,26,97,35,44,29,87,54,48,31,55,33,85,74,13,99,82,39,35,97,43,20,62,58,86,98,41,47,92,79,74,10,85,28,66,86,18,35,5,84,67,13,91,47,44,1,84,56,32,96,7,77,21,88,92,38,31,65,82,87,45,55,4,60,58,64,49,53,3,63,32,52,43,10,66,75,96,53,11,95,44,36,16,65,91,47,32,9,3,73,29,25,93,29,18,88,45,41,46,12,94,13,89,5,36,94,88,33,10,10,2,52,90,19,63,26,84,12,76,16,42,75,63,39,32,72,72,84,70,2,63,33,74,43,68,38,84,72,44,89,18,24,78,69,4,80,41,54,75,72,4,16,91,5,48,30,64,38,4,52,38,30,95,99,32,38,52,35,58,71,38,89,86,25,84,88,41,39,32,56,79,12,52,19,80,46,66,38,32,69,67,6,87,88,36,59,51,5,33,46,45,82,15,57,80,91,12,86,29,34,15,61,19,73,46,82,60,73,13,52,36,67,3,49,87,39,12,98,58,87,32,82,47,65,6,87,71,13,17,65,69,14,34,42,82,42,1,77,63,10,63,28,90,24,13,99,19,38,68,62,44,2,65,81,95,7,54,24,58,16,58,48,95,9,80,9,51,73,23,96,49,64,58,1,6,72,69,39,2,10,63,36,9,85,59,90,41,2,72,77,23,23,80,75,33,6,20,18,59,39,36,89,35,89,42,42,22,37,24,30,51,53,43,78,48,27,76,84,22,81,72,25,95,28,15,51,58,48,7,1,90,72,19,37,52,60,39,81,20,70,6,39,82,26,77,14,96,52,30,84,33,66,80,5,52,15,72,46,55,2,21,8,97,79,43,8,91,27,67,5,18,74,71,34,51,6,83,25,52,92,5,15,85,11,72,33,85,30,59,6,84,29,51,77,99,43,95,44,83,95,89,27,54,16,85,90,82,34,98,59,87,12,73,25,74,29,95,82,51,5,81,46,51,0,0,21,21,1,10,1,0,0,0,0,0,0
|
11
main.go
11
main.go
@ -35,6 +35,17 @@ var dayMap = []day{
|
|||||||
&days.Day02{},
|
&days.Day02{},
|
||||||
&days.Day03{},
|
&days.Day03{},
|
||||||
&days.Day04{},
|
&days.Day04{},
|
||||||
|
&days.Day05{},
|
||||||
|
&days.Day06{},
|
||||||
|
&days.Day07{},
|
||||||
|
&days.Day08{},
|
||||||
|
&days.Day09{},
|
||||||
|
&days.Day10{},
|
||||||
|
&days.Day11{},
|
||||||
|
&days.Day12{},
|
||||||
|
&days.Day13{},
|
||||||
|
&days.Day14{},
|
||||||
|
&days.Day15{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
12
utilities/array.go
Normal file
12
utilities/array.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
// ArrayContains returns whether the specified array contains the specified value
|
||||||
|
func ArrayContains[T comparable](array []T, val T) bool {
|
||||||
|
for _, v := range array {
|
||||||
|
if v == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
29
utilities/constraints.go
Normal file
29
utilities/constraints.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
type Ordered interface {
|
||||||
|
Integer | Float | ~string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Signed interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Unsigned interface {
|
||||||
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type Integer interface {
|
||||||
|
Signed | Unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
type Float interface {
|
||||||
|
~float32 | ~float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Complex interface {
|
||||||
|
~complex64 | ~complex128
|
||||||
|
}
|
||||||
|
|
||||||
|
type Number interface {
|
||||||
|
Integer | Float
|
||||||
|
}
|
@ -1,52 +1,257 @@
|
|||||||
package utilities
|
package utilities
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
opAdd = 1
|
opAdd = 1
|
||||||
opMul = 2
|
opMultiply = 2
|
||||||
opEnd = 99
|
opInput = 3
|
||||||
|
opOutput = 4
|
||||||
|
opJumpIfTrue = 5
|
||||||
|
opJumpIfFalse = 6
|
||||||
|
opLessThan = 7
|
||||||
|
opEquals = 8
|
||||||
|
opRelativeBase = 9
|
||||||
|
opHalt = 99
|
||||||
|
|
||||||
|
modePosition = 0
|
||||||
|
modeImmediate = 1
|
||||||
|
modeRelative = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
type IntcodeProgram []int64
|
type IntcodeProgram struct {
|
||||||
|
memory []int64
|
||||||
|
program []int64
|
||||||
|
relativeBase int
|
||||||
|
haltRequested bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type IntcodeProgramState struct {
|
||||||
|
program *IntcodeProgram
|
||||||
|
CurrentInstruction int
|
||||||
|
NextInstruction int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s IntcodeProgramState) IsHalting() bool {
|
||||||
|
return s.program.GetMemory(s.NextInstruction) == opHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProvideInputFunc func(inputStep int) int64
|
||||||
|
type ReceiveOutputFunc func(val int64, state IntcodeProgramState)
|
||||||
|
|
||||||
func ParseIntcodeProgram(programStr string) IntcodeProgram {
|
func ParseIntcodeProgram(programStr string) IntcodeProgram {
|
||||||
nums := strings.Split(programStr, ",")
|
nums := strings.Split(programStr, ",")
|
||||||
program := make(IntcodeProgram, len(nums))
|
program := IntcodeProgram{
|
||||||
|
program: make([]int64, len(nums)),
|
||||||
|
}
|
||||||
for idx, num := range nums {
|
for idx, num := range nums {
|
||||||
iNum, err := strconv.ParseInt(num, 10, 64)
|
iNum, err := strconv.ParseInt(num, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
program[idx] = iNum
|
program.program[idx] = iNum
|
||||||
}
|
}
|
||||||
|
|
||||||
return program
|
return program
|
||||||
}
|
}
|
||||||
|
|
||||||
func (program IntcodeProgram) Run() {
|
func (p *IntcodeProgram) makeState(instructionPointer int) IntcodeProgramState {
|
||||||
for instructionPointer := 0; instructionPointer < len(program); {
|
return IntcodeProgramState{
|
||||||
opcode := program[instructionPointer]
|
program: p,
|
||||||
switch opcode {
|
CurrentInstruction: instructionPointer,
|
||||||
case opAdd:
|
NextInstruction: instructionPointer + 1,
|
||||||
param1 := program[instructionPointer+1]
|
|
||||||
param2 := program[instructionPointer+2]
|
|
||||||
param3 := program[instructionPointer+3]
|
|
||||||
program[param3] = program[param1] + program[param2]
|
|
||||||
|
|
||||||
instructionPointer += 4
|
|
||||||
case opMul:
|
|
||||||
param1 := program[instructionPointer+1]
|
|
||||||
param2 := program[instructionPointer+2]
|
|
||||||
param3 := program[instructionPointer+3]
|
|
||||||
program[param3] = program[param1] * program[param2]
|
|
||||||
|
|
||||||
instructionPointer += 4
|
|
||||||
case opEnd:
|
|
||||||
instructionPointer = len(program)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) Copy() IntcodeProgram {
|
||||||
|
ret := IntcodeProgram{
|
||||||
|
program: make([]int64, len(p.program)),
|
||||||
|
}
|
||||||
|
copy(ret.program, p.program)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) init() {
|
||||||
|
if p.memory == nil {
|
||||||
|
p.memory = make([]int64, len(p.program))
|
||||||
|
copy(p.memory, p.program)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) getParamValue(param, mode int) int64 {
|
||||||
|
switch mode {
|
||||||
|
case modePosition:
|
||||||
|
return p.GetMemory(param)
|
||||||
|
|
||||||
|
case modeImmediate:
|
||||||
|
return int64(param)
|
||||||
|
|
||||||
|
case modeRelative:
|
||||||
|
return p.GetMemory(param + p.relativeBase)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("unhandled param mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) GetMemory(idx int) int64 {
|
||||||
|
p.ensureMemoryCapacity(idx)
|
||||||
|
return p.memory[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) SetMemory(idx int, val int64) {
|
||||||
|
p.init()
|
||||||
|
p.ensureMemoryCapacity(idx)
|
||||||
|
p.memory[idx] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) setMemory(idx int, val int64, mode int) {
|
||||||
|
if mode == modeImmediate {
|
||||||
|
panic("exception executing program - write parameter must never be in immediate mode")
|
||||||
|
}
|
||||||
|
if mode == modeRelative {
|
||||||
|
idx = idx + p.relativeBase
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SetMemory(idx, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) ensureMemoryCapacity(address int) {
|
||||||
|
if len(p.memory) > address {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.memory = append(p.memory, make([]int64, address+1-len(p.memory))...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) Reset() {
|
||||||
|
p.memory = nil
|
||||||
|
p.init()
|
||||||
|
copy(p.memory, p.program)
|
||||||
|
p.relativeBase = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) Run() {
|
||||||
|
p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) {
|
||||||
|
p.init()
|
||||||
|
|
||||||
|
inputsRequested := 0
|
||||||
|
for instructionPointer := 0; instructionPointer < len(p.program) && !p.haltRequested; {
|
||||||
|
instruction := p.GetMemory(instructionPointer)
|
||||||
|
instructionPointer++
|
||||||
|
|
||||||
|
paramModes := [3]int{
|
||||||
|
modePosition,
|
||||||
|
modePosition,
|
||||||
|
modePosition,
|
||||||
|
}
|
||||||
|
modes := instruction / 100
|
||||||
|
for i := 0; modes > 0; i++ {
|
||||||
|
paramModes[i] = int(modes % 10)
|
||||||
|
modes = modes / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode := instruction % 100
|
||||||
|
switch opcode {
|
||||||
|
case opAdd:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
param3 := p.GetMemory(instructionPointer + 2)
|
||||||
|
p.setMemory(int(param3), p.getParamValue(int(param1), paramModes[0])+p.getParamValue(int(param2), paramModes[1]), paramModes[2])
|
||||||
|
|
||||||
|
instructionPointer += 3
|
||||||
|
|
||||||
|
case opMultiply:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
param3 := p.GetMemory(instructionPointer + 2)
|
||||||
|
p.setMemory(int(param3), p.getParamValue(int(param1), paramModes[0])*p.getParamValue(int(param2), paramModes[1]), paramModes[2])
|
||||||
|
|
||||||
|
instructionPointer += 3
|
||||||
|
|
||||||
|
case opInput:
|
||||||
|
inputsRequested++
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
p.setMemory(int(param1), inputFunc(inputsRequested), paramModes[0])
|
||||||
|
|
||||||
|
instructionPointer += 1
|
||||||
|
|
||||||
|
case opOutput:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
outputFunc(p.getParamValue(int(param1), paramModes[0]), p.makeState(instructionPointer))
|
||||||
|
|
||||||
|
instructionPointer += 1
|
||||||
|
|
||||||
|
case opJumpIfTrue:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
|
||||||
|
if p.getParamValue(int(param1), paramModes[0]) != 0 {
|
||||||
|
instructionPointer = int(p.getParamValue(int(param2), paramModes[1]))
|
||||||
|
} else {
|
||||||
|
instructionPointer += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
case opJumpIfFalse:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
|
||||||
|
if p.getParamValue(int(param1), paramModes[0]) == 0 {
|
||||||
|
instructionPointer = int(p.getParamValue(int(param2), paramModes[1]))
|
||||||
|
} else {
|
||||||
|
instructionPointer += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
case opLessThan:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
param3 := p.GetMemory(instructionPointer + 2)
|
||||||
|
|
||||||
|
if p.getParamValue(int(param1), paramModes[0]) < p.getParamValue(int(param2), paramModes[1]) {
|
||||||
|
p.setMemory(int(param3), 1, paramModes[2])
|
||||||
|
} else {
|
||||||
|
p.setMemory(int(param3), 0, paramModes[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
instructionPointer += 3
|
||||||
|
|
||||||
|
case opEquals:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
param2 := p.GetMemory(instructionPointer + 1)
|
||||||
|
param3 := p.GetMemory(instructionPointer + 2)
|
||||||
|
|
||||||
|
if p.getParamValue(int(param1), paramModes[0]) == p.getParamValue(int(param2), paramModes[1]) {
|
||||||
|
p.setMemory(int(param3), 1, paramModes[2])
|
||||||
|
} else {
|
||||||
|
p.setMemory(int(param3), 0, paramModes[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
instructionPointer += 3
|
||||||
|
|
||||||
|
case opRelativeBase:
|
||||||
|
param1 := p.GetMemory(instructionPointer)
|
||||||
|
|
||||||
|
p.relativeBase += int(p.getParamValue(int(param1), paramModes[0]))
|
||||||
|
|
||||||
|
instructionPointer += 1
|
||||||
|
|
||||||
|
case opHalt:
|
||||||
|
instructionPointer = len(p.program)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("exception executing program - unhandled opcode %d", opcode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.haltRequested = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IntcodeProgram) Stop() {
|
||||||
|
p.haltRequested = true
|
||||||
|
}
|
||||||
|
17
utilities/map.go
Normal file
17
utilities/map.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
func MapKeys[T comparable, U any](m map[T]U) []T {
|
||||||
|
r := make([]T, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
r = append(r, k)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapValues[T comparable, U any](m map[T]U) []U {
|
||||||
|
r := make([]U, 0, len(m))
|
||||||
|
for _, v := range m {
|
||||||
|
r = append(r, v)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
49
utilities/math.go
Normal file
49
utilities/math.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
func GCD[T Integer](a, b T) T {
|
||||||
|
if b == 0 {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return GCD(b, a%b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LCM[T Integer](nums ...T) uint64 {
|
||||||
|
num := len(nums)
|
||||||
|
if num == 0 {
|
||||||
|
return 0
|
||||||
|
} else if num == 1 {
|
||||||
|
return uint64(nums[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := lcm(nums[0], nums[1])
|
||||||
|
for i := 2; i < len(nums); i++ {
|
||||||
|
ret = lcm(uint64(nums[i]), ret)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func lcm[T Integer](a, b T) uint64 {
|
||||||
|
return uint64(a*b) / uint64(GCD(a, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Min[T Number](nums ...T) T {
|
||||||
|
numNums := len(nums)
|
||||||
|
if numNums == 2 {
|
||||||
|
return T(math.Min(float64(nums[0]), float64(nums[1])))
|
||||||
|
}
|
||||||
|
|
||||||
|
if numNums == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
least := nums[0]
|
||||||
|
for i := 1; i < numNums; i++ {
|
||||||
|
if nums[i] < least {
|
||||||
|
least = nums[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return least
|
||||||
|
}
|
6
utilities/pair.go
Normal file
6
utilities/pair.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
type Pair[T, U any] struct {
|
||||||
|
First T
|
||||||
|
Second U
|
||||||
|
}
|
34
utilities/permutations.go
Normal file
34
utilities/permutations.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
type Permutable interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPermutations[T Permutable](arr ...T) [][]T {
|
||||||
|
var helper func([]T, int)
|
||||||
|
res := [][]T{}
|
||||||
|
|
||||||
|
helper = func(arr []T, n int) {
|
||||||
|
if n == 1 {
|
||||||
|
tmp := make([]T, len(arr))
|
||||||
|
copy(tmp, arr)
|
||||||
|
res = append(res, tmp)
|
||||||
|
} else {
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
helper(arr, n-1)
|
||||||
|
if n%2 == 1 {
|
||||||
|
tmp := arr[i]
|
||||||
|
arr[i] = arr[n-1]
|
||||||
|
arr[n-1] = tmp
|
||||||
|
} else {
|
||||||
|
tmp := arr[0]
|
||||||
|
arr[0] = arr[n-1]
|
||||||
|
arr[n-1] = tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(arr, len(arr))
|
||||||
|
return res
|
||||||
|
}
|
74
utilities/vector.go
Normal file
74
utilities/vector.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
type Vec2[T Number] struct {
|
||||||
|
X T
|
||||||
|
Y T
|
||||||
|
}
|
||||||
|
|
||||||
|
type Vec3[T Number] struct {
|
||||||
|
X T
|
||||||
|
Y T
|
||||||
|
Z T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) Dot(other Vec2[T]) T {
|
||||||
|
return (v.X * other.X) + (v.Y * other.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) Len() T {
|
||||||
|
return T(math.Sqrt(float64(v.LenSquared())))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) LenSquared() T {
|
||||||
|
return (v.X * v.X) + (v.Y * v.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) To(other Vec2[T]) Vec2[T] {
|
||||||
|
return Vec2[T]{
|
||||||
|
X: v.X - other.X,
|
||||||
|
Y: v.Y - other.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) AngleBetween(other Vec2[T]) float64 {
|
||||||
|
rad := math.Atan2(float64(other.Y-v.Y), float64(other.X-v.X))
|
||||||
|
return rad * 180 / math.Pi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec2[T]) Equals(other Vec2[T]) bool {
|
||||||
|
return v.X == other.X &&
|
||||||
|
v.Y == other.Y
|
||||||
|
}
|
||||||
|
|
||||||
|
func VecBetween[T Number](a, b Vec2[T]) Vec2[T] {
|
||||||
|
return Vec2[T]{
|
||||||
|
X: a.X - b.X,
|
||||||
|
Y: a.Y - b.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec3[T]) Dot(other Vec3[T]) T {
|
||||||
|
return (v.X * other.X) + (v.Y * other.Y) + (v.Z * other.Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec3[T]) Len() T {
|
||||||
|
return T(math.Sqrt(float64(v.LenSquared())))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec3[T]) LenSquared() T {
|
||||||
|
return (v.X * v.X) + (v.Y * v.Y) + (v.Z * v.Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Vec3[T]) Add(other Vec3[T]) {
|
||||||
|
v.X += other.X
|
||||||
|
v.Y += other.Y
|
||||||
|
v.Z += other.Z
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vec3[T]) Equals(other Vec3[T]) bool {
|
||||||
|
return v.X == other.X &&
|
||||||
|
v.Y == other.Y &&
|
||||||
|
v.Z == other.Z
|
||||||
|
}
|
Reference in New Issue
Block a user