Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
0a6d8ab256
|
|||
4c58e5c51c
|
|||
36615d7f06
|
|||
334aaee7a5
|
|||
1a6529c7d2
|
|||
34e6055782
|
|||
c4faba7636
|
|||
982576dc68
|
|||
19f91dbc50
|
|||
2ef1e0656a
|
|||
a0867490c9
|
|||
3d3ea6e266
|
|||
4b5bd0d4e0
|
|||
5bc089c83d
|
|||
c788813cd2
|
|||
788239e531
|
|||
37928d7138
|
|||
da5823aa17
|
|||
8282e09a42
|
|||
343007481a
|
|||
44eeb5a8a6
|
|||
f8d2758c90
|
|||
d9e0d9b649
|
|||
94d83695bf
|
|||
365edf82b1
|
|||
a099a86511
|
|||
acef5fdc12
|
|||
bdd007bb4d
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
__debug_bin
|
||||
aoc2019
|
||||
debug.test
|
||||
*.*prof
|
||||
|
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)
|
||||
}
|
113
days/14.go
Normal file
113
days/14.go
Normal file
@ -0,0 +1,113 @@
|
||||
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)
|
||||
lastSuccess := u.Bisect(estimate, estimate*2, 1, func(val int64) bool {
|
||||
oreConsumed := d.getOreRequiredForFuel(val)
|
||||
return oreConsumed < oreAvailable
|
||||
})
|
||||
|
||||
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")
|
||||
// d.program.SetDebugASCIIPrint(true)
|
||||
}
|
||||
|
||||
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
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
panic("unexpected read")
|
||||
}, 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 {
|
||||
d.program.FeedInputString(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"
|
||||
|
||||
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 reachableKeysMemo struct {
|
||||
pos rune
|
||||
keysFound int
|
||||
}
|
||||
|
||||
type minStepsMemo struct {
|
||||
pos string
|
||||
keysToFind int
|
||||
keysFound int
|
||||
}
|
||||
|
||||
type Day18 struct {
|
||||
entrance day18Vec
|
||||
grid [][]day18Cell
|
||||
doors map[day18Vec]int
|
||||
keys map[day18Vec]int
|
||||
knownReachableKeys map[reachableKeysMemo][]u.Pair[rune, int]
|
||||
knownMinimumSteps map[minStepsMemo]int
|
||||
}
|
||||
|
||||
func (d *Day18) Parse() {
|
||||
d.doors = make(map[day18Vec]int)
|
||||
d.keys = make(map[day18Vec]int)
|
||||
d.knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int])
|
||||
d.knownMinimumSteps = make(map[minStepsMemo]int, 0)
|
||||
|
||||
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 := make([]u.Pair[int, day18Vec], 0)
|
||||
visited := make(map[day18Vec]bool)
|
||||
for _, adjacent := range getAdjacent(inPos) {
|
||||
queue = append(queue, u.Pair[int, day18Vec]{First: 1, Second: adjacent})
|
||||
}
|
||||
|
||||
for len(queue) > 0 {
|
||||
next := queue[0]
|
||||
queue = queue[1:]
|
||||
|
||||
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 = append(queue, u.Pair[int, day18Vec]{First: next.First + 1, Second: neighbor})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
type day18PriorityQueue struct {
|
||||
distance int
|
||||
neighbor rune
|
||||
}
|
||||
type day18PriorityQueueHeap []day18PriorityQueue
|
||||
|
||||
func (h day18PriorityQueueHeap) Len() int { return len(h) }
|
||||
func (h day18PriorityQueueHeap) Less(i, j int) bool { return h[i].distance < h[j].distance }
|
||||
func (h day18PriorityQueueHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||
|
||||
func (h *day18PriorityQueueHeap) Push(x any) {
|
||||
*h = append(*h, x.(day18PriorityQueue))
|
||||
}
|
||||
|
||||
func (h *day18PriorityQueueHeap) Pop() any {
|
||||
old := *h
|
||||
n := len(old)
|
||||
x := old[n-1]
|
||||
*h = old[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
func (d Day18) reachableKeys(inPos rune, keysFound int, graph day18Graph) []u.Pair[rune, int] {
|
||||
memo := reachableKeysMemo{
|
||||
pos: inPos,
|
||||
keysFound: keysFound,
|
||||
}
|
||||
if v, exists := d.knownReachableKeys[memo]; exists {
|
||||
return v
|
||||
}
|
||||
|
||||
ret := make([]u.Pair[rune, int], 0)
|
||||
distance := make(map[rune]int)
|
||||
|
||||
ih := make(day18PriorityQueueHeap, 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.knownReachableKeys[memo] = ret
|
||||
return ret
|
||||
}
|
||||
|
||||
func (d Day18) minimumSteps(inPos string, keysToFind int, keysFound int, graph day18Graph) int {
|
||||
memo := minStepsMemo{
|
||||
pos: inPos,
|
||||
keysToFind: keysToFind,
|
||||
keysFound: keysFound,
|
||||
}
|
||||
if v, exists := d.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.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
|
||||
d.knownMinimumSteps = make(map[minStepsMemo]int)
|
||||
d.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)
|
||||
}
|
146
days/19.go
Normal file
146
days/19.go
Normal file
@ -0,0 +1,146 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type Day19 struct {
|
||||
program u.IntcodeProgram
|
||||
}
|
||||
|
||||
func (d *Day19) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("19p")
|
||||
}
|
||||
|
||||
func (d Day19) Num() int {
|
||||
return 19
|
||||
}
|
||||
|
||||
func (d *Day19) Part1() string {
|
||||
grid := make([][]bool, 50)
|
||||
for y := 0; y < len(grid); y++ {
|
||||
grid[y] = make([]bool, 50)
|
||||
}
|
||||
|
||||
count := int64(0)
|
||||
|
||||
for y := 0; y < 50; y++ {
|
||||
for x := 0; x < 50; x++ {
|
||||
d.program.Reset()
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
if inputStep == 1 {
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
return int64(y)
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
res := val == 1
|
||||
grid[y][x] = res
|
||||
if res {
|
||||
count++
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// fmt.Println("50x50 tractor view:")
|
||||
// for y := 0; y < len(grid); y++ {
|
||||
// for x := 0; x < len(grid[y]); x++ {
|
||||
// if grid[y][x] {
|
||||
// fmt.Print("█")
|
||||
// } else {
|
||||
// fmt.Print(" ")
|
||||
// }
|
||||
// }
|
||||
// fmt.Println()
|
||||
// }
|
||||
|
||||
return fmt.Sprintf("Points affected in 50x50 area: %s%d%s", u.TextBold, count, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day19) Part2() string {
|
||||
f := func(x, y int) bool {
|
||||
ret := false
|
||||
d.program.Reset()
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
if inputStep == 1 {
|
||||
return int64(x)
|
||||
}
|
||||
return int64(y)
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
ret = val == 1
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// find lower bound
|
||||
// this may not be necessary, but helps seed the bisect with a known-good lower bound
|
||||
startY := 0
|
||||
startX := 0
|
||||
for y := 1; startY == 0; y++ {
|
||||
for x := 0; x < 10*y; x++ {
|
||||
if f(x, y) {
|
||||
startY = y
|
||||
startX = x
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastGoodX := 0
|
||||
threshold := 1
|
||||
// add 100 to start y since we know it has to be a 100x100 square.
|
||||
// since we multiply x by 10,000 for the final result, that tells us y cannot be 10k+
|
||||
y := u.Bisect(startY+100, 9999, threshold, func(y int) bool {
|
||||
foundX := false
|
||||
for x := startX; ; x++ {
|
||||
// check top left
|
||||
if !f(x, y) {
|
||||
if !foundX {
|
||||
continue
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !foundX {
|
||||
foundX = true
|
||||
}
|
||||
|
||||
// check top right
|
||||
if !f(x+99, y) {
|
||||
return true
|
||||
}
|
||||
// check bottom left
|
||||
if !f(x, y+99) {
|
||||
continue
|
||||
}
|
||||
|
||||
// we believe the corners work, so run final validations on the full borders.
|
||||
// this may not be necessary, but i've seen some rows end up shorter than a
|
||||
// previous row because of the angle of the beam and our integer fidelity.
|
||||
// plus it's really not that much more expensive to do to be certain we're correct.
|
||||
for y2 := y; y2 < y+100; y2++ {
|
||||
// right wall
|
||||
if !f(x+99, y2) {
|
||||
return true
|
||||
}
|
||||
// left wall
|
||||
if !f(x, y2) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
lastGoodX = x
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
// since we invert our bisect success returns, we need to increment y to
|
||||
// tip back over into the "success" range
|
||||
y += threshold
|
||||
result := (lastGoodX * 10000) + y
|
||||
return fmt.Sprintf("Closest 100x100 square for the ship starts at %d,%d = %s%d%s", lastGoodX, y, u.TextBold, result, u.TextReset)
|
||||
}
|
398
days/20.go
Normal file
398
days/20.go
Normal file
@ -0,0 +1,398 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type day20Cell int8
|
||||
type day20Graph map[day20Portal][]u.Pair[day20Portal, int]
|
||||
|
||||
const (
|
||||
day20CellWall day20Cell = iota
|
||||
day20CellPath
|
||||
day20CellDonutHole
|
||||
)
|
||||
|
||||
var (
|
||||
day20AdjacentOffsets = []u.Vec2i{
|
||||
{X: -1, Y: 0},
|
||||
{X: 1, Y: 0},
|
||||
{X: 0, Y: -1},
|
||||
{X: 0, Y: 1},
|
||||
}
|
||||
|
||||
entrancePortal = day20Portal{name: "AA"}
|
||||
exitPortal = day20Portal{name: "ZZ"}
|
||||
)
|
||||
|
||||
type day20Portal struct {
|
||||
name string
|
||||
inner bool
|
||||
depth int
|
||||
}
|
||||
|
||||
type Day20 struct {
|
||||
grid [][]day20Cell
|
||||
entrance u.Vec2i
|
||||
exit u.Vec2i
|
||||
portals map[day20Portal]u.Vec2i
|
||||
portalNames []string
|
||||
}
|
||||
|
||||
func (d *Day20) Parse() {
|
||||
d.portals = make(map[day20Portal]u.Vec2i)
|
||||
d.portalNames = make([]string, 0)
|
||||
|
||||
lines := u.GetStringLines("20p")
|
||||
d.grid = make([][]day20Cell, len(lines)-4)
|
||||
currPortal := strings.Builder{}
|
||||
|
||||
for row, line := range lines {
|
||||
y := row - 2
|
||||
isGridRow := row >= 2 && row < len(lines)-2
|
||||
|
||||
if isGridRow {
|
||||
d.grid[y] = make([]day20Cell, len(line)-4)
|
||||
}
|
||||
|
||||
for col, ch := range lines[row] {
|
||||
x := col - 2
|
||||
isGridCol := col >= 2 && col < len(line)-2
|
||||
|
||||
if isGridRow && isGridCol {
|
||||
if ch == '#' {
|
||||
d.grid[y][x] = day20CellWall
|
||||
} else if ch == '.' {
|
||||
d.grid[y][x] = day20CellPath
|
||||
} else {
|
||||
d.grid[y][x] = day20CellDonutHole
|
||||
}
|
||||
}
|
||||
|
||||
if ch >= 'A' && ch <= 'Z' {
|
||||
portalX := 0
|
||||
portalY := 0
|
||||
if len(line) > col+1 && line[col+1] >= 'A' && line[col+1] <= 'Z' {
|
||||
currPortal.WriteRune(ch)
|
||||
currPortal.WriteRune(rune(line[col+1]))
|
||||
|
||||
if len(line) > col+2 && line[col+2] == '.' {
|
||||
portalY = y
|
||||
portalX = x + 2
|
||||
} else if col-1 >= 0 && line[col-1] == '.' {
|
||||
portalY = y
|
||||
portalX = x - 1
|
||||
} else {
|
||||
panic("!")
|
||||
}
|
||||
} else if len(lines) > row+1 && lines[row+1][col] >= 'A' && lines[row+1][col] <= 'Z' {
|
||||
currPortal.WriteRune(ch)
|
||||
currPortal.WriteRune(rune(lines[row+1][col]))
|
||||
|
||||
if len(lines) > row+2 && lines[row+2][col] == '.' {
|
||||
portalY = y + 2
|
||||
portalX = x
|
||||
} else if row-1 >= 0 && lines[row-1][col] == '.' {
|
||||
portalY = y - 1
|
||||
portalX = x
|
||||
} else {
|
||||
panic("!")
|
||||
}
|
||||
}
|
||||
|
||||
if currPortal.Len() == 2 {
|
||||
portalName := currPortal.String()
|
||||
portalVec := u.Vec2i{X: portalX, Y: portalY}
|
||||
|
||||
if portalName == entrancePortal.name {
|
||||
d.entrance = portalVec
|
||||
} else if portalName == exitPortal.name {
|
||||
d.exit = portalVec
|
||||
} else {
|
||||
portal := day20Portal{
|
||||
name: portalName,
|
||||
inner: !d.isOuterPortal(portalVec),
|
||||
}
|
||||
d.portals[portal] = portalVec
|
||||
|
||||
u.AddToArray(&d.portalNames, portalName)
|
||||
}
|
||||
|
||||
currPortal.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day20) Num() int {
|
||||
return 20
|
||||
}
|
||||
|
||||
func (d Day20) isPortal(vec u.Vec2i) (bool, int) {
|
||||
if d.grid[vec.Y][vec.X] != day20CellPath {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
for i, name := range d.portalNames {
|
||||
p, exists := d.portals[day20Portal{name: name, inner: !d.isOuterPortal(vec)}]
|
||||
if exists && vec == p {
|
||||
return true, i
|
||||
}
|
||||
}
|
||||
|
||||
return false, 0
|
||||
}
|
||||
|
||||
func (d Day20) Draw() {
|
||||
for y := range d.grid {
|
||||
for x := range d.grid[y] {
|
||||
switch d.grid[y][x] {
|
||||
case day20CellWall:
|
||||
fmt.Print("█")
|
||||
case day20CellDonutHole:
|
||||
fmt.Print(" ")
|
||||
case day20CellPath:
|
||||
posVec := u.Vec2i{X: x, Y: y}
|
||||
if posVec == d.entrance {
|
||||
fmt.Print("@")
|
||||
} else if posVec == d.exit {
|
||||
fmt.Print("!")
|
||||
} else {
|
||||
isPortal, portalIdx := d.isPortal(posVec)
|
||||
if isPortal {
|
||||
ch := 'a' + portalIdx
|
||||
if ch > 'z' {
|
||||
ch = 'A' + (portalIdx - 26)
|
||||
}
|
||||
fmt.Printf("%c", ch)
|
||||
} else {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day20) isOuterPortal(pos u.Vec2i) bool {
|
||||
return pos.X == 0 || pos.Y == 0 || pos.X == len(d.grid[0])-1 || pos.Y == len(d.grid)-1
|
||||
}
|
||||
|
||||
func (d Day20) findAdjacentCells(inPos u.Vec2i) []u.Pair[day20Portal, int] {
|
||||
found := make([]u.Pair[day20Portal, int], 0)
|
||||
|
||||
getAdjacent := func(pos u.Vec2i) []u.Vec2i {
|
||||
retAdjacent := make([]u.Vec2i, 0, len(day20AdjacentOffsets))
|
||||
for _, off := range day20AdjacentOffsets {
|
||||
offVec := u.Vec2i{X: pos.X + off.X, Y: pos.Y + off.Y}
|
||||
if offVec.Y < 0 || offVec.Y >= len(d.grid) || offVec.X < 0 || offVec.X >= len(d.grid[0]) {
|
||||
continue
|
||||
}
|
||||
if d.grid[offVec.Y][offVec.X] != day20CellPath {
|
||||
continue
|
||||
}
|
||||
retAdjacent = append(retAdjacent, offVec)
|
||||
}
|
||||
|
||||
return retAdjacent
|
||||
}
|
||||
|
||||
queue := make([]u.Pair[int, u.Vec2i], 0)
|
||||
visited := map[u.Vec2i]bool{
|
||||
inPos: true,
|
||||
}
|
||||
for _, adjacent := range getAdjacent(inPos) {
|
||||
queue = append(queue, u.Pair[int, u.Vec2i]{First: 1, Second: adjacent})
|
||||
}
|
||||
|
||||
for len(queue) > 0 {
|
||||
next := queue[0]
|
||||
queue = queue[1:]
|
||||
|
||||
if _, exists := visited[next.Second]; !exists {
|
||||
visited[next.Second] = true
|
||||
|
||||
adjacentIsPortal, portalIdx := d.isPortal(next.Second)
|
||||
if adjacentIsPortal || next.Second == d.entrance || next.Second == d.exit {
|
||||
var portalName string
|
||||
if next.Second == d.entrance {
|
||||
portalName = entrancePortal.name
|
||||
} else if next.Second == d.exit {
|
||||
portalName = exitPortal.name
|
||||
} else {
|
||||
portalName = d.portalNames[portalIdx]
|
||||
}
|
||||
|
||||
alreadyFound := false
|
||||
for _, p := range found {
|
||||
if p.First.name == portalName {
|
||||
alreadyFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !alreadyFound {
|
||||
found = append(found, u.Pair[day20Portal, int]{First: day20Portal{
|
||||
name: portalName,
|
||||
inner: !d.isOuterPortal(next.Second),
|
||||
}, Second: next.First})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for _, neighbor := range getAdjacent(next.Second) {
|
||||
if _, exists := visited[neighbor]; !exists {
|
||||
queue = append(queue, u.Pair[int, u.Vec2i]{First: next.First + 1, Second: neighbor})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
type day20PriorityQueue struct {
|
||||
distance int
|
||||
neighbor day20Portal
|
||||
}
|
||||
type day20PriorityQueueHeap []day20PriorityQueue
|
||||
|
||||
func (h day20PriorityQueueHeap) Len() int { return len(h) }
|
||||
func (h day20PriorityQueueHeap) Less(i, j int) bool { return h[i].distance < h[j].distance }
|
||||
func (h day20PriorityQueueHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||
|
||||
func (h *day20PriorityQueueHeap) Push(x any) {
|
||||
*h = append(*h, x.(day20PriorityQueue))
|
||||
}
|
||||
|
||||
func (h *day20PriorityQueueHeap) Pop() any {
|
||||
old := *h
|
||||
n := len(old)
|
||||
x := old[n-1]
|
||||
*h = old[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
func (d Day20) dijkstra(graph day20Graph, start, end day20Portal, neighborFunc func(inPortal day20Portal) []u.Pair[day20Portal, int]) int {
|
||||
distance := make(map[day20Portal]int)
|
||||
|
||||
ih := day20PriorityQueueHeap{
|
||||
day20PriorityQueue{
|
||||
distance: 0,
|
||||
neighbor: start,
|
||||
},
|
||||
}
|
||||
|
||||
heap.Init(&ih)
|
||||
visited := make(map[day20Portal]bool)
|
||||
|
||||
for ih.Len() > 0 {
|
||||
node := heap.Pop(&ih).(day20PriorityQueue)
|
||||
|
||||
if node.neighbor == end {
|
||||
return node.distance
|
||||
}
|
||||
|
||||
if _, exists := visited[node.neighbor]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
visited[node.neighbor] = true
|
||||
|
||||
for _, p := range neighborFunc(node.neighbor) {
|
||||
if _, exists := visited[p.First]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
newDistance := node.distance + p.Second
|
||||
if dist, exists := distance[p.First]; !exists || newDistance < dist {
|
||||
distance[p.First] = newDistance
|
||||
heap.Push(&ih, day20PriorityQueue{
|
||||
distance: newDistance,
|
||||
neighbor: p.First,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return math.MaxInt
|
||||
}
|
||||
|
||||
func (d Day20) buildGraph() day20Graph {
|
||||
graph := make(day20Graph, len(d.portals)+1)
|
||||
|
||||
adjacent := d.findAdjacentCells(d.entrance)
|
||||
graph[entrancePortal] = adjacent
|
||||
|
||||
for portal, portalVec := range d.portals {
|
||||
adjacent = d.findAdjacentCells(portalVec)
|
||||
graph[portal] = adjacent
|
||||
}
|
||||
|
||||
return graph
|
||||
}
|
||||
|
||||
func (d Day20) getDepthNeighbors(graph day20Graph, portal day20Portal) []u.Pair[day20Portal, int] {
|
||||
basePortal := portal
|
||||
basePortal.depth = 0
|
||||
baseNeighbors := graph[basePortal]
|
||||
|
||||
neighbors := make([]u.Pair[day20Portal, int], 0)
|
||||
|
||||
if portal.inner {
|
||||
n := day20Portal{name: portal.name, inner: false, depth: portal.depth + 1}
|
||||
neighbors = append(neighbors, u.Pair[day20Portal, int]{First: n, Second: 1})
|
||||
}
|
||||
|
||||
if portal.depth == 0 {
|
||||
for _, i := range baseNeighbors {
|
||||
if i.First.inner || i.First.name == entrancePortal.name || i.First.name == exitPortal.name {
|
||||
neighbors = append(neighbors, u.Pair[day20Portal, int]{First: i.First, Second: i.Second})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !portal.inner {
|
||||
n := day20Portal{name: portal.name, inner: true, depth: portal.depth - 1}
|
||||
neighbors = append(neighbors, u.Pair[day20Portal, int]{First: n, Second: 1})
|
||||
}
|
||||
|
||||
for _, i := range baseNeighbors {
|
||||
if i.First.name != entrancePortal.name && i.First.name != exitPortal.name {
|
||||
n := day20Portal{name: i.First.name, inner: i.First.inner, depth: portal.depth}
|
||||
neighbors = append(neighbors, u.Pair[day20Portal, int]{First: n, Second: i.Second})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return neighbors
|
||||
}
|
||||
|
||||
func (d *Day20) Part1() string {
|
||||
// d.Draw()
|
||||
|
||||
graph := d.buildGraph()
|
||||
|
||||
for portal, adjacent := range graph {
|
||||
if portal.name == entrancePortal.name {
|
||||
continue
|
||||
}
|
||||
|
||||
graph[portal] = append(adjacent, u.Pair[day20Portal, int]{First: day20Portal{name: portal.name, inner: !portal.inner}, Second: 1})
|
||||
}
|
||||
|
||||
distance := d.dijkstra(graph, entrancePortal, exitPortal, func(inPortal day20Portal) []u.Pair[day20Portal, int] { return graph[inPortal] })
|
||||
return fmt.Sprintf("Steps to traverse maze: %s%d%s", u.TextBold, distance, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day20) Part2() string {
|
||||
graph := d.buildGraph()
|
||||
distance := d.dijkstra(graph, entrancePortal, exitPortal, func(inPortal day20Portal) []u.Pair[day20Portal, int] { return d.getDepthNeighbors(graph, inPortal) })
|
||||
return fmt.Sprintf("Steps to traverse recursive maze: %s%d%s", u.TextBold, distance, u.TextReset)
|
||||
}
|
85
days/21.go
Normal file
85
days/21.go
Normal file
@ -0,0 +1,85 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type Day21 struct {
|
||||
program u.IntcodeProgram
|
||||
}
|
||||
|
||||
func (d *Day21) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("21p")
|
||||
// d.program.SetDebugASCIIPrint(true)
|
||||
}
|
||||
|
||||
func (d Day21) Num() int {
|
||||
return 21
|
||||
}
|
||||
|
||||
func (d *Day21) Part1() string {
|
||||
// if there's any hole up to 3 ahead of us but there's ground where we'd land if we jumped
|
||||
// (a jump takes 4 spaces), go ahead and jump
|
||||
cmds := []string{
|
||||
// check if a hole at 1 or 2 ahead
|
||||
"NOT A T",
|
||||
"NOT B J",
|
||||
// store that result in J
|
||||
"OR T J",
|
||||
// check if a hole at 3 ahead
|
||||
"NOT C T",
|
||||
// store hole in 1, 2, or 3 in T
|
||||
"OR J T",
|
||||
// set J true if hole in 1, 2, or 3
|
||||
"OR T J",
|
||||
// set J true if also no hole at 4 ahead
|
||||
"AND D J",
|
||||
"WALK",
|
||||
}
|
||||
instructionStr := strings.Join(cmds, "\n") + "\n"
|
||||
d.program.FeedInputString(instructionStr)
|
||||
|
||||
res := d.program.Run()
|
||||
|
||||
return fmt.Sprintf("Hull damage value when walking: %s%d%s", u.TextBold, res, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day21) Part2() string {
|
||||
// @
|
||||
// #####.#.##.##.###
|
||||
// ABCDEFGHI
|
||||
// using the first program, this kills us. if we jump, we land at D and H becomes our new D, so it won't jump again.
|
||||
// but if we waited to jump until we got one more ahead, we'd be ok.
|
||||
// so now we want to know essentially the same thing as part 1, but also if our multiple (immediate second jump) would be successful.
|
||||
// in problem terms, that's: if there's a hole at 1 or 2 ahead, and there's a hole at C with ground at H, and there's ground at D.
|
||||
// so now for the above example we'd wait to jump until here:
|
||||
// @
|
||||
// #####.#.##.##.###
|
||||
// ABCDEFGHI
|
||||
// and all will be well.
|
||||
cmds := []string{
|
||||
// check if a hole at 1 or 2 ahead
|
||||
"NOT A J",
|
||||
"NOT B T",
|
||||
// store that result in J
|
||||
"OR T J",
|
||||
// check if a hole at 3 ahead...
|
||||
"NOT C T",
|
||||
// and ground at 8 ahead (so we can immediately jump again if needed)...
|
||||
"AND H T",
|
||||
// combine those into J
|
||||
"OR T J",
|
||||
// and ensure we also still have a place to land if we jumped right away
|
||||
"AND D J",
|
||||
"RUN",
|
||||
}
|
||||
instructionStr := strings.Join(cmds, "\n") + "\n"
|
||||
d.program.FeedInputString(instructionStr)
|
||||
|
||||
res := d.program.Run()
|
||||
|
||||
return fmt.Sprintf("Hull damage value when running: %s%d%s", u.TextBold, res, u.TextReset)
|
||||
}
|
155
days/22.go
Normal file
155
days/22.go
Normal file
@ -0,0 +1,155 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type day22Instruction int
|
||||
|
||||
const (
|
||||
day22InstructionNewStack day22Instruction = iota
|
||||
day22InstructionCut
|
||||
day22InstructionDealIncrement
|
||||
)
|
||||
|
||||
type day22Shuffle struct {
|
||||
instruction day22Instruction
|
||||
arg int
|
||||
}
|
||||
|
||||
type Day22 struct {
|
||||
shuffles []day22Shuffle
|
||||
}
|
||||
|
||||
func (d *Day22) Parse() {
|
||||
lines := u.GetStringLines("22p")
|
||||
d.shuffles = make([]day22Shuffle, len(lines))
|
||||
|
||||
for idx, line := range lines {
|
||||
split := strings.Split(line, " ")
|
||||
if split[0] == "deal" {
|
||||
if split[1] == "into" {
|
||||
d.shuffles[idx] = day22Shuffle{instruction: day22InstructionNewStack}
|
||||
} else if split[1] == "with" {
|
||||
arg, err := strconv.Atoi(split[3])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d.shuffles[idx] = day22Shuffle{
|
||||
instruction: day22InstructionDealIncrement,
|
||||
arg: arg,
|
||||
}
|
||||
}
|
||||
} else if split[0] == "cut" {
|
||||
arg, err := strconv.Atoi(split[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d.shuffles[idx] = day22Shuffle{
|
||||
instruction: day22InstructionCut,
|
||||
arg: arg,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day22) Num() int {
|
||||
return 22
|
||||
}
|
||||
|
||||
func (d Day22) applyShuffle(s day22Shuffle, stack, scratch []int) {
|
||||
switch s.instruction {
|
||||
case day22InstructionNewStack:
|
||||
for i := 0; i < len(stack)/2; i++ {
|
||||
stack[i], stack[len(stack)-1-i] = stack[len(stack)-1-i], stack[i]
|
||||
}
|
||||
|
||||
// there's probably a way to do these two in place...
|
||||
case day22InstructionCut:
|
||||
absArg := int(math.Abs(float64(s.arg)))
|
||||
for i, v := range stack {
|
||||
if s.arg > 0 {
|
||||
if i < absArg {
|
||||
scratch[len(scratch)-absArg+i] = v
|
||||
} else {
|
||||
scratch[i-absArg] = v
|
||||
}
|
||||
} else {
|
||||
if i < absArg {
|
||||
scratch[i] = stack[len(stack)-absArg+i]
|
||||
} else {
|
||||
scratch[i] = stack[i-absArg]
|
||||
}
|
||||
}
|
||||
}
|
||||
copy(stack, scratch)
|
||||
|
||||
case day22InstructionDealIncrement:
|
||||
for i, v := range stack {
|
||||
scratch[(i*s.arg)%len(stack)] = v
|
||||
}
|
||||
copy(stack, scratch)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Day22) Part1() string {
|
||||
deckSize := 10007
|
||||
// deckSize := 10
|
||||
|
||||
stack := make([]int, deckSize)
|
||||
for i := range stack {
|
||||
stack[i] = i
|
||||
}
|
||||
|
||||
scratch := make([]int, len(stack))
|
||||
|
||||
for _, s := range d.shuffles {
|
||||
d.applyShuffle(s, stack, scratch)
|
||||
}
|
||||
|
||||
pos := -1
|
||||
for i, v := range stack {
|
||||
if v == 2019 {
|
||||
pos = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Card 2019 is at position %s%d%s", u.TextBold, pos, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day22) Part2() string {
|
||||
n, iter := big.NewInt(119315717514047), big.NewInt(101741582076661)
|
||||
offset, increment := big.NewInt(0), big.NewInt(1)
|
||||
for _, s := range d.shuffles {
|
||||
switch s.instruction {
|
||||
case day22InstructionNewStack:
|
||||
increment.Mul(increment, big.NewInt(-1))
|
||||
offset.Add(offset, increment)
|
||||
case day22InstructionCut:
|
||||
offset.Add(offset, big.NewInt(0).Mul(big.NewInt(int64(s.arg)), increment))
|
||||
case day22InstructionDealIncrement:
|
||||
increment.Mul(increment, big.NewInt(0).Exp(big.NewInt(int64(s.arg)), big.NewInt(0).Sub(n, big.NewInt(2)), n))
|
||||
}
|
||||
}
|
||||
|
||||
finalIncr := big.NewInt(0).Exp(increment, iter, n)
|
||||
|
||||
finalOffs := big.NewInt(0).Exp(increment, iter, n)
|
||||
finalOffs.Sub(big.NewInt(1), finalOffs)
|
||||
invmod := big.NewInt(0).Exp(big.NewInt(0).Sub(big.NewInt(1), increment), big.NewInt(0).Sub(n, big.NewInt(2)), n)
|
||||
finalOffs.Mul(finalOffs, invmod)
|
||||
finalOffs.Mul(finalOffs, offset)
|
||||
|
||||
answer := big.NewInt(0).Mul(big.NewInt(2020), finalIncr)
|
||||
answer.Add(answer, finalOffs)
|
||||
answer.Mod(answer, n)
|
||||
|
||||
return fmt.Sprintf("Card at position 2020: %s%d%s", u.TextBold, answer, u.TextReset)
|
||||
}
|
170
days/23.go
Normal file
170
days/23.go
Normal file
@ -0,0 +1,170 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type day23Computer struct {
|
||||
program u.IntcodeProgram
|
||||
id int
|
||||
packetQueue chan u.Vec2[int64]
|
||||
outputStep int
|
||||
nextPacketDest int
|
||||
sendingPacket u.Vec2[int64]
|
||||
hasQueuedPacket bool
|
||||
lastReceivedPacket u.Vec2[int64]
|
||||
idle bool
|
||||
}
|
||||
|
||||
func (d Day23) makeComputer(id int) *day23Computer {
|
||||
c := &day23Computer{
|
||||
program: d.program.Copy(),
|
||||
id: id,
|
||||
packetQueue: make(chan u.Vec2[int64]),
|
||||
idle: true,
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type Day23 struct {
|
||||
program u.IntcodeProgram
|
||||
}
|
||||
|
||||
func (d *Day23) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("23p")
|
||||
}
|
||||
|
||||
func (d Day23) Num() int {
|
||||
return 23
|
||||
}
|
||||
|
||||
func (d Day23) initComputers() []*day23Computer {
|
||||
computers := make([]*day23Computer, 50)
|
||||
for i := range computers {
|
||||
computers[i] = d.makeComputer(i)
|
||||
}
|
||||
return computers
|
||||
}
|
||||
|
||||
func (d Day23) execComputers(computers []*day23Computer, nat chan u.Vec2[int64]) *sync.WaitGroup {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(computers))
|
||||
for _, c := range computers {
|
||||
go func(c *day23Computer) {
|
||||
bootedUp := false
|
||||
c.program.RunIn(func(inputStep int) int64 {
|
||||
if !bootedUp {
|
||||
bootedUp = true
|
||||
return int64(c.id)
|
||||
}
|
||||
|
||||
if c.hasQueuedPacket {
|
||||
// fmt.Printf(" %d finished processing packet %v\n", c.id, c.lastReceivedPacket)
|
||||
c.hasQueuedPacket = false
|
||||
return c.lastReceivedPacket.Y
|
||||
}
|
||||
|
||||
select {
|
||||
case c.lastReceivedPacket = <-c.packetQueue:
|
||||
// fmt.Printf("computer %d received packet %v\n", c.id, packet)
|
||||
c.hasQueuedPacket = true
|
||||
return c.lastReceivedPacket.X
|
||||
default:
|
||||
c.idle = true
|
||||
return -1
|
||||
}
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
c.idle = false
|
||||
switch c.outputStep {
|
||||
case 0:
|
||||
c.nextPacketDest = int(val)
|
||||
case 1:
|
||||
c.sendingPacket.X = val
|
||||
case 2:
|
||||
c.sendingPacket.Y = val
|
||||
|
||||
if c.nextPacketDest == 255 {
|
||||
// fmt.Printf("computer %d sending %v to 255\n", c.id, c.sendingPacket)
|
||||
nat <- c.sendingPacket
|
||||
} else {
|
||||
// fmt.Printf("computer %d sending %v to computer %d\n", c.id, c.sendingPacket, c.nextPacketDest)
|
||||
computers[c.nextPacketDest].packetQueue <- c.sendingPacket
|
||||
}
|
||||
}
|
||||
|
||||
c.outputStep = (c.outputStep + 1) % 3
|
||||
})
|
||||
|
||||
wg.Done()
|
||||
}(c)
|
||||
}
|
||||
|
||||
return wg
|
||||
}
|
||||
|
||||
func (d *Day23) Part1() string {
|
||||
computers := d.initComputers()
|
||||
natChan := make(chan u.Vec2[int64])
|
||||
wg := d.execComputers(computers, natChan)
|
||||
|
||||
answer := <-natChan
|
||||
for _, c := range computers {
|
||||
c.program.Stop()
|
||||
}
|
||||
// not really necessary, but let's make sure they all shut down in case
|
||||
// we're running all days at once
|
||||
wg.Wait()
|
||||
|
||||
return fmt.Sprintf("First packet sent to 255 Y value: %s%d%s", u.TextBold, answer.Y, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day23) Part2() string {
|
||||
computers := d.initComputers()
|
||||
natChan := make(chan u.Vec2[int64])
|
||||
wg := d.execComputers(computers, natChan)
|
||||
|
||||
answerChan := make(chan int64)
|
||||
|
||||
go func() {
|
||||
var currVal u.Vec2[int64]
|
||||
var lastVal u.Vec2[int64]
|
||||
hasReceived := false
|
||||
for {
|
||||
select {
|
||||
case currVal = <-natChan:
|
||||
hasReceived = true
|
||||
default:
|
||||
}
|
||||
|
||||
allIdle := true
|
||||
for _, c := range computers {
|
||||
if !c.idle {
|
||||
allIdle = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if allIdle && hasReceived {
|
||||
// fmt.Printf("all idle, sending %v to computer 0\n", currVal)
|
||||
if lastVal.Y == currVal.Y {
|
||||
// fmt.Printf("found answer? %d\n", currVal.Y)
|
||||
answerChan <- currVal.Y
|
||||
}
|
||||
computers[0].packetQueue <- currVal
|
||||
lastVal = currVal
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
answer := <-answerChan
|
||||
for _, c := range computers {
|
||||
c.program.Stop()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
return fmt.Sprintf("First Y value sent to the NAT twice in a row: %s%d%s", u.TextBold, answer, u.TextReset)
|
||||
}
|
289
days/24.go
Normal file
289
days/24.go
Normal file
@ -0,0 +1,289 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
var (
|
||||
day24AdjacentOffsets = []u.Vec2i{
|
||||
{X: -1, Y: 0},
|
||||
{X: 1, Y: 0},
|
||||
{X: 0, Y: -1},
|
||||
{X: 0, Y: 1},
|
||||
}
|
||||
)
|
||||
|
||||
type Day24 struct {
|
||||
grid [][]bool
|
||||
}
|
||||
|
||||
func (d *Day24) Parse() {
|
||||
lines := u.GetStringLines("24p")
|
||||
d.grid = make([][]bool, len(lines))
|
||||
for i, line := range lines {
|
||||
d.grid[i] = make([]bool, len(line))
|
||||
for j, ch := range line {
|
||||
d.grid[i][j] = ch == '#'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day24) Num() int {
|
||||
return 24
|
||||
}
|
||||
|
||||
func (d Day24) calcActivatedNeighbors(grid [][]bool, i, j int) int {
|
||||
activatedNeighbors := 0
|
||||
for _, o := range day24AdjacentOffsets {
|
||||
newI := i + o.X
|
||||
newJ := j + o.Y
|
||||
if newI < 0 || newI >= len(grid) || newJ < 0 || newJ >= len(grid[i]) {
|
||||
continue
|
||||
}
|
||||
if grid[newI][newJ] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
|
||||
return activatedNeighbors
|
||||
}
|
||||
|
||||
func (d Day24) recursiveCalcActivatedNeighbors(gridMap map[int][][]bool, mapIdx, i, j int) int {
|
||||
activatedNeighbors := 0
|
||||
numNeighbors := 0
|
||||
thisGrid := gridMap[mapIdx]
|
||||
for _, o := range day24AdjacentOffsets {
|
||||
newI := i + o.X
|
||||
newJ := j + o.Y
|
||||
if newI < 0 || newI >= len(thisGrid) || newJ < 0 || newJ >= len(thisGrid[i]) {
|
||||
continue
|
||||
}
|
||||
if newI == 2 && newJ == 2 {
|
||||
continue
|
||||
}
|
||||
numNeighbors++
|
||||
if thisGrid[newI][newJ] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
|
||||
checkLower := (i == 1 && j == 2) ||
|
||||
(i == 2 && (j == 1 || j == 3)) ||
|
||||
(i == 3 && j == 2)
|
||||
if checkLower {
|
||||
if lowerGrid, exists := gridMap[mapIdx+1]; exists {
|
||||
if i == 1 {
|
||||
for _, b := range lowerGrid[0] {
|
||||
numNeighbors++
|
||||
if b {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
} else if i == 2 {
|
||||
if j == 1 {
|
||||
for _, r := range lowerGrid {
|
||||
numNeighbors++
|
||||
if r[0] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
} else if j == 3 {
|
||||
for _, r := range lowerGrid {
|
||||
numNeighbors++
|
||||
if r[len(lowerGrid[0])-1] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if i == 3 {
|
||||
for _, b := range lowerGrid[len(lowerGrid)-1] {
|
||||
numNeighbors++
|
||||
if b {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkUpper := (i == 0) || (i == len(thisGrid)-1) ||
|
||||
((i != 0 && i != len(thisGrid)) && (j == 0 || j == len(thisGrid[0])-1))
|
||||
if checkUpper {
|
||||
if upperGrid, exists := gridMap[mapIdx-1]; exists {
|
||||
if i == 0 {
|
||||
numNeighbors++
|
||||
if upperGrid[1][2] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
} else if i == len(thisGrid)-1 {
|
||||
numNeighbors++
|
||||
if upperGrid[3][2] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
if j == 0 {
|
||||
numNeighbors++
|
||||
if upperGrid[2][1] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
} else if j == len(thisGrid[0])-1 {
|
||||
numNeighbors++
|
||||
if upperGrid[2][3] {
|
||||
activatedNeighbors++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activatedNeighbors
|
||||
}
|
||||
|
||||
func (d Day24) calcRating(grid [][]bool) int {
|
||||
rating := 0
|
||||
for i, r := range grid {
|
||||
for j := range r {
|
||||
pow := (i * len(r)) + j
|
||||
if grid[i][j] {
|
||||
result := int(math.Pow(2, float64(pow)))
|
||||
rating += result
|
||||
}
|
||||
}
|
||||
}
|
||||
return rating
|
||||
}
|
||||
|
||||
func (d Day24) numBugs(gridMap map[int][][]bool) int {
|
||||
ret := 0
|
||||
for _, v := range gridMap {
|
||||
for _, r := range v {
|
||||
for _, b := range r {
|
||||
if b {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func copy2d[T comparable](dest [][]T, src [][]T) {
|
||||
for i, r := range src {
|
||||
copy(dest[i], r)
|
||||
}
|
||||
}
|
||||
|
||||
func (d Day24) Draw(grid [][]bool) {
|
||||
for _, r := range grid {
|
||||
for _, c := range r {
|
||||
if c {
|
||||
fmt.Print("#")
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func (d *Day24) Part1() string {
|
||||
grid := make([][]bool, len(d.grid))
|
||||
scratch := make([][]bool, len(grid))
|
||||
for i, g := range d.grid {
|
||||
grid[i] = make([]bool, len(g))
|
||||
scratch[i] = make([]bool, len(g))
|
||||
copy(grid[i], d.grid[i])
|
||||
}
|
||||
|
||||
found := false
|
||||
answer := 0
|
||||
seenRatings := make([]int, 0)
|
||||
for i := 1; !found; i++ {
|
||||
// d.Draw(grid)
|
||||
for i, r := range grid {
|
||||
for j := range r {
|
||||
numActivated := d.calcActivatedNeighbors(grid, i, j)
|
||||
if grid[i][j] {
|
||||
scratch[i][j] = numActivated == 1
|
||||
} else {
|
||||
scratch[i][j] = numActivated == 1 || numActivated == 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rating := d.calcRating(scratch)
|
||||
if u.ArrayContains(seenRatings, rating) {
|
||||
found = true
|
||||
// d.Draw(scratch)
|
||||
answer = rating
|
||||
}
|
||||
seenRatings = append(seenRatings, rating)
|
||||
copy2d(grid, scratch)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("First repeated biodiversity rating is %s%d%s", u.TextBold, answer, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day24) Part2() string {
|
||||
makeGrid := func(initialGrid [][]bool) ([][]bool, [][]bool) {
|
||||
grid := make([][]bool, len(d.grid))
|
||||
scratch := make([][]bool, len(grid))
|
||||
for i, g := range d.grid {
|
||||
grid[i] = make([]bool, len(g))
|
||||
scratch[i] = make([]bool, len(g))
|
||||
if initialGrid != nil {
|
||||
copy(grid[i], initialGrid[i])
|
||||
}
|
||||
}
|
||||
|
||||
return grid, scratch
|
||||
}
|
||||
|
||||
gridMap := make(map[int][][]bool)
|
||||
scratchMap := make(map[int][][]bool)
|
||||
gridMap[0], scratchMap[0] = makeGrid(d.grid)
|
||||
|
||||
min := 0
|
||||
max := 0
|
||||
|
||||
for i := 0; i < 200; i++ {
|
||||
gridMap[min-1], scratchMap[min-1] = makeGrid(nil)
|
||||
gridMap[max+1], scratchMap[max+1] = makeGrid(nil)
|
||||
min, max = min-1, max+1
|
||||
|
||||
// if i == 10 {
|
||||
// keys := u.MapKeys(gridMap)
|
||||
// sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
|
||||
// for _, k := range keys {
|
||||
// fmt.Println("Depth", k)
|
||||
// d.Draw(gridMap[k])
|
||||
// }
|
||||
// fmt.Println("# bugs:", d.numBugs(gridMap))
|
||||
// }
|
||||
|
||||
for depth, grid := range gridMap {
|
||||
for i, r := range grid {
|
||||
for j := range r {
|
||||
if i == 2 && j == 2 {
|
||||
continue
|
||||
}
|
||||
numActivated := d.recursiveCalcActivatedNeighbors(gridMap, depth, i, j)
|
||||
if grid[i][j] {
|
||||
scratchMap[depth][i][j] = numActivated == 1
|
||||
} else {
|
||||
scratchMap[depth][i][j] = numActivated == 1 || numActivated == 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for d := range gridMap {
|
||||
copy2d(gridMap[d], scratchMap[d])
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Bugs present after 200 minutes: %s%d%s", u.TextBold, d.numBugs(gridMap), 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)
|
||||
}
|
||||
|
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 @@
|
||||
#################################################################################
|
||||
#...............#.......#...............#.........#.......#.......#.....#.......#
|
||||
#.#########.#.###.#####.#.#.#######.#####.#######.#.#######.#.###.###.#.#.#####.#
|
||||
#.#.#.....#.#.#...#...#..f#...#.....#...#...#.....#.........#...#.....#...#m....#
|
||||
#.#.#.###.###.#.#####.#######.#######.#.#.#.#.#######.#########.###########.#####
|
||||
#...#...#.#...#.......#.....#.#.......#.#.#.#...#...#...#.......#..h......#.....#
|
||||
###.###.#.#.#########.#.###.#T#.#######.###.###.#B#.#.###.#######.#######.#####.#
|
||||
#...#...#...#.....#...#...#.#...#.....#.#...#.#...#.#.#...#.........#...#.......#
|
||||
#####.#######.###.#.###.#.#######.###.#.#.###.#####.###.#.###########.#.#######.#
|
||||
#...#...#.....#.#...#.#.#.....#...#.....#.#.....#...#...#.#...........#.#.....#.#
|
||||
#.#.###.#.#####.#####.#.#####.#.###.#####.#.###.#.###.#####.###########.#.###.#.#
|
||||
#.#.....#.#.....#.........#...#...#.#...#.#...#..x#...W.....#.....#.....#.#...#.#
|
||||
#.#######.###.#.#########.#.#####.###.#.#.###.#######.#######.###.#.#####.#.#####
|
||||
#.........#...#.......#.#.#.#...#.....#.#.#.#.#.....#...#.....#...#.#.....#.....#
|
||||
#.#########O#########.#.#.#.#.#.#.#####.#.#.#.###.#.#.###.#####.###.#.#########.#
|
||||
#.#.........#.........#...#.#.#.#...#.#.#.#.......#.#.#...#...#.#.......#.....#.#
|
||||
#.#####.#########.#########.#.#.###.#.#.#.#########.###.###.###.#####.###.###.#.#
|
||||
#.....#...#.....#.#.........#.#.#.....#.#.....#.....#...#...........#.#...#e..#.#
|
||||
#####.###.#K###.#.#####.#####.#.#######.#####.#####.#.#.###########.###.###.###.#
|
||||
#...#.....#.#...#.......#.....#.#.......#.....#...#...#.#.........#.....#.#.#...#
|
||||
#.#####.###.#.#########.#.#####.#.#####.#.#####.#.#######.#####.#.#######.#.#.#.#
|
||||
#.#j..#.#...#a..#.....#.#.#.......#.....#.......#...........#.#.#.......#.#...#.#
|
||||
#.#.#.#.#.#####.#.#####.#.#############.#.###################.#########.#.#####.#
|
||||
#...#.#.#.#...#...#.....#.#..z..#.....#.#.....#.......#.....#...#...#...#...#...#
|
||||
#.###.#.#.###.#####.#####.#.###.#.###.#######.#.#.#####.###.###.#.#.#.###.###.###
|
||||
#.#...#.#.....#.#...#...#.#...#.#.#.#...#.....#.#.....#...#.....#.#...#.#...#...#
|
||||
###.###.#####.#.#.###.#.#.###.#.#.#.###.#.###########.###.#######.#####.#.#.###.#
|
||||
#...#...#...#.#.......#.#.....#.#.....#.#.#.............#...#...#...#.....#.#...#
|
||||
#.#.#.#####.#.#############.###.###.###.#.#.#########.#####.###.#.#.#####.#.#.###
|
||||
#.#.#.#.....#.............#...#.....#...#.#.....#...#.#.....#...#.#.#...#.#.#.#.#
|
||||
#.###.#.#.###############.###.#####.#.#.#.#####.#.#.#.#.#####.###.#.#.#.#.#.#.#.#
|
||||
#.#...#.#.......#.........#...#...#.#.#.#.#.....#.#...#.#.........#.#.#.#.#...#.#
|
||||
#.#.#######.###.#.#########.###.#.###.#.#.#.###########.#.#########.#.#.#####.#.#
|
||||
#.#.......#...#.#.#.......#...#.#.#...#.#.#...#.......#.#.#.......#...#.#...#c..#
|
||||
#.#######.#.#.###.###.###.#####.#.#.###.#.###.#.#####.#.###.#####.#.###.#.#.###.#
|
||||
#.L..q..#.#.#...#...#.#.#.....#.#...#...#...#.....#...#.....#.....#...#...#.#...#
|
||||
#.#######.#####.###.#.#.#####.#.#####.#####.#######S#########.#############.#.###
|
||||
#...#...#.#.......#...#.#.....#.#...#...#...#.....#.....#...#.#.....#.....#k#...#
|
||||
#.#.#.#.#.#.#####.#####.#.#####.#.#.###.#.###.###.###.#.###.#.#.###.#.###.#.###.#
|
||||
#.#...#.....#...........#.......#.#...........#.......#.....#...#.....#.....#...#
|
||||
#######################################.@.#######################################
|
||||
#.#...#...........#u....#...#.......#...............#.....#...................#.#
|
||||
#.#.#.#.#####.###.#.#.#.#.#.#.#.#####.#.#####.#####.#.###.#.###.#############.#.#
|
||||
#.#.#...#...#...#.#.#.#.#.#...#.#s....#.#.....#...#.#.#.#..p#.#.#.....#.....#...#
|
||||
#.#.#######.###.###.#.###.#####.#.#####.#.#######.#.#.#.#####.#.#.###.#.###.###.#
|
||||
#...#.........#.#...#.#...#...#...#...#.#...#.....#...#.......#.#.#.#.....#.#.#.#
|
||||
#.###.#.#####.#.#.###.#.###.#######.#.#.#.#.#.###.#####.#######.#.#.#######.#.#.#
|
||||
#...#.#.#.....#...#...#.#...#.....#.#...#.#.#.#...#.....#.......#.#...#.V...#...#
|
||||
###.###.#.#########.###.#.#.#.###.#.###.###.#.#####.#.###.#######.###.#.#####.###
|
||||
#.#.....#.#.....#...#.....#.#...#...#...#...#.#.....#.......#...#.#...#.#.....#.#
|
||||
#.#######.#N#.#.#.#.#.#########.#.#######.###.#.#############.#.#.#.#.#.#.#####.#
|
||||
#.......#.#.#.#.#.#.#.#...#.....#.#.....#.#.........#.........#.#...#.#.#.....U.#
|
||||
#.#######.###.#.#.###.#.#P#.#######.###.#.###.#######.#########.#####.#.#######.#
|
||||
#.#.....#...#.#.#.....#.#...#.......#...#...#...#.....#.......#.......#.#...#...#
|
||||
#.#.###.###.#.#########.###.#.#######.#####.###.#.#####.###.###########.#.#.#.###
|
||||
#...#...#.#.#.#.....#...#...#.#.....#...#...#...#.......#...#.........#.#.#.#.#.#
|
||||
#.###.#.#.#.#.#.#.###.#######.#.###.###.#.#####.#####.#####.#.#######.#.#.#Q#.#.#
|
||||
#.#...#...#.#...#...#.....#...#.#...#...#.....#.....#.#.Yi#.#.#...#...#.#.#.#...#
|
||||
#.#.#######.###.###.#####.#.###.#.#.#.###.###.#######.#.#.#.#.###.#.###.#.#.###.#
|
||||
#.#.......#...#.#.....#...#.#...#.#.#...#.#...#.......#.#.#.#...#.....#.#.#.#...#
|
||||
#.#######.###.###.#.###.###.#####.#####.#.#.#.#.#######.#.#.###.#####.#.#.#.#####
|
||||
#.#.....#.....#...#.#.#.........#.....#.#.#.#.#.#...#...#.#.#.#.#...#...#.#.....#
|
||||
#.#.###.#######.#####.#########.#.#.###.#.#.#.#.#.###.###.#.#.#.#.#.#####.#####.#
|
||||
#.#.#.....#.........#.#.....#.#.#.#b#...#.#.#.#.#.#..y#.#.#.#.#.#.#...#...#.....#
|
||||
#.###.#####.#######.#.#.###.#.#.#.#.#.#####.###.#.#.###.#.###.#.#.###.#.###.###.#
|
||||
#.E.#....d..#.......#...#.#.#.#.#.#.#...#...#...#.#...#.#...I.#...#..l#.#...#...#
|
||||
###.#.#######.###########F#.#.#.###.###.#.#.#.###.###.#.#########.#.###.#.###J###
|
||||
#...#...#...#...........#...#.......#...#.#.#.#.....#.G.#.......#.#.....#.#.#.#.#
|
||||
#.#####.#.#########.#.#.#.#########.#.#.#.###.#####.###.#.###.#.#####.###.#.#.#.#
|
||||
#..v..#...#.......#.#.#.#.#...#.....#.#.#...#.......#.#.#...#.#.....#.#...#.#...#
|
||||
#####.#####.#####.###.###.#.#.#.#####.#.#Z#.#######X#.#.#####.#####.#.#.###.###.#
|
||||
#...#.....#...#.....#...#...#.#.#...#.#.#.#.......#...#.....#.....#.#.#.#...#...#
|
||||
#.#######.#.#.#####.###.#####.#.#.###.#.###.#.#####.#######.#.###.#.###.#.###.###
|
||||
#.........#.#.#...#...#...#...#...#...#.#...#.#...#.#.R....g#.#...#.....#.#...#.#
|
||||
#.###########.#.#.###.###.#.###.###.###.#.#####.#.#.#.#########.#########.#.###.#
|
||||
#...#.#.....#...#.#.#.#...#..t#.#...#...#.#.....#...#...#.....#.#..n....#.M.#...#
|
||||
###.#.#.#.#.#####.#.#.#.#####.###.#####.#.#.###########.#.###.#.#.#######.###.#.#
|
||||
#...#...#.#.#..w#.#.#.#.....#...#.....#.#.#.......#.....#.#...#.#.#.D...#.....#.#
|
||||
#C#######.#.#.#.#.#.#.###.#.###.#####.#.#.#######.#.#####.#.###.#.#.###.#######H#
|
||||
#......o..#...#...#.......#...#.A.....#.#.........#r......#.....#.....#.........#
|
||||
#################################################################################
|
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.#
|
||||
#############
|
1
inputs/19p.txt
Normal file
1
inputs/19p.txt
Normal file
@ -0,0 +1 @@
|
||||
109,424,203,1,21102,11,1,0,1105,1,282,21101,0,18,0,1105,1,259,2101,0,1,221,203,1,21102,1,31,0,1105,1,282,21102,1,38,0,1105,1,259,20102,1,23,2,21201,1,0,3,21102,1,1,1,21102,57,1,0,1106,0,303,2102,1,1,222,21002,221,1,3,20101,0,221,2,21101,0,259,1,21101,0,80,0,1105,1,225,21101,44,0,2,21102,91,1,0,1105,1,303,1202,1,1,223,21002,222,1,4,21102,259,1,3,21102,1,225,2,21102,225,1,1,21101,118,0,0,1106,0,225,21002,222,1,3,21101,163,0,2,21101,0,133,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21102,148,1,0,1106,0,259,1202,1,1,223,20101,0,221,4,21001,222,0,3,21102,1,24,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,195,0,0,105,1,108,20207,1,223,2,21002,23,1,1,21102,-1,1,3,21102,1,214,0,1106,0,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2101,0,-4,249,22102,1,-3,1,22101,0,-2,2,22101,0,-1,3,21102,250,1,0,1106,0,225,21202,1,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21202,-2,1,3,21101,0,343,0,1106,0,303,1106,0,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21101,384,0,0,1105,1,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21202,1,1,-4,109,-5,2105,1,0
|
113
inputs/20p.txt
Normal file
113
inputs/20p.txt
Normal file
@ -0,0 +1,113 @@
|
||||
G R U E Z S S
|
||||
W N C K Z G D
|
||||
#################################.###########.###.#######.#########.#.#######.#####################################
|
||||
#.#.......#.#.........#.#.#.....#.#.....#.#.#...#.....#.........#.....#...#.#...........#.......#.....#.....#.#...#
|
||||
#.#####.###.###.###.#.#.#.###.###.#.###.#.#.###.#.###.###.#####.#.###.###.#.###.#########.###.###.#######.###.#.###
|
||||
#.#.#.#...#...#.#.#.#.................#.#...#...#.#.#...#.#.....#.#.#.#.....................#.#.......#.........#.#
|
||||
#.#.#.#.###.#####.#########.###########.#.#.#.###.#.#######.###.#.#.#####.###.#.###.#.###.#.###.#######.#######.#.#
|
||||
#...#...#.#.#.#.........#...#...#.......#.#...#.......#.....#.#.#.....#.....#.#...#.#.#...#.#...#.#.........#.#.#.#
|
||||
#.#.###.#.#.#.#####.#.#.#######.#.#######.###.#.###.#####.###.#####.#.###.#########.#.#.#######.#.#####.#####.#.#.#
|
||||
#.#...#.#.#.#.#.....#.#.................#.#...#.#.#.....#...#.#.#...#...#.#.....#.#.#.#...#.#.#...........#.#.....#
|
||||
###.###.#.#.#.#.#.#####.#.###.#########.#.#######.#.#####.###.#.#.#.#####.#.#.###.#.#######.#.#.###.#######.###.#.#
|
||||
#...#.......#...#.#.#.#.#...#.#.........#.....#.......#.#.......#.#...#.....#.....#.#...#.........#...#.#.#.#.#.#.#
|
||||
###.#######.#######.#.###########.#.#####.###.#####.###.#.#####.#.###.#.#.###.#.#######.###.#####.#####.#.#.#.#####
|
||||
#.......#.#...#.......#.........#.#.#...#.#.#.#.....#.....#...#.#...#.#.#.#...#...#...#...#...#.#.#...........#.#.#
|
||||
#.#.###.#.#.#########.#########.#.###.###.#.#####.#.###.#.#.#.#.#.###########.#.###.###.###.###.###.###.#.#####.#.#
|
||||
#.#...#.....#.#...#.#.#.#.#.............#.....#...#...#.#.#.#...#...#.#.#.....#.........#...#.......#...#...#...#.#
|
||||
###########.#.#.###.#.#.#.#######.#####.#.#####.#.#######.#####.###.#.#.#####.#.#.###.#####.###.#############.#.#.#
|
||||
#.#.#.#.#.....#.#.....#.#.#.#.....#...#.#.....#.#.....#...#.#.#...#...#.#.#...#.#...#...#...#...#...#.#.......#.#.#
|
||||
#.#.#.#.###.###.#####.#.#.#.#####.#.###.#.#########.#######.#.#.###.###.#.#.###.###.#####.#####.#.###.#####.#####.#
|
||||
#.#...#.#...#.#.#...#...#.#.....#.#.....#.#...#.....#.......#.#.#...#.....#.#.#.#.......#.......#...#.#.#...#.#...#
|
||||
#.#.#.#.###.#.#.###.#.###.#.#####.#.###.#.###.###.###.#.#.###.#.#.###.#.#.###.#.###.#####.#.#####.###.#.###.#.###.#
|
||||
#.#.#.#.#...#.#...#...#.#.#...#...#...#.#.#.....#.#...#.#.#.....#.#...#.#.#.......#.......#...#.#.....#.........#.#
|
||||
#.#.###.###.#.#.#####.#.#.#.###.#.#####.#.#.###.#.###.#.###.#.###.#.###.#####.#####.#####.#####.###.#########.#.#.#
|
||||
#.....#...#.......#.#.#.......#.#.#...#.#...#.#.#.....#...#.#...#...#.#...#.......#...#.#...#...#...#.#.#.#.#.#.#.#
|
||||
###.###.#######.###.#.#.#.#.#########.#.#####.#.#.#####.#######.#####.#.#####.#.#.###.#.#######.###.#.#.#.#.#.###.#
|
||||
#.....#...#.#.#.......#.#.#.#.#.......#...#.....#.#.....#.......#.......#.#...#.#.#.#...#.....#.#.....#.#.#...#.#.#
|
||||
###.###.###.#.#######.#.#####.#####.#.#.###.#########.#.###.#.#####.#####.###.#####.#######.###.###.###.#.#.###.#.#
|
||||
#.....#.......#...#...#...#.#.#.#.#.#.#.#.......#.#...#.#.#.#...#.......#...#.......#...#.....#...#.#.........#...#
|
||||
#.#####.#######.###.#.#.###.#.#.#.#.#.#.###.#.###.#.#####.#####.#####.#####.###.#######.###.###.###.#########.#.###
|
||||
#...#...#...#.#.#...#.#.#.#.........#.....#.#.....#.......#.......#...#.............#...#...#.#.........#...#.#...#
|
||||
#.###.###.###.#.#####.#.#.#.#####.#############.#######.#####.#####.#######.###########.###.#.###.#######.###.#.###
|
||||
#...#...#...#...#.#...#...#.# S L B V G R #.#.#.#.....#.#.......#.#...#
|
||||
#.###.#.#.#####.#.###.#.###.# D M E H X Q #.#.#.#####.#.###.#####.#.###
|
||||
#.....#.#.................#.# #.........................#.#
|
||||
#.###.###.#####.#.#.#.###.### #.#.#.###.#######.###.#.#.#.#
|
||||
#.#.#.....#.#...#.#.#.#.....# RZ..#.#...#.....#.#...#.#.#.#..BE
|
||||
#.#.#####.#.#####.#.#####.### #######.#####.#.#.#######.#.#
|
||||
#.....#.#.....#.#.#.....#.#.# #.#.#.#.#.#...#.......#...#.#
|
||||
###.###.###.#.#.#.#.###.#.#.# #.#.#.###.#####.#.#######.#.#
|
||||
RI....#.....#.#.#...#.#.#.#....UW #.#.......#...#.#.#.#...#...#
|
||||
#####.###############.###.### #.###.#####.#.#####.#.#.#####
|
||||
#.....#.#.#...#.#.....#.#...# GW..........#.#.........#.#...#
|
||||
#.###.#.#.#.###.###.###.##### #.###.#.#.###.#######.###.###
|
||||
#...#...#.....#.#.......#....FM #.#...#.#.....#...#.........#
|
||||
###.###.#.#.#.#.#.#########.# ###.#######.###.###########.#
|
||||
AJ..#...#...#.#...#...#.....#.# #...#.#.#...#...#.#...#.#.#..GX
|
||||
#.#.#########.#.#.#######.#.# #####.#.#######.#.###.#.#.###
|
||||
#.....#.#.#.#.#.............# #...............#...#........DD
|
||||
#######.#.#.###########.###.# ###.#######.###.#.#.#.#.###.#
|
||||
#.....................#.#...# #.......#.....#...#.#.#.#...#
|
||||
###.###.#.#.###.#####.####### #####.#########.###.#.###.###
|
||||
GP..#...#.#.#.#.....#.#...#...# SG..#...#.....#...#.#.....#...#
|
||||
#.###.#####.#.#.#.#.###.###.# #.#.###.#.#######.#######.###
|
||||
#.#.....#.#.#.#.#.#.....#...# #.....#.#.#.#...#.#.#...#.#.#
|
||||
#.#.#####.#########.#######.# #########.#.###.#.#.#.#####.#
|
||||
#.....#...#..................SI DD....#........................UW
|
||||
#.#######.#####.###.###.##### #.###.#####.#.###.#.###.#####
|
||||
#.#.#...#...#.....#.#.#.#.#..AJ #.........#.#.#.#.#.#.....#.#
|
||||
###.#.###.#.#########.###.#.# #.#####.###.#.#.#######.###.#
|
||||
#.........#.#...#.....#.#.#.# #...#.....#.#...#.#.#.#.#....LM
|
||||
#########.#.###.#.###.#.#.#.# #########.#.#.###.#.#.#####.#
|
||||
AA......#.#.#.....#.#...#.....# #.#.#.#.#.#.#.#...#.#.#.....#
|
||||
#.#####.#.#.###.#.#.###.#.### #.#.#.#.#########.#.#.#####.#
|
||||
JO..........#...#...#.....#...# #.#.......#.#.............#.#
|
||||
#####.###############.###.#.# #.#.#.#####.###.###.#.###.#.#
|
||||
#.#.#...#.........#.#.#.#.#.# TX....#.............#.#...#...#
|
||||
#.#.#######.#.#.#.#.###.###.# #.###.#.###.#####.###########
|
||||
VH......#.....#.#.#.....#...#.# #.#...#.#...#...#.#.....#...#
|
||||
#####.#.###########.###.##### #############.#####.###.#.#.#
|
||||
#.....#.....#.#.......#.....# #.#...#...#.#.......#.#.#.#..RZ
|
||||
#.#.#######.#.#######.#.##### #.###.###.#.###.#.###.#.#.###
|
||||
#.#...........#.#............FW RN..#.....#...#.#.#.#.....#...#
|
||||
#########.###.#.#.########### #.#.#.###.###.###.#.#####.###
|
||||
#...#...#.#.....#.#.........# #...#.............#.......#.#
|
||||
#.#.#.#################.#.#.# ###############.###########.#
|
||||
AX..#...#.#...#.#...#...#.#.#..HR JO............#.#.#...........#
|
||||
#.#.###.###.#.#.#####.###.#.# #.#.#####.#.#.###.#.#.#####.#
|
||||
TX..#...#.......#...#.....#.#..EK #.#...#.#.#.......#.#...#.#..MM
|
||||
###.#.###.#.#.#.#.###.#.#.### #.###.#.#######.#.###.###.#.#
|
||||
#...#.....#.#...#.....#.....# #.#.#.....#.#...#...#.#.....#
|
||||
#####.#.#.#####.###.#######.# R Y G U A M S #.#.#.#.###.#####.#.#.###.#.#
|
||||
#.....#.#...#.....#.....#...# I Q P C X M Y #...#.#.#.....#...#.#...#.#.#
|
||||
#####.#########.###.#####.###########.#####.###.###########.#####.###########.#.#######.#.###.#.#########.#.#####.#
|
||||
#...#...#.#.......#.....#...#...#.....#.....#.....#.#.....#...#...........#...#...#...#.#.#.....#.#.......#.#.....#
|
||||
#.#.#.###.###.#.#.#######.#####.###.###.###.#####.#.###.#.#.#########.#####.#####.#.#########.###.###.#####.###.#.#
|
||||
#.#.......#...#.#.#.......#.....#.#.#.....#.#.....#...#.#.......#.#.#...#.......#.#.......#.#.#.#.....#.......#.#.#
|
||||
#.#.#.#.#####.###########.#####.#.#.#.#.#.#####.###.###.#########.#.#.#######.###.#.#######.###.###.#.###.#.#.#.#.#
|
||||
#.#.#.#...#.......#.......#.........#.#.#.....#.#.....#.........#.........#.#.#.....#.......#.......#.#.#.#.#.#.#.#
|
||||
#######.#.#.#.#####.#.#########.#############.#.#.###.#######.#####.#.#####.#.#.#######.#####.#.#.###.#.#.#######.#
|
||||
#.......#.#.#...#...#.#.........#.......#...#.#.....#.#.......#.....#...#.....#...........#.#.#.#.#.....#...#.....#
|
||||
#.#.#.#####.#.#.#####.#.#######.#.###.###.###.#.###.#.#.###.#.#.#.###.#.#####.#.###.#.#.###.###.#.#.#.#####.#####.#
|
||||
#.#.#.#.....#.#.#.....#...#.#.....#...#.......#.#...#.#...#.#.#.#...#.#.#.....#.#...#.#.......#.#.#.#...#.#.#.....#
|
||||
#.###.###.#.###.###.#.#.###.#.#.#.#.###.###.#.#######.###.#.###.#######.#.#.#.#####.#.#.#.#############.#.#####.###
|
||||
#.#.#.#.#.#...#.#...#.#.#.....#.#.#...#...#.#...#.....#...#...#...#.....#.#.#.....#.#.#.#.#.....#.#.#.......#...#.#
|
||||
###.#.#.#.#.###.#####.#############.#.#.#.#.#######.###.###.###.#############.#####.#####.###.###.#.#.#####.###.#.#
|
||||
#.......#.#.#.....#...#.#.......#...#.#.#.#.#.#.#.#...#...#.#.....#.#.#...#.....#.#.#...#...#.......#.....#...#...#
|
||||
###.###.#.###.#########.#######.#####.#.#####.#.#.#.###.#######.###.#.#.#####.###.#.#.###.###.#####.#.#.###.###.###
|
||||
#.....#.#.#.....#.....#.#.......#.#.#.#...#.......#.#.......#...#.....#.......#.........#.#.#.....#.#.#.#...#.....#
|
||||
#.#####.#.###.#.#####.#.#######.#.#.#.#.#######.#.#.###.#####.#.###.#.###.#.#####.###.#####.#.#######.###.#.#.#.###
|
||||
#.#.....#.#...#...#.......#.#.....#...#.#.#.....#...#.......#.#.....#.#...#...#.#...#...#.#.#.....#.#.#.#.#.#.#...#
|
||||
#####.#.#.###.#######.#.###.###.#.#.###.#.#####.#######.#######.#.#####.###.###.###.#####.#.#.#####.###.#######.#.#
|
||||
#.#.#.#.#.#.#.#...#...#...#.#.#.#...#.......#.#.....#.#.#...#...#.....#.#.......#.........#.#...#.#.........#.#.#.#
|
||||
#.#.#######.#####.#####.###.#.#.#########.###.#####.#.#.#.#######.#########.#.###.#########.###.#.#.#########.#.#.#
|
||||
#...#.#.#.#.....#.#...................#...#...#...#...#.....#...#.#...#...#.#.#.....#.#.......#.#.#.#.#.#.#...#.#.#
|
||||
###.#.#.#.#.###.#.#####.#############.###.#.#.#.#.###.#.#.#####.#.#.#####.###.#.###.#.#####.###.#.#.#.#.#.###.#.###
|
||||
#...........#.#.#...#...#.#.......#.#...#...#.#.#...#.#.#...#.#.......#.....#.#...#.#.#.#.#.....#.....#.#.....#...#
|
||||
#####.#.#.#.#.###.#####.#.#.#.###.#.#.#######.#.###.#.#.###.#.#####.###.###.#.#.###.#.#.#.#.#####.###.#.#.#########
|
||||
#.#...#.#.#.............#...#...#...#.....#...#...#...#.#.#.#...#...#...#.#...#.#...................#.............#
|
||||
#.#####.#######.#.###.###.#.#.#####.#.#######.###.#####.#.###.#.#.#####.#.###.#.#.#####.###.#####.###.#.###.#.#####
|
||||
#.......#.......#...#...#.#.#.#.........#.....#.....#.......#.#.......#.....#.#.#.....#...#.....#...#.#...#.#.....#
|
||||
###################################.#######.###.#########.#######.#########.#######.###############################
|
||||
Y S R S F F H
|
||||
Q Y Q I M W R
|
19
inputs/20s1.txt
Normal file
19
inputs/20s1.txt
Normal file
@ -0,0 +1,19 @@
|
||||
A
|
||||
A
|
||||
#######.#########
|
||||
#######.........#
|
||||
#######.#######.#
|
||||
#######.#######.#
|
||||
#######.#######.#
|
||||
##### B ###.#
|
||||
BC...## C ###.#
|
||||
##.## ###.#
|
||||
##...DE F ###.#
|
||||
##### G ###.#
|
||||
#########.#####.#
|
||||
DE..#######...###.#
|
||||
#.#########.###.#
|
||||
FG..#########.....#
|
||||
###########.#####
|
||||
Z
|
||||
Z
|
37
inputs/20s2.txt
Normal file
37
inputs/20s2.txt
Normal file
@ -0,0 +1,37 @@
|
||||
A
|
||||
A
|
||||
#################.#############
|
||||
#.#...#...................#.#.#
|
||||
#.#.#.###.###.###.#########.#.#
|
||||
#.#.#.......#...#.....#.#.#...#
|
||||
#.#########.###.#####.#.#.###.#
|
||||
#.............#.#.....#.......#
|
||||
###.###########.###.#####.#.#.#
|
||||
#.....# A C #.#.#.#
|
||||
####### S P #####.#
|
||||
#.#...# #......VT
|
||||
#.#.#.# #.#####
|
||||
#...#.# YN....#.#
|
||||
#.###.# #####.#
|
||||
DI....#.# #.....#
|
||||
#####.# #.###.#
|
||||
ZZ......# QG....#..AS
|
||||
###.### #######
|
||||
JO..#.#.# #.....#
|
||||
#.#.#.# ###.#.#
|
||||
#...#..DI BU....#..LF
|
||||
#####.# #.#####
|
||||
YN......# VT..#....QG
|
||||
#.###.# #.###.#
|
||||
#.#...# #.....#
|
||||
###.### J L J #.#.###
|
||||
#.....# O F P #.#...#
|
||||
#.###.#####.#.#####.#####.###.#
|
||||
#...#.#.#...#.....#.....#.#...#
|
||||
#.#####.###.###.#.#.#########.#
|
||||
#...#.#.....#...#.#.#.#.....#.#
|
||||
#.###.#####.###.###.#.#.#######
|
||||
#.#.........#...#.............#
|
||||
#########.###.###.#############
|
||||
B J C
|
||||
U P P
|
37
inputs/20s3.txt
Normal file
37
inputs/20s3.txt
Normal file
@ -0,0 +1,37 @@
|
||||
Z L X W C
|
||||
Z P Q B K
|
||||
###########.#.#.#.#######.###############
|
||||
#...#.......#.#.......#.#.......#.#.#...#
|
||||
###.#.#.#.#.#.#.#.###.#.#.#######.#.#.###
|
||||
#.#...#.#.#...#.#.#...#...#...#.#.......#
|
||||
#.###.#######.###.###.#.###.###.#.#######
|
||||
#...#.......#.#...#...#.............#...#
|
||||
#.#########.#######.#.#######.#######.###
|
||||
#...#.# F R I Z #.#.#.#
|
||||
#.###.# D E C H #.#.#.#
|
||||
#.#...# #...#.#
|
||||
#.###.# #.###.#
|
||||
#.#....OA WB..#.#..ZH
|
||||
#.###.# #.#.#.#
|
||||
CJ......# #.....#
|
||||
####### #######
|
||||
#.#....CK #......IC
|
||||
#.###.# #.###.#
|
||||
#.....# #...#.#
|
||||
###.### #.#.#.#
|
||||
XF....#.# RF..#.#.#
|
||||
#####.# #######
|
||||
#......CJ NM..#...#
|
||||
###.#.# #.###.#
|
||||
RE....#.# #......RF
|
||||
###.### X X L #.#.#.#
|
||||
#.....# F Q P #.#.#.#
|
||||
###.###########.###.#######.#########.###
|
||||
#.....#...#.....#.......#...#.....#.#...#
|
||||
#####.#.###.#######.#######.###.###.#.#.#
|
||||
#.......#.......#.#.#.#.#...#...#...#.#.#
|
||||
#####.###.#####.#.#.#.#.###.###.#.###.###
|
||||
#.......#.....#.#...#...............#...#
|
||||
#############.#.#.###.###################
|
||||
A O F N
|
||||
A A D M
|
1
inputs/21p.txt
Normal file
1
inputs/21p.txt
Normal file
File diff suppressed because one or more lines are too long
100
inputs/22p.txt
Normal file
100
inputs/22p.txt
Normal file
@ -0,0 +1,100 @@
|
||||
deal into new stack
|
||||
cut -2732
|
||||
deal into new stack
|
||||
deal with increment 57
|
||||
cut 5974
|
||||
deal into new stack
|
||||
deal with increment 32
|
||||
cut -1725
|
||||
deal with increment 24
|
||||
cut 6093
|
||||
deal with increment 6
|
||||
cut -2842
|
||||
deal with increment 14
|
||||
cut 2609
|
||||
deal with increment 12
|
||||
cut -6860
|
||||
deal with increment 51
|
||||
cut -6230
|
||||
deal with increment 61
|
||||
cut 3152
|
||||
deal with increment 28
|
||||
cut 2202
|
||||
deal into new stack
|
||||
deal with increment 60
|
||||
cut 433
|
||||
deal into new stack
|
||||
cut -6256
|
||||
deal with increment 13
|
||||
deal into new stack
|
||||
cut 8379
|
||||
deal into new stack
|
||||
deal with increment 54
|
||||
cut 1120
|
||||
deal with increment 16
|
||||
cut -5214
|
||||
deal with increment 63
|
||||
deal into new stack
|
||||
cut -8473
|
||||
deal with increment 11
|
||||
cut 228
|
||||
deal with increment 45
|
||||
cut -6755
|
||||
deal with increment 50
|
||||
cut -3391
|
||||
deal with increment 44
|
||||
cut -1341
|
||||
deal with increment 28
|
||||
cut -6788
|
||||
deal with increment 52
|
||||
cut 3062
|
||||
deal with increment 41
|
||||
cut 4541
|
||||
deal with increment 57
|
||||
cut -7962
|
||||
deal with increment 56
|
||||
cut 9621
|
||||
deal with increment 57
|
||||
cut 3881
|
||||
deal with increment 36
|
||||
deal into new stack
|
||||
deal with increment 45
|
||||
cut 522
|
||||
deal with increment 9
|
||||
deal into new stack
|
||||
deal with increment 60
|
||||
deal into new stack
|
||||
deal with increment 12
|
||||
cut -9181
|
||||
deal with increment 63
|
||||
deal into new stack
|
||||
deal with increment 14
|
||||
cut -2906
|
||||
deal with increment 10
|
||||
cut 848
|
||||
deal with increment 75
|
||||
cut 798
|
||||
deal with increment 29
|
||||
cut 1412
|
||||
deal with increment 10
|
||||
deal into new stack
|
||||
cut -5295
|
||||
deal into new stack
|
||||
cut 4432
|
||||
deal with increment 72
|
||||
cut -7831
|
||||
deal into new stack
|
||||
cut 6216
|
||||
deal into new stack
|
||||
deal with increment 7
|
||||
cut -1720
|
||||
deal into new stack
|
||||
cut -5465
|
||||
deal with increment 70
|
||||
cut -5173
|
||||
deal with increment 7
|
||||
cut 3874
|
||||
deal with increment 65
|
||||
cut 921
|
||||
deal with increment 8
|
||||
cut -3094
|
3
inputs/22s1.txt
Normal file
3
inputs/22s1.txt
Normal file
@ -0,0 +1,3 @@
|
||||
deal with increment 7
|
||||
deal into new stack
|
||||
deal into new stack
|
3
inputs/22s2.txt
Normal file
3
inputs/22s2.txt
Normal file
@ -0,0 +1,3 @@
|
||||
cut 6
|
||||
deal with increment 7
|
||||
deal into new stack
|
3
inputs/22s3.txt
Normal file
3
inputs/22s3.txt
Normal file
@ -0,0 +1,3 @@
|
||||
deal with increment 7
|
||||
deal with increment 9
|
||||
cut -2
|
10
inputs/22s4.txt
Normal file
10
inputs/22s4.txt
Normal file
@ -0,0 +1,10 @@
|
||||
deal into new stack
|
||||
cut -2
|
||||
deal with increment 7
|
||||
cut 8
|
||||
cut -4
|
||||
deal with increment 7
|
||||
cut 3
|
||||
deal with increment 9
|
||||
deal with increment 3
|
||||
cut -1
|
1
inputs/23p.txt
Normal file
1
inputs/23p.txt
Normal file
File diff suppressed because one or more lines are too long
5
inputs/24p.txt
Normal file
5
inputs/24p.txt
Normal file
@ -0,0 +1,5 @@
|
||||
##..#
|
||||
...##
|
||||
.#.##
|
||||
#..#.
|
||||
..#..
|
5
inputs/24s1.txt
Normal file
5
inputs/24s1.txt
Normal file
@ -0,0 +1,5 @@
|
||||
....#
|
||||
#..#.
|
||||
#..##
|
||||
..#..
|
||||
#....
|
5
inputs/24s2.txt
Normal file
5
inputs/24s2.txt
Normal file
@ -0,0 +1,5 @@
|
||||
.....
|
||||
.....
|
||||
.....
|
||||
#....
|
||||
.#...
|
59
main.go
59
main.go
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -26,8 +27,10 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
flagPart1 = flag.Bool("part1", false, "whether to run part1 or not; if no flags are present, all parts are run")
|
||||
flagPart2 = flag.Bool("part2", false, "whether to run part2 or not; if no flags are present, all parts are run")
|
||||
flagPart1 = flag.Bool("part1", false, "whether to run part1 or not; if no flags are present, all parts are run")
|
||||
flagPart2 = flag.Bool("part2", false, "whether to run part2 or not; if no flags are present, all parts are run")
|
||||
flagCpuProfile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
flagMemProfile = flag.String("memprofile", "", "write memory profile to file")
|
||||
)
|
||||
|
||||
var dayMap = []day{
|
||||
@ -35,11 +38,42 @@ 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{},
|
||||
&days.Day19{},
|
||||
&days.Day20{},
|
||||
&days.Day21{},
|
||||
&days.Day22{},
|
||||
&days.Day23{},
|
||||
&days.Day24{},
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *flagCpuProfile != "" {
|
||||
f, err := os.Create(*flagCpuProfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
arg := strconv.Itoa(len(dayMap))
|
||||
flagArgs := flag.Args()
|
||||
if len(flagArgs) > 0 && len(flagArgs[0]) > 0 {
|
||||
@ -64,7 +98,14 @@ func main() {
|
||||
solve(dayMap[iArg-1])
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
if *flagMemProfile != "" {
|
||||
f, err := os.Create(*flagMemProfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.WriteHeapProfile(f)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func solve(d day) {
|
||||
@ -84,6 +125,11 @@ func solve(d day) {
|
||||
part1Text = d.Part1()
|
||||
}
|
||||
part1Time := time.Since(part1Start)
|
||||
if runPart1 {
|
||||
fmt.Println(part1Header)
|
||||
fmt.Println(">", part1Text)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
part2Start := time.Now()
|
||||
var part2Text string
|
||||
@ -91,17 +137,12 @@ func solve(d day) {
|
||||
part2Text = d.Part2()
|
||||
}
|
||||
part2Time := time.Since(part2Start)
|
||||
|
||||
if runPart1 {
|
||||
fmt.Println(part1Header)
|
||||
fmt.Println(">", part1Text)
|
||||
fmt.Println()
|
||||
}
|
||||
if runPart2 {
|
||||
fmt.Println(part2Header)
|
||||
fmt.Println(">", part2Text)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
fmt.Print(utilities.ColorBrightBlack)
|
||||
fmt.Println("Parsed in", parseTime)
|
||||
if runPart1 {
|
||||
|
22
utilities/array.go
Normal file
22
utilities/array.go
Normal file
@ -0,0 +1,22 @@
|
||||
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
|
||||
}
|
||||
|
||||
func AddToArray[V comparable, T ~[]V](arr *T, val V) bool {
|
||||
for _, v := range *arr {
|
||||
if v == val {
|
||||
return false
|
||||
}
|
||||
}
|
||||
*arr = append(*arr, val)
|
||||
return true
|
||||
}
|
26
utilities/bisect.go
Normal file
26
utilities/bisect.go
Normal file
@ -0,0 +1,26 @@
|
||||
package utilities
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Bisect takes a known-good low and known-bad high value as the bounds
|
||||
// to bisect, and a function to test each value for success or failure.
|
||||
// If the function succeeds, the value is adjusted toward the maximum,
|
||||
// and if the function fails, the value is adjusted toward the minimum.
|
||||
// The final value is returned when the difference between the success
|
||||
// and the failure is less than or equal to the acceptance threshold
|
||||
// (usually 1, for integers).
|
||||
func Bisect[T Number](low, high, threshold T, tryFunc func(val T) bool) T {
|
||||
for T(math.Abs(float64(high-low))) > threshold {
|
||||
currVal := low + ((high - low) / 2)
|
||||
success := tryFunc(currVal)
|
||||
if success {
|
||||
low = currVal
|
||||
} else {
|
||||
high = currVal
|
||||
}
|
||||
}
|
||||
|
||||
return low
|
||||
}
|
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,292 @@
|
||||
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
|
||||
printASCII bool
|
||||
feedInput []rune
|
||||
}
|
||||
|
||||
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() {
|
||||
wiped := false
|
||||
if len(p.memory) != len(p.program) {
|
||||
wiped = true
|
||||
p.memory = nil
|
||||
}
|
||||
p.init()
|
||||
if !wiped {
|
||||
copy(p.memory, p.program)
|
||||
}
|
||||
p.relativeBase = 0
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) Run() int64 {
|
||||
return p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) int64 {
|
||||
p.init()
|
||||
|
||||
inputsRequested := 0
|
||||
lastOutput := int64(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)
|
||||
var inputVal int64
|
||||
if len(p.feedInput) > 0 {
|
||||
inputVal = int64(p.feedInput[0])
|
||||
p.feedInput = p.feedInput[1:]
|
||||
} else {
|
||||
inputVal = inputFunc(inputsRequested)
|
||||
}
|
||||
if p.printASCII && inputVal <= 255 {
|
||||
fmt.Printf("%c", rune(inputVal))
|
||||
}
|
||||
p.setMemory(int(param1), inputVal, paramModes[0])
|
||||
|
||||
instructionPointer += 1
|
||||
|
||||
case opOutput:
|
||||
param1 := p.GetMemory(instructionPointer)
|
||||
param1Val := p.getParamValue(int(param1), paramModes[0])
|
||||
if p.printASCII && param1Val <= 255 {
|
||||
fmt.Printf("%c", rune(param1Val))
|
||||
}
|
||||
outputFunc(param1Val, p.makeState(instructionPointer))
|
||||
lastOutput = param1Val
|
||||
|
||||
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
|
||||
|
||||
return lastOutput
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) Stop() {
|
||||
p.haltRequested = true
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) SetDebugASCIIPrint(enable bool) {
|
||||
p.printASCII = enable
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) FeedInputString(str string) {
|
||||
p.feedInput = make([]rune, len(str))
|
||||
copy(p.feedInput, []rune(str))
|
||||
}
|
||||
|
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
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user