12 Commits

Author SHA1 Message Date
7c4033a8d1 Day 14 complete 2022-06-12 11:21:40 -05:00
060cfeb610 Day 14 WIP 2022-06-11 16:40:57 -05:00
46cb381e8d Day 13 solution
This was incredibly cool and I had a really fun time with it. Uncomment everything to see the game play itself! Note that I'm not seeking around in the terminal window to make the drawing smooth, I'm just outputting each new frame as it happens, so there's some jitter, but it still looks great!

I messed around a bit with control codes to move the cursor around instead of the "draw the buffer over and over again" approach, and they work, mostly, but I'm sticking with this for now.
2022-06-10 23:55:27 -05:00
b29ea5d936 Day 12 solution
Okay, I had to seek help on this one. The orbital period + least-common-multiple solution was not coming to me.
2022-06-10 21:59:06 -05:00
20a7e892ab Day 11 solution 2022-06-10 17:43:37 -05:00
e289bd9f54 Day 10 solution
This one was an absolute beating for me. I am so bad at these sorts of problems. Ultimately I settled on a probably-not-ideal solution that crawls the graph with offsets of each variant of (+/-x,+/-y), marking nodes visited as we come across them so that we end up with a list of asteroids that we can see. Given that this is day 10, and knowing how bad I am at math, I'm assuming this is very far from the intended solution, but it works reasonably quickly and I managed to come up with it myself, so I'm not going to stress too much about it.

For asteroid destruction, the best method I could come up with for finding the correct order was to implement an entire Vector class and sort by angle, which worked, but again, I can't decide if it was the intended solution or not. I should start reusing past years' codebases so I don't have to keep building a utility library from scratch.
2022-06-10 15:29:46 -05:00
dd5af1f2cc Move Pair to a more reusable location
I originally used this in my day 10 solution, but ended up removing it. Either way, it's a general utility so it belongs here.
2022-06-10 15:29:39 -05:00
0b3cdc2331 Day 9 solution
This day showed me that when the input instruction was introduced and said "write addresses will never be in immediate mode", that didn't mean "so don't bother handling modes for input addresses", it meant "handle the mode, but assert if it's immediate mode". It was super helpful that this program contained a bootstrap sequence to validate each instruction.

Memory expansion came with a few caveats: obviously reads and writes needed to handle expanding the memory space, but a Reset also can no longer get away with simply copying the program into memory again because we need to ensure that any additional memory is cut off (or at least zeroed), so the quickest way to handle that in Go is to simply allocate a new buffer; I'd rather manipulate the existing buffer, but I'm having a hard time finding the best way to do that.

And finally, make sure you reset your relativeBase when resetting the program...that one was ugly to track down.
2022-06-10 10:37:38 -05:00
2d6150e318 Day 8 solution
I had fun with this one. I liked how straightforward it was, and it's always satisfying to see the code print a message visually when you're done.
2022-06-10 10:37:38 -05:00
1784ab77c8 Day 7 solution
I will probably end up regretting this since I assume the "wait to be given an input from some other process before continuing execution" paradigm is going to come up again, but this part 2 goroutine+channel solution felt good (taking advantage of Go features) and made me happy, so I rolled with it.
2022-06-10 10:37:38 -05:00
9a4fb7c734 Day 6 solution
I'm reasonably happy with this. I started with a bi-directional linked list, but realized that a flat list of all nodes came in handy for one use case while the linked list came in handy for another, so I settled on that.
2022-06-10 10:37:38 -05:00
52737dd7c3 Day 5 solution
This required an overhaul of the intcode machine to actually be its own type that could operate on its own memory and stuff. So I had to touch day 2 to make it adhere to the new API.

Feeling good about this foundation now. Until I get gobsmacked at some point later, which I expect to happen.
2022-06-10 10:37:32 -05:00
23 changed files with 106 additions and 993 deletions

View File

