14 Commits

Author SHA1 Message Date
788d22f33c Merge branch 'develop' into dev/19 2022-06-21 01:18:12 -05:00
34ece5dd77 Revert "Merge branch 'develop' into dev/19"
This reverts commit 5247ae9d72, reversing
changes made to 9947a9b559.
2022-06-21 01:18:05 -05:00
e153d022a7 Intcode Reset optimization
Initially I noticed that I was copying twice unnecessarily (once in init() after nulling out memory, and again after returning from init()). After cleaning that up, I realized that we don't need to create a new buffer at all if the program never malloc-ed, so sometimes we can skip the re-init and we can always avoid the double-copy. I don't know if this is actually measurable anywhere, but I spot-checked some results and I still seem to be getting the same answers, so I'm gonna roll with it.
2022-06-21 01:17:33 -05:00
b97ec2eb17 Add bisect utility
This is too common of an optimization to not have this readily accessible. And I kinda like how this worked out, too. Go is fun.
2022-06-21 01:17:31 -05:00
de07c7c987 First optimizations
This gets runtime down to about a quarter of what it was. I need to see if I can apply bisect to the X value, but I'm not sure I understand how/if that can work.
2022-06-21 01:16:42 -05:00
5247ae9d72 Merge branch 'develop' into dev/19 2022-06-21 00:22:40 -05:00
dfc2eb6e4f Intcode Reset optimization
Initially I noticed that I was copying twice unnecessarily (once in init() after nulling out memory, and again after returning from init()). After cleaning that up, I realized that we don't need to create a new buffer at all if the program never malloc-ed, so sometimes we can skip the re-init and we can always avoid the double-copy. I don't know if this is actually measurable anywhere, but I spot-checked some results and I still seem to be getting the same answers, so I'm gonna roll with it.
2022-06-21 00:21:58 -05:00
94471df109 Add bisect utility
This is too common of an optimization to not have this readily accessible. And I kinda like how this worked out, too. Go is fun.
2022-06-21 00:12:06 -05:00
9947a9b559 Day 19 functional
We're at about 1s runtime on my macbook, but we do get the right answer now.
2022-06-21 00:11:22 -05:00
cbaab27054 Day 19 almost
Part 1 works, part 2 is giving me trouble. I need to find a better way to validate whether 100x100 can fit, and then something faster to figure out the minimum position. In other words, the entire problem.
2022-06-20 08:58:58 -05:00
23bf2e9d84 Day 18 solution
This one was a doozy and took far more time than I'd like to admit. I hope it's the hardest problem of the year. My original solution gave correct answers, but took on the order of 3+ minutes to run, even with memoization (it wasn't finishing any time soon without it). I then tried dropping in some A* and Dijkstra libraries, but wasn't really happy with how things were progressing with them. Some research pointed me toward double-ended queues and priority queues as better solutions, which I should have come up with my own since they've been used along with memoization in other AoC's, and dropping those in took the runtimes down to 4-15 seconds on my m1 macbook air. Once I swapped out the memoized data structures from arrays to maps, the runtime finally dropped to a much more palatable 50-180 millisecond range.

I'm always suspicious when my solution is hundreds of lines of code, though, since you tend to see much more terse solutions from others in the AoC subreddit, but I attribute at least some of the bloat to "Go things" like how maps and arrays usually need to be "make"d first, how there's no easy "list comprehension" or "linq" style data structure queries, etc.

Finally: note that I've seen _dramatically_ different runtimes based on the input. One set of input I checked against ran in 30ms/10ms while another ran in 180ms/54ms. I guess it's never been promised that all inputs are created equally...
2022-06-18 23:13:19 -05:00
a0867490c9 Add utility for array AddUnique 2022-06-18 23:07:38 -05:00
3d3ea6e266 Add support for cpu and memory profiling
My day 18 was slow and I wasn't completely certain where it was all coming from, so I dove into Go's profiling stuff. It was super helpful in identifying the problem and giving me easy wins that took runtime from 4.6s/14.4s (part 1/part 2) to 180ms/50ms just from swapping some arrays for maps, which the profile pointed out very clearly.
2022-06-18 23:07:38 -05:00
4b5bd0d4e0 Display part1 output as soon as it's ready
When we start having problems that take a while to run, it sucks to have to wait for everything to finish before we see any output.
2022-06-18 22:49:28 -05:00
10 changed files with 315 additions and 141 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
__debug_bin __debug_bin
aoc2019 aoc2019
debug.test debug.test
*.*prof

View File

@ -104,26 +104,10 @@ func (d *Day14) Part1() string {
func (d *Day14) Part2() string { func (d *Day14) Part2() string {
oreAvailable := int64(1000000000000) oreAvailable := int64(1000000000000)
estimate := oreAvailable / d.getOreRequiredForFuel(1) estimate := oreAvailable / d.getOreRequiredForFuel(1)
lastSuccess := u.Bisect(estimate, estimate*2, 1, func(val int64) bool {
high := estimate * 2 oreConsumed := d.getOreRequiredForFuel(val)
low := estimate return oreConsumed < oreAvailable
})
lastSuccess := low
lastFailure := high
fuelProduced := low
for math.Abs(float64(lastFailure-lastSuccess)) > 1 {
oreConsumed := d.getOreRequiredForFuel(fuelProduced)
adjustment := (lastFailure - lastSuccess) / 2
if oreConsumed < oreAvailable {
lastSuccess = fuelProduced
} else {
lastFailure = fuelProduced
adjustment = -adjustment
}
fuelProduced += adjustment
}
return fmt.Sprintf("Maximum fuel we can make from 1 trillion ore: %s%d%s", u.TextBold, lastSuccess, u.TextReset) return fmt.Sprintf("Maximum fuel we can make from 1 trillion ore: %s%d%s", u.TextBold, lastSuccess, u.TextReset)
} }

View File

@ -28,16 +28,31 @@ var (
} }
) )
type reachableKeysMemo struct {
pos rune
keysFound int
}
type minStepsMemo struct {
pos string
keysToFind int
keysFound int
}
type Day18 struct { type Day18 struct {
entrance day18Vec entrance day18Vec
grid [][]day18Cell grid [][]day18Cell
doors map[day18Vec]int doors map[day18Vec]int
keys map[day18Vec]int keys map[day18Vec]int
knownReachableKeys map[reachableKeysMemo][]u.Pair[rune, int]
knownMinimumSteps map[minStepsMemo]int
} }
func (d *Day18) Parse() { func (d *Day18) Parse() {
d.doors = make(map[day18Vec]int) d.doors = make(map[day18Vec]int)
d.keys = 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") lines := u.GetStringLines("18p")
d.grid = make([][]day18Cell, len(lines)) d.grid = make([][]day18Cell, len(lines))
@ -155,17 +170,17 @@ type day18PriorityQueue struct {
distance int distance int
neighbor rune neighbor rune
} }
type PriorityQueueHeap []day18PriorityQueue type day18PriorityQueueHeap []day18PriorityQueue
func (h PriorityQueueHeap) Len() int { return len(h) } func (h day18PriorityQueueHeap) Len() int { return len(h) }
func (h PriorityQueueHeap) Less(i, j int) bool { return h[i].distance < h[j].distance } func (h day18PriorityQueueHeap) Less(i, j int) bool { return h[i].distance < h[j].distance }
func (h PriorityQueueHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h day18PriorityQueueHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *PriorityQueueHeap) Push(x any) { func (h *day18PriorityQueueHeap) Push(x any) {
*h = append(*h, x.(day18PriorityQueue)) *h = append(*h, x.(day18PriorityQueue))
} }
func (h *PriorityQueueHeap) Pop() any { func (h *day18PriorityQueueHeap) Pop() any {
old := *h old := *h
n := len(old) n := len(old)
x := old[n-1] x := old[n-1]
@ -173,26 +188,19 @@ func (h *PriorityQueueHeap) Pop() any {
return x return x
} }
type reachableKeysMemo struct {
pos rune
keysFound int
}
var knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int])
func (d Day18) reachableKeys(inPos rune, keysFound int, graph day18Graph) []u.Pair[rune, int] { func (d Day18) reachableKeys(inPos rune, keysFound int, graph day18Graph) []u.Pair[rune, int] {
memo := reachableKeysMemo{ memo := reachableKeysMemo{
pos: inPos, pos: inPos,
keysFound: keysFound, keysFound: keysFound,
} }
if v, exists := knownReachableKeys[memo]; exists { if v, exists := d.knownReachableKeys[memo]; exists {
return v return v
} }
ret := make([]u.Pair[rune, int], 0) ret := make([]u.Pair[rune, int], 0)
distance := make(map[rune]int) distance := make(map[rune]int)
ih := make(PriorityQueueHeap, 0) ih := make(day18PriorityQueueHeap, 0)
for _, p := range graph[inPos] { for _, p := range graph[inPos] {
ih = append(ih, day18PriorityQueue{ ih = append(ih, day18PriorityQueue{
@ -229,25 +237,17 @@ func (d Day18) reachableKeys(inPos rune, keysFound int, graph day18Graph) []u.Pa
} }
} }
knownReachableKeys[memo] = ret d.knownReachableKeys[memo] = ret
return ret return ret
} }
type minStepsMemo struct {
pos string
keysToFind int
keysFound int
}
var knownMinimumSteps = make(map[minStepsMemo]int, 0)
func (d Day18) minimumSteps(inPos string, keysToFind int, keysFound int, graph day18Graph) int { func (d Day18) minimumSteps(inPos string, keysToFind int, keysFound int, graph day18Graph) int {
memo := minStepsMemo{ memo := minStepsMemo{
pos: inPos, pos: inPos,
keysToFind: keysToFind, keysToFind: keysToFind,
keysFound: keysFound, keysFound: keysFound,
} }
if v, exists := knownMinimumSteps[memo]; exists { if v, exists := d.knownMinimumSteps[memo]; exists {
return v return v
} }
@ -278,7 +278,7 @@ func (d Day18) minimumSteps(inPos string, keysToFind int, keysFound int, graph d
} }
} }
knownMinimumSteps[memo] = int(best) d.knownMinimumSteps[memo] = int(best)
return int(best) return int(best)
} }
@ -335,8 +335,8 @@ func (d *Day18) Part2() string {
// d.Draw(grid, d.keys, d.doors, entrances...) // d.Draw(grid, d.keys, d.doors, entrances...)
// clear memoized maps that (might have) came from part1 // clear memoized maps that (might have) came from part1
knownMinimumSteps = make(map[minStepsMemo]int) d.knownMinimumSteps = make(map[minStepsMemo]int)
knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int]) d.knownReachableKeys = make(map[reachableKeysMemo][]u.Pair[rune, int])
graph := d.buildGraph(entrances, d.keys, d.doors, grid) graph := d.buildGraph(entrances, d.keys, d.doors, grid)
minSteps := d.minimumSteps("1234", len(d.keys), 0, graph) minSteps := d.minimumSteps("1234", len(d.keys), 0, graph)

