Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
68ca26e3aa
|
|||
267146ed8e
|
|||
8f0dc931c1
|
|||
5bc089c83d
|
|||
c788813cd2
|
|||
788239e531
|
|||
37928d7138
|
|||
da5823aa17
|
|||
8282e09a42
|
|||
343007481a
|
|||
44eeb5a8a6
|
|||
f8d2758c90
|
|||
d9e0d9b649
|
|||
94d83695bf
|
|||
365edf82b1
|
|||
a099a86511
|
|||
acef5fdc12
|
|||
bdd007bb4d
|
28
days/02.go
28
days/02.go
@ -18,19 +18,20 @@ func (d Day02) Num() int {
|
||||
return 2
|
||||
}
|
||||
|
||||
func (d *Day02) getProgramWithParams(param1, param2 int64) utilities.IntcodeProgram {
|
||||
program := make(utilities.IntcodeProgram, len(d.program))
|
||||
copy(program, d.program)
|
||||
program[1] = param1
|
||||
program[2] = param2
|
||||
return program
|
||||
func (d *Day02) setParams(param1, param2 int64) {
|
||||
d.program.Reset()
|
||||
d.program.SetMemory(1, param1)
|
||||
d.program.SetMemory(2, param2)
|
||||
}
|
||||
|
||||
func (d *Day02) Part1() string {
|
||||
program := d.getProgramWithParams(12, 2)
|
||||
program.Run()
|
||||
d.setParams(12, 2)
|
||||
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 {
|
||||
@ -41,10 +42,10 @@ func (d *Day02) Part2() string {
|
||||
found := false
|
||||
for noun = 0; noun <= 99; noun++ {
|
||||
for verb = 0; verb <= 99; verb++ {
|
||||
program := d.getProgramWithParams(noun, verb)
|
||||
program.Run()
|
||||
d.setParams(noun, verb)
|
||||
d.program.Run()
|
||||
|
||||
if program[0] == sentinel {
|
||||
if d.program.GetMemory(0) == sentinel {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -58,6 +59,9 @@ func (d *Day02) Part2() string {
|
||||
if !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",
|
||||
sentinel,
|
||||
|
99
days/03.go
99
days/03.go
@ -6,29 +6,24 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"parnic.com/aoc2019/utilities"
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type Pair[T, U any] struct {
|
||||
a T
|
||||
b U
|
||||
}
|
||||
|
||||
type Day03 struct {
|
||||
line1 []Pair[byte, int]
|
||||
line2 []Pair[byte, int]
|
||||
visited map[Pair[int, int]]int
|
||||
overlaps []Pair[Pair[int, int], int]
|
||||
line1 []u.Pair[byte, int]
|
||||
line2 []u.Pair[byte, int]
|
||||
visited map[u.Pair[int, int]]int
|
||||
overlaps []u.Pair[u.Pair[int, int], int]
|
||||
}
|
||||
|
||||
func (d *Day03) Parse() {
|
||||
lines := utilities.GetStringLines("03p")
|
||||
lines := u.GetStringLines("03p")
|
||||
|
||||
line1data := strings.Split(lines[0], ",")
|
||||
line2data := strings.Split(lines[1], ",")
|
||||
|
||||
d.line1 = make([]Pair[byte, int], len(line1data))
|
||||
d.line2 = make([]Pair[byte, int], len(line2data))
|
||||
d.line1 = make([]u.Pair[byte, int], len(line1data))
|
||||
d.line2 = make([]u.Pair[byte, int], len(line2data))
|
||||
|
||||
for idx, instr := range line1data {
|
||||
dir := instr[0]
|
||||
@ -38,7 +33,7 @@ func (d *Day03) Parse() {
|
||||
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 {
|
||||
@ -49,7 +44,7 @@ func (d *Day03) Parse() {
|
||||
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 {
|
||||
d.visited = make(map[Pair[int, int]]int)
|
||||
d.visited = make(map[u.Pair[int, int]]int)
|
||||
var x int
|
||||
var y int
|
||||
var steps int
|
||||
for _, inst := range d.line1 {
|
||||
switch inst.a {
|
||||
switch inst.First {
|
||||
case 'R':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
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
|
||||
y = 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 {
|
||||
switch inst.a {
|
||||
switch inst.First {
|
||||
case 'R':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
steps++
|
||||
if _, exists := d.visited[Pair[int, int]{x + i, y}]; exists {
|
||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x + i, y}, b: steps})
|
||||
if _, exists := d.visited[u.Pair[int, int]{First: x + i, Second: y}]; exists {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
steps++
|
||||
if _, exists := d.visited[Pair[int, int]{x, y + i}]; exists {
|
||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x, y + i}, b: steps})
|
||||
if _, exists := d.visited[u.Pair[int, int]{First: x, Second: y + i}]; exists {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
steps++
|
||||
if _, exists := d.visited[Pair[int, int]{x - i, y}]; exists {
|
||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x - i, y}, b: steps})
|
||||
if _, exists := d.visited[u.Pair[int, int]{First: x - i, Second: y}]; exists {
|
||||
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':
|
||||
for i := 1; i <= inst.b; i++ {
|
||||
for i := 1; i <= inst.Second; i++ {
|
||||
steps++
|
||||
if _, exists := d.visited[Pair[int, int]{x, y - i}]; exists {
|
||||
d.overlaps = append(d.overlaps, Pair[Pair[int, int], int]{a: Pair[int, int]{x, y - i}, b: steps})
|
||||
if _, exists := d.visited[u.Pair[int, int]{First: x, Second: y - i}]; exists {
|
||||
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
|
||||
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 {
|
||||
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 {
|
||||
minOverlap := math.MaxInt
|
||||
for _, overlap := range d.overlaps {
|
||||
line1Steps := d.visited[overlap.a]
|
||||
line2Steps := overlap.b
|
||||
line1Steps := d.visited[overlap.First]
|
||||
line2Steps := overlap.Second
|
||||
|
||||
totalSteps := line1Steps + line2Steps
|
||||
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: %s%d%s", utilities.TextBold, diagCode, utilities.TextReset)
|
||||
}
|
||||
|
||||
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: %s%d%s", utilities.TextBold, diagCode, utilities.TextReset)
|
||||
}
|
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)
|
||||
}
|
102
days/08.go
Normal file
102
days/08.go
Normal file
@ -0,0 +1,102 @@
|
||||
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.WriteString("Message received:\n")
|
||||
outStr.WriteString(utilities.TextBold)
|
||||
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')
|
||||
}
|
||||
outStr.WriteString(utilities.TextReset)
|
||||
|
||||
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)
|
||||
}
|
118
days/11.go
Normal file
118
days/11.go
Normal file
@ -0,0 +1,118 @@
|
||||
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.WriteString("Registration identifier:\n")
|
||||
outStr.WriteString(u.TextBold)
|
||||
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')
|
||||
}
|
||||
outStr.WriteString(u.TextReset)
|
||||
|
||||
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("Minimum ore to produce 1 FUEL: %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("Maximum fuel we can make from 1 trillion ore: %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("Time to fill the area with oxygen: %s%d%s minutes", 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]]
|
||||
}
|
104
days/16.go
Normal file
104
days/16.go
Normal file
@ -0,0 +1,104 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type Day16 struct {
|
||||
numberSet []int8
|
||||
}
|
||||
|
||||
func (d *Day16) Parse() {
|
||||
numberSequence := u.GetStringContents("16p")
|
||||
d.numberSet = make([]int8, len(numberSequence))
|
||||
for i, numRune := range numberSequence {
|
||||
d.numberSet[i] = int8(numRune - '0')
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day16) Num() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
func (d *Day16) Part1() string {
|
||||
transformed := make([]int8, len(d.numberSet))
|
||||
copy(transformed, d.numberSet)
|
||||
|
||||
transformPattern := []int8{0, 1, 0, -1}
|
||||
|
||||
phases := 100
|
||||
workingSet := make([]int8, len(transformed))
|
||||
for i := 0; i < phases; i++ {
|
||||
copy(workingSet, transformed)
|
||||
|
||||
// fmt.Printf("Phase %d. Input signal: %v\n", (i + 1), transformed)
|
||||
for destIdx := range transformed {
|
||||
repeated := 0
|
||||
patternIdx := 0
|
||||
workingVal := int64(0)
|
||||
for idx := range transformed {
|
||||
if repeated >= destIdx {
|
||||
repeated = 0
|
||||
patternIdx++
|
||||
if patternIdx == len(transformPattern) {
|
||||
patternIdx = 0
|
||||
}
|
||||
} else {
|
||||
repeated++
|
||||
}
|
||||
|
||||
// fmt.Printf("%d*%d", transformed[idx], transformPattern[patternIdx])
|
||||
// if idx < len(transformed)-1 {
|
||||
// fmt.Print(" + ")
|
||||
// }
|
||||
workingVal += int64(transformed[idx] * transformPattern[patternIdx])
|
||||
}
|
||||
|
||||
workingSet[destIdx] = int8(int64(math.Abs(float64(workingVal))) % 10)
|
||||
// fmt.Printf(" = %d\n", workingSet[destIdx])
|
||||
}
|
||||
|
||||
copy(transformed, workingSet)
|
||||
}
|
||||
|
||||
finalVal := 0
|
||||
for i := range transformed[0:8] {
|
||||
finalVal += int(transformed[i]) * int(math.Pow10(8-1-i))
|
||||
}
|
||||
return fmt.Sprintf("First 8 digits of the final output list: %s%d%s", u.TextBold, finalVal, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day16) Part2() string {
|
||||
transformed := make([]int8, len(d.numberSet)*10000)
|
||||
for i := 0; i < 10000; i++ {
|
||||
copy(transformed[i*len(d.numberSet):(i*len(d.numberSet))+len(d.numberSet)], d.numberSet)
|
||||
}
|
||||
|
||||
finalMsgOffset := 0
|
||||
for i := 0; i < 7; i++ {
|
||||
finalMsgOffset += int(d.numberSet[i]) * int(math.Pow10(7-1-i))
|
||||
}
|
||||
|
||||
if finalMsgOffset < len(transformed)/2 {
|
||||
panic("offset must be in the back half of the message for this solution to work")
|
||||
}
|
||||
|
||||
phases := 100
|
||||
for p := 0; p < phases; p++ {
|
||||
rollingTotal := int8(0)
|
||||
for i := len(transformed) - 1; i >= finalMsgOffset; i-- {
|
||||
rollingTotal += transformed[i]
|
||||
rollingTotal = rollingTotal % 10
|
||||
transformed[i] = rollingTotal
|
||||
}
|
||||
}
|
||||
|
||||
finalVal := 0
|
||||
for i := range transformed[finalMsgOffset : finalMsgOffset+8] {
|
||||
finalVal += int(transformed[finalMsgOffset+i]) * int(math.Pow10(8-1-i))
|
||||
}
|
||||
return fmt.Sprintf("Embedded message in the final output list: %s%d%s", u.TextBold, finalVal, u.TextReset)
|
||||
}
|
422
days/17.go
Normal file
422
days/17.go
Normal file
@ -0,0 +1,422 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type camViewCellType int
|
||||
type botFacing int
|
||||
type day17Grid [][]camViewCellType
|
||||
|
||||
const (
|
||||
cellTypeScaffold camViewCellType = iota
|
||||
cellTypeOpen
|
||||
cellTypeInvalid
|
||||
)
|
||||
|
||||
const (
|
||||
botFacingUp botFacing = iota
|
||||
botFacingLeft
|
||||
botFacingDown
|
||||
botFacingRight
|
||||
|
||||
botFacingFirst = botFacingUp
|
||||
botFacingLast = botFacingRight
|
||||
)
|
||||
|
||||
const (
|
||||
dirLeft = 1
|
||||
dirRight = -1
|
||||
maxInstructionSetLength = 20
|
||||
)
|
||||
|
||||
var (
|
||||
day17AdjacentOffsets = []u.Vec2i{
|
||||
{X: -1, Y: 0},
|
||||
{X: 1, Y: 0},
|
||||
{X: 0, Y: -1},
|
||||
{X: 0, Y: 1},
|
||||
}
|
||||
)
|
||||
|
||||
type Day17 struct {
|
||||
program u.IntcodeProgram
|
||||
}
|
||||
|
||||
func (d *Day17) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("17p")
|
||||
}
|
||||
|
||||
func (d Day17) Num() int {
|
||||
return 17
|
||||
}
|
||||
|
||||
func (currentDir botFacing) getNewFacingDir(turnDir int) botFacing {
|
||||
currentDir += botFacing(turnDir)
|
||||
if currentDir < botFacingFirst {
|
||||
currentDir = botFacingLast
|
||||
} else if currentDir > botFacingLast {
|
||||
currentDir = botFacingFirst
|
||||
}
|
||||
|
||||
return currentDir
|
||||
}
|
||||
|
||||
func (grid day17Grid) Draw(botLocation u.Vec2i, botFacingDir botFacing, endLocation u.Vec2i) {
|
||||
for y := range grid {
|
||||
for x := range grid[y] {
|
||||
switch grid[y][x] {
|
||||
case cellTypeOpen:
|
||||
fmt.Print(" ")
|
||||
case cellTypeScaffold:
|
||||
char := "█"
|
||||
color := u.ColorBlack
|
||||
if botLocation.X == x && botLocation.Y == y {
|
||||
switch botFacingDir {
|
||||
case botFacingUp:
|
||||
char = "^"
|
||||
case botFacingLeft:
|
||||
char = "<"
|
||||
case botFacingDown:
|
||||
char = "v"
|
||||
case botFacingRight:
|
||||
char = ">"
|
||||
}
|
||||
} else if endLocation.X == x && endLocation.Y == y {
|
||||
char = "@"
|
||||
} else {
|
||||
color = u.ColorWhite
|
||||
}
|
||||
fmt.Printf("%s%s%s%s", u.BackgroundWhite, color, char, u.TextReset)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func (grid day17Grid) getAdjacentScaffolds(y, x int) []u.Vec2i {
|
||||
retval := make([]u.Vec2i, 0)
|
||||
for _, offset := range day17AdjacentOffsets {
|
||||
offY := y + offset.Y
|
||||
offX := x + offset.X
|
||||
if offY < 0 || offY >= len(grid) ||
|
||||
offX < 0 || offX >= len(grid[0]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if grid[offY][offX] == cellTypeScaffold {
|
||||
retval = append(retval, u.Vec2i{X: offX, Y: offY})
|
||||
}
|
||||
}
|
||||
|
||||
return retval
|
||||
}
|
||||
|
||||
func (grid day17Grid) forEachCellOfType(t camViewCellType, f func(y, x int)) {
|
||||
for y := range grid {
|
||||
for x := range grid[y] {
|
||||
if grid[y][x] == t {
|
||||
f(y, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (grid *day17Grid) processGridUpdate(y int, rVal rune, currBotLocation u.Vec2i, currBotFacing botFacing) (int, u.Vec2i, botFacing) {
|
||||
grid.appendValue(rVal, y)
|
||||
|
||||
switch rVal {
|
||||
case '\n':
|
||||
y++
|
||||
case '^', '<', 'v', '>':
|
||||
currBotLocation = u.Vec2i{X: len((*grid)[y]) - 1, Y: y}
|
||||
switch rVal {
|
||||
case '^':
|
||||
currBotFacing = botFacingUp
|
||||
case '<':
|
||||
currBotFacing = botFacingLeft
|
||||
case 'v':
|
||||
currBotFacing = botFacingDown
|
||||
case '>':
|
||||
currBotFacing = botFacingRight
|
||||
}
|
||||
}
|
||||
|
||||
return y, currBotLocation, currBotFacing
|
||||
}
|
||||
|
||||
func (grid day17Grid) getCellTypeInDirection(y, x int, facingDir botFacing) (camViewCellType, int, int) {
|
||||
newX := x
|
||||
newY := y
|
||||
switch facingDir {
|
||||
case botFacingUp:
|
||||
newY--
|
||||
case botFacingLeft:
|
||||
newX--
|
||||
case botFacingDown:
|
||||
newY++
|
||||
case botFacingRight:
|
||||
newX++
|
||||
}
|
||||
|
||||
if newY < 0 || newY >= len(grid) || newX < 0 || newX >= len(grid[0]) {
|
||||
return cellTypeInvalid, newY, newX
|
||||
}
|
||||
|
||||
return grid[newY][newX], newY, newX
|
||||
}
|
||||
|
||||
func (grid *day17Grid) appendValue(rVal rune, row int) {
|
||||
ensureCapacity := func(y int) {
|
||||
for len(*grid) <= y {
|
||||
*grid = append(*grid, make([]camViewCellType, 0))
|
||||
}
|
||||
}
|
||||
|
||||
switch rVal {
|
||||
case '#':
|
||||
ensureCapacity(row)
|
||||
(*grid)[row] = append((*grid)[row], cellTypeScaffold)
|
||||
case '.':
|
||||
ensureCapacity(row)
|
||||
(*grid)[row] = append((*grid)[row], cellTypeOpen)
|
||||
case '^', '<', 'v', '>':
|
||||
ensureCapacity(row)
|
||||
(*grid)[row] = append((*grid)[row], cellTypeScaffold)
|
||||
}
|
||||
}
|
||||
|
||||
func (grid day17Grid) findEndLocation(botLocation u.Vec2i) u.Vec2i {
|
||||
var endLocation u.Vec2i
|
||||
grid.forEachCellOfType(cellTypeScaffold, func(y, x int) {
|
||||
if numSurrounding := len(grid.getAdjacentScaffolds(y, x)); numSurrounding == 1 {
|
||||
if botLocation.X != x || botLocation.Y != y {
|
||||
endLocation = u.Vec2i{X: x, Y: y}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return endLocation
|
||||
}
|
||||
|
||||
func (grid day17Grid) getTurnDirectionFromCorner(pos u.Vec2i, botFacingDir botFacing) (int, string) {
|
||||
adj := grid.getAdjacentScaffolds(pos.Y, pos.X)
|
||||
turnDirection := 0
|
||||
// this is so awful. i'm sure there's a better way, but i'm tired.
|
||||
if botFacingDir == botFacingUp || botFacingDir == botFacingDown {
|
||||
if u.ArrayContains(adj, u.Vec2i{X: pos.X - 1, Y: pos.Y}) {
|
||||
if botFacingDir == botFacingUp {
|
||||
turnDirection = dirLeft
|
||||
} else if botFacingDir == botFacingDown {
|
||||
turnDirection = dirRight
|
||||
}
|
||||
} else if u.ArrayContains(adj, u.Vec2i{X: pos.X + 1, Y: pos.Y}) {
|
||||
if botFacingDir == botFacingUp {
|
||||
turnDirection = dirRight
|
||||
} else if botFacingDir == botFacingDown {
|
||||
turnDirection = dirLeft
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if u.ArrayContains(adj, u.Vec2i{X: pos.X, Y: pos.Y - 1}) {
|
||||
if botFacingDir == botFacingLeft {
|
||||
turnDirection = dirRight
|
||||
} else if botFacingDir == botFacingRight {
|
||||
turnDirection = dirLeft
|
||||
}
|
||||
} else if u.ArrayContains(adj, u.Vec2i{X: pos.X, Y: pos.Y + 1}) {
|
||||
if botFacingDir == botFacingLeft {
|
||||
turnDirection = dirLeft
|
||||
} else if botFacingDir == botFacingRight {
|
||||
turnDirection = dirRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirAscii := "L"
|
||||
if turnDirection == dirRight {
|
||||
dirAscii = "R"
|
||||
}
|
||||
|
||||
return turnDirection, dirAscii
|
||||
}
|
||||
|
||||
func buildInstructionString(instructions []string) string {
|
||||
workingInstructions := make([]string, len(instructions))
|
||||
copy(workingInstructions, instructions)
|
||||
|
||||
minimumRecurrence := 3
|
||||
initialInstructionSubsetLen := 4
|
||||
|
||||
instructionStr := strings.Join(workingInstructions, ",")
|
||||
progs := make([][]string, 3)
|
||||
for i := range progs {
|
||||
numFound := minimumRecurrence
|
||||
subLen := initialInstructionSubsetLen
|
||||
for numFound >= minimumRecurrence {
|
||||
numFound = 1
|
||||
instructionSubset := strings.Join(workingInstructions[0:subLen], ",")
|
||||
if len(instructionSubset) > maxInstructionSetLength {
|
||||
break
|
||||
}
|
||||
for x := len(instructionSubset); x <= len(instructionStr)-len(instructionSubset); x++ {
|
||||
if instructionStr[x:x+len(instructionSubset)] == instructionSubset {
|
||||
numFound++
|
||||
x += len(instructionSubset)
|
||||
}
|
||||
}
|
||||
if numFound >= minimumRecurrence {
|
||||
subLen += 2
|
||||
}
|
||||
}
|
||||
if numFound < minimumRecurrence {
|
||||
subLen -= 2
|
||||
}
|
||||
progs[i] = make([]string, subLen)
|
||||
copy(progs[i], workingInstructions[0:subLen])
|
||||
|
||||
instructionStr = strings.ReplaceAll(instructionStr, strings.Join(progs[i], ","), "")
|
||||
instructionStr = strings.TrimPrefix(strings.ReplaceAll(instructionStr, ",,", ","), ",")
|
||||
|
||||
if len(instructionStr) == 0 {
|
||||
workingInstructions = nil
|
||||
} else {
|
||||
workingInstructions = strings.Split(instructionStr, ",")
|
||||
}
|
||||
}
|
||||
|
||||
if workingInstructions != nil {
|
||||
panic("failed to use up all instructions")
|
||||
}
|
||||
|
||||
programStr := strings.Join(instructions, ",")
|
||||
for i := range progs {
|
||||
programStr = strings.ReplaceAll(programStr, strings.Join(progs[i], ","), fmt.Sprintf("%c", 'A'+i))
|
||||
}
|
||||
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(programStr)
|
||||
sb.WriteRune('\n')
|
||||
|
||||
for i := range progs {
|
||||
sb.WriteString(strings.Join(progs[i], ","))
|
||||
sb.WriteRune('\n')
|
||||
}
|
||||
|
||||
runDebug := 'n'
|
||||
sb.WriteRune(runDebug)
|
||||
sb.WriteRune('\n')
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (grid day17Grid) solvePath(botLocation u.Vec2i, botFacingDir botFacing) string {
|
||||
instructions := make([]string, 0)
|
||||
|
||||
pos := botLocation
|
||||
endLocation := grid.findEndLocation(botLocation)
|
||||
for {
|
||||
if pos == endLocation {
|
||||
break
|
||||
}
|
||||
|
||||
turnDirection, dirAscii := grid.getTurnDirectionFromCorner(pos, botFacingDir)
|
||||
if turnDirection == 0 {
|
||||
panic("at an invalid location somehow")
|
||||
}
|
||||
|
||||
instructions = append(instructions, dirAscii)
|
||||
|
||||
botFacingDir = botFacingDir.getNewFacingDir(turnDirection)
|
||||
numMoved := 0
|
||||
for {
|
||||
cell, newY, newX := grid.getCellTypeInDirection(pos.Y, pos.X, botFacingDir)
|
||||
if cell != cellTypeScaffold {
|
||||
break
|
||||
}
|
||||
pos.X = newX
|
||||
pos.Y = newY
|
||||
numMoved++
|
||||
}
|
||||
instructions = append(instructions, fmt.Sprintf("%d", numMoved))
|
||||
}
|
||||
|
||||
return buildInstructionString(instructions)
|
||||
}
|
||||
|
||||
func (d *Day17) Part1() string {
|
||||
grid := day17Grid{}
|
||||
y := 0
|
||||
var botLocation u.Vec2i
|
||||
var botFacingDir botFacing
|
||||
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
return 0
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
rVal := rune(val)
|
||||
y, botLocation, botFacingDir = grid.processGridUpdate(y, rVal, botLocation, botFacingDir)
|
||||
})
|
||||
|
||||
alignmentParameterTotal := 0
|
||||
grid.forEachCellOfType(cellTypeScaffold, func(y, x int) {
|
||||
if numSurrounding := len(grid.getAdjacentScaffolds(y, x)); numSurrounding == 4 {
|
||||
alignmentParameterTotal += y * x
|
||||
}
|
||||
})
|
||||
|
||||
// endLocation := grid.findEndLocation(botLocation)
|
||||
// grid.Draw(botLocation, botFacingDir, endLocation)
|
||||
|
||||
return fmt.Sprintf("Alignment parameter sum: %s%d%s", u.TextBold, alignmentParameterTotal, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day17) Part2() string {
|
||||
beforeGrid := day17Grid{}
|
||||
var beforeBotLocation u.Vec2i
|
||||
var beforeBotFacing botFacing
|
||||
|
||||
afterGrid := day17Grid{}
|
||||
var afterBotLocation u.Vec2i
|
||||
var afterBotFacing botFacing
|
||||
|
||||
d.program.Reset()
|
||||
d.program.SetMemory(0, 2)
|
||||
|
||||
row := 0
|
||||
var outputState int
|
||||
var lastOutput int64
|
||||
var instructionStr string
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
return int64(instructionStr[inputStep-1])
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
rVal := rune(val)
|
||||
if outputState == 0 {
|
||||
row, beforeBotLocation, beforeBotFacing = beforeGrid.processGridUpdate(row, rVal, beforeBotLocation, beforeBotFacing)
|
||||
} else if outputState == 2 {
|
||||
row, afterBotLocation, afterBotFacing = afterGrid.processGridUpdate(row, rVal, afterBotLocation, afterBotFacing)
|
||||
}
|
||||
|
||||
if rVal == '\n' && lastOutput == '\n' {
|
||||
if outputState == 0 {
|
||||
instructionStr = beforeGrid.solvePath(beforeBotLocation, beforeBotFacing)
|
||||
}
|
||||
outputState++
|
||||
row = 0
|
||||
}
|
||||
|
||||
lastOutput = val
|
||||
})
|
||||
|
||||
// fmt.Println("initial grid:")
|
||||
// beforeEndLocation := beforeGrid.findEndLocation(beforeBotLocation)
|
||||
// beforeGrid.Draw(beforeBotLocation, beforeBotFacing, beforeEndLocation)
|
||||
|
||||
// fmt.Println("completed grid:")
|
||||
// afterEndLocation := afterGrid.findEndLocation(afterBotLocation)
|
||||
// afterGrid.Draw(afterBotLocation, afterBotFacing, afterEndLocation)
|
||||
|
||||
return fmt.Sprintf("Dust collected after traveling all paths: %s%d%s", u.TextBold, lastOutput, u.TextReset)
|
||||
}
|
345
days/18.go
Normal file
345
days/18.go
Normal file
@ -0,0 +1,345 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/edwingeng/deque/v2"
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type day18Cell int
|
||||
type day18Vec u.Vec2[int]
|
||||
type day18Graph map[rune][]u.Pair[rune, int]
|
||||
|
||||
const (
|
||||
day18CellWall day18Cell = iota
|
||||
day18CellOpen
|
||||
)
|
||||
|
||||
var (
|
||||
day18AdjacentOffsets = []day18Vec{
|
||||
{X: -1, Y: 0},
|
||||
{X: 1, Y: 0},
|
||||
{X: 0, Y: -1},
|
||||
{X: 0, Y: 1},
|
||||
}
|
||||
)
|
||||
|
||||
type Day18 struct {
|
||||
entrance day18Vec
|
||||
grid [][]day18Cell
|
||||
doors map[day18Vec]int
|
||||
keys map[day18Vec]int
|
||||
}
|
||||
|
||||
func (d *Day18) Parse() {
|
||||
d.doors = make(map[day18Vec]int)
|
||||
d.keys = make(map[day18Vec]int)
|
||||
|
||||
lines := u.GetStringLines("18p")
|
||||
d.grid = make([][]day18Cell, len(lines))
|
||||
for i, line := range lines {
|
||||
d.grid[i] = make([]day18Cell, len(line))
|
||||
for j, char := range line {
|
||||
if char == '#' {
|
||||
d.grid[i][j] = day18CellWall
|
||||
} else if char == '.' {
|
||||
d.grid[i][j] = day18CellOpen
|
||||
} else if char == '@' {
|
||||
d.grid[i][j] = day18CellOpen
|
||||
d.entrance = day18Vec{X: j, Y: i}
|
||||
} else if char >= 'A' && char <= 'Z' {
|
||||
d.grid[i][j] = day18CellOpen
|
||||
d.doors[day18Vec{X: j, Y: i}] = int(char - 'A')
|
||||
} else if char >= 'a' && char <= 'z' {
|
||||
d.grid[i][j] = day18CellOpen
|
||||
d.keys[day18Vec{X: j, Y: i}] = int(char - 'a')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day18) Num() int {
|
||||
return 18
|
||||
}
|
||||
|
||||
func (d Day18) Draw(grid [][]day18Cell, keys, doors map[day18Vec]int, entrances ...day18Vec) {
|
||||
for y := range grid {
|
||||
for x := range grid[y] {
|
||||
switch grid[y][x] {
|
||||
case day18CellWall:
|
||||
fmt.Print("█")
|
||||
case day18CellOpen:
|
||||
posVec := day18Vec{X: x, Y: y}
|
||||
if _, exists := doors[posVec]; exists {
|
||||
fmt.Printf("%c", rune(doors[posVec]+'A'))
|
||||
} else if _, exists := keys[posVec]; exists {
|
||||
fmt.Printf("%c", rune(keys[posVec]+'a'))
|
||||
} else if u.ArrayContains(entrances, posVec) {
|
||||
fmt.Print("@")
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day18) findAdjacentCells(inPos day18Vec, keys, doors map[day18Vec]int, grid [][]day18Cell) []u.Pair[rune, int] {
|
||||
found := make([]u.Pair[rune, int], 0)
|
||||
|
||||
getAdjacent := func(pos day18Vec) []day18Vec {
|
||||
retAdjacent := make([]day18Vec, 0, len(day18AdjacentOffsets))
|
||||
for _, off := range day18AdjacentOffsets {
|
||||
offVec := day18Vec{X: pos.X + off.X, Y: pos.Y + off.Y}
|
||||
if grid[offVec.Y][offVec.X] == day18CellWall {
|
||||
continue
|
||||
}
|
||||
retAdjacent = append(retAdjacent, offVec)
|
||||
}
|
||||
|
||||
return retAdjacent
|
||||
}
|
||||
|
||||
queue := deque.NewDeque[u.Pair[int, day18Vec]]()
|
||||
visited := make(map[day18Vec]bool)
|
||||
for _, adjacent := range getAdjacent(inPos) {
|
||||
queue.PushBack(u.Pair[int, day18Vec]{First: 1, Second: adjacent})
|
||||
}
|
||||
|
||||
for !queue.IsEmpty() {
|
||||
next := queue.PopFront()
|
||||
|
||||
if _, exists := visited[next.Second]; !exists {
|
||||
visited[next.Second] = true
|
||||
|
||||
key, adjacentIsKey := keys[next.Second]
|
||||
door, adjacentIsDoor := doors[next.Second]
|
||||
if adjacentIsKey || adjacentIsDoor {
|
||||
var rVal rune
|
||||
if adjacentIsKey {
|
||||
rVal = rune('a' + key)
|
||||
} else if adjacentIsDoor {
|
||||
rVal = rune('A' + door)
|
||||
}
|
||||
|
||||
alreadyFound := false
|
||||
for _, p := range found {
|
||||
if p.First == rVal {
|
||||
alreadyFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !alreadyFound {
|
||||
found = append(found, u.Pair[rune, int]{First: rVal, Second: next.First})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for _, neighbor := range getAdjacent(next.Second) {
|
||||
if _, exists := visited[neighbor]; !exists {
|
||||
queue.PushBack(u.Pair[int, day18Vec]{First: next.First + 1, Second: neighbor})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
type day18PriorityQueue struct {
|
||||
distance int
|
||||
neighbor rune
|
||||
}
|
||||
type PriorityQueueHeap []day18PriorityQueue
|
||||
|
||||
func (h PriorityQueueHeap) Len() int { return len(h) }
|
||||
func (h PriorityQueueHeap) Less(i, j int) bool { return h[i].distance < h[j].distance }
|
||||
func (h PriorityQueueHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||
|
||||
func (h *PriorityQueueHeap) Push(x any) {
|
||||
*h = append(*h, x.(day18PriorityQueue))
|
||||
}
|
||||
|
||||
func (h *PriorityQueueHeap) Pop() any {
|
||||
old := *h
|
||||
n := len(old)
|
||||
x := old[n-1]
|
||||
*h = old[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
type reachableKeysMemo struct {
|
||||
pos rune
|
||||
keysFound int
|
||||
}
|
||||
|
||||
var knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int])
|
||||
|
||||
func (d Day18) reachableKeys(inPos rune, keysFound int, graph day18Graph) []u.Pair[rune, int] {
|
||||
memo := reachableKeysMemo{
|
||||
pos: inPos,
|
||||
keysFound: keysFound,
|
||||
}
|
||||
if v, exists := knownReachableKeys[memo]; exists {
|
||||
return v
|
||||
}
|
||||
|
||||
ret := make([]u.Pair[rune, int], 0)
|
||||
distance := make(map[rune]int)
|
||||
|
||||
ih := make(PriorityQueueHeap, 0)
|
||||
|
||||
for _, p := range graph[inPos] {
|
||||
ih = append(ih, day18PriorityQueue{
|
||||
distance: p.Second,
|
||||
neighbor: p.First,
|
||||
})
|
||||
}
|
||||
|
||||
heap.Init(&ih)
|
||||
|
||||
for ih.Len() > 0 {
|
||||
node := heap.Pop(&ih).(day18PriorityQueue)
|
||||
|
||||
// it's a key and we haven't picked it up yet...
|
||||
if node.neighbor >= 'a' && node.neighbor <= 'z' && (1<<int(node.neighbor-'a')&keysFound) == 0 {
|
||||
ret = append(ret, u.Pair[rune, int]{First: node.neighbor, Second: node.distance})
|
||||
continue
|
||||
}
|
||||
|
||||
// it's a door but we don't have the key yet...
|
||||
if node.neighbor >= 'A' && node.neighbor <= 'Z' && ((1<<int(node.neighbor-'A'))&keysFound) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, p := range graph[node.neighbor] {
|
||||
newDistance := node.distance + p.Second
|
||||
if dist, exists := distance[p.First]; !exists || newDistance < dist {
|
||||
distance[p.First] = newDistance
|
||||
heap.Push(&ih, day18PriorityQueue{
|
||||
distance: newDistance,
|
||||
neighbor: p.First,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
knownReachableKeys[memo] = ret
|
||||
return ret
|
||||
}
|
||||
|
||||
type minStepsMemo struct {
|
||||
pos string
|
||||
keysToFind int
|
||||
keysFound int
|
||||
}
|
||||
|
||||
var knownMinimumSteps = make(map[minStepsMemo]int, 0)
|
||||
|
||||
func (d Day18) minimumSteps(inPos string, keysToFind int, keysFound int, graph day18Graph) int {
|
||||
memo := minStepsMemo{
|
||||
pos: inPos,
|
||||
keysToFind: keysToFind,
|
||||
keysFound: keysFound,
|
||||
}
|
||||
if v, exists := knownMinimumSteps[memo]; exists {
|
||||
return v
|
||||
}
|
||||
|
||||
if keysToFind == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
best := math.Inf(1)
|
||||
for _, item := range inPos {
|
||||
for _, p := range d.reachableKeys(item, keysFound, graph) {
|
||||
sb := strings.Builder{}
|
||||
oldIdx := strings.IndexRune(inPos, item)
|
||||
for i := range inPos {
|
||||
if i == oldIdx {
|
||||
sb.WriteRune(p.First)
|
||||
} else {
|
||||
sb.WriteByte(inPos[i])
|
||||
}
|
||||
}
|
||||
newKeys := keysFound + (1 << (p.First - 'a'))
|
||||
dist := p.Second
|
||||
|
||||
dist += d.minimumSteps(sb.String(), keysToFind-1, newKeys, graph)
|
||||
|
||||
if float64(dist) < best {
|
||||
best = float64(dist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
knownMinimumSteps[memo] = int(best)
|
||||
return int(best)
|
||||
}
|
||||
|
||||
func (d Day18) buildGraph(pos []day18Vec, keys map[day18Vec]int, doors map[day18Vec]int, grid [][]day18Cell) day18Graph {
|
||||
graph := make(day18Graph)
|
||||
for i, p := range pos {
|
||||
adjacent := d.findAdjacentCells(p, keys, doors, grid)
|
||||
graph[rune('1'+i)] = adjacent
|
||||
}
|
||||
for keyPos, keyType := range keys {
|
||||
graph[rune('a'+keyType)] = d.findAdjacentCells(keyPos, keys, doors, grid)
|
||||
}
|
||||
for doorPos, doorType := range doors {
|
||||
graph[rune('A'+doorType)] = d.findAdjacentCells(doorPos, keys, doors, grid)
|
||||
}
|
||||
|
||||
return graph
|
||||
}
|
||||
|
||||
func (d Day18) part2PatchMap(grid [][]day18Cell, entrance day18Vec) []day18Vec {
|
||||
grid[entrance.Y-1][entrance.X] = day18CellWall
|
||||
grid[entrance.Y][entrance.X-1] = day18CellWall
|
||||
grid[entrance.Y][entrance.X] = day18CellWall
|
||||
grid[entrance.Y][entrance.X+1] = day18CellWall
|
||||
grid[entrance.Y+1][entrance.X] = day18CellWall
|
||||
|
||||
return []day18Vec{
|
||||
{X: entrance.X - 1, Y: entrance.Y - 1},
|
||||
{X: entrance.X + 1, Y: entrance.Y - 1},
|
||||
{X: entrance.X - 1, Y: entrance.Y + 1},
|
||||
{X: entrance.X + 1, Y: entrance.Y + 1},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Day18) Part1() string {
|
||||
// fmt.Println("initial state:")
|
||||
// d.Draw(d.grid, d.keys, d.doors, d.entrance)
|
||||
|
||||
graph := d.buildGraph([]day18Vec{d.entrance}, d.keys, d.doors, d.grid)
|
||||
minSteps := d.minimumSteps("1", len(d.keys), 0, graph)
|
||||
|
||||
return fmt.Sprintf("Total distance traveled: %s%d%s", u.TextBold, minSteps, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day18) Part2() string {
|
||||
// fmt.Println("initial state:")
|
||||
grid := make([][]day18Cell, len(d.grid))
|
||||
for i := range d.grid {
|
||||
grid[i] = make([]day18Cell, len(d.grid[i]))
|
||||
copy(grid[i], d.grid[i])
|
||||
}
|
||||
|
||||
entrances := d.part2PatchMap(grid, d.entrance)
|
||||
// d.Draw(grid, d.keys, d.doors, entrances...)
|
||||
|
||||
// clear memoized maps that (might have) came from part1
|
||||
knownMinimumSteps = make(map[minStepsMemo]int)
|
||||
knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int])
|
||||
|
||||
graph := d.buildGraph(entrances, d.keys, d.doors, grid)
|
||||
minSteps := d.minimumSteps("1234", len(d.keys), 0, graph)
|
||||
|
||||
return fmt.Sprintf("Total distance traveled: %s%d%s", u.TextBold, minSteps, u.TextReset)
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"parnic.com/aoc2019/utilities"
|
||||
"fmt"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type DayTemplate struct {
|
||||
}
|
||||
|
||||
func (d *DayTemplate) Parse() {
|
||||
utilities.GetIntLines("Templatep")
|
||||
u.GetIntLines("Templatep")
|
||||
}
|
||||
|
||||
func (d DayTemplate) Num() int {
|
||||
@ -16,9 +18,9 @@ func (d DayTemplate) Num() int {
|
||||
}
|
||||
|
||||
func (d *DayTemplate) Part1() string {
|
||||
return ""
|
||||
return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *DayTemplate) Part2() string {
|
||||
return ""
|
||||
return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset)
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -1,3 +1,5 @@
|
||||
module parnic.com/aoc2019
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/edwingeng/deque/v2 v2.0.1
|
||||
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/edwingeng/deque/v2 v2.0.1 h1:yNEsA9tUImO0vyw2hmVGiK4nnkoxBQ8stMYpdVq2ZmQ=
|
||||
github.com/edwingeng/deque/v2 v2.0.1/go.mod h1:HukI8CQe9KDmZCcURPZRYVYjH79Zy2tIjTF9sN3Bgb0=
|
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,102,1,1034,1039,101,0,1036,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,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,3,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,0,2,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,37,1044,1106,0,224,1102,1,0,1044,1105,1,224,1006,1044,247,101,0,1039,1034,101,0,1040,1035,1001,1041,0,1036,1002,1043,1,1038,101,0,1042,1037,4,1044,1106,0,0,42,4,15,10,25,91,86,34,69,14,50,9,24,24,54,10,18,63,17,2,88,36,31,60,20,13,20,76,94,25,41,36,78,3,39,17,94,10,25,22,16,67,72,31,47,15,25,66,8,17,54,8,89,67,29,28,92,11,54,14,4,64,78,28,80,66,6,70,36,56,13,63,17,19,83,17,27,29,34,54,4,93,24,71,6,66,22,21,92,93,39,4,31,76,72,25,74,89,18,62,18,27,57,35,83,39,14,23,95,2,79,25,97,86,13,79,1,34,90,81,29,45,31,38,67,17,92,32,31,50,1,42,81,1,2,87,7,52,74,20,85,22,32,47,16,77,96,28,14,74,22,55,15,75,44,29,19,8,73,2,54,18,26,64,95,21,98,48,25,36,11,78,77,5,16,70,18,10,76,51,51,10,25,43,56,12,13,48,8,17,68,10,64,25,93,42,3,52,24,72,99,23,54,13,44,17,15,8,68,59,15,95,61,9,50,8,51,23,8,39,13,95,64,12,28,56,90,1,62,27,12,60,6,5,18,24,13,99,12,18,92,97,7,56,22,48,91,34,87,32,98,20,89,74,16,51,84,21,46,14,23,52,17,57,12,50,17,97,23,99,11,21,68,21,61,89,13,45,64,89,18,36,40,35,90,9,1,3,81,33,32,83,99,97,34,4,46,31,21,90,62,14,93,11,22,99,51,70,88,51,2,4,29,36,35,48,17,25,30,69,34,3,39,89,31,89,33,30,88,77,18,30,67,17,40,61,19,40,85,26,23,49,22,41,30,13,79,6,34,40,33,43,49,84,19,78,43,10,74,18,61,15,22,51,86,2,78,11,33,92,24,88,27,24,44,2,97,4,4,49,72,93,24,65,79,21,60,33,46,36,22,15,87,33,78,2,49,70,7,78,78,11,14,64,41,61,41,6,1,49,35,78,47,65,14,66,10,86,76,2,32,88,3,24,14,87,9,95,32,19,4,10,67,60,15,19,53,47,24,29,65,5,95,35,1,70,16,43,53,11,64,17,34,84,74,65,30,18,58,2,35,48,38,33,46,16,87,27,12,79,11,88,35,7,5,35,67,83,38,6,17,56,82,13,45,32,30,67,25,62,7,43,63,9,36,14,58,53,25,98,12,38,78,13,63,93,33,11,54,9,66,32,79,62,47,28,6,67,31,53,71,2,30,59,12,90,59,67,2,58,52,1,30,51,49,22,89,88,27,19,41,27,13,19,76,5,82,58,12,49,51,17,15,73,35,25,74,90,29,14,96,83,69,11,18,14,10,40,93,35,31,35,36,58,36,16,48,7,66,98,31,47,34,47,33,5,28,82,88,1,30,80,95,32,87,2,19,91,74,74,19,8,25,63,65,51,30,14,41,98,99,21,90,15,91,3,31,74,27,31,77,28,74,4,27,88,82,11,54,35,52,13,88,71,93,20,82,18,36,68,33,83,1,18,5,42,46,29,62,10,78,67,9,84,48,22,33,74,36,53,58,31,5,8,55,10,24,49,34,81,1,4,86,5,25,2,75,36,49,2,24,88,72,8,64,36,38,10,23,36,93,28,51,90,4,99,57,31,10,14,94,21,27,61,34,70,41,32,14,91,20,83,30,54,26,44,30,85,96,87,35,16,61,99,16,32,53,68,87,1,89,43,9,17,4,39,50,61,8,49,27,48,13,51,34,47,30,89,68,50,18,63,99,50,32,41,33,71,1,43,57,64,24,95,9,89,8,64,18,75,23,97,74,67,24,55,1,87,97,44,0,0,21,21,1,10,1,0,0,0,0,0,0
|
1
inputs/16p.txt
Normal file
1
inputs/16p.txt
Normal file
@ -0,0 +1 @@
|
||||
59791875142707344554745984624833270124746225787022156176259864082972613206097260696475359886661459314067969858521185244807128606896674972341093111690401527976891268108040443281821862422244152800144859031661510297789792278726877676645835805097902853584093615895099152578276185267316851163313487136731134073054989870018294373731775466754420075119913101001966739563592696702233028356328979384389178001923889641041703308599918672055860556825287836987992883550004999016194930620165247185883506733712391462975446192414198344745434022955974228926237100271949068464343172968939069550036969073411905889066207300644632441054836725463178144030305115977951503567
|
1
inputs/16s1.txt
Normal file
1
inputs/16s1.txt
Normal file
@ -0,0 +1 @@
|
||||
12345678
|
1
inputs/16s2.txt
Normal file
1
inputs/16s2.txt
Normal file
@ -0,0 +1 @@
|
||||
80871224585914546619083218645595
|
1
inputs/16s3.txt
Normal file
1
inputs/16s3.txt
Normal file
@ -0,0 +1 @@
|
||||
19617804207202209144916044189917
|
1
inputs/16s4.txt
Normal file
1
inputs/16s4.txt
Normal file
@ -0,0 +1 @@
|
||||
69317163492948606335995924319873
|
1
inputs/17p.txt
Normal file
1
inputs/17p.txt
Normal file
@ -0,0 +1 @@
|
||||
1,330,331,332,109,2734,1102,1182,1,15,1102,1,1429,24,1002,0,1,570,1006,570,36,1001,571,0,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,15,1,15,1008,15,1429,570,1006,570,14,21102,58,1,0,1105,1,786,1006,332,62,99,21101,0,333,1,21102,73,1,0,1105,1,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,1001,574,0,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21102,1,340,1,1105,1,177,21101,0,477,1,1106,0,177,21101,0,514,1,21101,0,176,0,1106,0,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,1001,572,0,1182,21102,1,375,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21102,1,222,0,1105,1,979,21102,1,388,1,21102,233,1,0,1105,1,579,21101,1182,22,1,21101,0,244,0,1106,0,979,21101,401,0,1,21101,0,255,0,1105,1,579,21101,1182,33,1,21102,266,1,0,1106,0,979,21102,1,414,1,21102,1,277,0,1106,0,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21102,1182,1,1,21101,313,0,0,1106,0,622,1005,575,327,1102,1,1,575,21102,327,1,0,1105,1,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,6,0,0,109,4,1202,-3,1,587,20101,0,0,-1,22101,1,-3,-3,21101,0,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2106,0,0,109,5,2102,1,-4,630,20102,1,0,-2,22101,1,-4,-4,21102,0,1,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,652,21002,0,1,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,0,702,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1106,0,786,1105,1,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,0,756,0,1106,0,786,1106,0,774,21202,-1,-11,1,22101,1182,1,1,21102,774,1,0,1105,1,622,21201,-3,1,-3,1105,1,640,109,-5,2106,0,0,109,7,1005,575,802,21002,576,1,-6,20101,0,577,-5,1105,1,814,21102,1,0,-1,21102,1,0,-5,21102,0,1,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,29,-3,22201,-6,-3,-3,22101,1429,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1105,1,924,1205,-2,873,21102,1,35,-4,1105,1,924,1202,-3,1,878,1008,0,1,570,1006,570,916,1001,374,1,374,2101,0,-3,895,1101,2,0,0,2102,1,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,922,20101,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,29,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,45,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,1,0,575,21101,973,0,0,1105,1,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1105,1,1041,21102,-4,1,-2,1106,0,1041,21101,-5,0,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1201,-2,0,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2101,0,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,439,0,1,1105,1,1150,21102,1,477,1,1105,1,1150,21102,1,514,1,21102,1,1149,0,1105,1,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,2101,0,-5,1176,1202,-4,1,0,109,-6,2105,1,0,6,5,28,1,28,1,28,1,28,1,28,1,20,11,1,7,10,1,7,1,1,1,1,1,5,1,10,1,5,11,1,1,10,1,5,1,1,1,1,1,1,1,3,1,1,1,10,9,1,1,1,1,1,5,16,1,3,1,1,1,1,1,1,1,18,5,1,1,1,1,1,1,24,1,1,1,1,1,24,1,1,1,1,1,24,1,1,1,1,1,24,5,7,1,18,1,9,1,18,1,9,1,18,1,9,1,18,1,9,1,18,1,9,1,12,7,9,1,12,1,15,1,12,1,15,1,12,1,15,1,12,1,15,1,12,1,15,1,2,5,5,1,9,7,2,1,3,1,5,1,9,1,8,1,3,1,5,1,9,1,8,1,3,1,5,1,9,1,8,1,3,13,3,1,8,1,9,1,5,1,3,1,8,11,5,1,1,5,22,1,1,1,1,1,1,1,22,1,1,1,1,1,1,1,22,1,1,1,1,1,1,1,22,13,18,1,1,1,1,1,5,1,16,5,1,1,5,1,16,1,1,1,3,1,5,1,16,1,1,11,16,1,5,1,22,7,6
|
81
inputs/18p.txt
Normal file
81
inputs/18p.txt
Normal file
@ -0,0 +1,81 @@
|
||||
#################################################################################
|
||||
#...#.........P...................#.....#.........#.......#.........#...........#
|
||||
#.###.#############.#.###########.#.#.###.#########.###.###.#######.#.###########
|
||||
#.#...#.#...V.....#.#..t..#.......#.#..a#...........#.#..c..#...#.#.#...........#
|
||||
#.#.###.#.#######.#####.#.#####.#######.#.###########.#######.#.#.#.###########.#
|
||||
#...#...#...#.#...#.J.#.#.....#.........#.......#.......#.....#.#.#.......#...#.#
|
||||
#Z###.#####.#.#.###.#.###.###.#################.#.###.#.#.#####.#.#######.#.#.#.#
|
||||
#.....#...#.#.......#...#...#.#...#.....#...#.#.#.#...#.#...#.....#.......#.#.#.#
|
||||
###.###.#.#.###########.###.#.#.#.#.###.#.#.#.#.#.#.###.###.#######.#######.#.#.#
|
||||
#.#.#...#..y#.........#...#.#...#...#...#.#...#.#.#.#.......#.......#.......#...#
|
||||
#.#.#.#######.#######.###.#######.###.###.###.#.###.#######.#.#######.#########.#
|
||||
#.#.#..q........#.....#.#...#.E.#...#...#.#...#...#.....#.#.#.#...........#...#.#
|
||||
#.#.#############.#####.###.#.#.#######.#.###.###.#.###.#.#.#.#####.#####.#.#.#.#
|
||||
#.#...F.......#...#...#.......#.........#...#.#...#.#...#.#.#.....#.#.....#.#...#
|
||||
#.#########.###.###.#S###################.#I###.#####.###.#.#####.#.#.#########.#
|
||||
#...#...#...#...#...#....u......#.#.....#.#...#.#...#.#...#.....#.#.#.#.......#.#
|
||||
#.###.#.#.###.###.#############.#.#.###.#####.#.#.#.#.#.#######.#.#.#.#.#####.#.#
|
||||
#.#...#.#.#.#.#s..#...#hG.#...#.#.#...#.#.....#...#...#.#.......#.#.#...#...#.#.#
|
||||
#.#.###.#.#.#O#.###.#.#.#.#.#.#.#.#.###.#.###.#########.#.#######.###.###.###.#.#
|
||||
#m..#.#...#.#.#.#...#...#...#g#.#.#.#...#.#.#.#.........#.#.#...#...#.....#...#.#
|
||||
#.###.#####.#.#.#H###########.#.#.#.#.###.#.#.###.#.#####.#.#.#.#.#.#.#####.###.#
|
||||
#.#.........#...#.....#...#...#.#...#...#.#...#...#.#...#.#.#.#.#.#.#.#..w#.#.#.#
|
||||
#.#.#####.#.#############.#.###U###.###.#.#.###.###.#.#.#.#.###.###.#.#.#.#.#.#.#
|
||||
#.#.....#.#.#.....#.......#.#.....#.#...#.#.....#...#.#.#.#...#...#.#.#.#...#...#
|
||||
#.#######.#.###.#.#####.###.#####.###.#.#.#######.###.#.#.#.#####.#.###.#####.###
|
||||
#.#.......#.....#.....#...#.#...#b#...#.#.#.#.....#...#.....#.....#...#.#.....#.#
|
||||
#.#.#################.#.#.#.#.#.#.#.###.#.#.#.#####.#########.#######.#.#.#####.#
|
||||
#.#.#.......#.......#.#.#.#.B.#...#.#.#.#.#.....#...#.....#...#.......#.#...#...#
|
||||
#.#.#.#######.###.###.#.#.#########.#.#.#.#######.###.#.###.#####.#.###N###.#.###
|
||||
#.#.#...#.....#...#...#.#...........#.#.#.......#.#...#.#...#...#.#.#...#...#...#
|
||||
#.#.#.#.#.#####.###.###.###########.#.#.#.#####.#.#.###.#.###.#.###.#.###.###.#.#
|
||||
#...#.#.#.#...#.....#.#.#...#.......#...#.#..r#...#.#...#.....#.....#.#.#...#.#.#
|
||||
#######.#.###.#######.#.###.#.#######.###.###.#######.#.#############.#.###.#.#.#
|
||||
#.......#...#.......#.#...#.#.#.....#.#.#.....#.......#.......#.......#...#.#.#.#
|
||||
###.###.###.#.#####.#.###.#.#.###.#.#.#.#####.#.#.###########.###.#####.#.#.###.#
|
||||
#...#...#...#...#.#.#.......#...#.#.#.#.#.#...#.#...#...#...#...#.#.....#.#...#.#
|
||||
#D###.###.###.#.#.#.###########.#.###.#.#.#.###.###.#.#.#.#.###.#.#.###.#####.#.#
|
||||
#...#...#.#...#.#.#...........#.#.#...#.#...#...#...#.#...#...#...#.#.#.......#.#
|
||||
#.#.#####.#####.#.###########.#.#.#.###.#.#######.###.#######.#####.#.#########.#
|
||||
#.#.............#...............#.................#.........#.................M.#
|
||||
#######################################.@.#######################################
|
||||
#.#...#.......#...............................#.........#.........#..d#...#.....#
|
||||
#.#.#.#.#####.#.#######################.###.#.#.#######.#.###.###.###.#.#.#.#.#K#
|
||||
#...#...#...#.#.#...#.................#.#...#.#.#.#.....#...#.#.#.....#.#...#.#.#
|
||||
#.#########.#.#.#.#.#.###############.#.#.###.#.#.#.#########.#.#####.#.#####.###
|
||||
#.....#...#.#.#.#.#.#.#...#.........#...#.#...#.#.#.......#...#.#.....#.....#...#
|
||||
#####.#.#.#.#.#.#.#.#.#.#.#.#####.#####.#.#.###.#.#######.#.###.#.#########.###.#
|
||||
#...#.#.#...#.....#.#.#.#.#...#...#...#.#.#.#...#...........#.....#.......#.#...#
|
||||
#.#.#.#.###.#########.#.#.###.#####.#.#.#.#.###.###.###########.###.###.###.#.#.#
|
||||
#.#.#...#.W...#.......#.#...#.......#.#.#.#...#...#.#...#.#...#.#...#l#.#...#.#.#
|
||||
#.###.#########.#######.###.#.#######.#.#.###.###.#.#.#.#.#.#.###.###.#.#.###.#.#
|
||||
#.....#.........#...#...#...#.......#...#.#...#...#...#...#.#.#.......#.#...#.#.#
|
||||
#.#####.#######.#.#.#.###.###.#####.#####.###.#.#####.#####.#.#.#######.###.#.###
|
||||
#.#...#.#.....#.#.#...#...#...#...#.....#...#.R.#...#.#.....#.....#...#...#x#...#
|
||||
#.#.#.#.###.###.#.#####.#######.#.#######.#.#####.#.###.###########.#.#.###.###.#
|
||||
#...#.#...#...#.#.#...#...#...#.#.#.....#.#.#.....#.#...#.#.........#.#.......#.#
|
||||
#####.###.###.#.#.###.###.#.#.#.#.#.###.#.#.#.#####.#.###.#.#########.#.#######.#
|
||||
#...#...#...#...#...#.......#...#.#...#.#.#...#.#...#.....#.#.......#.#.#.......#
|
||||
###.###.###.###.###.#############.###.#.#.#####.#.#######.#.#.#.#####Y###.#####.#
|
||||
#...#.....#...#...#.......#.#...#.....#.#.#..i..#.......#.#.#.#.......#...#.#...#
|
||||
#.###.#######.###.#######.#.#.#.#######.#.#.###.#####.###.#Q###.#######.###.#.###
|
||||
#...#.#.......#..n#.#.....#...#...#.....#.#.#...#...#.#...#.#.#.#...#...#.#...#.#
|
||||
#.#.#.#.###.#####.#.#######.#####.#.#####.#.#.###.###.#.###.#.#.#.#.#.###.#.###.#
|
||||
#.#...#.#...#...#.....#...#.#...#...#...#...#...#.#...#...#..o#...#.#.#.......#.#
|
||||
#.#####.#####.#.#######.#.#.#.#.#####.#.#######.#.#.###.###########.#.#######.#.#
|
||||
#.....#...#...#.#.......#.#.#.#.....#.#.#.....#.#.#.....#.........#.#.#...#.....#
|
||||
#####L###.#.###.#.#######.#.###.###.###.###.#.#.#.#######.#.#####.#.#.#.#.#######
|
||||
#...#.#...#.#...#...#...#.#...#.#.......#...#.#...#.....#.#.....#.#.#.#.#.......#
|
||||
#.#.#.#.###.#.#.###.#.#.#.###.#.#######.#.#######.#.#.###.#####.###.#.#.#######.#
|
||||
#.#.#.#.....#.#.#...#.#.....#.#.......#.#.......#...#.#...#..j..#..v#.........#.#
|
||||
#.#.#.#######.#.#.###.#.#####.###.###.###.#####.###.###.###.###.#.###.#########.#
|
||||
#.#.#.#...#...#.#...#.#.#...#...#...#...#...#.#.#...#...#.#.#...#.#.#.#.........#
|
||||
###.#.#.#.#.#######.#.###.#.###.#####.#.###.#.#.#.###.###.#.#####.#.#.#.#######.#
|
||||
#...#...#.#.........#.....#...#.....#f#.#.....#.....#e..#.#.......#.#.#.#.#...#.#
|
||||
#.#######.#################.#.#####.###.#.#############A#.#########.#.#.#.#.#.#.#
|
||||
#...#.....#.....#...#.....#.#.....#.....#...#...#.....#...#...#.......#.#.#.#..z#
|
||||
#.#.#.#####.###.###.#.###C#.###########.###.#.#T#.#.#####.#.###.#######.#.#.#####
|
||||
#.#.#.X.#k..#.#...#...#...#.....#.....#.#...#.#...#.......#.....#....p..#...#...#
|
||||
#.#.###.###.#.###.#####.#.#####.#.#.###.#.###.###################.#######.###.#.#
|
||||
#.#.........#...........#.....#...#.....#...#.....................#...........#.#
|
||||
#################################################################################
|
3
inputs/18s1.txt
Normal file
3
inputs/18s1.txt
Normal file
@ -0,0 +1,3 @@
|
||||
#########
|
||||
#b.A.@.a#
|
||||
#########
|
5
inputs/18s2.txt
Normal file
5
inputs/18s2.txt
Normal file
@ -0,0 +1,5 @@
|
||||
########################
|
||||
#f.D.E.e.C.b.A.@.a.B.c.#
|
||||
######################.#
|
||||
#d.....................#
|
||||
########################
|
5
inputs/18s3.txt
Normal file
5
inputs/18s3.txt
Normal file
@ -0,0 +1,5 @@
|
||||
########################
|
||||
#...............b.C.D.f#
|
||||
#.######################
|
||||
#.....@.a.B.c.d.A.e.F.g#
|
||||
########################
|
9
inputs/18s4.txt
Normal file
9
inputs/18s4.txt
Normal file
@ -0,0 +1,9 @@
|
||||
#################
|
||||
#i.G..c...e..H.p#
|
||||
########.########
|
||||
#j.A..b...f..D.o#
|
||||
########@########
|
||||
#k.E..a...g..B.n#
|
||||
########.########
|
||||
#l.F..d...h..C.m#
|
||||
#################
|
6
inputs/18s5.txt
Normal file
6
inputs/18s5.txt
Normal file
@ -0,0 +1,6 @@
|
||||
########################
|
||||
#@..............ac.GI.b#
|
||||
###d#e#f################
|
||||
###A#B#C################
|
||||
###g#h#i################
|
||||
########################
|
7
inputs/18s6.txt
Normal file
7
inputs/18s6.txt
Normal file
@ -0,0 +1,7 @@
|
||||
#######
|
||||
#a.#Cd#
|
||||
##...##
|
||||
##.@.##
|
||||
##...##
|
||||
#cB#Ab#
|
||||
#######
|
7
inputs/18s7.txt
Normal file
7
inputs/18s7.txt
Normal file
@ -0,0 +1,7 @@
|
||||
###############
|
||||
#d.ABC.#.....a#
|
||||
######...######
|
||||
######.@.######
|
||||
######...######
|
||||
#b.....#.....c#
|
||||
###############
|
7
inputs/18s8.txt
Normal file
7
inputs/18s8.txt
Normal file
@ -0,0 +1,7 @@
|
||||
#############
|
||||
#DcBa.#.GhKl#
|
||||
#.###...#I###
|
||||
#e#d#.@.#j#k#
|
||||
###C#...###J#
|
||||
#fEbA.#.FgHi#
|
||||
#############
|
9
inputs/18s9.txt
Normal file
9
inputs/18s9.txt
Normal file
@ -0,0 +1,9 @@
|
||||
#############
|
||||
#g#f.D#..h#l#
|
||||
#F###e#E###.#
|
||||
#dCba...BcIJ#
|
||||
#####.@.#####
|
||||
#nK.L...G...#
|
||||
#M###N#H###.#
|
||||
#o#m..#i#jk.#
|
||||
#############
|
14
main.go
14
main.go
@ -35,6 +35,20 @@ var dayMap = []day{
|
||||
&days.Day02{},
|
||||
&days.Day03{},
|
||||
&days.Day04{},
|
||||
&days.Day05{},
|
||||
&days.Day06{},
|
||||
&days.Day07{},
|
||||
&days.Day08{},
|
||||
&days.Day09{},
|
||||
&days.Day10{},
|
||||
&days.Day11{},
|
||||
&days.Day12{},
|
||||
&days.Day13{},
|
||||
&days.Day14{},
|
||||
&days.Day15{},
|
||||
&days.Day16{},
|
||||
&days.Day17{},
|
||||
&days.Day18{},
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
opAdd = 1
|
||||
opMul = 2
|
||||
opEnd = 99
|
||||
opAdd = 1
|
||||
opMultiply = 2
|
||||
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 {
|
||||
nums := strings.Split(programStr, ",")
|
||||
program := make(IntcodeProgram, len(nums))
|
||||
program := IntcodeProgram{
|
||||
program: make([]int64, len(nums)),
|
||||
}
|
||||
for idx, num := range nums {
|
||||
iNum, err := strconv.ParseInt(num, 10, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
program[idx] = iNum
|
||||
program.program[idx] = iNum
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
func (program IntcodeProgram) Run() {
|
||||
for instructionPointer := 0; instructionPointer < len(program); {
|
||||
opcode := program[instructionPointer]
|
||||
switch opcode {
|
||||
case opAdd:
|
||||
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) makeState(instructionPointer int) IntcodeProgramState {
|
||||
return IntcodeProgramState{
|
||||
program: p,
|
||||
CurrentInstruction: instructionPointer,
|
||||
NextInstruction: instructionPointer + 1,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
27
utilities/map.go
Normal file
27
utilities/map.go
Normal file
@ -0,0 +1,27 @@
|
||||
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
|
||||
}
|
||||
|
||||
// CopyMap returns a copy of the passed-in map. Note: currently only works if [U]
|
||||
// is not a map or slice.
|
||||
func CopyMap[T comparable, U any](m map[T]U) map[T]U {
|
||||
r := make(map[T]U)
|
||||
for k, v := range m {
|
||||
r[k] = 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
|
||||
}
|
81
utilities/vector.go
Normal file
81
utilities/vector.go
Normal file
@ -0,0 +1,81 @@
|
||||
package utilities
|
||||
|
||||
import "math"
|
||||
|
||||
type Vec2[T Number] struct {
|
||||
X T
|
||||
Y T
|
||||
}
|
||||
|
||||
type Vec3[T Number] struct {
|
||||
X T
|
||||
Y T
|
||||
Z T
|
||||
}
|
||||
|
||||
type Vec2i Vec2[int]
|
||||
|
||||
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 (v Vec2[T]) ManhattanDistance(other Vec2[T]) T {
|
||||
return T(math.Abs(float64(v.X-other.X)) + math.Abs(float64(v.Y-other.Y)))
|
||||
}
|
||||
|
||||
func VecBetween[T Number](a, b Vec2[T]) Vec2[T] {
|
||||
return a.To(b)
|
||||
}
|
||||
|
||||
func ManhattanDistance[T Number](a, b Vec2[T]) T {
|
||||
return a.ManhattanDistance(b)
|
||||
}
|
||||
|
||||
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