@ -169,7 +169,7 @@ func (d *Day05) Part1() string {
}
})
return fmt.Sprintf("Diagnostic code: %s%d%s", utilities.TextBold, diagCode, utilities.TextReset)
return fmt.Sprintf("Diagnostic code: %d", diagCode)
}
func (d *Day05) Part2() string {
@ -184,5 +184,5 @@ func (d *Day05) Part2() string {
diagCode = val
})
return fmt.Sprintf("Diagnostic code: %s%d%s", utilities.TextBold, diagCode, utilities.TextReset)
return fmt.Sprintf("Diagnostic code: %d", diagCode)
}

View File

@ -28,7 +28,7 @@ func (d *Day07) Part1() string {
var highestVal int64
var highestSequence []int64
allSequences := utilities.GetPermutations([]int64{0, 1, 2, 3, 4}...)
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")
@ -68,7 +68,7 @@ func (d *Day07) Part2() string {
var highestVal int64
var highestSequence []int64
allSequences := utilities.GetPermutations([]int64{5, 6, 7, 8, 9}...)
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")

View File

@ -84,8 +84,7 @@ func (d *Day08) Part2() string {
}
outStr := strings.Builder{}
outStr.WriteString("Message received:\n")
outStr.WriteString(utilities.TextBold)
outStr.WriteRune('\n')
for y := 0; y < imgHeight; y++ {
for x := 0; x < imgWidth; x++ {
if finalImg[(y*imgWidth)+x] == 0 {
@ -96,7 +95,6 @@ func (d *Day08) Part2() string {
}
outStr.WriteRune('\n')
}
outStr.WriteString(utilities.TextReset)
return outStr.String()
}

View File

@ -99,8 +99,7 @@ func (d *Day11) Part2() string {
_, min, max := d.paintHull()
outStr := strings.Builder{}
outStr.WriteString("Registration identifier:\n")
outStr.WriteString(u.TextBold)
outStr.WriteRune('\n')
for x := min.First; x <= max.First; x++ {
for y := min.Second; y <= max.Second; y++ {
val, exists := d.painted[u.Pair[int, int]{First: x, Second: y}]
@ -112,7 +111,6 @@ func (d *Day11) Part2() string {
}
outStr.WriteRune('\n')
}
outStr.WriteString(u.TextReset)
return outStr.String()
}

View File

@ -10,15 +10,18 @@ import (
)
type reaction struct {
inputs map[string]int64
inputs map[string]int
output u.Pair[string, int]
}
type Day14 struct {
reactions []reaction
leftovers map[string]int
}
func (d *Day14) Parse() {
d.leftovers = make(map[string]int)
lines := u.GetStringLines("14p")
d.reactions = make([]reaction, len(lines))
for i, line := range lines {
@ -29,10 +32,10 @@ func (d *Day14) Parse() {
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)
d.reactions[i].inputs = make(map[string]int)
for _, input := range inputs {
pair := strings.Split(input, " ")
d.reactions[i].inputs[pair[1]], _ = strconv.ParseInt(pair[0], 10, 64)
d.reactions[i].inputs[pair[1]], _ = strconv.Atoi(pair[0])
}
}
}
@ -51,7 +54,7 @@ func (d Day14) Num() int {
return 14
}
func (d *Day14) getOreRequiredForFuel(qty int64) int64 {
func (d *Day14) oreRequiredStock(qty int64) int64 {
oreRequired := int64(0)
needs := map[string]int64{
"FUEL": qty,
@ -59,36 +62,33 @@ func (d *Day14) getOreRequiredForFuel(qty int64) int64 {
excess := make(map[string]int64)
getFromExcess := func(qty int64, chemical string) int64 {
available := u.Min(excess[chemical], qty)
excess[chemical] -= available
return available
inStock := excess[chemical]
qty -= inStock
excess[chemical] = int64(math.Min(math.Abs(float64(qty)), 0))
return inStock - excess[chemical]
}
for len(needs) > 0 {
keys := u.MapKeys(needs)
producing := keys[0]
qtyRequired := needs[producing]
delete(needs, producing)
chemical := keys[len(keys)-1]
qtyRequired := needs[chemical]
delete(needs, chemical)
fromExcess := getFromExcess(qtyRequired, producing)
if fromExcess == qtyRequired {
continue
}
fromExcess := getFromExcess(qtyRequired, chemical)
qtyRequired -= fromExcess
reaction := d.getReactionProducing(producing)
reaction := d.getReactionProducing(chemical)
qtyProduced := int64(reaction.output.Second)
reactionsNeeded := int64(math.Ceil(float64(qtyRequired) / float64(qtyProduced)))
ingredients := reaction.inputs
excess[producing] = (qtyProduced * reactionsNeeded) - qtyRequired
n := int64(math.Ceil(float64(qtyRequired) / float64(qtyProduced)))
for reagent, inputQty := range reaction.inputs {
qtyNeeded := inputQty * reactionsNeeded
if reagent == "ORE" {
oreRequired += qtyNeeded
excess[chemical] = (qtyProduced * n) - qtyRequired
for ingredient, qtyIngredient := range ingredients {
if ingredient == "ORE" {
oreRequired += int64(int64(qtyIngredient) * n)
} else {
needs[reagent] += qtyNeeded
needs[ingredient] += int64(qtyIngredient) * n
}
}
}
@ -97,13 +97,13 @@ func (d *Day14) getOreRequiredForFuel(qty int64) int64 {
}
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)
neededOre := d.oreRequiredStock(1)
return fmt.Sprintf("%s%d%s", u.TextBold, neededOre, u.TextReset)
}
func (d *Day14) Part2() string {
oreAvailable := int64(1000000000000)
estimate := oreAvailable / d.getOreRequiredForFuel(1)
estimate := oreAvailable / d.oreRequiredStock(1)
high := estimate * 2
low := estimate
@ -112,18 +112,16 @@ func (d *Day14) Part2() string {
lastFailure := high
fuelProduced := low
for math.Abs(float64(lastFailure-lastSuccess)) > 1 {
oreConsumed := d.getOreRequiredForFuel(fuelProduced)
adjustment := (lastFailure - lastSuccess) / 2
for math.Abs(float64(lastFailure)-float64(lastSuccess)) > 1 {
oreConsumed := d.oreRequiredStock(fuelProduced)
if oreConsumed < oreAvailable {
lastSuccess = fuelProduced
fuelProduced += (lastFailure - lastSuccess) / 2
} else {
lastFailure = fuelProduced
adjustment = -adjustment
fuelProduced -= (lastFailure - lastSuccess) / 2
}
}
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("%s%d%s", u.TextBold, lastSuccess, u.TextReset)
}

View File

@ -1,332 +0,0 @@
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)
}

View File

@ -1,66 +0,0 @@
// 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]]
}

View File

@ -1,104 +0,0 @@
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)
}

View File

@ -1,340 +0,0 @@
package days
import (
"fmt"
"strings"
u "parnic.com/aoc2019/utilities"
)
type camViewCellType int
type botFacing int
const (
cellTypeScaffold camViewCellType = iota
cellTypeOpen
cellTypeInvalid
)
const (
botFacingUp botFacing = iota
botFacingLeft
botFacingDown
botFacingRight
botFacingFirst = botFacingUp
botFacingLast = botFacingRight
)
const (
dirLeft dirType = 1
dirRight dirType = -1
)
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
grid [][]camViewCellType
botLocation u.Vec2i
botFacingDir botFacing
endLocation u.Vec2i
}
func (d *Day17) Parse() {
d.program = u.LoadIntcodeProgram("17p")
d.grid = [][]camViewCellType{{}}
}
func (d Day17) Num() int {
return 17
}
func (d Day17) Draw() {
for y := range d.grid {
for x := range d.grid[y] {
switch d.grid[y][x] {
case cellTypeOpen:
fmt.Print(" ")
case cellTypeScaffold:
char := "█"
color := u.ColorBlack
if d.botLocation.X == x && d.botLocation.Y == y {
switch d.botFacingDir {
case botFacingUp:
char = "^"
case botFacingLeft:
char = "<"
case botFacingDown:
char = "v"
case botFacingRight:
char = ">"
}
} else if d.endLocation.X == x && d.endLocation.Y == y {
char = "@"
} else {
color = u.ColorWhite
}
fmt.Printf("%s%s%s%s", u.BackgroundWhite, color, char, u.TextReset)
}
}
fmt.Println()
}
}
func (d Day17) 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(d.grid) ||
offX < 0 || offX >= len(d.grid[0]) {
continue
}
if d.grid[offY][offX] == cellTypeScaffold {
retval = append(retval, u.Vec2i{X: offX, Y: offY})
}
}
return retval
}
func (d Day17) getNumSurroundingScaffolds(y, x int) int {
return len(d.getAdjacentScaffolds(y, x))
}
func (d Day17) forEachCellOfType(t camViewCellType, f func(y, x int)) {
for y := range d.grid {
for x := range d.grid[y] {
if d.grid[y][x] == t {
f(y, x)
}
}
}
}
func (d Day17) getNewFacingDir(currentDir botFacing, turnDir dirType) botFacing {
currentDir += botFacing(turnDir)
if currentDir < botFacingFirst {
currentDir = botFacingLast
} else if currentDir > botFacingLast {
currentDir = botFacingFirst
}
return currentDir
}
func (d Day17) 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(d.grid) || newX < 0 || newX >= len(d.grid[0]) {
return cellTypeInvalid, newY, newX
}
return d.grid[newY][newX], newY, newX
}
func (d *Day17) Part1() string {
y := 0
d.program.RunIn(func(inputStep int) int64 {
return 0
}, func(val int64, state u.IntcodeProgramState) {
rVal := rune(val)
switch rVal {
case '\n':
y++
d.grid = append(d.grid, make([]camViewCellType, 0))
case '#':
d.grid[y] = append(d.grid[y], cellTypeScaffold)
case '.':
d.grid[y] = append(d.grid[y], cellTypeOpen)
case '^', '<', 'v', '>':
d.botLocation = u.Vec2i{X: len(d.grid[y]), Y: y}
d.grid[y] = append(d.grid[y], cellTypeScaffold)
switch rVal {
case '^':
d.botFacingDir = botFacingUp
case '<':
d.botFacingDir = botFacingLeft
case 'v':
d.botFacingDir = botFacingDown
case '>':
d.botFacingDir = botFacingRight
}
}
})
for y := len(d.grid) - 1; y >= 0; y-- {
if len(d.grid[y]) == 0 {
d.grid = d.grid[0 : len(d.grid)-1]
}
}
alignmentParameterTotal := 0
d.forEachCellOfType(cellTypeScaffold, func(y, x int) {
if numSurrounding := d.getNumSurroundingScaffolds(y, x); numSurrounding == 4 {
alignmentParameterTotal += y * x
} else if numSurrounding == 1 {
if d.botLocation.X != x || d.botLocation.Y != y {
d.endLocation = u.Vec2i{X: x, Y: y}
}
}
})
// d.Draw()
return fmt.Sprintf("Alignment parameter sum: %s%d%s", u.TextBold, alignmentParameterTotal, u.TextReset)
}
func (d *Day17) Part2() string {
instructions := make([]string, 0)
pos := d.botLocation
botFacingDir := d.botFacingDir
for {
if pos == d.endLocation {
fmt.Println()
break
}
adj := d.getAdjacentScaffolds(pos.Y, pos.X)
turnDirection := dirType(0)
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
}
}
}
if turnDirection == 0 {
panic("at an invalid location somehow")
}
dirAscii := "L"
if turnDirection == dirRight {
dirAscii = "R"
}
instructions = append(instructions, dirAscii)
botFacingDir = d.getNewFacingDir(botFacingDir, turnDirection)
numMoved := 0
for {
cell, newY, newX := d.getCellTypeInDirection(pos.Y, pos.X, botFacingDir)
if cell != cellTypeScaffold {
break
}
pos.X = newX
pos.Y = newY
numMoved++
}
instructions = append(instructions, fmt.Sprintf("%d", numMoved))
}
workingInstructions := make([]string, len(instructions))
copy(workingInstructions, instructions)
instructionStr := strings.Join(workingInstructions, ",")
progs := make([][]string, 3)
for i := 0; i < 3; i++ {
numFound := 3
subLen := 4
for numFound >= 3 {
numFound = 1
instructionSubset := strings.Join(workingInstructions[0:subLen], ",")
if len(instructionSubset) > 20 {
break
}
for x := len(instructionSubset); x <= len(instructionStr)-len(instructionSubset); x++ {
if instructionStr[x:x+len(instructionSubset)] == instructionSubset {
numFound++
x += len(instructionSubset)
}
}
if numFound >= 3 {
subLen += 2
}
}
if numFound < 3 {
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("didn't empty instructions")
}
instructionStr = strings.Join(instructions, ",")
instructionStr = strings.ReplaceAll(instructionStr, strings.Join(progs[0], ","), "A")
instructionStr = strings.ReplaceAll(instructionStr, strings.Join(progs[1], ","), "B")
instructionStr = strings.ReplaceAll(instructionStr, strings.Join(progs[2], ","), "C")
instructionStr = fmt.Sprintf("%s\n%s\n%s\n%s\nn\n",
instructionStr,
strings.Join(progs[0], ","),
strings.Join(progs[1], ","),
strings.Join(progs[2], ","),
)
d.program.Reset()
d.program.SetMemory(0, 2)
dustCollected := int64(0)
d.program.RunIn(func(inputStep int) int64 {
return int64(instructionStr[inputStep-1])
}, func(val int64, state u.IntcodeProgramState) {
dustCollected = val
})
return fmt.Sprintf("Dust collected after traveling all paths: %s%d%s", u.TextBold, dustCollected, u.TextReset)
}