122
days/19.go Normal file
View File

@ -0,0 +1,122 @@
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
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
y := u.Bisect(startY+100, 9999, threshold, func(y int) bool {
foundX := false
for x := startX; ; x++ {
if !f(x, y) {
if !foundX {
continue
} else {
return true
}
}
if !foundX {
foundX = true
}
if !f(x+99, y) {
return true
}
if !f(x, y+99) {
continue
}
lastGoodX = x
return false
}
})
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)
}

View File

@ -1,81 +1,81 @@
################################################################################# #################################################################################
#...#.........P...................#.....#.........#.......#.........#...........# #...............#.......#...............#.........#.......#.......#.....#.......#
#.###.#############.#.###########.#.#.###.#########.###.###.#######.#.########### #.#########.#.###.#####.#.#.#######.#####.#######.#.#######.#.###.###.#.#.#####.#
#.#...#.#...V.....#.#..t..#.......#.#..a#...........#.#..c..#...#.#.#...........# #.#.#.....#.#.#...#...#..f#...#.....#...#...#.....#.........#...#.....#...#m....#
#.#.###.#.#######.#####.#.#####.#######.#.###########.#######.#.#.#.###########.# #.#.#.###.###.#.#####.#######.#######.#.#.#.#.#######.#########.###########.#####
#...#...#...#.#...#.J.#.#.....#.........#.......#.......#.....#.#.#.......#...#.# #...#...#.#...#.......#.....#.#.......#.#.#.#...#...#...#.......#..h......#.....#
#Z###.#####.#.#.###.#.###.###.#################.#.###.#.#.#####.#.#######.#.#.#.# ###.###.#.#.#########.#.###.#T#.#######.###.###.#B#.#.###.#######.#######.#####.#
#.....#...#.#.......#...#...#.#...#.....#...#.#.#.#...#.#...#.....#.......#.#.#.# #...#...#...#.....#...#...#.#...#.....#.#...#.#...#.#.#...#.........#...#.......#
###.###.#.#.###########.###.#.#.#.#.###.#.#.#.#.#.#.###.###.#######.#######.#.#.# #####.#######.###.#.###.#.#######.###.#.#.###.#####.###.#.###########.#.#######.#
#.#.#...#..y#.........#...#.#...#...#...#.#...#.#.#.#.......#.......#.......#...# #...#...#.....#.#...#.#.#.....#...#.....#.#.....#...#...#.#...........#.#.....#.#
#.#.#.#######.#######.###.#######.###.###.###.#.###.#######.#.#######.#########.# #.#.###.#.#####.#####.#.#####.#.###.#####.#.###.#.###.#####.###########.#.###.#.#
#.#.#..q........#.....#.#...#.E.#...#...#.#...#...#.....#.#.#.#...........#...#.# #.#.....#.#.....#.........#...#...#.#...#.#...#..x#...W.....#.....#.....#.#...#.#
#.#.#############.#####.###.#.#.#######.#.###.###.#.###.#.#.#.#####.#####.#.#.#.# #.#######.###.#.#########.#.#####.###.#.#.###.#######.#######.###.#.#####.#.#####
#.#...F.......#...#...#.......#.........#...#.#...#.#...#.#.#.....#.#.....#.#...# #.........#...#.......#.#.#.#...#.....#.#.#.#.#.....#...#.....#...#.#.....#.....#
#.#########.###.###.#S###################.#I###.#####.###.#.#####.#.#.#########.# #.#########O#########.#.#.#.#.#.#.#####.#.#.#.###.#.#.###.#####.###.#.#########.#
#...#...#...#...#...#....u......#.#.....#.#...#.#...#.#...#.....#.#.#.#.......#.# #.#.........#.........#...#.#.#.#...#.#.#.#.......#.#.#...#...#.#.......#.....#.#
#.###.#.#.###.###.#############.#.#.###.#####.#.#.#.#.#.#######.#.#.#.#.#####.#.# #.#####.#########.#########.#.#.###.#.#.#.#########.###.###.###.#####.###.###.#.#
#.#...#.#.#.#.#s..#...#hG.#...#.#.#...#.#.....#...#...#.#.......#.#.#...#...#.#.# #.....#...#.....#.#.........#.#.#.....#.#.....#.....#...#...........#.#...#e..#.#
#.#.###.#.#.#O#.###.#.#.#.#.#.#.#.#.###.#.###.#########.#.#######.###.###.###.#.# #####.###.#K###.#.#####.#####.#.#######.#####.#####.#.#.###########.###.###.###.#
#m..#.#...#.#.#.#...#...#...#g#.#.#.#...#.#.#.#.........#.#.#...#...#.....#...#.# #...#.....#.#...#.......#.....#.#.......#.....#...#...#.#.........#.....#.#.#...#
#.###.#####.#.#.#H###########.#.#.#.#.###.#.#.###.#.#####.#.#.#.#.#.#.#####.###.# #.#####.###.#.#########.#.#####.#.#####.#.#####.#.#######.#####.#.#######.#.#.#.#
#.#.........#...#.....#...#...#.#...#...#.#...#...#.#...#.#.#.#.#.#.#.#..w#.#.#.# #.#j..#.#...#a..#.....#.#.#.......#.....#.......#...........#.#.#.......#.#...#.#
#.#.#####.#.#############.#.###U###.###.#.#.###.###.#.#.#.#.###.###.#.#.#.#.#.#.# #.#.#.#.#.#####.#.#####.#.#############.#.###################.#########.#.#####.#
#.#.....#.#.#.....#.......#.#.....#.#...#.#.....#...#.#.#.#...#...#.#.#.#...#...# #...#.#.#.#...#...#.....#.#..z..#.....#.#.....#.......#.....#...#...#...#...#...#
#.#######.#.###.#.#####.###.#####.###.#.#.#######.###.#.#.#.#####.#.###.#####.### #.###.#.#.###.#####.#####.#.###.#.###.#######.#.#.#####.###.###.#.#.#.###.###.###
#.#.......#.....#.....#...#.#...#b#...#.#.#.#.....#...#.....#.....#...#.#.....#.# #.#...#.#.....#.#...#...#.#...#.#.#.#...#.....#.#.....#...#.....#.#...#.#...#...#
#.#.#################.#.#.#.#.#.#.#.###.#.#.#.#####.#########.#######.#.#.#####.# ###.###.#####.#.#.###.#.#.###.#.#.#.###.#.###########.###.#######.#####.#.#.###.#
#.#.#.......#.......#.#.#.#.B.#...#.#.#.#.#.....#...#.....#...#.......#.#...#...# #...#...#...#.#.......#.#.....#.#.....#.#.#.............#...#...#...#.....#.#...#
#.#.#.#######.###.###.#.#.#########.#.#.#.#######.###.#.###.#####.#.###N###.#.### #.#.#.#####.#.#############.###.###.###.#.#.#########.#####.###.#.#.#####.#.#.###
#.#.#...#.....#...#...#.#...........#.#.#.......#.#...#.#...#...#.#.#...#...#...# #.#.#.#.....#.............#...#.....#...#.#.....#...#.#.....#...#.#.#...#.#.#.#.#
#.#.#.#.#.#####.###.###.###########.#.#.#.#####.#.#.###.#.###.#.###.#.###.###.#.# #.###.#.#.###############.###.#####.#.#.#.#####.#.#.#.#.#####.###.#.#.#.#.#.#.#.#
#...#.#.#.#...#.....#.#.#...#.......#...#.#..r#...#.#...#.....#.....#.#.#...#.#.# #.#...#.#.......#.........#...#...#.#.#.#.#.....#.#...#.#.........#.#.#.#.#...#.#
#######.#.###.#######.#.###.#.#######.###.###.#######.#.#############.#.###.#.#.# #.#.#######.###.#.#########.###.#.###.#.#.#.###########.#.#########.#.#.#####.#.#
#.......#...#.......#.#...#.#.#.....#.#.#.....#.......#.......#.......#...#.#.#.# #.#.......#...#.#.#.......#...#.#.#...#.#.#...#.......#.#.#.......#...#.#...#c..#
###.###.###.#.#####.#.###.#.#.###.#.#.#.#####.#.#.###########.###.#####.#.#.###.# #.#######.#.#.###.###.###.#####.#.#.###.#.###.#.#####.#.###.#####.#.###.#.#.###.#
#...#...#...#...#.#.#.......#...#.#.#.#.#.#...#.#...#...#...#...#.#.....#.#...#.# #.L..q..#.#.#...#...#.#.#.....#.#...#...#...#.....#...#.....#.....#...#...#.#...#
#D###.###.###.#.#.#.###########.#.###.#.#.#.###.###.#.#.#.#.###.#.#.###.#####.#.# #.#######.#####.###.#.#.#####.#.#####.#####.#######S#########.#############.#.###
#...#...#.#...#.#.#...........#.#.#...#.#...#...#...#.#...#...#...#.#.#.......#.# #...#...#.#.......#...#.#.....#.#...#...#...#.....#.....#...#.#.....#.....#k#...#
#.#.#####.#####.#.###########.#.#.#.###.#.#######.###.#######.#####.#.#########.# #.#.#.#.#.#.#####.#####.#.#####.#.#.###.#.###.###.###.#.###.#.#.###.#.###.#.###.#
#.#.............#...............#.................#.........#.................M.# #.#...#.....#...........#.......#.#...........#.......#.....#...#.....#.....#...#
#######################################.@.####################################### #######################################.@.#######################################
#.#...#.......#...............................#.........#.........#..d#...#.....# #.#...#...........#u....#...#.......#...............#.....#...................#.#
#.#.#.#.#####.#.#######################.###.#.#.#######.#.###.###.###.#.#.#.#.#K# #.#.#.#.#####.###.#.#.#.#.#.#.#.#####.#.#####.#####.#.###.#.###.#############.#.#
#...#...#...#.#.#...#.................#.#...#.#.#.#.....#...#.#.#.....#.#...#.#.# #.#.#...#...#...#.#.#.#.#.#...#.#s....#.#.....#...#.#.#.#..p#.#.#.....#.....#...#
#.#########.#.#.#.#.#.###############.#.#.###.#.#.#.#########.#.#####.#.#####.### #.#.#######.###.###.#.###.#####.#.#####.#.#######.#.#.#.#####.#.#.###.#.###.###.#
#.....#...#.#.#.#.#.#.#...#.........#...#.#...#.#.#.......#...#.#.....#.....#...# #...#.........#.#...#.#...#...#...#...#.#...#.....#...#.......#.#.#.#.....#.#.#.#
#####.#.#.#.#.#.#.#.#.#.#.#.#####.#####.#.#.###.#.#######.#.###.#.#########.###.# #.###.#.#####.#.#.###.#.###.#######.#.#.#.#.#.###.#####.#######.#.#.#######.#.#.#
#...#.#.#...#.....#.#.#.#.#...#...#...#.#.#.#...#...........#.....#.......#.#...# #...#.#.#.....#...#...#.#...#.....#.#...#.#.#.#...#.....#.......#.#...#.V...#...#
#.#.#.#.###.#########.#.#.###.#####.#.#.#.#.###.###.###########.###.###.###.#.#.# ###.###.#.#########.###.#.#.#.###.#.###.###.#.#####.#.###.#######.###.#.#####.###
#.#.#...#.W...#.......#.#...#.......#.#.#.#...#...#.#...#.#...#.#...#l#.#...#.#.# #.#.....#.#.....#...#.....#.#...#...#...#...#.#.....#.......#...#.#...#.#.....#.#
#.###.#########.#######.###.#.#######.#.#.###.###.#.#.#.#.#.#.###.###.#.#.###.#.# #.#######.#N#.#.#.#.#.#########.#.#######.###.#.#############.#.#.#.#.#.#.#####.#
#.....#.........#...#...#...#.......#...#.#...#...#...#...#.#.#.......#.#...#.#.# #.......#.#.#.#.#.#.#.#...#.....#.#.....#.#.........#.........#.#...#.#.#.....U.#
#.#####.#######.#.#.#.###.###.#####.#####.###.#.#####.#####.#.#.#######.###.#.### #.#######.###.#.#.###.#.#P#.#######.###.#.###.#######.#########.#####.#.#######.#
#.#...#.#.....#.#.#...#...#...#...#.....#...#.R.#...#.#.....#.....#...#...#x#...# #.#.....#...#.#.#.....#.#...#.......#...#...#...#.....#.......#.......#.#...#...#
#.#.#.#.###.###.#.#####.#######.#.#######.#.#####.#.###.###########.#.#.###.###.# #.#.###.###.#.#########.###.#.#######.#####.###.#.#####.###.###########.#.#.#.###
#...#.#...#...#.#.#...#...#...#.#.#.....#.#.#.....#.#...#.#.........#.#.......#.# #...#...#.#.#.#.....#...#...#.#.....#...#...#...#.......#...#.........#.#.#.#.#.#
#####.###.###.#.#.###.###.#.#.#.#.#.###.#.#.#.#####.#.###.#.#########.#.#######.# #.###.#.#.#.#.#.#.###.#######.#.###.###.#.#####.#####.#####.#.#######.#.#.#Q#.#.#
#...#...#...#...#...#.......#...#.#...#.#.#...#.#...#.....#.#.......#.#.#.......# #.#...#...#.#...#...#.....#...#.#...#...#.....#.....#.#.Yi#.#.#...#...#.#.#.#...#
###.###.###.###.###.#############.###.#.#.#####.#.#######.#.#.#.#####Y###.#####.# #.#.#######.###.###.#####.#.###.#.#.#.###.###.#######.#.#.#.#.###.#.###.#.#.###.#
#...#.....#...#...#.......#.#...#.....#.#.#..i..#.......#.#.#.#.......#...#.#...# #.#.......#...#.#.....#...#.#...#.#.#...#.#...#.......#.#.#.#...#.....#.#.#.#...#
#.###.#######.###.#######.#.#.#.#######.#.#.###.#####.###.#Q###.#######.###.#.### #.#######.###.###.#.###.###.#####.#####.#.#.#.#.#######.#.#.###.#####.#.#.#.#####
#...#.#.......#..n#.#.....#...#...#.....#.#.#...#...#.#...#.#.#.#...#...#.#...#.# #.#.....#.....#...#.#.#.........#.....#.#.#.#.#.#...#...#.#.#.#.#...#...#.#.....#
#.#.#.#.###.#####.#.#######.#####.#.#####.#.#.###.###.#.###.#.#.#.#.#.###.#.###.# #.#.###.#######.#####.#########.#.#.###.#.#.#.#.#.###.###.#.#.#.#.#.#####.#####.#
#.#...#.#...#...#.....#...#.#...#...#...#...#...#.#...#...#..o#...#.#.#.......#.# #.#.#.....#.........#.#.....#.#.#.#b#...#.#.#.#.#.#..y#.#.#.#.#.#.#...#...#.....#
#.#####.#####.#.#######.#.#.#.#.#####.#.#######.#.#.###.###########.#.#######.#.# #.###.#####.#######.#.#.###.#.#.#.#.#.#####.###.#.#.###.#.###.#.#.###.#.###.###.#
#.....#...#...#.#.......#.#.#.#.....#.#.#.....#.#.#.....#.........#.#.#...#.....# #.E.#....d..#.......#...#.#.#.#.#.#.#...#...#...#.#...#.#...I.#...#..l#.#...#...#
#####L###.#.###.#.#######.#.###.###.###.###.#.#.#.#######.#.#####.#.#.#.#.####### ###.#.#######.###########F#.#.#.###.###.#.#.#.###.###.#.#########.#.###.#.###J###
#...#.#...#.#...#...#...#.#...#.#.......#...#.#...#.....#.#.....#.#.#.#.#.......# #...#...#...#...........#...#.......#...#.#.#.#.....#.G.#.......#.#.....#.#.#.#.#
#.#.#.#.###.#.#.###.#.#.#.###.#.#######.#.#######.#.#.###.#####.###.#.#.#######.# #.#####.#.#########.#.#.#.#########.#.#.#.###.#####.###.#.###.#.#####.###.#.#.#.#
#.#.#.#.....#.#.#...#.#.....#.#.......#.#.......#...#.#...#..j..#..v#.........#.# #..v..#...#.......#.#.#.#.#...#.....#.#.#...#.......#.#.#...#.#.....#.#...#.#...#
#.#.#.#######.#.#.###.#.#####.###.###.###.#####.###.###.###.###.#.###.#########.# #####.#####.#####.###.###.#.#.#.#####.#.#Z#.#######X#.#.#####.#####.#.#.###.###.#
#.#.#.#...#...#.#...#.#.#...#...#...#...#...#.#.#...#...#.#.#...#.#.#.#.........# #...#.....#...#.....#...#...#.#.#...#.#.#.#.......#...#.....#.....#.#.#.#...#...#
###.#.#.#.#.#######.#.###.#.###.#####.#.###.#.#.#.###.###.#.#####.#.#.#.#######.# #.#######.#.#.#####.###.#####.#.#.###.#.###.#.#####.#######.#.###.#.###.#.###.###
#...#...#.#.........#.....#...#.....#f#.#.....#.....#e..#.#.......#.#.#.#.#...#.# #.........#.#.#...#...#...#...#...#...#.#...#.#...#.#.R....g#.#...#.....#.#...#.#
#.#######.#################.#.#####.###.#.#############A#.#########.#.#.#.#.#.#.# #.###########.#.#.###.###.#.###.###.###.#.#####.#.#.#.#########.#########.#.###.#
#...#.....#.....#...#.....#.#.....#.....#...#...#.....#...#...#.......#.#.#.#..z# #...#.#.....#...#.#.#.#...#..t#.#...#...#.#.....#...#...#.....#.#..n....#.M.#...#
#.#.#.#####.###.###.#.###C#.###########.###.#.#T#.#.#####.#.###.#######.#.#.##### ###.#.#.#.#.#####.#.#.#.#####.###.#####.#.#.###########.#.###.#.#.#######.###.#.#
#.#.#.X.#k..#.#...#...#...#.....#.....#.#...#.#...#.......#.....#....p..#...#...# #...#...#.#.#..w#.#.#.#.....#...#.....#.#.#.......#.....#.#...#.#.#.D...#.....#.#
#.#.###.###.#.###.#####.#.#####.#.#.###.#.###.###################.#######.###.#.# #C#######.#.#.#.#.#.#.###.#.###.#####.#.#.#######.#.#####.#.###.#.#.###.#######H#
#.#.........#...........#.....#...#.....#...#.....................#...........#.# #......o..#...#...#.......#...#.A.....#.#.........#r......#.....#.....#.........#
################################################################################# #################################################################################