View File

@ -1,16 +1,14 @@
package days
import (
"fmt"
u "parnic.com/aoc2019/utilities"
"parnic.com/aoc2019/utilities"
)
type DayTemplate struct {
}
func (d *DayTemplate) Parse() {
u.GetIntLines("Templatep")
utilities.GetIntLines("Templatep")
}
func (d DayTemplate) Num() int {
@ -18,9 +16,9 @@ func (d DayTemplate) Num() int {
}
func (d *DayTemplate) Part1() string {
return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset)
return ""
}
func (d *DayTemplate) Part2() string {
return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset)
return ""
}

View File

@ -1,56 +1,60 @@
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
11 RVCS => 8 CBMDT
29 QXPB, 8 QRGRH => 8 LGMKD
3 VPRVD => 6 PMFZG
1 CNWNQ, 11 MJVXS => 6 SPLM
13 SPDRZ, 13 PMFZG => 2 BLFM
8 QWPFN => 7 LWVB
1 SPLM => 8 TKWQ
2 QRGRH, 6 CNWNQ => 7 DTZW
2 DMLT, 1 SPLM, 1 TMDK => 9 NKNS
1 MJVXS, 1 HLBV => 7 PQCQH
1 JZHZP, 9 LWVB => 7 MJSCQ
29 DGFR => 7 QRGRH
14 XFLKQ, 2 NKNS, 4 KMNJF, 3 MLZGQ, 7 TKWQ, 24 WTDW, 11 CBMDT => 4 GJKX
4 TKWQ, 1 WLCFR => 4 PDKGT
2 NKNS => 4 GDKL
4 WRZST => 9 XFLKQ
19 DGFR => 4 VPRVD
10 MJSCQ, 4 QWPFN, 4 QXPB => 2 MLZGQ
1 JZHZP => 7 QWPFN
1 XFLKQ => 9 FQGVL
3 GQGXC => 9 VHGP
3 NQZTV, 1 JZHZP => 2 NVZWL
38 WLCFR, 15 GJKX, 44 LGMKD, 2 CBVXG, 2 GDKL, 77 FQGVL, 10 MKRCZ, 29 WJQD, 33 BWXGC, 19 PQCQH, 24 BKXD => 1 FUEL
102 ORE => 5 DGFR
17 NWKLB, 1 SBPLK => 5 HRQM
3 BWXGC => 8 TQDP
1 TQDP => 2 PSZDZ
2 MJVXS => 9 WNXG
2 NBTW, 1 HRQM => 2 SVHBH
8 CNWNQ, 1 DTZW => 4 RVCS
4 VHGP, 20 WNXG, 2 SVHBH => 3 SPDRZ
110 ORE => 5 TXMC
10 QRGRH => 5 NWKLB
1 SBPLK => 3 MJVXS
9 DGFR => 5 RFSRL
5 LBTV => 3 DMLT
1 NWKLB, 1 KMNJF, 1 HDQXB, 6 LBTV, 2 PSZDZ, 34 PMFZG, 2 SVHBH => 2 WJQD
1 RVCS => 5 MKRCZ
14 NQZTV, 3 FPLT, 1 SJMS => 2 GQGXC
18 RFSRL, 13 VHGP, 23 NBTW => 5 WTDW
1 VHGP, 6 TKWQ => 7 QXPB
1 JZHZP, 1 CNWNQ => 5 KMNJF
109 ORE => 9 BWXGC
2 CNWNQ, 1 PDKGT, 2 KMNJF => 5 HDQXB
1 PDKGT, 18 WRZST, 9 MJSCQ, 3 VHGP, 1 BLFM, 1 LGMKD, 7 WLCFR => 2 BKXD
11 MLJK => 6 FPLT
8 DGFR, 2 TXMC, 3 WJRC => 9 SJMS
2 SBPLK => 1 LBTV
22 QWPFN => 4 WRZST
5 WRZST, 22 WNXG, 1 VHGP => 7 NBTW
7 RVCS => 9 TMDK
1 DGFR, 14 TXMC => 5 JZHZP
2 JZHZP => 3 SBPLK
19 PDKGT => 8 HLBV
195 ORE => 6 WJRC
6 GQGXC => 8 CNWNQ
1 NVZWL, 4 GQGXC => 2 CBVXG
1 NVZWL, 1 KMNJF => 8 WLCFR
153 ORE => 4 MLJK
1 BWXGC => 6 NQZTV