1
inputs/19p.txt Normal file
View File

@ -0,0 +1 @@
109,424,203,1,21102,11,1,0,1105,1,282,21102,18,1,0,1105,1,259,1201,1,0,221,203,1,21101,31,0,0,1105,1,282,21101,38,0,0,1106,0,259,21002,23,1,2,22101,0,1,3,21102,1,1,1,21101,0,57,0,1105,1,303,1201,1,0,222,20102,1,221,3,21001,221,0,2,21101,259,0,1,21101,0,80,0,1105,1,225,21102,1,76,2,21101,91,0,0,1106,0,303,1201,1,0,223,21001,222,0,4,21102,1,259,3,21101,0,225,2,21102,1,225,1,21102,1,118,0,1106,0,225,20101,0,222,3,21101,100,0,2,21102,1,133,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1105,1,259,2102,1,1,223,20102,1,221,4,21001,222,0,3,21101,0,17,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,0,195,0,106,0,109,20207,1,223,2,21002,23,1,1,21102,1,-1,3,21101,214,0,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,22101,0,-3,1,21201,-2,0,2,22102,1,-1,3,21101,0,250,0,1106,0,225,22101,0,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,2105,1,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22101,0,-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,22101,0,-2,3,21102,1,343,0,1105,1,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,21102,1,384,0,1106,0,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,21201,1,0,-4,109,-5,2106,0,0

40
main.go
View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"runtime/pprof"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -26,8 +27,10 @@ const (
) )
var ( var (
flagPart1 = flag.Bool("part1", false, "whether to run part1 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") 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{ var dayMap = []day{
@ -49,11 +52,23 @@ var dayMap = []day{
&days.Day16{}, &days.Day16{},
&days.Day17{}, &days.Day17{},
&days.Day18{}, &days.Day18{},
&days.Day19{},
} }
func main() { func main() {
flag.Parse() 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)) arg := strconv.Itoa(len(dayMap))
flagArgs := flag.Args() flagArgs := flag.Args()
if len(flagArgs) > 0 && len(flagArgs[0]) > 0 { if len(flagArgs) > 0 && len(flagArgs[0]) > 0 {
@ -78,7 +93,14 @@ func main() {
solve(dayMap[iArg-1]) 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) { func solve(d day) {
@ -98,6 +120,11 @@ func solve(d day) {
part1Text = d.Part1() part1Text = d.Part1()
} }
part1Time := time.Since(part1Start) part1Time := time.Since(part1Start)
if runPart1 {
fmt.Println(part1Header)
fmt.Println(">", part1Text)
fmt.Println()
}
part2Start := time.Now() part2Start := time.Now()
var part2Text string var part2Text string
@ -105,17 +132,12 @@ func solve(d day) {
part2Text = d.Part2() part2Text = d.Part2()
} }
part2Time := time.Since(part2Start) part2Time := time.Since(part2Start)
if runPart1 {
fmt.Println(part1Header)
fmt.Println(">", part1Text)
fmt.Println()
}
if runPart2 { if runPart2 {
fmt.Println(part2Header) fmt.Println(part2Header)
fmt.Println(">", part2Text) fmt.Println(">", part2Text)
fmt.Println() fmt.Println()
} }
fmt.Print(utilities.ColorBrightBlack) fmt.Print(utilities.ColorBrightBlack)
fmt.Println("Parsed in", parseTime) fmt.Println("Parsed in", parseTime)
if runPart1 { if runPart1 {

View File

@ -10,3 +10,13 @@ func ArrayContains[T comparable](array []T, val T) bool {
return false 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
}

28
utilities/bisect.go Normal file
View File

@ -0,0 +1,28 @@
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 {
currVal := low
for T(math.Abs(float64(high-low))) > threshold {
currVal = low + ((high - low) / 2)
success := tryFunc(currVal)
if success {
low = currVal
} else {
high = currVal
}
}
return currVal
}

View File

@ -128,9 +128,15 @@ func (p *IntcodeProgram) ensureMemoryCapacity(address int) {
} }
func (p *IntcodeProgram) Reset() { func (p *IntcodeProgram) Reset() {
p.memory = nil wiped := false
if len(p.memory) != len(p.program) {
wiped = true
p.memory = nil
}
p.init() p.init()
copy(p.memory, p.program) if !wiped {
copy(p.memory, p.program)
}
p.relativeBase = 0 p.relativeBase = 0
} }