View File

@ -1 +0,0 @@
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

View File

@ -1 +0,0 @@
59791875142707344554745984624833270124746225787022156176259864082972613206097260696475359886661459314067969858521185244807128606896674972341093111690401527976891268108040443281821862422244152800144859031661510297789792278726877676645835805097902853584093615895099152578276185267316851163313487136731134073054989870018294373731775466754420075119913101001966739563592696702233028356328979384389178001923889641041703308599918672055860556825287836987992883550004999016194930620165247185883506733712391462975446192414198344745434022955974228926237100271949068464343172968939069550036969073411905889066207300644632441054836725463178144030305115977951503567

View File

@ -1 +0,0 @@
12345678

View File

@ -1 +0,0 @@
80871224585914546619083218645595

View File

@ -1 +0,0 @@
19617804207202209144916044189917

View File

@ -1 +0,0 @@
69317163492948606335995924319873

View File

@ -1 +0,0 @@
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

View File

@ -45,9 +45,6 @@ var dayMap = []day{
&days.Day12{},
&days.Day13{},
&days.Day14{},
&days.Day15{},
&days.Day16{},
&days.Day17{},
}
func main() {

View File

@ -27,7 +27,6 @@ type IntcodeProgram struct {
memory []int64
program []int64
relativeBase int
haltRequested bool
}
type IntcodeProgramState struct {
@ -142,7 +141,7 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
p.init()
inputsRequested := 0
for instructionPointer := 0; instructionPointer < len(p.program) && !p.haltRequested; {
for instructionPointer := 0; instructionPointer < len(p.program); {
instruction := p.GetMemory(instructionPointer)
instructionPointer++
@ -248,10 +247,4 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
panic(fmt.Sprintf("exception executing program - unhandled opcode %d", opcode))
}
}
p.haltRequested = false
}
func (p *IntcodeProgram) Stop() {
p.haltRequested = true
}

View File

@ -1,7 +1,5 @@
package utilities
import "math"
func GCD[T Integer](a, b T) T {
if b == 0 {
return a
@ -27,23 +25,3 @@ func LCM[T Integer](nums ...T) uint64 {
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
}

View File

@ -4,7 +4,7 @@ type Permutable interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
func GetPermutations[T Permutable](arr ...T) [][]T {
func GetPermutations[T Permutable](arr []T) [][]T {
var helper func([]T, int)
res := [][]T{}

View File

@ -13,8 +13,6 @@ type Vec3[T Number] struct {
Z T
}
type Vec2i Vec2[int]
func (v Vec2[T]) Dot(other Vec2[T]) T {
return (v.X * other.X) + (v.Y * other.Y)
}