├── .gitignore
├── LICENSE
├── README.md
├── aoc
├── challenges
├── 2020
│ ├── 01-reportRepair
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ │ └── testCases.json
│ ├── 02-passwordPhilosophy
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ │ └── testCases.json
│ ├── 03-tobogganTrajectory
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 04-passportProcessing
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ │ └── testCases.json
│ ├── 05-binaryBoarding
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 06-customCustoms
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 07-handyHaversacks
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 08-handheldHalting
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 09-encodingError
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 10-adapterArray
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 11-seatingSystem
│ │ ├── 0.gif
│ │ ├── 1.gif
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ ├── partTwo.py
│ │ │ └── visualise.py
│ ├── 12-rainRisk
│ │ ├── 0.gif
│ │ ├── 1.gif
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ ├── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ ├── partTwo.py
│ │ │ └── visualise.py
│ │ ├── quadrants.png
│ │ └── rotation.png
│ ├── 13-shuttleSearch
│ │ ├── README.md
│ │ ├── info.json
│ │ ├── python
│ │ │ ├── __main__.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ │ └── working.jpg
│ ├── 14-dockingData
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 15-rambunctiousRecitation
│ │ ├── 0.png
│ │ ├── 1-hires.png
│ │ ├── 1-lores.png
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ ├── partTwo.py
│ │ │ └── visualise.py
│ ├── 16-ticketTranslation
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 17-conwayCubes
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 18-operationOrder
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── partOne.py
│ │ │ ├── partTwo.py
│ │ │ └── test.py
│ ├── 19-monsterMessages
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 20-jurassicJigsaw
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 21-allergenAmusement
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 22-crabCombat
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 23-crabCups
│ │ ├── README.md
│ │ ├── crab.jpg
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 24-lobbyLayout
│ │ ├── README.md
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── 25-comboBreaker
│ │ ├── README.md
│ │ ├── go
│ │ │ ├── challenge
│ │ │ │ ├── common.go
│ │ │ │ ├── partOne.go
│ │ │ │ └── partTwo.go
│ │ │ └── main.go
│ │ ├── info.json
│ │ └── python
│ │ │ ├── __main__.py
│ │ │ ├── common.py
│ │ │ ├── partOne.py
│ │ │ └── partTwo.py
│ ├── README.md
│ └── clocgraph.png
├── 2021
│ ├── 01-sonarSweep
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── go
│ │ │ └── challenge.go
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 02-dive
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── go
│ │ │ └── challenge.go
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 03-binaryDiagnostic
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 04-giantSquid
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 05-hydrothermalVenture
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── go
│ │ │ └── challenge.go
│ │ ├── info.json
│ │ ├── napkinmath.jpg
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 06-lanternfish
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── py
│ │ │ └── __init__.py
│ │ └── whiteboard.jpg
│ ├── 07-theTreacheryOfWhales
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 08-sevenSegmentSearch
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── go
│ │ │ └── challenge.go
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 09-smokeBasin
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── partTwo.mp4
│ │ └── py
│ │ │ └── __init__.py
│ ├── 10-syntaxScoring
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 11-dumboOctopus
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 12-passagePathing
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── go
│ │ │ └── challenge.go
│ │ ├── graph.py
│ │ └── info.json
│ ├── 13-transparentOrigami
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 14-extendedPolymerization
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 15-chiton
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 16-packetDecoder
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 20-trenchMap
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ ├── part2.mp4
│ │ └── py
│ │ │ └── __init__.py
│ ├── 21-diracDice
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 22-reactorReboot
│ │ ├── README.md
│ │ ├── blender-part-2.png
│ │ ├── info.json
│ │ ├── openscad-generate.py
│ │ ├── openscad-part-2.png
│ │ ├── part.1.scad
│ │ ├── part.2.scad
│ │ └── py
│ │ │ └── __init__.py
│ ├── 25-seaCucumber
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── README.md
│ └── running-times.png
├── 2022
│ ├── 01-calorieCounting
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── java
│ │ │ └── src
│ │ │ │ ├── Challenge.java
│ │ │ │ └── Main.java
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 02-rockPaperScissors
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 03-rucksackReorganization
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 04-campCleanup
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 05-supplyStacks
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 06-tuningTrouble
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 07-noSpaceLeftOnDevice
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 08-treetopTreeHouse
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 09-ropeBridge
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── nim
│ │ │ └── challenge.nim
│ │ └── py
│ │ │ └── __init__.py
│ ├── 10-cathodeRayTube
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 11-monkeyInTheMiddle
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 12-hillClimbingAlgorithm
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 13-distressSignal
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 14-regolithReservoir
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 15-beaconExclusionZone
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── doodles.jpg
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 16-proboscideaVolcanium
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 17-pyroclasticFlow
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 18-boilingBoulders
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ ├── openscad-generate.py
│ │ └── py
│ │ │ └── __init__.py
│ ├── 19-notEnoughMinerals
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 20-grovePositioningSystem
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 21-monkeyMath
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 22-monkeyMap
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 23-unstableDiffusion
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 24-blizzardBasin
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── 25-fullOfHotAir
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── info.json
│ │ └── py
│ │ │ └── __init__.py
│ ├── README.md
│ └── running-times.png
├── 2023
│ ├── 01-trebuchet
│ │ ├── README.md
│ │ ├── main.hs
│ │ ├── main.py
│ │ └── tests.json
│ ├── 02-cubeConundrum
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 03-gearRatios
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 04-scratchcards
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 05-ifYouGiveASeedAFertilizer
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 06-waitForIt
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 07-camelCards
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 08-hauntedWasteland
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 09-mirageMaintenance
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 10-pipeMaze
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 11-cosmicExpansion
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 12-hotSprings
│ │ ├── README.md
│ │ ├── main.py
│ │ ├── p1before.svg
│ │ ├── p2after.svg
│ │ └── tests.json
│ ├── 13-pointOfIncidence
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 14-parabolicReflectorDish
│ │ ├── README.md
│ │ ├── digits.txt
│ │ ├── generate-vis.sh
│ │ ├── main.py
│ │ ├── out.mp4
│ │ ├── tests.json
│ │ └── vis.py
│ ├── 15-lensLibrary
│ │ ├── README.md
│ │ ├── main.go
│ │ └── tests.json
│ ├── 16-theFloorWillBeLava
│ │ ├── README.md
│ │ ├── main.py
│ │ ├── test.txt
│ │ └── tests.json
│ ├── 17-clumsyCrucible
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 18-lavaductLagoon
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 19-aplenty
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 20-pulsePropagation
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 21-stepCounter
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 22-sandSlabs
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 23-aLongWalk
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 24-neverTellMeTheOdds
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── 25-snowverload
│ │ ├── README.md
│ │ ├── main.py
│ │ └── tests.json
│ ├── README.md
│ ├── benchmark-graph.png
│ └── benchmarks.jsonl
└── 2024
│ ├── 01-historianHysteria
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 02-redNosedReports
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 03-mullItOver
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 04-ceresSearch
│ ├── README.md
│ ├── generate-vis.sh
│ ├── heatmap-1.png
│ ├── heatmap-2.png
│ ├── main.py
│ ├── tests.json
│ └── vis.py
│ ├── 05-printQueue
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 06-guardGallivant
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 07-bridgeRepair
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── 08-resonantCollinearity
│ ├── README.md
│ ├── generate-vis.sh
│ ├── main.py
│ ├── out.mp4
│ ├── tests.json
│ └── vis.py
│ ├── 09-diskFragmenter
│ ├── README.md
│ ├── main.py
│ └── tests.json
│ ├── README.md
│ ├── benchmark-graph.png
│ └── benchmarks.jsonl
├── generate-benchmark-graph.py
├── gridutil
├── __init__.py
├── coord.py
└── grid.py
├── runners
├── buildGo.sh
├── buildKotlin.sh
├── jar.sh
└── py.sh
└── templates
├── main.go
├── main.hs
├── main.kt
└── main.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 - 2022 codemicro
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/README.md:
--------------------------------------------------------------------------------
1 | # [Day 1: Report Repair](https://adventofcode.com/2020/day/1)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 1 - Report Repair
8 |
9 | Test cases
10 | 1.1 pass
11 | 2.1 pass
12 |
13 | Answers
14 | Part 1: 1010884
15 | Part 2: 253928438
16 |
17 | ❯ go run .\go\
18 | AoC 2020: day 1 - Report Repair
19 | Go go1.15.2
20 |
21 | Test cases
22 | 1.1 pass
23 | 2.1 pass
24 |
25 | Answers
26 | Part 1: 1010884
27 | Part 2: 253928438
28 | ```
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | func parse(instr string) []int {
9 | inputSlice := strings.Split(strings.TrimSpace(instr), "\n")
10 |
11 | var values []int
12 | for _, v := range inputSlice {
13 | str, _ := strconv.Atoi(v)
14 | values = append(values, str)
15 | }
16 |
17 | return values
18 | }
19 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | values := parse(instr)
5 |
6 | for _, i := range values {
7 | for _, v := range values {
8 | if v+i == 2020 {
9 | return v * i
10 | }
11 | }
12 | }
13 |
14 | return 0
15 | }
16 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | values := parse(instr)
5 |
6 | for _, i := range values {
7 | for _, v := range values {
8 | for _, x := range values {
9 | if v+i+x == 2020 {
10 | return v * i * x
11 | }
12 | }
13 | }
14 | }
15 |
16 | return 0
17 | }
18 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List:
5 | return [int(x) for x in instr.strip().split("\n")]
6 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | values = parse(instr)
6 |
7 | for i in values:
8 | for v in values:
9 | if v + i == 2020:
10 | return v * i
11 |
12 | return 0
13 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partTwo(instr: str) -> int:
5 | values = parse(instr)
6 |
7 | for i in values:
8 | for v in values:
9 | for x in values:
10 | if v + i + x == 2020:
11 | return v * i * x
12 |
13 | return 0
14 |
--------------------------------------------------------------------------------
/challenges/2020/01-reportRepair/testCases.json:
--------------------------------------------------------------------------------
1 | {
2 | "one": [
3 | {
4 | "input": "1721\n979\n366\n299\n675\n1456",
5 | "expected": 514579
6 | }
7 | ],
8 | "two": [
9 | {
10 | "input": "1721\n979\n366\n299\n675\n1456",
11 | "expected": 241861950
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/README.md:
--------------------------------------------------------------------------------
1 | # [Day 2: Password Philosophy](https://adventofcode.com/2020/day/2)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 2 - Password Philosophy
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 |
14 | Answers
15 | Part 1: 500
16 | Part 2: 313
17 |
18 | ❯ go run .\go\
19 | AoC 2020: day 2 - Password Philosophy
20 | Go go1.15.2
21 |
22 | Test cases
23 | 1.1 pass
24 | 2.1 pass
25 |
26 | Answers
27 | Part 1: 500
28 | Part 2: 313
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | )
7 |
8 | func parse(instr string) []string {
9 | return strings.Split(strings.TrimSpace(string(instr)), "\n")
10 | }
11 |
12 | var parserRegex = regexp.MustCompile(`(?m)(\d+)-(\d+) ([a-z]): (.+)`)
13 |
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | )
6 |
7 | func PartOne(instr string) int {
8 | inputSlice := parse(instr)
9 |
10 | type Password struct {
11 | plaintext string
12 | targetLetter rune
13 | minRepeats int
14 | maxRepeats int
15 | }
16 |
17 | var passwords []Password
18 | for _, line := range inputSlice {
19 | matches := parserRegex.FindAllStringSubmatch(line, -1)
20 | miR, _ := strconv.Atoi(matches[0][1])
21 | maR, _ := strconv.Atoi(matches[0][2])
22 | passwords = append(passwords, Password{
23 | plaintext: matches[0][4],
24 | targetLetter: rune(matches[0][3][0]),
25 | minRepeats: miR,
26 | maxRepeats: maR,
27 | })
28 | }
29 |
30 | var num_valid_passwords int
31 |
32 | for _, password := range passwords {
33 | var target_letter_count int
34 | for _, char := range password.plaintext {
35 | if char == password.targetLetter {
36 | target_letter_count += 1
37 | }
38 | }
39 |
40 | if (target_letter_count >= password.minRepeats) && (target_letter_count <= password.maxRepeats) {
41 | num_valid_passwords += 1
42 | }
43 | }
44 |
45 | return num_valid_passwords
46 | }
47 |
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | )
6 |
7 | func PartTwo(instr string) int {
8 | inputSlice := parse(instr)
9 |
10 | type Password struct {
11 | plaintext string
12 | targetLetter rune
13 | positionOne int
14 | positionTwo int
15 | }
16 |
17 | var passwords []Password
18 | for _, line := range inputSlice {
19 | matches := parserRegex.FindAllStringSubmatch(line, -1)
20 | miR, _ := strconv.Atoi(matches[0][1])
21 | maR, _ := strconv.Atoi(matches[0][2])
22 | passwords = append(passwords, Password{
23 | plaintext: matches[0][4],
24 | targetLetter: rune(matches[0][3][0]),
25 | positionOne: miR - 1,
26 | positionTwo: maR - 1,
27 | })
28 | }
29 |
30 | var num_valid_passwords int
31 |
32 | for _, password := range passwords {
33 | positionOneMatches := rune(password.plaintext[password.positionOne]) == password.targetLetter
34 | positionTwoMatches := rune(password.plaintext[password.positionTwo]) == password.targetLetter
35 |
36 | if positionOneMatches != positionTwoMatches {
37 | num_valid_passwords += 1
38 | }
39 | }
40 |
41 | return num_valid_passwords
42 | }
43 |
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List:
5 | return instr.strip().split("\n")
6 |
--------------------------------------------------------------------------------
/challenges/2020/02-passwordPhilosophy/testCases.json:
--------------------------------------------------------------------------------
1 | {
2 | "one": [
3 | {
4 | "input": "1-3 a: abcde\n1-3 b: cdefg\n2-9 c: ccccccccc",
5 | "expected": 2
6 | }
7 | ],
8 | "two": [
9 | {
10 | "input": "1-3 a: abcde\n1-3 b: cdefg\n2-9 c: ccccccccc",
11 | "expected": 1
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/README.md:
--------------------------------------------------------------------------------
1 | # [Day 3: Toboggan Trajectory](https://adventofcode.com/2020/day/3)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 3 - Toboggan Trajectory
8 | Python 3.8.5
9 |
10 | Info: could not open testCases.json. Skipping tests
11 |
12 | Answers
13 | Part 1: 292
14 | Part 2: 9354744432
15 |
16 | ❯ go run .\go\
17 | AoC 2020: day 3 - Toboggan Trajectory
18 | Go go1.15.2
19 |
20 | Info: could not open testCases.json. Skipping tests
21 |
22 | Answers
23 | Part 1: 292
24 | Part 2: 9354744432
25 | ```
26 |
27 |
28 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "strings"
4 |
5 | func parse(instr string) [][]rune {
6 | inputSlice := strings.Split(strings.TrimSpace(instr), "\n")
7 |
8 | var forest [][]rune
9 | for _, line := range inputSlice {
10 | forest = append(forest, []rune(line))
11 | }
12 | return forest
13 | }
14 |
15 | var tree_char = []rune("#")[0] // No idea why I can't just do rune("#")
16 |
17 | func findCollisions(forest [][]rune, xOffset, yOffset int) int {
18 | var encounteredTrees int
19 | var xPointer int
20 | var yPointer int
21 |
22 | for yPointer < len(forest) {
23 | row := forest[yPointer]
24 | targetIndex := xPointer % len(row)
25 | if row[targetIndex] == tree_char {
26 | encounteredTrees += 1
27 | }
28 | xPointer += xOffset
29 | yPointer += yOffset
30 | }
31 |
32 | return encounteredTrees
33 | }
34 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | return findCollisions(parse(instr), 3, 1)
5 | }
6 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | forest := parse(instr)
5 |
6 | offsetPairs := [][]int{
7 | {3, 1},
8 | {1, 1},
9 | {5, 1},
10 | {7, 1},
11 | {1, 2},
12 | }
13 |
14 | treeProduct := 1
15 |
16 | for _, pair := range offsetPairs {
17 | encounteredTrees := findCollisions(forest, pair[0], pair[1])
18 | treeProduct *= encounteredTrees
19 | }
20 |
21 | return treeProduct
22 | }
23 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 | tree_char = "#"
4 |
5 |
6 | def parse(instr: str) -> List:
7 | return [[char for char in line] for line in instr.strip().split("\n")]
8 |
9 |
10 | def find_collisions(forest: list, x_offset: int, y_offset: int) -> int:
11 | encountered_trees = 0
12 | x_pointer = 0
13 |
14 | for row in forest[::y_offset]:
15 | target_index = x_pointer % len(row)
16 | if row[target_index] == tree_char:
17 | encountered_trees += 1
18 | x_pointer += x_offset
19 |
20 | return encountered_trees
21 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | return find_collisions(parse(instr), 3, 1)
6 |
--------------------------------------------------------------------------------
/challenges/2020/03-tobogganTrajectory/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partTwo(instr: str) -> int:
5 | forest = parse(instr)
6 |
7 | tree_product = 1
8 |
9 | offset_pairs = [(3, 1), (1, 1), (5, 1), (7, 1), (1, 2)]
10 |
11 | for i, pair in enumerate(offset_pairs):
12 | encountered_trees = find_collisions(forest, *pair)
13 | tree_product *= encountered_trees
14 |
15 | return tree_product
16 |
--------------------------------------------------------------------------------
/challenges/2020/04-passportProcessing/README.md:
--------------------------------------------------------------------------------
1 | # [Day 4: Passport Processing](https://adventofcode.com/2020/day/4)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 4 - Passport Processing
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 | 2.2 pass
14 |
15 | Answers
16 | Part 1: 213
17 | Part 2: 147
18 |
19 | ❯ go run .\go\
20 | AoC 2020: day 4 - Passport Processing
21 | Go go1.15.2
22 |
23 | Test cases
24 | 1.1 pass
25 | 2.1 pass
26 | 2.2 pass
27 |
28 | Answers
29 | Part 1: 213
30 | Part 2: 147
31 | ```
32 |
33 |
34 |
--------------------------------------------------------------------------------
/challenges/2020/04-passportProcessing/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "strings"
4 |
5 | func parse(instr string) []string {
6 | inputSlice := strings.Split(strings.TrimSpace(instr), "\n\n")
7 | for i, x := range inputSlice {
8 | inputSlice[i] = strings.ReplaceAll(x, "\n", " ")
9 | }
10 | return inputSlice
11 | }
12 |
--------------------------------------------------------------------------------
/challenges/2020/04-passportProcessing/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "regexp"
4 |
5 | func PartOne(instr string) int {
6 | inputSlice := parse(instr)
7 |
8 | var valid_passports int
9 |
10 | testCases := []*regexp.Regexp{
11 | regexp.MustCompile(`byr:([^ ]+)`),
12 | regexp.MustCompile(`iyr:([^ ]+)`),
13 | regexp.MustCompile(`eyr:([^ ]+)`),
14 | regexp.MustCompile(`hgt:([^ ]+)`),
15 | regexp.MustCompile(`hcl:([^ ]+)`),
16 | regexp.MustCompile(`ecl:([^ ]+)`),
17 | regexp.MustCompile(`pid:([^ ]+)`),
18 | }
19 |
20 | for _, passport := range inputSlice {
21 | valid := true
22 | for _, tc := range testCases {
23 | if !tc.MatchString(passport) {
24 | valid = false
25 | break
26 | }
27 | }
28 |
29 | if valid {
30 | valid_passports += 1
31 | }
32 |
33 | }
34 |
35 | return valid_passports
36 | }
37 |
--------------------------------------------------------------------------------
/challenges/2020/04-passportProcessing/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List:
5 | return [x.replace("\n", " ") for x in instr.strip().split("\n\n")]
6 |
--------------------------------------------------------------------------------
/challenges/2020/04-passportProcessing/python/partOne.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | from common import *
4 |
5 |
6 | def partOne(instr: str) -> int:
7 | input_list = parse(instr)
8 |
9 | test_cases = [
10 | # Regex to match expression, bool if can be skipped
11 | [r"byr:([^ ]+)", False],
12 | [r"iyr:([^ ]+)", False],
13 | [r"eyr:([^ ]+)", False],
14 | [r"hgt:([^ ]+)", False],
15 | [r"hcl:([^ ]+)", False],
16 | [r"ecl:([^ ]+)", False],
17 | [r"pid:([^ ]+)", False],
18 | [r"cid:([^ ]+)", True],
19 | ]
20 |
21 | valid_passports = 0
22 |
23 | for passport in input_list:
24 |
25 | results = []
26 | for tc in test_cases:
27 | results.append([re.search(tc[0], passport) is not None, tc[1]])
28 |
29 | valid = True
30 | for r in results:
31 | if not (r[0] or r[1]):
32 | valid = False
33 | break
34 |
35 | valid_passports += 1 if valid else 0
36 |
37 | return valid_passports
38 |
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/README.md:
--------------------------------------------------------------------------------
1 | # [Day 5: Binary Boarding](https://adventofcode.com/2020/day/5)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 5 - Binary Boarding
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 1.2 pass
13 | 1.3 pass
14 |
15 | Answers
16 | Part 1: 989
17 | Part 2: 548
18 |
19 | ❯ go run .\go\
20 | AoC 2020: day 5 - Binary Boarding
21 | Go go1.15.2
22 |
23 | Test cases
24 | 1.1 pass
25 | 1.2 pass
26 | 1.3 pass
27 |
28 | Answers
29 | Part 1: 989
30 | Part 2: 548
31 | ```
32 |
33 |
34 |
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | inputSlice := parse(instr)
5 |
6 | var highestSeatId int
7 | for _, seat := range inputSlice {
8 | psr, psc := parseSeat(seat)
9 | seatId := getSeatId(psr, psc)
10 | if seatId > highestSeatId {
11 | highestSeatId = seatId
12 | }
13 | }
14 |
15 | return highestSeatId
16 | }
17 |
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | inputSlice := parse(instr)
5 |
6 | var seatMatrix [numRows][numCols]bool
7 | for _, seat := range inputSlice {
8 | row, col := parseSeat(seat)
9 | seatMatrix[row][col] = true
10 | }
11 |
12 | var (
13 | lastOne bool
14 | lastTwo bool
15 | )
16 |
17 | for row := 0; row < len(seatMatrix); row += 1 {
18 | for col := 0; col < len(seatMatrix[row]); col += 1 {
19 | this := seatMatrix[row][col]
20 | if lastTwo && !lastOne && this {
21 | // We need to get the previous item because at this point, we've already moved on one
22 | prevRow := row
23 | prevCol := col - 1
24 | if prevCol < 0 {
25 | prevRow -= 1
26 | prevCol += numCols
27 | }
28 | return getSeatId(prevRow, prevCol)
29 | }
30 | lastTwo = lastOne
31 | lastOne = this
32 | }
33 | }
34 |
35 | return 0
36 | }
37 |
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "5",
4 | "title": "Binary Boarding",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "BFFFBBFRRR",
9 | "expected": 567
10 | },
11 | {
12 | "input": "FFFBBBFRRR",
13 | "expected": 119
14 | },
15 | {
16 | "input": "BBFFBBFRLL",
17 | "expected": 820
18 | }
19 | ],
20 | "two": []
21 | }
22 | }
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 | front = "F"
4 | back = "B"
5 | left = "L"
6 | right = "R"
7 |
8 | num_rows = 128
9 | num_cols = 8
10 |
11 |
12 | def parse(instr: str) -> List:
13 | return instr.strip().split("\n")
14 |
15 |
16 | def decode_position(row_string: str, dec_char: str, inc_char: str, max_val: int) -> int:
17 | min_val = 0
18 | max_val -= 1
19 |
20 | current_range = (max_val + 1) - min_val
21 |
22 | for char in row_string.upper():
23 |
24 | range_modifier = current_range / 2
25 |
26 | if char == dec_char:
27 | max_val -= range_modifier
28 | elif char == inc_char:
29 | min_val += range_modifier
30 |
31 | current_range /= 2
32 |
33 | if row_string[-1] == dec_char:
34 | return min_val
35 | else:
36 | return max_val
37 |
38 |
39 | def parse_seat(seat_string: str) -> Tuple[int, int]:
40 | row = decode_position(seat_string[:7], front, back, num_rows)
41 | col = decode_position(seat_string[7:], left, right, num_cols)
42 |
43 | return int(row), int(col)
44 |
45 |
46 | def get_seat_id(row: int, col: int) -> int:
47 | return (row * 8) + col
48 |
--------------------------------------------------------------------------------
/challenges/2020/05-binaryBoarding/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | input_list = parse(instr)
6 |
7 | highest_seat_id = 0
8 | for seat in input_list:
9 | parsed_seat = parse_seat(seat)
10 | seat_id = get_seat_id(*parsed_seat)
11 | if seat_id > highest_seat_id:
12 | highest_seat_id = seat_id
13 |
14 | return highest_seat_id
15 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/README.md:
--------------------------------------------------------------------------------
1 | # [Day 6: Custom Customs](https://adventofcode.com/2020/day/6)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 6 - Custom Customs
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 |
14 | Answers
15 | Part 1: 6310
16 | Part 2: 3193
17 |
18 | ❯ go run .\go\
19 | AoC 2020: day 6 - Custom Customs
20 | Go go1.15.2
21 |
22 | Test cases
23 | 1.1 pass
24 | 2.1 pass
25 |
26 | Answers
27 | Part 1: 6310
28 | Part 2: 3193
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "strings"
4 |
5 | func parse(instr string) []string {
6 | return strings.Split(strings.TrimSpace(instr), "\n\n")
7 | }
8 |
9 | type Group struct {
10 | Questions []rune
11 | NumPax int
12 | }
13 |
14 | func IsRuneInSlice(r rune, s []rune) bool {
15 | for _, v := range s {
16 | if v == r {
17 | return true
18 | }
19 | }
20 | return false
21 | }
22 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "strings"
4 |
5 | func PartOne(instr string) int {
6 | newGroup := func(instr string) Group {
7 | g := Group{}
8 |
9 | individualPax := strings.Split(instr, "\n")
10 | g.NumPax = len(individualPax)
11 |
12 | for _, pax := range individualPax {
13 | for _, char := range pax {
14 | if !IsRuneInSlice(char, g.Questions) {
15 | g.Questions = append(g.Questions, char)
16 | }
17 | }
18 | }
19 |
20 | return g
21 | }
22 |
23 | var questionTotal int
24 |
25 | for _, x := range parse(instr) {
26 | questionTotal += len(newGroup(x).Questions)
27 | }
28 |
29 | return questionTotal
30 | }
31 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "strings"
4 |
5 | func PartTwo(instr string) int {
6 |
7 | checkChar := func(aq map[int][]rune, char rune) (isInAll bool) {
8 |
9 | isInAll = true
10 | for _, val := range aq {
11 | if !IsRuneInSlice(char, val) {
12 | isInAll = false
13 | break
14 | }
15 | }
16 |
17 | return
18 | }
19 |
20 | newGroup := func(instr string) Group {
21 | g := Group{}
22 |
23 | individualPax := strings.Split(instr, "\n")
24 | g.NumPax = len(individualPax)
25 |
26 | paxQuestions := make(map[int][]rune)
27 | for i, pax := range individualPax {
28 | paxQuestions[i] = []rune(pax)
29 | }
30 |
31 | for _, val := range paxQuestions {
32 | for _, char := range val {
33 | if checkChar(paxQuestions, char) {
34 | if !IsRuneInSlice(char, g.Questions) {
35 | g.Questions = append(g.Questions, char)
36 | }
37 | }
38 | }
39 | }
40 |
41 | return g
42 | }
43 |
44 | var questionTotal int
45 |
46 | for _, x := range parse(instr) {
47 | questionTotal += len(newGroup(x).Questions)
48 | }
49 |
50 | return questionTotal
51 | }
52 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "6",
4 | "title": "Custom Customs",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "abc\n\na\nb\nc\n\nab\nac\n\na\na\na\na\n\nb\n",
9 | "expected": 11
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "abc\n\na\nb\nc\n\nab\nac\n\na\na\na\na\n\nb\n",
15 | "expected": 6
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List[str]:
5 | return instr.strip().split("\n\n")
6 |
--------------------------------------------------------------------------------
/challenges/2020/06-customCustoms/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | class Group:
5 | questions: List[str]
6 | num_pax: int
7 |
8 | def __init__(self, instr: str) -> None:
9 | individual_pax = instr.split("\n")
10 | self.num_pax = len(individual_pax)
11 |
12 | self.questions = []
13 |
14 | for pax in individual_pax:
15 | for char in pax:
16 | if char not in self.questions:
17 | self.questions.append(char)
18 |
19 |
20 | def partOne(instr: str) -> int:
21 | groups = [Group(x) for x in parse(instr)]
22 |
23 | question_total = 0
24 |
25 | for group in groups:
26 | question_total += len(group.questions)
27 |
28 | return question_total
29 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/README.md:
--------------------------------------------------------------------------------
1 | # [Day 7: Handy Haversacks](https://adventofcode.com/2020/day/7)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 7 - Handy Haversacks
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 | 2.2 pass
14 |
15 | Answers
16 | Part 1: 300
17 | Part 2: 8030
18 |
19 | ❯ go run .\go\
20 | AoC 2020: day 7 - Handy Haversacks
21 | Go go1.15.2
22 |
23 | Test cases
24 | 1.1 pass
25 | 2.1 pass
26 | 2.2 pass
27 |
28 | Answers
29 | Part 1: 300
30 | Part 2: 8030
31 | ```
32 |
33 |
34 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "regexp"
5 | "strconv"
6 | "strings"
7 | )
8 |
9 | var (
10 | ruleRegex = regexp.MustCompile(`(.+) bags contain (.+).`)
11 | definitionRegex = regexp.MustCompile(`(\d+) (.+) bags?`)
12 | )
13 |
14 | const (
15 | targetColour = "shiny gold"
16 | )
17 |
18 | func parse(instr string) map[string]map[string]int {
19 | inp := strings.Split(strings.TrimSpace(instr), "\n")
20 | rules := make(map[string]map[string]int)
21 |
22 | for _, rule := range inp {
23 | rr := ruleRegex.FindAllStringSubmatch(rule, -1)
24 | containerBag := rr[0][1]
25 | ruleSet := strings.Split(rr[0][2], ", ")
26 |
27 | bagRules := make(map[string]int)
28 |
29 | for _, definition := range ruleSet {
30 | rsr := definitionRegex.FindAllStringSubmatch(definition, -1)
31 | if len(rsr) != 0 {
32 | i, _ := strconv.Atoi(rsr[0][1])
33 | bagRules[rsr[0][2]] = i
34 | }
35 | }
36 |
37 | rules[containerBag] = bagRules
38 |
39 | }
40 |
41 | return rules
42 | }
43 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func checkBag(ruleset map[string]map[string]int, testCl, targetCl string) bool {
4 | {
5 | var isPresent bool
6 | for v := range ruleset[testCl] {
7 | if v == targetCl {
8 | isPresent = true
9 | break
10 | }
11 | }
12 | if isPresent {
13 | return true
14 | }
15 | }
16 |
17 | for childColour := range ruleset[testCl] {
18 | if checkBag(ruleset, childColour, targetCl) {
19 | return true
20 | }
21 | }
22 |
23 | return false
24 |
25 | }
26 |
27 | func PartOne(instr string) int {
28 | rules := parse(instr)
29 |
30 | canContainTarget := 0
31 |
32 | for bagColour, _ := range rules {
33 | if bagColour != targetColour {
34 | if checkBag(rules, bagColour, targetColour) {
35 | canContainTarget += 1
36 | }
37 | }
38 | }
39 |
40 | return canContainTarget
41 | }
42 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func countForBag(ruleset map[string]map[string]int, testCl string) int {
4 | if len(ruleset[testCl]) == 0 {
5 | return -1
6 | }
7 |
8 | count := 0
9 |
10 | for childColour := range ruleset[testCl] {
11 | childBags := countForBag(ruleset, childColour)
12 | var v int
13 | if childBags == -1 {
14 | v = ruleset[testCl][childColour]
15 | } else {
16 | v = ruleset[testCl][childColour] * childBags
17 | v += ruleset[testCl][childColour]
18 | }
19 | count += v
20 | }
21 |
22 | return count
23 |
24 | }
25 |
26 | func PartTwo(instr string) int {
27 | return countForBag(parse(instr), targetColour)
28 | }
29 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/python/common.py:
--------------------------------------------------------------------------------
1 | import re
2 | from typing import Dict
3 |
4 |
5 | rule_regex = re.compile(r"(.+) bags contain (.+).")
6 | definition_regex = re.compile(
7 | r"(\d+) (.+) bags?"
8 | ) # A definiton is the section of a rule that contains the conditions
9 |
10 |
11 | target_colour = "shiny gold"
12 |
13 |
14 | def parse(instr: str) -> Dict[str, Dict[str, int]]:
15 | inp = instr.strip().split("\n")
16 |
17 | rules = {}
18 |
19 | for rule in inp:
20 | rr = rule_regex.match(rule)
21 | container_bag = rr.group(1)
22 | rule_set = rr.group(2).split(", ")
23 |
24 | bag_rules = {}
25 |
26 | for definition in rule_set:
27 | rsr = definition_regex.match(definition)
28 | # if this is false, it probably means we've encountered something saying "no other bags"
29 | if rsr is not None:
30 | bag_rules[rsr.group(2)] = int(rsr.group(1))
31 |
32 | rules[container_bag] = bag_rules
33 |
34 | return rules
35 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | from typing import Dict
3 |
4 |
5 | def check_bag(ruleset: Dict[str, Dict[str, int]], test_cl: str, target_cl: str) -> bool:
6 | if (
7 | target_cl in ruleset[test_cl]
8 | ): # bag colour can directly contain the target colour
9 | return True
10 |
11 | for child_colours in ruleset[test_cl]:
12 | if check_bag(ruleset, child_colours, target_cl):
13 | return True
14 |
15 | return False
16 |
17 |
18 | def partOne(instr: str) -> int:
19 | rules = parse(instr)
20 |
21 | can_contain_target = 0
22 |
23 | for bag_colour in rules:
24 | if bag_colour != target_colour:
25 | if check_bag(rules, bag_colour, target_colour):
26 | can_contain_target += 1
27 |
28 | return can_contain_target
29 |
--------------------------------------------------------------------------------
/challenges/2020/07-handyHaversacks/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | from typing import Dict
3 |
4 |
5 | def count_for_bag(ruleset: Dict[str, Dict[str, int]], test_cl: str) -> int:
6 | if len(ruleset[test_cl]) == 0:
7 | return -1
8 |
9 | count = 0
10 |
11 | for child_colour in ruleset[test_cl]:
12 | child_bags = count_for_bag(ruleset, child_colour)
13 | if child_bags == -1:
14 | v = ruleset[test_cl][child_colour]
15 | else:
16 | v = ruleset[test_cl][child_colour] * child_bags
17 | # The below line includes the number of bags that contain all the children - for
18 | # example, if you had a bag type that had 6 child bags, and there were 3 of these
19 | # master bags, the line above would add all the child bags (6*3 of them), and the line
20 | # below would add the 3 container bags.
21 | v += ruleset[test_cl][child_colour]
22 | count += v
23 |
24 | return count
25 |
26 |
27 | def partTwo(instr: str) -> int:
28 | rules = parse(instr)
29 | return count_for_bag(rules, target_colour)
30 |
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/README.md:
--------------------------------------------------------------------------------
1 | # [Day 8: Handheld Halting](https://adventofcode.com/2020/day/8)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 8 - Handheld Halting
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 |
14 | Answers
15 | Part 1: 1816
16 | Part 2: 1149
17 |
18 | ❯ go run .\go\
19 | AoC 2020: day 8 - Handheld Halting
20 | Go go1.15.2
21 |
22 | Test cases
23 | 1.1 pass
24 | 2.1 pass
25 |
26 | Answers
27 | Part 1: 1816
28 | Part 2: 1149
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | type Instruction struct {
9 | Opcode string
10 | Operand int
11 | }
12 |
13 | func NewInstruction(instr string) Instruction {
14 | icp := strings.Split(instr, " ")
15 | opc, err := strconv.Atoi(icp[1])
16 | if err != nil {
17 | panic(err)
18 | }
19 | return Instruction{
20 | Opcode: icp[0],
21 | Operand: opc,
22 | }
23 | }
24 |
25 | func parse(instr string) (o []Instruction) {
26 | for _, v := range strings.Split(strings.TrimSpace(instr), "\n") {
27 | o = append(o, NewInstruction(v))
28 | }
29 | return
30 | }
31 |
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | instructions := parse(instr)
5 |
6 | var (
7 | acc int
8 | pc int
9 | visited []int
10 | )
11 |
12 | for {
13 | {
14 | var found bool
15 | for _, v := range visited {
16 | if v == pc {
17 | found = true
18 | break
19 | }
20 | }
21 | if found {
22 | return acc
23 | } else {
24 | visited = append(visited, pc)
25 | }
26 | }
27 |
28 | cir := instructions[pc]
29 |
30 | if cir.Opcode == "jmp" {
31 | pc += cir.Operand
32 | } else {
33 | switch cir.Opcode {
34 | case "acc":
35 | acc += cir.Operand
36 | case "nop":
37 | }
38 |
39 | pc += 1
40 |
41 | }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "8",
4 | "title": "Handheld Halting",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "nop +0\nacc +1\njmp +4\nacc +3\njmp -3\nacc -99\nacc +1\njmp -4\nacc +6",
9 | "expected": 5
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "nop +0\nacc +1\njmp +4\nacc +3\njmp -3\nacc -99\nacc +1\njmp -4\nacc +6",
15 | "expected": 8
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | class Instruction:
5 | opcode: str
6 | operand: int
7 |
8 | def __init__(self, instr: str) -> None:
9 | self.opcode, t = instr.split(" ")
10 | self.operand = int(t)
11 |
12 |
13 | def parse(instr: str) -> List[Instruction]:
14 | return [Instruction(x) for x in instr.strip().split("\n")]
15 |
--------------------------------------------------------------------------------
/challenges/2020/08-handheldHalting/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | instructions = parse(instr)
6 |
7 | acc = 0
8 | pc = 0
9 |
10 | visited = [] # indexes of visited instructions
11 |
12 | while True:
13 |
14 | if pc in visited:
15 | return acc
16 | else:
17 | visited.append(pc)
18 |
19 | cir = instructions[pc]
20 |
21 | if cir.opcode == "jmp":
22 | pc += cir.operand
23 | else:
24 | if cir.opcode == "acc":
25 | acc += cir.operand
26 | elif cir.opcode == "nop":
27 | pass
28 | pc += 1
29 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/README.md:
--------------------------------------------------------------------------------
1 | # [Day 9: Encoding Error](https://adventofcode.com/2020/day/9)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 9 - Encoding Error
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 |
14 | Answers
15 | Part 1: 530627549
16 | Part 2: 77730285
17 |
18 | ❯ go run .\go\
19 | AoC 2020: day 9 - Encoding Error
20 | Go go1.15.2
21 |
22 | Test cases
23 | 1.1 pass
24 | 2.1 pass
25 |
26 | Answers
27 | Part 1: 530627549
28 | Part 2: 77730285
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | func parse(instr string) (o []int) {
9 | for _, x := range strings.Split(strings.TrimSpace(instr), "\n") {
10 | i, err := strconv.Atoi(x)
11 | if err != nil {
12 | panic(err)
13 | }
14 | o = append(o, i)
15 | }
16 | return
17 | }
18 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | inputSlice := parse(instr)
5 |
6 | targetValue := PartOne(instr)
7 | if targetValue == 0 {
8 | return 0
9 | }
10 |
11 | var pointer int
12 | for pointer < len(inputSlice) {
13 | startPoint := pointer
14 | iptr := pointer
15 | var count int
16 | for iptr < len(inputSlice) {
17 | count += inputSlice[iptr]
18 |
19 | if count == targetValue {
20 | if iptr-startPoint < 2 {
21 | break
22 | }
23 |
24 | allValues := inputSlice[startPoint : iptr+1]
25 | min := allValues[0]
26 | max := allValues[0]
27 | for _, v := range allValues {
28 | if v < min {
29 | min = v
30 | }
31 | if v > max {
32 | max = v
33 | }
34 | }
35 | return min + max
36 | }
37 |
38 | if count > targetValue {
39 | break
40 | }
41 |
42 | iptr += 1
43 | }
44 |
45 | pointer += 1
46 | }
47 |
48 | return 0
49 | }
50 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "9",
4 | "title": "Encoding Error",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "35\n20\n15\n25\n47\n40\n62\n55\n65\n95\n102\n117\n150\n182\n127\n219\n299\n277\n309\n576",
9 | "expected": 127
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "35\n20\n15\n25\n47\n40\n62\n55\n65\n95\n102\n117\n150\n182\n127\n219\n299\n277\n309\n576",
15 | "expected": 62
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List[int]:
5 | return [int(x) for x in instr.strip().split("\n")]
6 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/python/partOne.py:
--------------------------------------------------------------------------------
1 | from typing import Set
2 |
3 | from common import *
4 |
5 |
6 | def has_combinations(options: Set[int], target: int) -> bool:
7 | # Returns true of the options set has two values that sum to be the target, else returns false
8 |
9 | options = sorted(options)
10 |
11 | l_ptr = 0
12 | r_ptr = len(options) - 1
13 |
14 | while l_ptr < r_ptr:
15 | v = options[l_ptr] + options[r_ptr]
16 | if v == target:
17 | return True
18 | elif v < target:
19 | l_ptr += 1
20 | else:
21 | r_ptr -= 1
22 |
23 | return False
24 |
25 |
26 | def partOne(instr: str) -> int:
27 | input_list = parse(instr)
28 |
29 | preamble_len = 25
30 | if len(input_list) < 30: # This is for tests
31 | preamble_len = 5
32 |
33 | pointer = preamble_len
34 | while pointer < len(input_list):
35 | if not has_combinations(
36 | set(input_list[pointer - preamble_len : pointer]), input_list[pointer]
37 | ):
38 | return input_list[pointer]
39 | pointer += 1
40 |
41 | return 0
42 |
--------------------------------------------------------------------------------
/challenges/2020/09-encodingError/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | from partOne import partOne
3 |
4 |
5 | def partTwo(instr: str) -> int:
6 | input_list = parse(instr)
7 |
8 | target_value = partOne(instr)
9 | if target_value == 0:
10 | return 0
11 |
12 | pointer = 0
13 | while pointer < len(input_list):
14 | # iterate consecutive values from here
15 | start_point = pointer
16 | iptr = pointer # Internal PoinTeR
17 | count = 0
18 | while iptr < len(input_list):
19 | count += input_list[iptr]
20 |
21 | if count == target_value:
22 | # must be at least two values
23 | if iptr - start_point < 2:
24 | break
25 |
26 | all_values = input_list[start_point : iptr + 1]
27 | return min(all_values) + max(all_values)
28 |
29 | if count > target_value:
30 | break
31 |
32 | iptr += 1
33 |
34 | pointer += 1
35 |
36 | return 0
37 |
--------------------------------------------------------------------------------
/challenges/2020/10-adapterArray/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "sort"
5 | "strconv"
6 | "strings"
7 | )
8 |
9 | func PartTwo(instr string) int {
10 | var joltages []int
11 | for _, x := range strings.Split(strings.TrimSpace(instr), "\n") {
12 | i, err := strconv.Atoi(x)
13 | if err != nil {
14 | panic(err)
15 | }
16 | joltages = append(joltages, i)
17 | }
18 | sort.Ints(joltages)
19 |
20 | routeLengths := map[int]int{0: 1}
21 |
22 | for _, joltage := range joltages {
23 | var totalRoutes int
24 | for _, n := range []int{1, 2, 3} {
25 | v, exists := routeLengths[joltage-n]
26 | if !exists {
27 | v = 0
28 | }
29 | totalRoutes += v
30 | }
31 | routeLengths[joltage] = totalRoutes
32 | }
33 |
34 | return routeLengths[joltages[len(joltages)-1]]
35 | }
36 |
--------------------------------------------------------------------------------
/challenges/2020/10-adapterArray/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "10",
4 | "title": "Adapter Array",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "16\n10\n15\n5\n1\n11\n7\n19\n6\n12\n4",
9 | "expected": 35
10 | },
11 | {
12 | "input": "28\n33\n18\n42\n31\n14\n46\n20\n48\n47\n24\n23\n49\n45\n19\n38\n39\n11\n1\n32\n25\n35\n8\n17\n7\n9\n4\n2\n34\n10\n3",
13 | "expected": 220
14 | }
15 | ],
16 | "two": [
17 | {
18 | "input": "16\n10\n15\n5\n1\n11\n7\n19\n6\n12\n4",
19 | "expected": 8
20 | },
21 | {
22 | "input": "28\n33\n18\n42\n31\n14\n46\n20\n48\n47\n24\n23\n49\n45\n19\n38\n39\n11\n1\n32\n25\n35\n8\n17\n7\n9\n4\n2\n34\n10\n3",
23 | "expected": 19208
24 | }
25 | ]
26 | }
27 | }
--------------------------------------------------------------------------------
/challenges/2020/10-adapterArray/python/partTwo.py:
--------------------------------------------------------------------------------
1 | def partTwo(instr: str) -> int:
2 | joltages = sorted([int(x) for x in instr.strip().split("\n")])
3 |
4 | route_lengths = {0: 1}
5 | for joltage in joltages:
6 | total_routes = 0
7 | # Get the route lengths for the three previous joltages
8 | for n in [1, 2, 3]:
9 | total_routes += route_lengths.get(joltage - n, 0)
10 | print(joltage, total_routes)
11 | route_lengths[joltage] = total_routes
12 |
13 | return route_lengths[max(joltages)]
14 |
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/0.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/11-seatingSystem/0.gif
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/11-seatingSystem/1.gif
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/README.md:
--------------------------------------------------------------------------------
1 | # [Day 11: Seating System](https://adventofcode.com/2020/day/11)
2 |
3 | ### Related
4 |
5 | * [Wikipedia - Cellular automata](https://en.wikipedia.org/wiki/Cellular_automaton)
6 | * [Wikipedia - Moore neighbourhood](https://en.wikipedia.org/wiki/Moore_neighborhood)
7 |
8 | ### Visualisation
9 |
10 | | Part one | Part two |
11 | | ------------------------------ | ------------------------------ |
12 | |  |  |
13 |
14 | ---
15 |
16 | Script output
17 |
18 | ```
19 | ❯ python .\python\
20 | AoC 2020: day 11 - Seating System
21 | Python 3.8.5
22 |
23 | Test cases
24 | 1.1 pass
25 | 2.1 pass
26 |
27 | Answers
28 | Part 1: 2283
29 | Part 2: 2054
30 |
31 | ❯ go run .\go\
32 | AoC 2020: day 11 - Seating System
33 | Go go1.15.2
34 |
35 | Test cases
36 | 1.1 pass
37 | 2.1 pass
38 |
39 | Answers
40 | Part 1: 2283
41 | Part 2: 2054
42 | ```
43 |
44 |
45 |
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func getNewStateOne(numNeighbours int, oldState rune) rune {
4 | if numNeighbours == 0 {
5 | return filledSeat
6 | } else if numNeighbours >= 4 && oldState == filledSeat {
7 | return openSeat
8 | }
9 | return oldState
10 | }
11 |
12 | func countNeighboursOne(hall [][]rune, currentPos [2]int, hallSize [2]int) (numNeighbours int) {
13 | row := currentPos[0]
14 | col := currentPos[1]
15 |
16 | for _, position := range lookupPositions {
17 | test_x_pos := position[0] + col
18 | test_y_pos := position[1] + row
19 |
20 | if 0 <= test_x_pos && test_x_pos < hallSize[0] && 0 <= test_y_pos && test_y_pos < hallSize[1] {
21 | if hall[test_y_pos][test_x_pos] == filledSeat {
22 | numNeighbours += 1
23 | }
24 | }
25 | }
26 |
27 | return
28 | }
29 |
30 | func PartOne(instr string) int {
31 | return run(parse(instr), countNeighboursOne, getNewStateOne)
32 | }
33 |
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func getNewStateTwo(numNeighbours int, oldState rune) rune {
4 | if numNeighbours == 0 {
5 | return filledSeat
6 | } else if numNeighbours >= 5 && oldState == filledSeat {
7 | return openSeat
8 | }
9 | return oldState
10 | }
11 |
12 | func countNeighboursTwo(hall [][]rune, currentPos [2]int, hallSize [2]int) (numNeighbours int) {
13 | row := currentPos[0]
14 | col := currentPos[1]
15 |
16 | for _, position := range lookupPositions {
17 | test_x_pos := position[0] + col
18 | test_y_pos := position[1] + row
19 |
20 | for 0 <= test_x_pos && test_x_pos < hallSize[0] && 0 <= test_y_pos && test_y_pos < hallSize[1] {
21 |
22 | testLocation := hall[test_y_pos][test_x_pos]
23 |
24 | if testLocation == filledSeat {
25 | numNeighbours += 1
26 | }
27 |
28 | if testLocation == openSeat || testLocation == filledSeat {
29 | break
30 | }
31 |
32 | test_x_pos += position[0]
33 | test_y_pos += position[1]
34 |
35 | }
36 | }
37 |
38 | return
39 | }
40 |
41 | func PartTwo(instr string) int {
42 | return run(parse(instr), countNeighboursTwo, getNewStateTwo)
43 | }
44 |
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "11",
4 | "title": "Seating System",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "L.LL.LL.LL\nLLLLLLL.LL\nL.L.L..L..\nLLLL.LL.LL\nL.LL.LL.LL\nL.LLLLL.LL\n..L.L.....\nLLLLLLLLLL\nL.LLLLLL.L\nL.LLLLL.LL\n",
9 | "expected": 37
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "L.LL.LL.LL\nLLLLLLL.LL\nL.L.L..L..\nLLLL.LL.LL\nL.LL.LL.LL\nL.LLLLL.LL\n..L.L.....\nLLLLLLLLLL\nL.LLLLLL.L\nL.LLLLL.LL\n",
15 | "expected": 26
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/11-seatingSystem/python/partOne.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 | from common import *
4 |
5 |
6 | def get_new_state(num_neighbours: int, old_state: str) -> str:
7 | if num_neighbours == 0:
8 | return filled_seat
9 | elif num_neighbours >= 4 and old_state == filled_seat:
10 | return open_seat
11 |
12 | return old_state
13 |
14 |
15 | def count_neighbours(
16 | hall: List[List[str]], current_pos: Tuple[int, int], hall_size: Tuple[int, int]
17 | ) -> int:
18 | num_neighbours = 0
19 |
20 | row, col = current_pos
21 |
22 | for (x, y) in lookup_positions:
23 | test_x_pos = x + col
24 | test_y_pos = y + row
25 |
26 | if 0 <= test_x_pos < hall_size[0] and 0 <= test_y_pos < hall_size[1]:
27 | if hall[test_y_pos][test_x_pos] == filled_seat:
28 | num_neighbours += 1
29 |
30 | return num_neighbours
31 |
32 |
33 | def partOne(instr: str) -> int:
34 | return run(parse(instr), count_neighbours, get_new_state)
35 |
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/0.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/12-rainRisk/0.gif
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/12-rainRisk/1.gif
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "12",
4 | "title": "Rain Risk",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "F10\nN3\nF7\nR90\nF11",
9 | "expected": 25
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "F10\nN3\nF7\nR90\nF11",
15 | "expected": 286
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 |
4 | class Instruction:
5 | action: str
6 | magnitude: int
7 | raw: str
8 |
9 | def __init__(self, instruction: str) -> None:
10 | self.action = instruction[0].lower()
11 | self.magnitude = int(instruction[1:])
12 | self.raw = instruction
13 |
14 |
15 | def parse(instr: str) -> List[Instruction]:
16 | return [Instruction(x) for x in instr.strip().split("\n")]
17 |
18 |
19 | def calculate_direction_deltas(direction: str, amount: int) -> Tuple[int, int]:
20 | # returns a pair of deltas representing lat,long
21 | lat_delta = 0
22 | long_delta = 0
23 |
24 | if direction == "n":
25 | lat_delta += amount
26 | elif direction == "s":
27 | lat_delta -= amount
28 |
29 | elif direction == "e":
30 | long_delta += amount
31 | elif direction == "w":
32 | long_delta -= amount
33 |
34 | else:
35 | raise AssertionError(f"invalid direction '{direction}'")
36 |
37 | return lat_delta, long_delta
38 |
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/quadrants.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/12-rainRisk/quadrants.png
--------------------------------------------------------------------------------
/challenges/2020/12-rainRisk/rotation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/12-rainRisk/rotation.png
--------------------------------------------------------------------------------
/challenges/2020/13-shuttleSearch/README.md:
--------------------------------------------------------------------------------
1 | # [Day 13: Shuttle Search](https://adventofcode.com/2020/day/13)
2 |
3 | No, I don't really know why the maths works, but it works!
4 |
5 | Here are the notes I made for part two to work this out for a test case before implementing it for the first time to make sure that my method worked.
6 |
7 | 
8 |
9 | ### Related
10 |
11 | * [Maths with Jay - Chinese remainder theorem](https://www.youtube.com/watch?v=zIFehsBHB8o)
12 | * [StackOverflow - Modular multiplicative inverse function in Python](https://stackoverflow.com/a/9758173)
13 |
14 | Script output
15 |
16 | ```
17 | ❯ python .\python\
18 | AoC 2020: day 13 - Shuttle Search
19 | Python 3.8.5
20 |
21 | Test cases
22 | 1.1 pass
23 | 2.1 pass
24 | 2.2 pass
25 | 2.3 pass
26 | 2.4 pass
27 | 2.5 pass
28 | 2.6 pass
29 |
30 | Answers
31 | Part 1: 4782
32 | Part 2: 1118684865113056
33 | ```
34 |
35 |
36 |
--------------------------------------------------------------------------------
/challenges/2020/13-shuttleSearch/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "13",
4 | "title": "Shuttle Search",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "939\n7,13,x,x,59,x,31,19",
9 | "expected": 295
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "939\n7,13,x,x,59,x,31,19",
15 | "expected": 1068781
16 | },
17 | {
18 | "input": "1\n17,x,13,19",
19 | "expected": 3417
20 | },
21 | {
22 | "input": "1\n67,7,59,61",
23 | "expected": 754018
24 | },
25 | {
26 | "input": "1\n67,x,7,59,61",
27 | "expected": 779210
28 | },
29 | {
30 | "input": "1\n67,7,x,59,61",
31 | "expected": 1261476
32 | },
33 | {
34 | "input": "1\n1789,37,47,1889",
35 | "expected": 1202161486
36 | }
37 | ]
38 | }
39 | }
--------------------------------------------------------------------------------
/challenges/2020/13-shuttleSearch/python/partOne.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | class Timetable:
5 | earliest_departure: int
6 | services: List[int]
7 |
8 | def __init__(self, earliest_departure: int, services: str):
9 | self.earliest_departure = earliest_departure
10 | self.services = [int(s) for s in services.split(",") if s != "x"]
11 |
12 |
13 | def parse(instr: str) -> Timetable:
14 | instr = instr.strip().split("\n")
15 | return Timetable(int(instr[0]), instr[1])
16 |
17 |
18 | def partOne(instr: str) -> int:
19 | timetable = parse(instr)
20 |
21 | earliest_times = []
22 | for service in timetable.services:
23 | earliest_times.append(
24 | (service, (int(timetable.earliest_departure / service) + 1) * service)
25 | )
26 |
27 | route, earliest_departure = min(earliest_times, key=lambda x: x[1])
28 |
29 | return route * (earliest_departure - timetable.earliest_departure)
30 |
--------------------------------------------------------------------------------
/challenges/2020/13-shuttleSearch/python/partTwo.py:
--------------------------------------------------------------------------------
1 | def partTwo(instr: str) -> int:
2 | # This is the parsing section
3 | service_list = instr.strip().split("\n")[-1].split(",")
4 |
5 | eqns = []
6 | for i, svc in enumerate(service_list):
7 | if svc == "x":
8 | continue
9 | svc = int(svc)
10 |
11 | v = 0
12 | if i != 0:
13 | v = svc - i # This is the only maths stuff in the parsing
14 |
15 | eqns.append((v, svc))
16 |
17 | # This is the maths section
18 |
19 | n = 1
20 | for (_, v) in eqns:
21 | n *= v
22 |
23 | sigma_x = 0
24 | for (bi, ni) in eqns:
25 | # this type cast could potentially cause a problem.
26 | # int required for pow function and the division *should* produce a whole number anyway
27 | Ni = int(n / ni)
28 | yi = pow(Ni, -1, ni) # https://stackoverflow.com/a/9758173
29 | sigma_x += bi * Ni * yi
30 |
31 | return sigma_x % n
32 |
--------------------------------------------------------------------------------
/challenges/2020/13-shuttleSearch/working.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/13-shuttleSearch/working.jpg
--------------------------------------------------------------------------------
/challenges/2020/14-dockingData/README.md:
--------------------------------------------------------------------------------
1 | # [Day 14: Docking Data](https://adventofcode.com/2020/day/14)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\
7 | AoC 2020: day 14 - Docking Data
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass
12 | 2.1 pass
13 |
14 | Answers
15 | Part 1: 8570568288597
16 | Part 2: 3289441921203
17 |
18 | ❯ go run .\go\
19 | AoC 2020: day 14 - Docking Data
20 | Go go1.15.2
21 |
22 | Test cases
23 | 1.1 pass
24 | 2.1 pass
25 |
26 | Answers
27 | Part 1: 8570568288597
28 | Part 2: 3289441921203
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/challenges/2020/14-dockingData/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | func applyMask(number int, mask string) int {
9 | mask = strings.ToLower(mask)
10 | value := numberToBase(number, 2)
11 | value = zfill(value, len(mask)-len(value))
12 | var combi string
13 | for i := 0; i < len(value); i += 1 {
14 | v := string(value[i])
15 | m := string(mask[i])
16 |
17 | if m == "x" {
18 | combi += v
19 | } else {
20 | combi += m
21 | }
22 | }
23 | ix, err := strconv.ParseInt(combi, 2, 64)
24 | if err != nil {
25 | panic(err)
26 | }
27 | return int(ix)
28 | }
29 |
30 | func PartOne(instr string) int {
31 | inputInstructions := parse(instr)
32 | memory := make(map[int]int)
33 |
34 | for _, instruction := range inputInstructions {
35 | memory[instruction.Address] = applyMask(instruction.Value, instruction.Mask)
36 | }
37 |
38 | var sigma int
39 | for _, v := range memory {
40 | sigma += v
41 | }
42 | return sigma
43 | }
44 |
--------------------------------------------------------------------------------
/challenges/2020/14-dockingData/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "14",
4 | "title": "Docking Data",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X\nmem[8] = 11\nmem[7] = 101\nmem[8] = 0\n",
9 | "expected": 165
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "mask = 000000000000000000000000000000X1001X\nmem[42] = 100\nmask = 00000000000000000000000000000000X0XX\nmem[26] = 1\n",
15 | "expected": 208
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/14-dockingData/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def apply_mask(number: int, mask: str) -> int:
5 | # There has to be a better way to do this... but oh well
6 | # it works, after all
7 | value = number_to_base(number, 2).zfill(len(mask))
8 | combi = ""
9 | for (v, m) in zip(value, mask.lower()):
10 | if m == "x":
11 | combi += v
12 | else:
13 | combi += m
14 | return int(combi, 2)
15 |
16 |
17 | def partOne(instr: str) -> int:
18 | input_instructions = parse(instr)
19 | memory = {}
20 |
21 | for instruction in input_instructions:
22 | memory[instruction.address] = apply_mask(instruction.value, instruction.mask)
23 |
24 | sigma = 0
25 | for key in memory:
26 | sigma += memory[key]
27 |
28 | return sigma
29 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/15-rambunctiousRecitation/0.png
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/1-hires.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/15-rambunctiousRecitation/1-hires.png
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/1-lores.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/15-rambunctiousRecitation/1-lores.png
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/README.md:
--------------------------------------------------------------------------------
1 | # [Day 15: Rambunctious Recitation](https://adventofcode.com/2020/day/15)
2 |
3 | ### Visualisation
4 |
5 | | Part one | Part two |
6 | | ------------------------------ | ------------------------------------ |
7 | |  |  |
8 |
9 | ### Related
10 |
11 | - [Numberphile - Don't Know (the Van Eck Sequence)](https://www.youtube.com/watch?v=etMJxB-igrc)
12 |
13 | Script output
14 |
15 | ```
16 | ❯ python .\python\
17 | AoC 2020: day 15 - Rambunctious Recitation
18 | Python 3.8.5
19 |
20 | Test cases
21 | 1.1 pass
22 | 1.2 pass
23 | 1.3 pass
24 | 1.4 pass
25 | 1.5 pass
26 | 1.6 pass
27 | 2.1 pass
28 |
29 | Answers
30 | Part 1: 206
31 | Part 2: 955
32 |
33 | ❯ go run .\go\
34 | AoC 2020: day 15 - Rambunctious Recitation
35 | Go go1.15.2
36 |
37 | Test cases
38 | 1.1 pass
39 | 1.2 pass
40 | 1.3 pass
41 | 1.4 pass
42 | 1.5 pass
43 | 1.6 pass
44 | 2.1 pass
45 |
46 | Answers
47 | Part 1: 206
48 | Part 2: 955
49 | ```
50 |
51 |
52 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | func findValueN(instr string, threshold int) int {
9 | var inp []int
10 | for _, x := range strings.Split(strings.TrimSpace(instr), ",") {
11 | i, err := strconv.Atoi(x)
12 | if err != nil {
13 | panic(err)
14 | }
15 | inp = append(inp, i)
16 | }
17 |
18 | indexes := make(map[int]int)
19 |
20 | for i, n := range inp {
21 | indexes[n] = i
22 | }
23 |
24 | for len(inp) < threshold {
25 | c := len(inp) - 1
26 | previousNumber := inp[c]
27 |
28 | var previousOccuranceIndex int
29 | val, found := indexes[previousNumber]
30 | if !found {
31 | previousOccuranceIndex = -1
32 | } else {
33 | previousOccuranceIndex = val
34 | }
35 |
36 | var newNumber int
37 |
38 | if previousOccuranceIndex != -1 {
39 | newNumber = c - previousOccuranceIndex
40 | }
41 |
42 | indexes[previousNumber] = c
43 | inp = append(inp, newNumber)
44 | }
45 |
46 | return inp[len(inp)-1]
47 | }
48 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | return findValueN(instr, 2020)
5 | }
6 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | return findValueN(instr, 30000000)
5 | }
6 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "15",
4 | "title": "Rambunctious Recitation",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "0,3,6",
9 | "expected": 436
10 | },
11 | {
12 | "input": "1,3,2",
13 | "expected": 1
14 | },
15 | {
16 | "input": "1,2,3",
17 | "expected": 27
18 | },
19 | {
20 | "input": "2,3,1",
21 | "expected": 78
22 | },
23 | {
24 | "input": "3,2,1",
25 | "expected": 438
26 | },
27 | {
28 | "input": "3,1,2",
29 | "expected": 1836
30 | }
31 | ],
32 | "two": [
33 | {
34 | "input": "0,3,6",
35 | "info": "other test cases ommitted because part two takes quite a while",
36 | "expected": 175594
37 | }
38 | ]
39 | }
40 | }
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 |
4 | def find_value_n(instr: str, threshold: int) -> Tuple[int, List[int]]:
5 | inp = [int(x) for x in instr.strip().split(",")]
6 |
7 | indexes = {}
8 |
9 | for i, n in enumerate(inp):
10 | indexes[n] = i
11 |
12 | while len(inp) < threshold:
13 | c = len(inp) - 1
14 | previous_number = inp[c]
15 |
16 | previous_occurance_index = indexes.get(previous_number, None)
17 | new_number = 0
18 |
19 | if previous_occurance_index is not None:
20 | new_number = c - previous_occurance_index
21 |
22 | indexes[previous_number] = c
23 |
24 | inp.append(new_number)
25 |
26 | return inp[-1], inp
27 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | x, _ = find_value_n(instr, 2020)
6 | return x
7 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partTwo(instr: str) -> int:
5 | x, _ = find_value_n(instr, 30000000)
6 | return x
7 |
--------------------------------------------------------------------------------
/challenges/2020/15-rambunctiousRecitation/python/visualise.py:
--------------------------------------------------------------------------------
1 | import common
2 | import matplotlib.pyplot as plt
3 | from typing import List
4 |
5 |
6 | def make_graph(data: List[int], n: int):
7 | line_colour = "#3572a5"
8 | plt.plot(list(range(len(data))), data, color=line_colour)
9 | plt.title(f"AoC 2020, day 15 part {n}")
10 | plt.xlabel("Iteration number")
11 | plt.ylabel("Value")
12 |
13 |
14 | def visualise(instr: str):
15 | print("Running part one...")
16 | _, one = common.find_value_n(instr, 2020)
17 | print("Making graph")
18 | make_graph(one, 1)
19 | print("Saving")
20 | plt.savefig("0.png")
21 | plt.clf()
22 | print("Running part two...")
23 | _, two = common.find_value_n(instr, 30000000)
24 | print("Making graph")
25 | make_graph(two, 2)
26 | print("Saving low resolution")
27 | plt.savefig("1-lores.png")
28 | print("Saving high resolution")
29 | fig = plt.gcf()
30 | fig.set_size_inches(20.48, 10.8)
31 | fig.savefig("1-hires.png", dpi=100)
32 |
--------------------------------------------------------------------------------
/challenges/2020/16-ticketTranslation/README.md:
--------------------------------------------------------------------------------
1 | # [Day 16: Ticket Translation](https://adventofcode.com/2020/day/16)
2 |
3 | It took me a long while to realise each column could have multiple different possibilities for which ticket field it could be.
4 |
5 | Script output
6 |
7 | ```
8 | ❯ python .\python\
9 | AoC 2020: day 16 - Ticket Translation
10 | Python 3.8.5
11 |
12 | Test cases
13 | 1.1 pass
14 | 2.1 pass
15 |
16 | Answers
17 | Part 1: 29019
18 | Part 2: 517827547723
19 |
20 | ❯ go run .\go\
21 | AoC 2020: day 16 - Ticket Translation
22 | Go go1.15.2
23 |
24 | Test cases
25 | 1.1 pass
26 | 2.1 pass
27 |
28 | Answers
29 | Part 1: 29019
30 | Part 2: 517827547723
31 | ```
32 |
33 |
34 |
--------------------------------------------------------------------------------
/challenges/2020/16-ticketTranslation/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartOne(instr string) int {
4 | rules, _, tickets := parse(instr)
5 | invalidValues, _ := findInvalid(rules, tickets)
6 |
7 | var sigma int
8 | for _, v := range invalidValues {
9 | sigma += v
10 | }
11 |
12 | return sigma
13 | }
14 |
--------------------------------------------------------------------------------
/challenges/2020/16-ticketTranslation/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "16",
4 | "title": "Ticket Translation",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "class: 1-3 or 5-7\nrow: 6-11 or 33-44\nseat: 13-40 or 45-50\n\nyour ticket:\n7,1,14\n\nnearby tickets:\n7,3,47\n40,4,50\n55,2,20\n38,6,12",
9 | "expected": 71
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input":"departure class: 0-1 or 4-19\nrow: 0-5 or 8-19\nseat: 0-13 or 16-19\n\nyour ticket:\n11,12,13\n\nnearby tickets:\n3,9,18\n15,1,5\n5,14,9\n",
15 | "expected": 12
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/16-ticketTranslation/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | rules, _, tickets = parse(instr)
6 |
7 | invalid_values, _ = find_invalid(rules, tickets)
8 |
9 | return sum(invalid_values)
10 |
--------------------------------------------------------------------------------
/challenges/2020/17-conwayCubes/README.md:
--------------------------------------------------------------------------------
1 | # [Day 17: Conway Cubes](https://adventofcode.com/2020/day/17)
2 |
3 | I would not have got this if it wasn't for [this Reddit comment](https://www.reddit.com/r/adventofcode/comments/kf5mzc/2020_day_17_i_am_now_sad/gg6u25j).
4 |
5 | Script output
6 |
7 | ```
8 | ❯ python .\python\
9 | AoC 2020: day 17 - Conway Cubes
10 | Python 3.8.5
11 |
12 | Test cases
13 | 1.1 pass
14 | 2.1 pass
15 |
16 | Answers
17 | Part 1: 232
18 | Part 2: 1620
19 | ```
20 |
21 |
--------------------------------------------------------------------------------
/challenges/2020/17-conwayCubes/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "17",
4 | "title": "Conway Cubes",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": ".#.\n..#\n###\n",
9 | "expected": 112
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": ".#.\n..#\n###\n",
15 | "expected": 848
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/17-conwayCubes/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, Tuple, Callable
2 | import itertools
3 |
4 |
5 | active_marker = "#"
6 | inactive_marker = "."
7 |
8 |
9 | translation_vectors_3d = [
10 | p for p in itertools.product([-1, 0, 1], repeat=3) if p != (0, 0, 0)
11 | ]
12 | translation_vectors_4d = [
13 | p for p in itertools.product([-1, 0, 1], repeat=4) if p != (0, 0, 0, 0)
14 | ]
15 |
16 |
17 | def parse(
18 | instr: str, key: Callable[[int, int], int]
19 | ) -> Dict[Tuple[int, int, int], str]:
20 | input_lists = [[x for x in y] for y in instr.strip().split("\n")]
21 |
22 | rtvl = {}
23 |
24 | for y, row in enumerate(input_lists):
25 | for x, col in enumerate(row):
26 | if col != inactive_marker:
27 | rtvl[key(x, y)] = col
28 |
29 | return rtvl
30 |
--------------------------------------------------------------------------------
/challenges/2020/18-operationOrder/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "18",
4 | "title": "Operation Order",
5 | "testCases": {
6 | "one": [
7 | {"input":"1 + 2 * 3 + 4 * 5 + 6", "expected":71},
8 | {"input":"1 + (2 * 3) + (4 * (5 + 6))", "expected":51},
9 | {"input":"2 * 3 + (4 * 5)", "expected":26},
10 | {"input":"5 + (8 * 3 + 9 + 3 * 4 * 3)", "expected":437},
11 | {"input":"5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))", "expected":12240},
12 | {"input":"((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2", "expected":13632}
13 | ],
14 | "two": [
15 | {"input":"1 + 2 * 3 + 4 * 5 + 6", "expected":231},
16 | {"input":"1 + (2 * 3) + (4 * (5 + 6))", "expected": 51},
17 | {"input":"2 * 3 + (4 * 5)", "expected": 46},
18 | {"input":"5 + (8 * 3 + 9 + 3 * 4 * 3)", "expected": 1445},
19 | {"input":"5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))", "expected": 669060},
20 | {"input":"((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2", "expected": 23340}
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/challenges/2020/18-operationOrder/python/test.py:
--------------------------------------------------------------------------------
1 | # This file is a proof of concept for using the implementation in part one to complete part two
2 | # after added extra brackets to evert expression.
3 |
4 | import partOne
5 |
6 | instr = open("../input.txt").read()
7 | expressions = instr.strip().split("\n")
8 |
9 | expressions = [
10 | partOne.parse_expression(
11 | list(("( " + x.replace("*", ") * (") + " )").replace(" ", ""))
12 | )[0]
13 | for x in instr.strip().split("\n")
14 | ]
15 |
16 | sigma = 0
17 |
18 | for expression in expressions:
19 | sigma += partOne.calculate(expression)
20 |
21 | print(sigma)
22 |
--------------------------------------------------------------------------------
/challenges/2020/19-monsterMessages/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "regexp"
4 |
5 | func PartOne(instr string) int {
6 | rules, messages := parse(instr)
7 | ruleRegex := regexp.MustCompile(makeRulesetRegex(rules))
8 | return run(messages, ruleRegex)
9 | }
10 |
--------------------------------------------------------------------------------
/challenges/2020/19-monsterMessages/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | )
7 |
8 | func PartTwo(instr string) int {
9 |
10 | // patch input
11 | instr = strings.ReplaceAll(instr, "8: 42", "8: 42 | 42 8")
12 | instr = strings.ReplaceAll(instr, "11: 42 31", "11: 42 31 | 42 11 31")
13 |
14 | rules, messages := parse(instr)
15 |
16 | // Since we have sections of our ruleset, we have markers in the regex returned by `make_ruleset_regex`
17 | // that denote where we need to insert a copy of the rule 11 regular expression (which also happens to
18 | // have one of those markers in it)
19 |
20 | rr := makeRulesetRegex(rules)
21 | elevenRegex := generateRuleRegex(rules, 11)
22 | for i := 0; i < 10; i += 2 {
23 | rr = strings.ReplaceAll(rr, replaceMarker, elevenRegex)
24 | }
25 |
26 | // run as usual
27 | ruleRegex := regexp.MustCompile(rr)
28 | return run(messages, ruleRegex)
29 | }
30 |
--------------------------------------------------------------------------------
/challenges/2020/19-monsterMessages/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | import re
3 |
4 |
5 | def partOne(instr: str) -> int:
6 | rules, messages = parse(instr)
7 | rule_regex = re.compile(make_ruleset_regex(rules))
8 | return run(messages, rule_regex)
9 |
--------------------------------------------------------------------------------
/challenges/2020/19-monsterMessages/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | import re
3 |
4 |
5 | def partTwo(instr: str) -> int:
6 |
7 | # patch input
8 | instr = instr.replace(
9 | "8: 42", "8: 42 | 42 8"
10 | ) # the new rule 8 can be expressed as 42 | 42+
11 | instr = instr.replace("11: 42 31", "11: 42 31 | 42 11 31")
12 |
13 | rules, messages = parse(instr)
14 |
15 | # Since we have sections of our ruleset, we have markers in the regex returned by `make_ruleset_regex`
16 | # that denote where we need to insert a copy of the rule 11 regular expression (which also happens to
17 | # have one of those markers in it)
18 |
19 | rr = make_ruleset_regex(rules)
20 | eleven_regex = generate_rule_regex(rules, 11)
21 | for _ in range(10):
22 | rr = rr.replace(replace_marker, eleven_regex)
23 |
24 | # run as usual
25 | rule_regex = re.compile(rr)
26 | return run(messages, rule_regex)
27 |
--------------------------------------------------------------------------------
/challenges/2020/20-jurassicJigsaw/README.md:
--------------------------------------------------------------------------------
1 | # [Day 20: Jurassic Jigsaw](https://adventofcode.com/2020/day/20)
2 |
3 | ~~Gave up on this one. I was struggling to find a decent logical way to do it manually, yet alone write a set of rules to get a computer to do it.~~
4 |
5 | ~~Okay, so I had a lightbulb moment and came back to take another look at part one, which I got pretty easily. I'm going to take another crack on part two, since tiles have certain properties that I didn't realise were present.~~
6 |
7 | No.
8 |
9 | Script output
10 |
11 | ```
12 | ❯ python .\python\
13 | AoC 2020: day 20 - Jurassic Jigsaw
14 | Python 3.8.5
15 |
16 | Test cases
17 | 1.1 pass
18 | 2.1 fail (got 0, expected 273)
19 |
20 | Answers
21 | Part 1: 83775126454273
22 | Part 2: 0
23 | ```
24 |
25 |
--------------------------------------------------------------------------------
/challenges/2020/20-jurassicJigsaw/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | from pprint import pprint
3 |
4 |
5 | def partOne(instr: str) -> int:
6 | tiles = parse(instr)
7 |
8 | _, shared_edge_count = get_edge_information(tiles)
9 |
10 | # find the product of all tile numbers that have 2 matching edges
11 |
12 | c = 1
13 | for x in shared_edge_count:
14 | if shared_edge_count[x] == 2:
15 | c *= x
16 |
17 | return c
18 |
--------------------------------------------------------------------------------
/challenges/2020/20-jurassicJigsaw/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partTwo(instr: str) -> int:
5 | tiles_list = parse(instr)
6 | edges, shared_edge_count = get_edge_information(tiles_list)
7 |
8 | # from here onwards, it's going to make more sense to use a dictionary that has tile numbers to the tile object
9 | tiles = {}
10 | for tile in tiles_list:
11 | tiles[tile.number] = tile
12 |
13 | used_tiles = []
14 | matrix = {}
15 |
16 | # get a single corner, set that as the start point
17 | for tile_id in shared_edge_count:
18 | if shared_edge_count[tile_id] == 2:
19 | matrix[(0, 0)] = tiles[tile_id].components
20 |
21 | print(matrix)
22 |
23 | return 0
24 |
--------------------------------------------------------------------------------
/challenges/2020/21-allergenAmusement/README.md:
--------------------------------------------------------------------------------
1 | # [Day 21: Allergen Amusement](https://adventofcode.com/2020/day/21)
2 |
3 | This one isn't going to be translated to go because **a)** Go has no sets and **b)** Go is statically typed and I cannot be bothered to try and tweak the return type for part two.
4 |
5 | *I made the assumption we'd only ever have numeric solutions when I built the boilerplate, goddamnit!*
6 |
7 | Script output
8 |
9 | ```
10 | ❯ python .\python\
11 | AoC 2020: day 21 - Allergen Amusement
12 | Python 3.8.5
13 |
14 | Test cases
15 | 1.1 pass
16 | 2.1 pass
17 |
18 | Answers
19 | Part 1: 2307
20 | Part 2: cljf,frtfg,vvfjj,qmrps,hvnkk,qnvx,cpxmpc,qsjszn
21 | ```
22 |
23 |
--------------------------------------------------------------------------------
/challenges/2020/21-allergenAmusement/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "21",
4 | "title": "Allergen Amusement",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "mxmxvkd kfcds sqjhc nhms (contains dairy, fish)\ntrh fvjkl sbzzf mxmxvkd (contains dairy)\nsqjhc fvjkl (contains soy)\nsqjhc mxmxvkd sbzzf (contains fish)\n",
9 | "expected": 5
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "mxmxvkd kfcds sqjhc nhms (contains dairy, fish)\ntrh fvjkl sbzzf mxmxvkd (contains dairy)\nsqjhc fvjkl (contains soy)\nsqjhc mxmxvkd sbzzf (contains fish)\n",
15 | "expected": "mxmxvkd,sqjhc,fvjkl"
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/21-allergenAmusement/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | foods, allergens = parse(instr)
6 | possibilities = get_possibilities(foods, allergens)
7 |
8 | bad_ingredients = set()
9 | for x in possibilities:
10 | bad_ingredients.update(possibilities[x])
11 |
12 | count = 0
13 | for food in foods:
14 | for ingredient in food.ingredients:
15 | if ingredient not in bad_ingredients:
16 | count += 1
17 |
18 | return count
19 |
--------------------------------------------------------------------------------
/challenges/2020/22-crabCombat/README.md:
--------------------------------------------------------------------------------
1 | # [Day 22: Crab Combat](https://adventofcode.com/2020/day/22)
2 |
3 | Script output
4 |
5 | ```
6 | ❯ python .\python\ ft
7 | AoC 2020: day 22 - Crab Combat
8 | Python 3.8.5
9 |
10 | Test cases
11 | 1.1 pass in 0.0 seconds
12 | 2.1 pass in 0.0 seconds
13 |
14 | Answers
15 | Part 1: 35397 in 0.0005002021789550781 seconds
16 | Part 2: 33889 in 2.854492425918579 seconds
17 | ```
18 |
19 |
20 |
--------------------------------------------------------------------------------
/challenges/2020/22-crabCombat/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "22",
4 | "title": "Crab Combat",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "Player 1:\n9\n2\n6\n3\n1\n\nPlayer 2:\n5\n8\n4\n7\n10\n",
9 | "expected": 306
10 | }
11 | ],
12 | "two": [
13 | {
14 | "input": "Player 1:\n9\n2\n6\n3\n1\n\nPlayer 2:\n5\n8\n4\n7\n10\n",
15 | "expected": 291
16 | }
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/challenges/2020/22-crabCombat/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 |
4 | def parse(instr: str) -> Tuple[List[int], List[int]]:
5 |
6 | deck_one_str, deck_two_str = instr.strip().split("\n\n")
7 |
8 | deck_one = [int(x) for x in deck_one_str.split("\n")[1:]]
9 | deck_two = [int(x) for x in deck_two_str.split("\n")[1:]]
10 |
11 | return deck_one, deck_two
12 |
13 |
14 | def calc_score(deck: List[int]) -> int:
15 | score = 0
16 |
17 | deck_len = len(deck)
18 | for i, v in enumerate(deck):
19 | score += v * (deck_len - i)
20 |
21 | return score
22 |
--------------------------------------------------------------------------------
/challenges/2020/22-crabCombat/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 | import time
3 |
4 |
5 | def play_round(deck_one: List[int], deck_two: List[int]) -> None:
6 |
7 | top_one = deck_one.pop(0)
8 | top_two = deck_two.pop(0)
9 |
10 | if top_one > top_two:
11 | deck_one.append(top_one)
12 | deck_one.append(top_two)
13 | elif top_two > top_one:
14 | deck_two.append(top_two)
15 | deck_two.append(top_one)
16 |
17 |
18 | def partOne(instr: str) -> int:
19 | deck_one, deck_two = parse(instr)
20 |
21 | while len(deck_one) > 0 and len(deck_two) > 0:
22 | play_round(deck_one, deck_two)
23 |
24 | return calc_score(deck_one if len(deck_one) != 0 else deck_two)
25 |
--------------------------------------------------------------------------------
/challenges/2020/23-crabCups/README.md:
--------------------------------------------------------------------------------
1 | # [Day 23: Crab Cups](https://adventofcode.com/2020/day/23)
2 |
3 | The point at which I was unable to debug my solution because the sample solution didn't extend to 100 iterations was the point at which I gave up.
4 |
5 | This challenge seemed so simple, yet somehow managed to break me. Oh well. Fingers crossed the final two days are more doable.
6 |
7 | Here is a crab in place of anything actually useful written here.
8 |
9 | 
10 |
11 | Script output
12 |
13 | ```
14 | There is none.
15 | ```
16 |
17 |
18 |
--------------------------------------------------------------------------------
/challenges/2020/23-crabCups/crab.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/23-crabCups/crab.jpg
--------------------------------------------------------------------------------
/challenges/2020/23-crabCups/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "23",
4 | "title": "Crab Cups",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "389125467",
9 | "expected": 67384529
10 | }
11 | ],
12 | "two": []
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/challenges/2020/23-crabCups/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List[int]:
5 | return [int(x) for x in instr.strip()]
6 |
--------------------------------------------------------------------------------
/challenges/2020/23-crabCups/python/partTwo.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partTwo(instr: str) -> int:
5 | input_list = parse(instr)
6 | return 0
7 |
--------------------------------------------------------------------------------
/challenges/2020/24-lobbyLayout/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def partOne(instr: str) -> int:
5 | tiles_locations = parse(instr)
6 | tiles = make_initial_state(tiles_locations)
7 | return count_black_tiles(tiles)
8 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/README.md:
--------------------------------------------------------------------------------
1 | # [Day 25: Combo Breaker](https://adventofcode.com/2020/day/25)
2 |
3 | Merry Christmas!
4 |
5 | That's Advent of Code done for this year. At the time of writing this, I've not gotten all 49 stars up to this point, so I've got no way to get the 50th star. Even so, I feel slightly cheated out of a part two haha.
6 |
7 | I might go back and try some of the other challenges from this year that I didn't complete.
8 |
9 | Script output
10 |
11 | ```
12 | ❯ python python ft
13 | AoC 2020: day 25 - Combo Breaker
14 | Python 3.8.5
15 |
16 | Test cases
17 | 1.1 pass in 0.0 seconds
18 |
19 | Answers
20 | Part 1: 297257 in 7.089499235153198 seconds
21 | Part 2: 0 in 0.0 seconds
22 |
23 | ❯ go run .\go\ ft
24 | AoC 2020: day 25 - Combo Breaker
25 | Go go1.15.2
26 |
27 | Test cases
28 | 1.1 pass in 0.00000000 seconds
29 |
30 | Answers
31 | Part 1: 297257 in 0.13749980 seconds
32 | Part 2: 0 in 0.00000000 seconds
33 | ```
34 |
35 |
36 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/go/challenge/common.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | func parse(instr string) []int {
9 | var o []int
10 | for _, x := range strings.Split(strings.TrimSpace(instr), "\n") {
11 | i, err := strconv.Atoi(x)
12 | if err != nil {
13 | panic(err)
14 | }
15 | o = append(o, i)
16 | }
17 | return o
18 | }
19 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/go/challenge/partOne.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | import "errors"
4 |
5 | func singleTransformation(v, subjectNumber int) int {
6 | return (v * subjectNumber) % 20201227
7 | }
8 |
9 | func transform(loopSize, subjectNumber int) int {
10 | v := 1
11 | for i := 0; i < loopSize; i += 1 {
12 | v = singleTransformation(v, subjectNumber)
13 | }
14 | return v
15 | }
16 |
17 | func findLoopSize(targetPubkey int) int {
18 | var c int
19 | v := 1
20 | for {
21 | c += 1
22 | v = singleTransformation(v, 7)
23 | if v == targetPubkey {
24 | return c
25 | }
26 | }
27 | }
28 |
29 | func PartOne(instr string) int {
30 | inputSlice := parse(instr)
31 |
32 | pubkeyOne := inputSlice[0]
33 | pubkeyTwo := inputSlice[1]
34 |
35 | loopSizeOne := findLoopSize(pubkeyOne)
36 | loopSizeTwo := findLoopSize(pubkeyTwo)
37 |
38 | encryptionKey := transform(loopSizeTwo, pubkeyOne)
39 | if encryptionKey != transform(loopSizeOne, pubkeyTwo) {
40 | panic(errors.New("encryption keys do not match"))
41 | }
42 |
43 | return encryptionKey
44 | }
45 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/go/challenge/partTwo.go:
--------------------------------------------------------------------------------
1 | package challenge
2 |
3 | func PartTwo(instr string) int {
4 | return 0
5 | }
6 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "year": "2020",
3 | "day": "25",
4 | "title": "Combo Breaker",
5 | "testCases": {
6 | "one": [
7 | {
8 | "input": "5764801\n17807724",
9 | "expected": 14897079
10 | }
11 | ],
12 | "two": []
13 | }
14 | }
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/python/common.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | def parse(instr: str) -> List[int]:
5 | return [int(x) for x in instr.strip().split("\n")]
6 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/python/partOne.py:
--------------------------------------------------------------------------------
1 | from common import *
2 |
3 |
4 | def single_transformation(v:int, subject_number:int=7) -> int:
5 | return (v * subject_number) % 20201227
6 |
7 |
8 | def transform(loop_size:int, subject_number:int=7) -> int:
9 | v = 1
10 | for _ in range(loop_size):
11 | v = single_transformation(v, subject_number=subject_number)
12 | return v
13 |
14 |
15 | def find_loop_size(target_pubkey:int) -> int:
16 | c = 0
17 | v = 1
18 | while True:
19 | c += 1
20 | v = single_transformation(v)
21 | if v == target_pubkey:
22 | return c
23 |
24 |
25 | def partOne(instr: str) -> int:
26 | pubkey_one, pubkey_two = parse(instr)
27 |
28 | loop_size_one = find_loop_size(pubkey_one)
29 | loop_size_two = find_loop_size(pubkey_two)
30 |
31 | encryption_key = transform(loop_size_two, subject_number=pubkey_one)
32 | assert encryption_key == transform(loop_size_one, subject_number=pubkey_two), "encryption keys do not match"
33 |
34 | return encryption_key
35 |
--------------------------------------------------------------------------------
/challenges/2020/25-comboBreaker/python/partTwo.py:
--------------------------------------------------------------------------------
1 | def partTwo(instr: str) -> int:
2 | return 0
3 |
--------------------------------------------------------------------------------
/challenges/2020/clocgraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2020/clocgraph.png
--------------------------------------------------------------------------------
/challenges/2021/01-sonarSweep/README.md:
--------------------------------------------------------------------------------
1 | # [Day 1: Sonar Sweep](https://adventofcode.com/2021/day/1)
2 |
3 | ```
4 | ➜ adventOfCode git:(master) go run github.com/codemicro/adventOfCode/runtime -y 2021
5 | Selecting year 2021
6 | Automatically selecting day 1 (Sonar Sweep)
7 | ? Which implementation do you want to use? Python
8 |
9 | Running...
10 |
11 | Test 1.0: pass in 0.0000 seconds
12 | Test 2.0: pass in 0.0000 seconds
13 | Part 1: in 0.0005 seconds
14 | Part 2: in 0.0008 seconds
15 | ```
--------------------------------------------------------------------------------
/challenges/2021/01-sonarSweep/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 1,
3 | "dir": "challenges/2021/01-sonarSweep",
4 | "implementations": {
5 | "Golang": {
6 | "part.1.avg": 0.0002590258829999999,
7 | "part.1.max": 0.01844078,
8 | "part.1.min": 0.000056368,
9 | "part.2.avg": 0.00041728208699999965,
10 | "part.2.max": 0.025912989,
11 | "part.2.min": 0.000067722
12 | },
13 | "Nim": {
14 | "part.1.avg": 0.001190464674,
15 | "part.1.max": 0.012474971,
16 | "part.1.min": 0.000310218,
17 | "part.2.avg": 0.0012603544370000013,
18 | "part.2.max": 0.019855291,
19 | "part.2.min": 0.000310509
20 | },
21 | "Python": {
22 | "part.1.avg": 0.0013292949199676513,
23 | "part.1.max": 0.0059168338775634766,
24 | "part.1.min": 0.0004954338073730469,
25 | "part.2.avg": 0.0022176058292388916,
26 | "part.2.max": 0.016942262649536133,
27 | "part.2.min": 0.0008616447448730469
28 | }
29 | },
30 | "numRuns": 1000
31 | }
--------------------------------------------------------------------------------
/challenges/2021/01-sonarSweep/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "199\n200\n208\n210\n200\n207\n240\n269\n260\n263",
7 | "expected": "7"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "199\n200\n208\n210\n200\n207\n240\n269\n260\n263",
13 | "expected": "5"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/01-sonarSweep/nim/challenge.nim:
--------------------------------------------------------------------------------
1 | import std/strutils
2 | import std/sequtils
3 |
4 | proc parseInput(instr: string): seq[int] =
5 | result = instr.
6 | splitLines.
7 | toSeq.
8 | filter(proc(x: string): bool = x != "").
9 | map(parseInt)
10 |
11 | proc countIncreases(data: seq[int]): int =
12 | for i in 1..data.high:
13 | if data[i] > data[i-1]:
14 | result = result + 1
15 |
16 | proc partOne*(instr: string): int =
17 | let input = parseInput(instr)
18 | return countIncreases(input)
19 |
20 | proc partTwo*(instr: string): int =
21 | let input = parseInput(instr)
22 | var sums: seq[int]
23 | for i in countup(0, len(input)-3):
24 | sums.add(input[i] + input[i+1] + input[i+2])
25 | # sums.add(
26 | # (@input[i..i+2]).foldl(a+b),
27 | # )
28 | return countIncreases(sums)
29 |
--------------------------------------------------------------------------------
/challenges/2021/01-sonarSweep/py/__init__.py:
--------------------------------------------------------------------------------
1 | from typing import List, Any
2 | from aocpy import BaseChallenge
3 |
4 |
5 | def parse(instr: str) -> List[int]:
6 | return [int(x) for x in instr.splitlines() if x != ""]
7 |
8 |
9 | def count_increases(data: List[int]) -> int:
10 | c = 0
11 | for i in range(1, len(data)):
12 | if data[i] > data[i - 1]:
13 | c += 1
14 | return c
15 |
16 |
17 | class Challenge(BaseChallenge):
18 | @staticmethod
19 | def one(instr: str) -> int:
20 | data = parse(instr)
21 | return count_increases(data)
22 |
23 | @staticmethod
24 | def two(instr: str) -> int:
25 | data = parse(instr)
26 | sums = [sum(data[i : i + 3]) for i in range(len(data) - 2)]
27 | return count_increases(sums)
28 |
--------------------------------------------------------------------------------
/challenges/2021/02-dive/README.md:
--------------------------------------------------------------------------------
1 | # [Day 2: Dive!](https://adventofcode.com/2021/day/2)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/02-dive/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 2,
3 | "dir": "challenges/2021/02-dive",
4 | "implementations": {
5 | "Golang": {
6 | "part.1.avg": 0.00043523502199999955,
7 | "part.1.max": 0.008638925,
8 | "part.1.min": 0.000157245,
9 | "part.2.avg": 0.0004556505770000001,
10 | "part.2.max": 0.014578633,
11 | "part.2.min": 0.000159105
12 | },
13 | "Python": {
14 | "part.1.avg": 0.002370833396911621,
15 | "part.1.max": 0.024700403213500977,
16 | "part.1.min": 0.0007102489471435547,
17 | "part.2.avg": 0.002402855157852173,
18 | "part.2.max": 0.019526958465576172,
19 | "part.2.min": 0.0007097721099853516
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2021/02-dive/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "forward 5\ndown 5\nforward 8\nup 3\ndown 8\nforward 2\n",
7 | "expected": "150"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "forward 5\ndown 5\nforward 8\nup 3\ndown 8\nforward 2\n",
13 | "expected": "900"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/03-binaryDiagnostic/README.md:
--------------------------------------------------------------------------------
1 | # [Day 3: Binary Diagnostic](https://adventofcode.com/2021/day/3)
2 |
3 | The Nim code is a direct translation of the Python code - see the Python code for descriptive comments.
--------------------------------------------------------------------------------
/challenges/2021/03-binaryDiagnostic/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 3,
3 | "dir": "challenges/2021/03-binaryDiagnostic",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.0005255849699999996,
7 | "part.1.max": 0.003743778,
8 | "part.1.min": 0.000228979,
9 | "part.2.avg": 0.0005072320390000003,
10 | "part.2.max": 0.002042921,
11 | "part.2.min": 0.000207734
12 | },
13 | "Python": {
14 | "part.1.avg": 0.004413741111755371,
15 | "part.1.max": 0.012727022171020508,
16 | "part.1.min": 0.0021619796752929688,
17 | "part.2.avg": 0.0034146361351013186,
18 | "part.2.max": 0.0129547119140625,
19 | "part.2.min": 0.0016372203826904297
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2021/03-binaryDiagnostic/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "00100\n11110\n10110\n10111\n10101\n01111\n00111\n11100\n10000\n11001\n00010\n01010\n",
7 | "expected": "198"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "00100\n11110\n10110\n10111\n10101\n01111\n00111\n11100\n10000\n11001\n00010\n01010\n",
13 | "expected": "230"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/04-giantSquid/README.md:
--------------------------------------------------------------------------------
1 | # [Day 4: Giant Squid](https://adventofcode.com/2021/day/4)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/04-giantSquid/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 4,
3 | "dir": "challenges/2021/04-giantSquid",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.017204525232315065,
7 | "part.1.max": 0.09171009063720703,
8 | "part.1.min": 0.0072062015533447266,
9 | "part.2.avg": 0.0352356481552124,
10 | "part.2.max": 0.13428831100463867,
11 | "part.2.min": 0.015462875366210938
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/04-giantSquid/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1\n\n22 13 17 11 0\n 8 2 23 4 24\n21 9 14 16 7\n 6 10 3 18 5\n 1 12 20 15 19\n\n 3 15 0 2 22\n 9 18 13 17 5\n19 8 7 25 23\n20 11 10 24 4\n14 21 16 12 6\n\n14 21 17 24 4\n10 16 15 9 19\n18 8 23 26 20\n22 11 13 6 5\n 2 0 12 3 7",
7 | "expected": "4512"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1\n\n22 13 17 11 0\n 8 2 23 4 24\n21 9 14 16 7\n 6 10 3 18 5\n 1 12 20 15 19\n\n 3 15 0 2 22\n 9 18 13 17 5\n19 8 7 25 23\n20 11 10 24 4\n14 21 16 12 6\n\n14 21 17 24 4\n10 16 15 9 19\n18 8 23 26 20\n22 11 13 6 5\n 2 0 12 3 7",
13 | "expected": "1924"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/05-hydrothermalVenture/README.md:
--------------------------------------------------------------------------------
1 | # [Day 5: Hydrothermal Venture](https://adventofcode.com/2021/day/5)
2 |
3 | ### Part one
4 |
5 | * Parse input and output a list of pairs of points.
6 | * Remove diagonal lines by filtering the list using the condition that `p1.x == p2.x or p1.y == p2.y`
7 | * Count overlapping points
8 | * Create a dictionary that uses the point coordinate as a key and contains an integer `n` for each key
9 | * Iterate over each line in the input, adding 1 to `n` for each coordinate in the line
10 | * The coordinates were founid by computing the x and y deltas between the two points that made up the line
11 | * The sign of the deltas determines the direction we step in
12 | * We then step through each point in the line based on the step directions until the final point is encountered
13 | * Iterate over all keys in the dictionary and count every point where `n > 1`
14 |
15 | ### Part two
16 |
17 | The same as part one, but without the list filtering step.
18 |
19 | ---
20 |
21 | Involved literal napkin maths.
22 |
23 | 
24 |
--------------------------------------------------------------------------------
/challenges/2021/05-hydrothermalVenture/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 5,
3 | "dir": "challenges/2021/05-hydrothermalVenture",
4 | "implementations": {
5 | "Golang": {
6 | "part.1.avg": 0.053760980892,
7 | "part.1.max": 0.144833474,
8 | "part.1.min": 0.038262183,
9 | "part.2.avg": 0.08442973864,
10 | "part.2.max": 0.192854485,
11 | "part.2.min": 0.061950775
12 | },
13 | "Nim": {
14 | "part.1.avg": 0.014279042672000008,
15 | "part.1.max": 0.078472313,
16 | "part.1.min": 0.01031939,
17 | "part.2.avg": 0.021206030867999978,
18 | "part.2.max": 0.097470179,
19 | "part.2.min": 0.014612315
20 | },
21 | "Python": {
22 | "part.1.avg": 0.26107834911346434,
23 | "part.1.max": 0.8465554714202881,
24 | "part.1.min": 0.15942978858947754,
25 | "part.2.avg": 0.43654474210739136,
26 | "part.2.max": 1.4235708713531494,
27 | "part.2.min": 0.26850223541259766
28 | }
29 | },
30 | "numRuns": 500
31 | }
--------------------------------------------------------------------------------
/challenges/2021/05-hydrothermalVenture/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "0,9 -> 5,9\n8,0 -> 0,8\n9,4 -> 3,4\n2,2 -> 2,1\n7,0 -> 7,4\n6,4 -> 2,0\n0,9 -> 2,9\n3,4 -> 1,4\n0,0 -> 8,8\n5,5 -> 8,2\n",
7 | "expected": "5"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "0,9 -> 5,9\n8,0 -> 0,8\n9,4 -> 3,4\n2,2 -> 2,1\n7,0 -> 7,4\n6,4 -> 2,0\n0,9 -> 2,9\n3,4 -> 1,4\n0,0 -> 8,8\n5,5 -> 8,2\n",
13 | "expected": "12"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/05-hydrothermalVenture/napkinmath.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/05-hydrothermalVenture/napkinmath.jpg
--------------------------------------------------------------------------------
/challenges/2021/06-lanternfish/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 6,
3 | "dir": "challenges/2021/06-lanternfish",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.00020124888420104982,
7 | "part.1.max": 0.0004673004150390625,
8 | "part.1.min": 0.0001266002655029297,
9 | "part.2.avg": 0.0004714465141296387,
10 | "part.2.max": 0.0010838508605957031,
11 | "part.2.min": 0.00030684471130371094
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/06-lanternfish/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "3,4,3,1,2",
7 | "expected": "5934"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "3,4,3,1,2",
13 | "expected": "26984457539"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/06-lanternfish/whiteboard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/06-lanternfish/whiteboard.jpg
--------------------------------------------------------------------------------
/challenges/2021/07-theTreacheryOfWhales/README.md:
--------------------------------------------------------------------------------
1 | # [Day 7: The Treachery of Whales](https://adventofcode.com/2021/day/7)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/07-theTreacheryOfWhales/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 7,
3 | "dir": "challenges/2021/07-theTreacheryOfWhales",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.0003524906635284424,
7 | "part.1.max": 0.0011348724365234375,
8 | "part.1.min": 0.00024008750915527344,
9 | "part.2.avg": 0.033716694355010984,
10 | "part.2.max": 0.08556342124938965,
11 | "part.2.min": 0.025210857391357422
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/07-theTreacheryOfWhales/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "16,1,2,0,4,2,7,1,2,14",
7 | "expected": "37"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "16,1,2,0,4,2,7,1,2,14",
13 | "expected": "168"
14 | }
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/challenges/2021/08-sevenSegmentSearch/README.md:
--------------------------------------------------------------------------------
1 | # [Day 8: Sevent Segment Search](https://adventofcode.com/2021/day/8)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/08-sevenSegmentSearch/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 8,
3 | "dir": "challenges/2021/08-seventSegmentSearch",
4 | "implementations": {
5 | "Golang": {
6 | "part.1.avg": 0.0011630151239999996,
7 | "part.1.max": 0.002068547,
8 | "part.1.min": 0.000927415,
9 | "part.2.avg": 0.326909703884,
10 | "part.2.max": 0.398817152,
11 | "part.2.min": 0.296369163
12 | },
13 | "Python": {
14 | "part.1.avg": 0.0018209447860717772,
15 | "part.1.max": 0.0030808448791503906,
16 | "part.1.min": 0.0014312267303466797,
17 | "part.2.avg": 0.7365821332931518,
18 | "part.2.max": 0.8698751926422119,
19 | "part.2.min": 0.6725485324859619
20 | }
21 | },
22 | "numRuns": 250
23 | }
--------------------------------------------------------------------------------
/challenges/2021/09-smokeBasin/README.md:
--------------------------------------------------------------------------------
1 | # [Day 9: Smoke Basin](https://adventofcode.com/2021/day/9)
2 |
3 | The key to solving part two is knowing that you don't need to itelligently think about the depths of the basins.
4 |
5 | Because we know that
6 |
7 | > Locations of height `9` do not count as being in any basin, and all other locations will always be part of exactly one basin
8 |
9 | we can determine that a given basin is bounded by `9`s or the edge of the board. For example, the sample input looks like this if you remove all digits apart from `9`.
10 |
11 | ```
12 | --999-----
13 | -9---9-9--
14 | 9-----9-9-
15 | -----9---9
16 | 9-999-----
17 | ```
18 |
19 | We can find every lowest point, and work outwards from that point to find the entire basin.
20 |
21 | ---
22 |
23 | [Part two visualisation](partTwo.mp4)
24 |
25 | To run the visualisation, use the following command:
26 |
27 | ```
28 | PYTHONPATH=/lib python3 -B -c "import py;inp=open('input.txt').read();py.Challenge.vis(inp,'visdir')"
29 | ```
--------------------------------------------------------------------------------
/challenges/2021/09-smokeBasin/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 9,
3 | "dir": "challenges/2021/09-smokeBasin",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.04718727922439575,
7 | "part.1.max": 0.19989562034606934,
8 | "part.1.min": 0.01859116554260254,
9 | "part.2.avg": 0.10986182379722595,
10 | "part.2.max": 0.3891136646270752,
11 | "part.2.min": 0.041121721267700195
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/09-smokeBasin/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "2199943210\n3987894921\n9856789892\n8767896789\n9899965678\n",
7 | "expected": "15"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "2199943210\n3987894921\n9856789892\n8767896789\n9899965678\n",
13 | "expected": "1134"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/09-smokeBasin/partTwo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/09-smokeBasin/partTwo.mp4
--------------------------------------------------------------------------------
/challenges/2021/10-syntaxScoring/README.md:
--------------------------------------------------------------------------------
1 | # [Day 10: Syntax Scoring](https://adventofcode.com/2021/day/10)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/10-syntaxScoring/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 10,
3 | "dir": "challenges/2021/10-syntaxScoring",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.001248321533203125,
7 | "part.1.max": 0.004151821136474609,
8 | "part.1.min": 0.0008554458618164062,
9 | "part.2.avg": 0.0030763609409332274,
10 | "part.2.max": 0.028047800064086914,
11 | "part.2.min": 0.002079486846923828
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/10-syntaxScoring/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "[({(<(())[]>[[{[]{<()<>>\n[(()[<>])]({[<{<<[]>>(\n{([(<{}[<>[]}>{[]{[(<()>\n(((({<>}<{<{<>}{[]{[]{}\n[[<[([]))<([[{}[[()]]]\n[{[{({}]{}}([{[{{{}}([]\n{<[[]]>}<{[{[{[]{()[[[]\n[<(<(<(<{}))><([]([]()\n<{([([[(<>()){}]>(<<{{\n<{([{{}}[<[[[<>{}]]]>[]]\n",
7 | "expected": "26397"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "[({(<(())[]>[[{[]{<()<>>\n[(()[<>])]({[<{<<[]>>(\n{([(<{}[<>[]}>{[]{[(<()>\n(((({<>}<{<{<>}{[]{[]{}\n[[<[([]))<([[{}[[()]]]\n[{[{({}]{}}([{[{{{}}([]\n{<[[]]>}<{[{[{[]{()[[[]\n[<(<(<(<{}))><([]([]()\n<{([([[(<>()){}]>(<<{{\n<{([{{}}[<[[[<>{}]]]>[]]\n",
13 | "expected": "288957"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/11-dumboOctopus/README.md:
--------------------------------------------------------------------------------
1 | # [Day 11: Dumbo Octopus](https://adventofcode.com/2021/day/11)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/11-dumboOctopus/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 11,
3 | "dir": "challenges/2021/11-dumboOctopus",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.002156735096000002,
7 | "part.1.max": 0.006734169,
8 | "part.1.min": 0.001474201,
9 | "part.2.avg": 0.008079303889999999,
10 | "part.2.max": 0.038707332,
11 | "part.2.min": 0.005537803
12 | },
13 | "Python": {
14 | "part.1.avg": 0.008022420167922973,
15 | "part.1.max": 0.022809743881225586,
16 | "part.1.min": 0.005808591842651367,
17 | "part.2.avg": 0.031094204664230348,
18 | "part.2.max": 0.08413910865783691,
19 | "part.2.min": 0.023587465286254883
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2021/11-dumboOctopus/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "11111\n19991\n19191\n19991\n11111\n",
7 | "expected": "259"
8 | },
9 | {
10 | "input": "5483143223\n2745854711\n5264556173\n6141336146\n6357385478\n4167524645\n2176841721\n6882881134\n4846848554\n5283751526\n",
11 | "expected": "1656"
12 | }
13 | ],
14 | "two": [
15 | {
16 | "input": "5483143223\n2745854711\n5264556173\n6141336146\n6357385478\n4167524645\n2176841721\n6882881134\n4846848554\n5283751526\n",
17 | "expected": "195"
18 | }
19 | ]
20 | }
21 | }
--------------------------------------------------------------------------------
/challenges/2021/12-passagePathing/README.md:
--------------------------------------------------------------------------------
1 | # [Day 12: Passage Pathing](https://adventofcode.com/2021/day/12)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/12-passagePathing/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 12,
3 | "dir": "challenges/2021/12-passagePathing",
4 | "implementations": {
5 | "Golang": {
6 | "part.1.avg": 0.004089135783000003,
7 | "part.1.max": 0.015094977,
8 | "part.1.min": 0.002771765,
9 | "part.2.avg": 0.090934005394,
10 | "part.2.max": 0.250616487,
11 | "part.2.min": 0.065061159
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/12-passagePathing/graph.py:
--------------------------------------------------------------------------------
1 | import networkx as nx
2 | import matplotlib.pyplot as plt
3 |
4 | edges = []
5 | nodes = []
6 | with open("input.txt") as f:
7 | for line in f.read().strip().splitlines():
8 | f, t = line.split("-")
9 | edges.append((f,t))
10 | for x in [f, t]:
11 | if x not in nodes:
12 | nodes.append(x)
13 |
14 | graph = nx.Graph()
15 | graph.add_edges_from(edges)
16 | pos = nx.kamada_kawai_layout(graph)
17 | nx.draw_networkx_nodes(graph, pos, nodelist=nodes)
18 | nx.draw_networkx_labels(graph, pos)
19 | nx.draw_networkx_edges(graph, pos, edgelist=graph.edges())
20 | plt.show()
--------------------------------------------------------------------------------
/challenges/2021/13-transparentOrigami/README.md:
--------------------------------------------------------------------------------
1 | # [Day 13: Transparent Origami](https://adventofcode.com/2021/day/13)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/13-transparentOrigami/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 13,
3 | "dir": "challenges/2021/13-transparentOrigami",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.0015621956039999975,
7 | "part.1.max": 0.003880651,
8 | "part.1.min": 0.00031427,
9 | "part.2.avg": 0.002502785954,
10 | "part.2.max": 0.005894322,
11 | "part.2.min": 0.000524984
12 | },
13 | "Python": {
14 | "part.1.avg": 0.0020371160507202148,
15 | "part.1.max": 0.007749795913696289,
16 | "part.1.min": 0.0005323886871337891,
17 | "part.2.avg": 0.005764168262481689,
18 | "part.2.max": 0.01631307601928711,
19 | "part.2.min": 0.0014383792877197266
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2021/13-transparentOrigami/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "6,10\n0,14\n9,10\n0,3\n10,4\n4,11\n6,0\n6,12\n4,1\n0,13\n10,12\n3,4\n3,0\n8,4\n1,10\n2,14\n8,10\n9,0\n\nfold along y=7\nfold along x=5",
7 | "expected": "17"
8 | }
9 | ],
10 | "two": []
11 | }
12 | }
--------------------------------------------------------------------------------
/challenges/2021/14-extendedPolymerization/README.md:
--------------------------------------------------------------------------------
1 | # [Day 14: Extended Polymerization](https://adventofcode.com/2021/day/14)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/14-extendedPolymerization/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 14,
3 | "dir": "challenges/2021/14-extendedPolymerization",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.0009306585788726807,
7 | "part.1.max": 0.002932310104370117,
8 | "part.1.min": 0.0006134510040283203,
9 | "part.2.avg": 0.0037261221408843993,
10 | "part.2.max": 0.008280754089355469,
11 | "part.2.min": 0.0021991729736328125
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/14-extendedPolymerization/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "NNCB\n\nCH -> B\nHH -> N\nCB -> H\nNH -> C\nHB -> C\nHC -> B\nHN -> C\nNN -> C\nBH -> H\nNC -> B\nNB -> B\nBN -> B\nBB -> N\nBC -> B\nCC -> N\nCN -> C",
7 | "expected": "1588"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "NNCB\n\nCH -> B\nHH -> N\nCB -> H\nNH -> C\nHB -> C\nHC -> B\nHN -> C\nNN -> C\nBH -> H\nNC -> B\nNB -> B\nBN -> B\nBB -> N\nBC -> B\nCC -> N\nCN -> C",
13 | "expected": "2188189693529"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/15-chiton/README.md:
--------------------------------------------------------------------------------
1 | # [Day 15: Chiton](https://adventofcode.com/2021/day/15)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/15-chiton/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 15,
3 | "dir": "challenges/2021/15-chiton",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.10024118185043335,
7 | "part.1.max": 0.26880645751953125,
8 | "part.1.min": 0.04713582992553711,
9 | "part.2.avg": 4.993094868659973,
10 | "part.2.max": 10.088721990585327,
11 | "part.2.min": 2.554753065109253
12 | }
13 | },
14 | "numRuns": 100
15 | }
--------------------------------------------------------------------------------
/challenges/2021/15-chiton/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "1163751742\n1381373672\n2136511328\n3694931569\n7463417111\n1319128137\n1359912421\n3125421639\n1293138521\n2311944581\n",
7 | "expected": "40"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "1163751742\n1381373672\n2136511328\n3694931569\n7463417111\n1319128137\n1359912421\n3125421639\n1293138521\n2311944581\n",
13 | "expected": "315"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/16-packetDecoder/README.md:
--------------------------------------------------------------------------------
1 | # [Day 16: Packet Decoder](https://adventofcode.com/2021/day/16)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/16-packetDecoder/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 16,
3 | "dir": "challenges/2021/16-packetDecoder",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.002915963888168335,
7 | "part.1.max": 0.011673688888549805,
8 | "part.1.min": 0.0016696453094482422,
9 | "part.2.avg": 0.0029851856231689453,
10 | "part.2.max": 0.019982337951660156,
11 | "part.2.min": 0.0017099380493164062
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/20-trenchMap/README.md:
--------------------------------------------------------------------------------
1 | # [Day 20: Trench Map](https://adventofcode.com/2021/day/20)
2 |
3 | [Part two visualisation](./part2.mp4)
--------------------------------------------------------------------------------
/challenges/2021/20-trenchMap/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 20,
3 | "dir": "challenges/2021/20-trenchMap",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.019850478899999996,
7 | "part.1.max": 0.048351829,
8 | "part.1.min": 0.008844087,
9 | "part.2.avg": 1.18194288576,
10 | "part.2.max": 2.369594795,
11 | "part.2.min": 0.635431931
12 | },
13 | "Python": {
14 | "part.1.avg": 0.18487148761749267,
15 | "part.1.max": 0.3699030876159668,
16 | "part.1.min": 0.09880661964416504,
17 | "part.2.avg": 10.631744318008423,
18 | "part.2.max": 18.34923243522644,
19 | "part.2.min": 5.976168155670166
20 | }
21 | },
22 | "numRuns": 50
23 | }
--------------------------------------------------------------------------------
/challenges/2021/20-trenchMap/part2.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/20-trenchMap/part2.mp4
--------------------------------------------------------------------------------
/challenges/2021/21-diracDice/README.md:
--------------------------------------------------------------------------------
1 | # [Day 21: Dirac Dice](https://adventofcode.com/2021/day/21)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/21-diracDice/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 21,
3 | "dir": "challenges/2021/21-diracDice",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.0007445704936981201,
7 | "part.1.max": 0.00394892692565918,
8 | "part.1.min": 0.0004050731658935547,
9 | "part.2.avg": 0.000006680965423583984,
10 | "part.2.max": 0.000054836273193359375,
11 | "part.2.min": 0.0000011920928955078125
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2021/21-diracDice/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "Player 1 starting position: 4\nPlayer 2 starting position: 8\n",
7 | "expected": "739785"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "Player 1 starting position: 4\nPlayer 2 starting position: 8\n",
13 | "expected": "444356092776315"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2021/22-reactorReboot/README.md:
--------------------------------------------------------------------------------
1 | # [Day 22: Reactor Reboot](https://adventofcode.com/2021/day/22)
2 |
3 | Today's solution is a little weird...
4 |
5 | I solved part one using the easy, store every point method. However, for part two, I didn't want to go to the trouble of writing code to work out the intersections of all the cubes. Instead, I chose to do the following:
6 |
7 | * Wrote some Python code (`openscad-generate.py`) to generate some [OpenSCAD](http://openscad.org/) code based on the challenge input
8 | * This made liberal use of nested `union()`, `difference()`, `translate()` and `cube()` functions
9 | * Ran this code in OpenSCAD and exported the resultant model as an STL
10 | * Imported this STL file into Blender and used the 3D-Print Toolbox addon to calculate the total volume of the object
11 | * Typed this number into the AoC website
12 | * Obtained the 2nd star ★ :D
13 |
14 | 
15 |
16 | 
--------------------------------------------------------------------------------
/challenges/2021/22-reactorReboot/blender-part-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/22-reactorReboot/blender-part-2.png
--------------------------------------------------------------------------------
/challenges/2021/22-reactorReboot/openscad-part-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/22-reactorReboot/openscad-part-2.png
--------------------------------------------------------------------------------
/challenges/2021/25-seaCucumber/README.md:
--------------------------------------------------------------------------------
1 | # [Day 25: Sea Cucumber](https://adventofcode.com/2021/day/25)
2 |
3 |
--------------------------------------------------------------------------------
/challenges/2021/25-seaCucumber/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 25,
3 | "dir": "challenges/2021/25-seaCucumber",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 1.2896365237236023,
7 | "part.1.max": 1.4006781578063965,
8 | "part.1.min": 1.2583773136138916,
9 | "part.2.avg": 0.000003247261047363281,
10 | "part.2.max": 0.000013828277587890625,
11 | "part.2.min": 0.0000016689300537109375
12 | }
13 | },
14 | "numRuns": 100
15 | }
--------------------------------------------------------------------------------
/challenges/2021/25-seaCucumber/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "v...>>.vv>\n.vv>>.vv..\n>>.>v>...v\n>>v>>.>.v.\nv>v.vv.v..\n>.>>..v...\n.vv..>.>v.\nv.v..>>v.v\n....v..v.>",
7 | "expected": "58"
8 | }
9 | ],
10 | "two": []
11 | },
12 | "incorrect": {
13 | "one": ["406", "312"]
14 | }
15 | }
--------------------------------------------------------------------------------
/challenges/2021/running-times.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2021/running-times.png
--------------------------------------------------------------------------------
/challenges/2022/01-calorieCounting/README.md:
--------------------------------------------------------------------------------
1 | # [Day 1: Calorie Counting](https://adventofcode.com/2022/day/1)
2 |
--------------------------------------------------------------------------------
/challenges/2022/01-calorieCounting/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 1,
3 | "dir": "challenges/2022/01-calorieCounting",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.001049538246,
7 | "part.1.max": 0.010881062,
8 | "part.1.min": 0.000266989,
9 | "part.2.avg": 0.0011080301140000003,
10 | "part.2.max": 0.003602068,
11 | "part.2.min": 0.000278025
12 | },
13 | "Python": {
14 | "part.1.avg": 0.001036302089691162,
15 | "part.1.max": 0.0028290748596191406,
16 | "part.1.min": 0.00023937225341796875,
17 | "part.2.avg": 0.0011057097911834717,
18 | "part.2.max": 0.003584623336791992,
19 | "part.2.min": 0.0002548694610595703
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/01-calorieCounting/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000\n",
7 | "expected": "24000"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000\n",
13 | "expected": "45000"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/01-calorieCounting/java/src/Main.java:
--------------------------------------------------------------------------------
1 | import java.io.FileNotFoundException;
2 |
3 | public class Main {
4 | public static void main(String[] args) throws FileNotFoundException {
5 | Challenge c = new Challenge("input.txt");
6 | System.out.println(c.partOne());
7 | System.out.println(c.partTwo());
8 | }
9 | }
--------------------------------------------------------------------------------
/challenges/2022/01-calorieCounting/nim/challenge.nim:
--------------------------------------------------------------------------------
1 | import std/strutils
2 | import std/sequtils
3 | import std/algorithm
4 |
5 | proc parseInput(instr: string): seq[seq[int]] =
6 | result = instr.
7 | strip.
8 | split("\n\n").
9 | map(proc(x: string): seq[int] = x.splitLines.map(parseInt))
10 |
11 | proc sum(x: openArray[int]): int =
12 | for i in 0.. List[List[int]]:
6 | return [map(int, x.split("\n")) for x in instr.strip().split("\n\n")]
7 |
8 |
9 | class Challenge(BaseChallenge):
10 | @staticmethod
11 | def one(instr: str) -> int:
12 | parsed = parse(instr)
13 | x = [sum(y) for y in parsed]
14 | return max(x)
15 |
16 | @staticmethod
17 | def two(instr: str) -> int:
18 | parsed = parse(instr)
19 | x = [sum(y) for y in parsed]
20 | x = list(sorted(x, reverse=True))
21 | return sum(x[:3])
22 |
--------------------------------------------------------------------------------
/challenges/2022/02-rockPaperScissors/README.md:
--------------------------------------------------------------------------------
1 | # [Day 2: Rock Paper Scissors](https://adventofcode.com/2022/day/2)
2 |
--------------------------------------------------------------------------------
/challenges/2022/02-rockPaperScissors/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 2,
3 | "dir": "challenges/2022/02-rockPaperScissors",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.0006056322499999992,
7 | "part.1.max": 0.002023021,
8 | "part.1.min": 0.000160608,
9 | "part.2.avg": 0.000544890418,
10 | "part.2.max": 0.002167248,
11 | "part.2.min": 0.000143214
12 | },
13 | "Python": {
14 | "part.1.avg": 0.005041266918182373,
15 | "part.1.max": 0.049498796463012695,
16 | "part.1.min": 0.001485586166381836,
17 | "part.2.avg": 0.002977017641067505,
18 | "part.2.max": 0.0347900390625,
19 | "part.2.min": 0.0008869171142578125
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/02-rockPaperScissors/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "A Y\nB X\nC Z\n",
7 | "expected": "15"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "A Y\nB X\nC Z\n",
13 | "expected": "12"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/03-rucksackReorganization/README.md:
--------------------------------------------------------------------------------
1 | # [Day 3: Rucksack Reorganization](https://adventofcode.com/2022/day/3)
2 |
--------------------------------------------------------------------------------
/challenges/2022/03-rucksackReorganization/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 3,
3 | "dir": "challenges/2022/03-rucksackReorganization",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.001724590531000001,
7 | "part.1.max": 0.004034478,
8 | "part.1.min": 0.000354275,
9 | "part.2.avg": 0.001641240340999998,
10 | "part.2.max": 0.003942411,
11 | "part.2.min": 0.000368459
12 | },
13 | "Python": {
14 | "part.1.avg": 0.0012067508697509765,
15 | "part.1.max": 0.0058939456939697266,
16 | "part.1.min": 0.0003886222839355469,
17 | "part.2.avg": 0.000901190996170044,
18 | "part.2.max": 0.0058858394622802734,
19 | "part.2.min": 0.0002906322479248047
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/03-rucksackReorganization/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "vJrwpWtwJgWrhcsFMMfFFhFp\njqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL\nPmmdzqPrVvPwwTWBwg\nwMqvLMZHhHMvwLHjbvcjnnSBnvTQFn\nttgJtRGJQctTZtZT\nCrZsJsPPZsGzwwsLwLmpwMDw",
7 | "expected": "157"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "vJrwpWtwJgWrhcsFMMfFFhFp\njqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL\nPmmdzqPrVvPwwTWBwg\nwMqvLMZHhHMvwLHjbvcjnnSBnvTQFn\nttgJtRGJQctTZtZT\nCrZsJsPPZsGzwwsLwLmpwMDw",
13 | "expected": "70"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/03-rucksackReorganization/nim/challenge.nim:
--------------------------------------------------------------------------------
1 | import std/sets
2 | import std/strutils
3 |
4 | proc parse(instr: string): seq[string] = instr.strip.splitlines
5 |
6 | proc getPriority(ch: char): int =
7 | let co = ch.ord
8 | if ord('a') <= co and co <= ord('z'):
9 | return (co - ord('a')) + 1
10 | return (co - ord('A')) + 27
11 |
12 | proc partOne*(instr: string): int =
13 | let inp = parse(instr)
14 |
15 | var sigma = 0
16 | for x in inp:
17 | assert x.len mod 2 == 0
18 | let l = x.len div 2
19 | var y = intersection(
20 | toHashSet(x[0.. int:
6 | for i in range(len(instr) - length):
7 | if len(set(instr[i : i + length])) == length:
8 | return i + length
9 | raise ValueError("cannot solve")
10 |
11 |
12 | class Challenge(BaseChallenge):
13 | @staticmethod
14 | def one(instr: str) -> int:
15 | return find_unique_sequence(instr, 4)
16 |
17 | @staticmethod
18 | def two(instr: str) -> int:
19 | return find_unique_sequence(instr, 14)
20 |
--------------------------------------------------------------------------------
/challenges/2022/07-noSpaceLeftOnDevice/README.md:
--------------------------------------------------------------------------------
1 | # [Day 7: No Space Left On Device](https://adventofcode.com/2022/day/7)
2 |
--------------------------------------------------------------------------------
/challenges/2022/07-noSpaceLeftOnDevice/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 7,
3 | "dir": "challenges/2022/07-noSpaceLeftOnDevice",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.005115992285999994,
7 | "part.1.max": 0.020854849,
8 | "part.1.min": 0.002606261,
9 | "part.2.avg": 0.0051005765810000015,
10 | "part.2.max": 0.018048126,
11 | "part.2.min": 0.002556105
12 | },
13 | "Python": {
14 | "part.1.avg": 0.00848755979537964,
15 | "part.1.max": 0.0318598747253418,
16 | "part.1.min": 0.0057828426361083984,
17 | "part.2.avg": 0.008544703245162964,
18 | "part.2.max": 0.03149008750915527,
19 | "part.2.min": 0.005964994430541992
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/07-noSpaceLeftOnDevice/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "$ cd /\n$ ls\ndir a\n14848514 b.txt\n8504156 c.dat\ndir d\n$ cd a\n$ ls\ndir e\n29116 f\n2557 g\n62596 h.lst\n$ cd e\n$ ls\n584 i\n$ cd ..\n$ cd ..\n$ cd d\n$ ls\n4060174 j\n8033020 d.log\n5626152 d.ext\n7214296 k\n",
7 | "expected": "95437"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "$ cd /\n$ ls\ndir a\n14848514 b.txt\n8504156 c.dat\ndir d\n$ cd a\n$ ls\ndir e\n29116 f\n2557 g\n62596 h.lst\n$ cd e\n$ ls\n584 i\n$ cd ..\n$ cd ..\n$ cd d\n$ ls\n4060174 j\n8033020 d.log\n5626152 d.ext\n7214296 k\n",
13 | "expected": "24933642"
14 | }
15 | ]
16 | },
17 | "not": {
18 | "one": ["1366030"]
19 | }
20 | }
--------------------------------------------------------------------------------
/challenges/2022/08-treetopTreeHouse/README.md:
--------------------------------------------------------------------------------
1 | # [Day 8: Treetop Tree House](https://adventofcode.com/2022/day/8)
2 |
--------------------------------------------------------------------------------
/challenges/2022/08-treetopTreeHouse/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 8,
3 | "dir": "challenges/2022/08-treetopTreeHouse",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.006382409829000001,
7 | "part.1.max": 0.026628604,
8 | "part.1.min": 0.004007148,
9 | "part.2.avg": 0.007344551142000002,
10 | "part.2.max": 0.034047325,
11 | "part.2.min": 0.004595712
12 | },
13 | "Python": {
14 | "part.1.avg": 0.0385476336479187,
15 | "part.1.max": 0.09098124504089355,
16 | "part.1.min": 0.025599002838134766,
17 | "part.2.avg": 0.04808542013168335,
18 | "part.2.max": 0.1426246166229248,
19 | "part.2.min": 0.031610965728759766
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/08-treetopTreeHouse/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "30373\n25512\n65332\n33549\n35390",
7 | "expected": "21"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "30373\n25512\n65332\n33549\n35390",
13 | "expected": "8"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/09-ropeBridge/README.md:
--------------------------------------------------------------------------------
1 | # [Day 9: Rope Bridge](https://adventofcode.com/2022/day/9)
2 |
--------------------------------------------------------------------------------
/challenges/2022/09-ropeBridge/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 9,
3 | "dir": "challenges/2022/09-ropeBridge",
4 | "implementations": {
5 | "Nim": {
6 | "part.1.avg": 0.002931661109000006,
7 | "part.1.max": 0.007730762,
8 | "part.1.min": 0.000887947,
9 | "part.2.avg": 0.004008995328999999,
10 | "part.2.max": 0.011666485,
11 | "part.2.min": 0.001218443
12 | },
13 | "Python": {
14 | "part.1.avg": 0.015390190362930298,
15 | "part.1.max": 0.03382277488708496,
16 | "part.1.min": 0.010709762573242188,
17 | "part.2.avg": 0.0444308967590332,
18 | "part.2.max": 0.14687561988830566,
19 | "part.2.min": 0.03348994255065918
20 | }
21 | },
22 | "numRuns": 1000
23 | }
--------------------------------------------------------------------------------
/challenges/2022/09-ropeBridge/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2",
7 | "expected": "13"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2",
13 | "expected": "1"
14 | },
15 | {
16 | "input": "R 5\nU 8\nL 8\nD 3\nR 17\nD 10\nL 25\nU 20\n",
17 | "expected": "36"
18 | }
19 | ]
20 | }
21 | }
--------------------------------------------------------------------------------
/challenges/2022/10-cathodeRayTube/README.md:
--------------------------------------------------------------------------------
1 | # [Day 10: Cathode Ray Tube](https://adventofcode.com/2022/day/10)
2 |
--------------------------------------------------------------------------------
/challenges/2022/10-cathodeRayTube/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 10,
3 | "dir": "challenges/2022/10-cathodeRayTube",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.0004485485553741455,
7 | "part.1.max": 0.0012202262878417969,
8 | "part.1.min": 0.00010895729064941406,
9 | "part.2.avg": 0.0006327939033508301,
10 | "part.2.max": 0.0017185211181640625,
11 | "part.2.min": 0.0001571178436279297
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2022/11-monkeyInTheMiddle/README.md:
--------------------------------------------------------------------------------
1 | # [Day 11: Monkey In The Middle](https://adventofcode.com/2022/day/11)
2 |
--------------------------------------------------------------------------------
/challenges/2022/11-monkeyInTheMiddle/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 11,
3 | "dir": "challenges/2022/11-monkeyInTheMiddle",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.0008889389038085938,
7 | "part.1.max": 0.002737283706665039,
8 | "part.1.min": 0.0006763935089111328,
9 | "part.2.avg": 0.46039318370819093,
10 | "part.2.max": 0.6005921363830566,
11 | "part.2.min": 0.3884415626525879
12 | }
13 | },
14 | "numRuns": 250
15 | }
--------------------------------------------------------------------------------
/challenges/2022/12-hillClimbingAlgorithm/README.md:
--------------------------------------------------------------------------------
1 | # [Day 12: Hill Climbing Algorithm](https://adventofcode.com/2022/day/12)
2 |
--------------------------------------------------------------------------------
/challenges/2022/12-hillClimbingAlgorithm/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 12,
3 | "dir": "challenges/2022/12-hillClimbingAlgorithm",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 2.804302930831909,
7 | "part.1.max": 2.804302930831909,
8 | "part.1.min": 2.804302930831909,
9 | "part.2.avg": 191.0712034702301,
10 | "part.2.max": 191.0712034702301,
11 | "part.2.min": 191.0712034702301
12 | }
13 | },
14 | "numRuns": 1
15 | }
--------------------------------------------------------------------------------
/challenges/2022/12-hillClimbingAlgorithm/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "Sabqponm\nabcryxxl\naccszExk\nacctuvwj\nabdefghi\n",
7 | "expected": "31"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "Sabqponm\nabcryxxl\naccszExk\nacctuvwj\nabdefghi\n",
13 | "expected": "29"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/13-distressSignal/README.md:
--------------------------------------------------------------------------------
1 | # [Day 13: Distress Signal](https://adventofcode.com/2022/day/13)
2 |
--------------------------------------------------------------------------------
/challenges/2022/13-distressSignal/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 13,
3 | "dir": "challenges/2022/13-distressSignal",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.002429138422012329,
7 | "part.1.max": 0.013918876647949219,
8 | "part.1.min": 0.0013120174407958984,
9 | "part.2.avg": 0.008559255361557007,
10 | "part.2.max": 0.03811001777648926,
11 | "part.2.min": 0.004506111145019531
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2022/13-distressSignal/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "[1,1,3,1,1]\n[1,1,5,1,1]\n\n[[1],[2,3,4]]\n[[1],4]\n\n[9]\n[[8,7,6]]\n\n[[4,4],4,4]\n[[4,4],4,4,4]\n\n[7,7,7,7]\n[7,7,7]\n\n[]\n[3]\n\n[[[]]]\n[[]]\n\n[1,[2,[3,[4,[5,6,7]]]],8,9]\n[1,[2,[3,[4,[5,6,0]]]],8,9]\n",
7 | "expected": "13"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "[1,1,3,1,1]\n[1,1,5,1,1]\n\n[[1],[2,3,4]]\n[[1],4]\n\n[9]\n[[8,7,6]]\n\n[[4,4],4,4]\n[[4,4],4,4,4]\n\n[7,7,7,7]\n[7,7,7]\n\n[]\n[3]\n\n[[[]]]\n[[]]\n\n[1,[2,[3,[4,[5,6,7]]]],8,9]\n[1,[2,[3,[4,[5,6,0]]]],8,9]\n",
13 | "expected": "140"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/14-regolithReservoir/README.md:
--------------------------------------------------------------------------------
1 | # [Day 14: Regolith Reservoir](https://adventofcode.com/2022/day/14)
2 |
--------------------------------------------------------------------------------
/challenges/2022/14-regolithReservoir/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 14,
3 | "dir": "challenges/2022/14-regolithReservoir",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.052977256774902344,
7 | "part.1.max": 0.059580087661743164,
8 | "part.1.min": 0.04468560218811035,
9 | "part.2.avg": 3.079384412765503,
10 | "part.2.max": 3.293449640274048,
11 | "part.2.min": 2.7332167625427246
12 | }
13 | },
14 | "numRuns": 25
15 | }
--------------------------------------------------------------------------------
/challenges/2022/14-regolithReservoir/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "498,4 -> 498,6 -> 496,6\n503,4 -> 502,4 -> 502,9 -> 494,9\n",
7 | "expected": "24"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "498,4 -> 498,6 -> 496,6\n503,4 -> 502,4 -> 502,9 -> 494,9\n",
13 | "expected": "93"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/15-beaconExclusionZone/README.md:
--------------------------------------------------------------------------------
1 | # [Day 15: Beacon Exclusion Zone](https://adventofcode.com/2022/day/15)
2 |
3 | Here's some of my whiteboard doodles (don't mind that they're wrong in places)
4 |
5 | 
--------------------------------------------------------------------------------
/challenges/2022/15-beaconExclusionZone/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 15,
3 | "dir": "challenges/2022/15-beaconExclusionZone",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 2.488755464553833,
7 | "part.1.max": 2.488755464553833,
8 | "part.1.min": 2.488755464553833,
9 | "part.2.avg": 295.4520,
10 | "part.2.max": 295.4520,
11 | "part.2.min": 295.4520
12 | }
13 | },
14 | "numRuns": 1
15 | }
--------------------------------------------------------------------------------
/challenges/2022/15-beaconExclusionZone/doodles.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2022/15-beaconExclusionZone/doodles.jpg
--------------------------------------------------------------------------------
/challenges/2022/16-proboscideaVolcanium/README.md:
--------------------------------------------------------------------------------
1 | # [Day 16: Proboscidea Volcanium](https://adventofcode.com/2022/day/16)
2 |
3 | [This solution was used to end up with my solution](https://github.com/davearussell/advent2022/blob/master/day16/solve.py).
--------------------------------------------------------------------------------
/challenges/2022/16-proboscideaVolcanium/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 16,
3 | "dir": "challenges/2022/16-proboscideaVolcanium",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 3.520505666732788,
7 | "part.1.max": 3.520505666732788,
8 | "part.1.min": 3.520505666732788,
9 | "part.2.avg": 18.672574281692505,
10 | "part.2.max": 18.672574281692505,
11 | "part.2.min": 18.672574281692505
12 | }
13 | },
14 | "numRuns": 1
15 | }
--------------------------------------------------------------------------------
/challenges/2022/17-pyroclasticFlow/README.md:
--------------------------------------------------------------------------------
1 | # [Day 17: Pyroclastic Flow](https://adventofcode.com/2022/day/17)
2 |
--------------------------------------------------------------------------------
/challenges/2022/17-pyroclasticFlow/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 17,
3 | "dir": "challenges/2022/17-pyroclasticFlow",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.5983425378799438,
7 | "part.1.max": 0.6658821105957031,
8 | "part.1.min": 0.5308029651641846,
9 | "part.2.avg": 12.261357307434082,
10 | "part.2.max": 12.877821207046509,
11 | "part.2.min": 11.644893407821655
12 | }
13 | },
14 | "numRuns": 2
15 | }
--------------------------------------------------------------------------------
/challenges/2022/17-pyroclasticFlow/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>",
7 | "expected": "3068"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>",
13 | "expected": "1514285714288"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/18-boilingBoulders/README.md:
--------------------------------------------------------------------------------
1 | # [Day 18: Boiling Boulders](https://adventofcode.com/2022/day/18)
2 |
--------------------------------------------------------------------------------
/challenges/2022/18-boilingBoulders/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 18,
3 | "dir": "challenges/2022/18-boilingBoulders",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.02251845836639404,
7 | "part.1.max": 0.03545045852661133,
8 | "part.1.min": 0.018925189971923828,
9 | "part.2.avg": 0.12088701725006104,
10 | "part.2.max": 0.1763911247253418,
11 | "part.2.min": 0.10623359680175781
12 | }
13 | },
14 | "numRuns": 200
15 | }
--------------------------------------------------------------------------------
/challenges/2022/18-boilingBoulders/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "2,2,2\n1,2,2\n3,2,2\n2,1,2\n2,3,2\n2,2,1\n2,2,3\n2,2,4\n2,2,6\n1,2,5\n3,2,5\n2,1,5\n2,3,5\n",
7 | "expected": "64"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "2,2,2\n1,2,2\n3,2,2\n2,1,2\n2,3,2\n2,2,1\n2,2,3\n2,2,4\n2,2,6\n1,2,5\n3,2,5\n2,1,5\n2,3,5\n",
13 | "expected": "58"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/18-boilingBoulders/openscad-generate.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | inp = sys.stdin.read()
4 |
5 | print(len(inp), file=sys.stderr)
6 |
7 | print("union(){")
8 |
9 | for line in inp.strip().splitlines():
10 | print(f"\ttranslate([{line}]) cube(1);")
11 |
12 | print("};")
13 |
--------------------------------------------------------------------------------
/challenges/2022/19-notEnoughMinerals/README.md:
--------------------------------------------------------------------------------
1 | # [Day 19: Not Enough Minerals](https://adventofcode.com/2022/day/19)
2 |
3 | My part 2 took 48 minutes to run. ***48!!*** Even though part 1 only took 17 seconds! aaaaaaaaaaa
4 |
--------------------------------------------------------------------------------
/challenges/2022/19-notEnoughMinerals/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 19,
3 | "dir": "challenges/2022/19-notEnoughMinerals",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 17.7188,
7 | "part.1.max": 17.7188,
8 | "part.1.min": 17.7188,
9 | "part.2.avg": 2903.2192,
10 | "part.2.max": 2903.2192,
11 | "part.2.min": 2903.2192
12 | }
13 | },
14 | "numRuns": 1
15 | }
--------------------------------------------------------------------------------
/challenges/2022/19-notEnoughMinerals/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.\n",
7 | "expected": "33"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.\n",
13 | "expected": "3472"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/20-grovePositioningSystem/README.md:
--------------------------------------------------------------------------------
1 | # [Day 20: Grove Positioning System](https://adventofcode.com/2022/day/20)
2 |
--------------------------------------------------------------------------------
/challenges/2022/20-grovePositioningSystem/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 20,
3 | "dir": "challenges/2022/20-grovePositioningSystem",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.6482098897298177,
7 | "part.1.max": 0.6944289207458496,
8 | "part.1.min": 0.5697693824768066,
9 | "part.2.avg": 12.018423795700073,
10 | "part.2.max": 12.624868154525757,
11 | "part.2.min": 11.30324387550354
12 | }
13 | },
14 | "numRuns": 3
15 | }
--------------------------------------------------------------------------------
/challenges/2022/20-grovePositioningSystem/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "1\n2\n-3\n3\n-2\n0\n4\n",
7 | "expected": "3"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "1\n2\n-3\n3\n-2\n0\n4\n",
13 | "expected": "1623178306"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/21-monkeyMath/README.md:
--------------------------------------------------------------------------------
1 | # [Day 21: Monkey Math](https://adventofcode.com/2022/day/21)
2 |
--------------------------------------------------------------------------------
/challenges/2022/21-monkeyMath/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 21,
3 | "dir": "challenges/2022/21-monkeyMath",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.004400461912155151,
7 | "part.1.max": 0.018651485443115234,
8 | "part.1.min": 0.003258943557739258,
9 | "part.2.avg": 0.007683101415634155,
10 | "part.2.max": 0.03519558906555176,
11 | "part.2.min": 0.005395650863647461
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2022/21-monkeyMath/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "root: pppw + sjmn\ndbpl: 5\ncczh: sllz + lgvd\nzczc: 2\nptdq: humn - dvpt\ndvpt: 3\nlfqf: 4\nhumn: 5\nljgn: 2\nsjmn: drzm * dbpl\nsllz: 4\npppw: cczh / lfqf\nlgvd: ljgn * ptdq\ndrzm: hmdt - zczc\nhmdt: 32\n",
7 | "expected": "152"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "root: pppw + sjmn\ndbpl: 5\ncczh: sllz + lgvd\nzczc: 2\nptdq: humn - dvpt\ndvpt: 3\nlfqf: 4\nhumn: 5\nljgn: 2\nsjmn: drzm * dbpl\nsllz: 4\npppw: cczh / lfqf\nlgvd: ljgn * ptdq\ndrzm: hmdt - zczc\nhmdt: 32\n",
13 | "expected": "301"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/22-monkeyMap/README.md:
--------------------------------------------------------------------------------
1 | # [Day 22: Monkey Map](https://adventofcode.com/2022/day/22)
2 |
3 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
--------------------------------------------------------------------------------
/challenges/2022/22-monkeyMap/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 22,
3 | "dir": "challenges/2022/22-monkeyMap",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.3011732864379883,
7 | "part.1.max": 0.4757208824157715,
8 | "part.1.min": 0.23815560340881348,
9 | "part.2.avg": 0.07583048105239869,
10 | "part.2.max": 0.1293351650238037,
11 | "part.2.min": 0.062180280685424805
12 | }
13 | },
14 | "numRuns": 100
15 | }
--------------------------------------------------------------------------------
/challenges/2022/22-monkeyMap/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": " ...#\n .#..\n #...\n ....\n...#.......#\n........#...\n..#....#....\n..........#.\n ...#....\n .....#..\n .#......\n ......#.\n\n10R5L5R10L4R5L5\n",
7 | "expected": "6032"
8 | }
9 | ]
10 | }
11 | }
--------------------------------------------------------------------------------
/challenges/2022/23-unstableDiffusion/README.md:
--------------------------------------------------------------------------------
1 | # [Day 23: Unstable Diffusion](https://adventofcode.com/2022/day/23)
2 |
--------------------------------------------------------------------------------
/challenges/2022/23-unstableDiffusion/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 23,
3 | "dir": "challenges/2022/23-unstableDiffusion",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.5044037818908691,
7 | "part.1.max": 0.6002228260040283,
8 | "part.1.min": 0.4217519760131836,
9 | "part.2.avg": 39.05081315040589,
10 | "part.2.max": 41.361868143081665,
11 | "part.2.min": 38.02052927017212
12 | }
13 | },
14 | "numRuns": 5
15 | }
--------------------------------------------------------------------------------
/challenges/2022/23-unstableDiffusion/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": ".....\n..##.\n..#..\n.....\n..##.\n.....",
7 | "expected": "25"
8 | },
9 | {
10 | "input": "....#..\n..###.#\n#...#.#\n.#...##\n#.###..\n##.#.##\n.#..#..\n",
11 | "expected": "110"
12 | }
13 | ],
14 | "two": [
15 | {
16 | "input": ".....\n..##.\n..#..\n.....\n..##.\n.....",
17 | "expected": "4"
18 | },
19 | {
20 | "input": "....#..\n..###.#\n#...#.#\n.#...##\n#.###..\n##.#.##\n.#..#..\n",
21 | "expected": "20"
22 | }
23 | ]
24 | }
25 | }
--------------------------------------------------------------------------------
/challenges/2022/24-blizzardBasin/README.md:
--------------------------------------------------------------------------------
1 | # [Day 24: Blizzard Basin](https://adventofcode.com/2022/day/24)
2 |
--------------------------------------------------------------------------------
/challenges/2022/24-blizzardBasin/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 24,
3 | "dir": "challenges/2022/24-blizzardBasin",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 3.8155926863352456,
7 | "part.1.max": 3.83038330078125,
8 | "part.1.min": 3.801712989807129,
9 | "part.2.avg": 11.761492411295572,
10 | "part.2.max": 11.78315782546997,
11 | "part.2.min": 11.74697995185852
12 | }
13 | },
14 | "numRuns": 3
15 | }
--------------------------------------------------------------------------------
/challenges/2022/24-blizzardBasin/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "#.######\n#>>.<^<#\n#.<..<<#\n#>v.><>#\n#<^v^^>#\n######.#\n",
7 | "expected": "18"
8 | }
9 | ],
10 | "two": [
11 | {
12 | "input": "#.######\n#>>.<^<#\n#.<..<<#\n#>v.><>#\n#<^v^^>#\n######.#\n",
13 | "expected": "54"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/challenges/2022/25-fullOfHotAir/README.md:
--------------------------------------------------------------------------------
1 | # [Day 25: Full Of Hot Air](https://adventofcode.com/2022/day/25)
2 |
--------------------------------------------------------------------------------
/challenges/2022/25-fullOfHotAir/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "day": 25,
3 | "dir": "challenges/2022/25-fullOfHotAir",
4 | "implementations": {
5 | "Python": {
6 | "part.1.avg": 0.001312760591506958,
7 | "part.1.max": 0.003961801528930664,
8 | "part.1.min": 0.0003647804260253906,
9 | "part.2.avg": 0.0000055599212646484376,
10 | "part.2.max": 0.000046253204345703125,
11 | "part.2.min": 0.000001430511474609375
12 | }
13 | },
14 | "numRuns": 1000
15 | }
--------------------------------------------------------------------------------
/challenges/2022/25-fullOfHotAir/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputFile": "input.txt",
3 | "testCases": {
4 | "one": [
5 | {
6 | "input": "1=-0-2\n12111\n2=0=\n21\n2=01\n111\n20012\n112\n1=-1=\n1-12\n12\n1=\n122\n",
7 | "expected": "2=-1=0"
8 | },
9 | {"input": "1", "expected": "1"},
10 | {"input": "2", "expected": "2"},
11 | {"input": "1=", "expected": "1="},
12 | {"input": "1-", "expected": "1-"},
13 | {"input": "10", "expected": "10"},
14 | {"input": "11", "expected": "11"},
15 | {"input": "12", "expected": "12"},
16 | {"input": "2=", "expected": "2="},
17 | {"input": "2-", "expected": "2-"},
18 | {"input": "20", "expected": "20"},
19 | {"input": "1=0", "expected": "1=0"},
20 | {"input": "1-0", "expected": "1-0"},
21 | {"input": "1=11-2", "expected": "1=11-2"},
22 | {"input": "1-0---0", "expected": "1-0---0"},
23 | {"input": "1121-1110-1=0", "expected": "1121-1110-1=0"}
24 | ]
25 | }
26 | }
--------------------------------------------------------------------------------
/challenges/2022/running-times.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2022/running-times.png
--------------------------------------------------------------------------------
/challenges/2023/01-trebuchet/README.md:
--------------------------------------------------------------------------------
1 | # [Day 1: Trebuchet?!](https://adventofcode.com/2023/day/1)
2 |
3 | The Haskell implementation included here is only partial, mostly because I ran out of patience with it after taking an age to implement the CLI required.
4 |
--------------------------------------------------------------------------------
/challenges/2023/01-trebuchet/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"input": "1abc2\npqr3stu8vwx\na1b2c3d4e5f\ntreb7uchet", "is": "142"}
4 | ],
5 | "2": [
6 | {"input": "two1nine\neightwothree\nabcone2threexyz\nxtwone3four\n4nineeightseven2\nzoneight234\n7pqrstsixteen", "is": "281"},
7 | {"input": "eighthree", "is": "83"},
8 | {"input": "sevenine", "is": "79"}
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/challenges/2023/02-cubeConundrum/README.md:
--------------------------------------------------------------------------------
1 | # [Day 2: Cube Conundrum](https://adventofcode.com/2023/day/2)
2 |
--------------------------------------------------------------------------------
/challenges/2023/02-cubeConundrum/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"input": "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green\nGame 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue\nGame 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red\nGame 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red\nGame 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green", "is": "8"}
4 | ],
5 | "2": [
6 | {"input": "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green\nGame 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue\nGame 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red\nGame 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red\nGame 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green", "is": "2286"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/challenges/2023/03-gearRatios/README.md:
--------------------------------------------------------------------------------
1 | # [Day 3: Gear Ratios](https://adventofcode.com/2023/day/3)
2 |
--------------------------------------------------------------------------------
/challenges/2023/03-gearRatios/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "4361", "input": "467..114..\n...*......\n..35..633.\n......#...\n617*......\n.....+.58.\n..592.....\n......755.\n...$.*....\n.664.598.."}
4 | ],
5 | "2": [
6 | {"is": "467835", "input": "467..114..\n...*......\n..35..633.\n......#...\n617*......\n.....+.58.\n..592.....\n......755.\n...$.*....\n.664.598.."}
7 | ]
8 | }
--------------------------------------------------------------------------------
/challenges/2023/04-scratchcards/README.md:
--------------------------------------------------------------------------------
1 | # [Day 4: Scratchcards](https://adventofcode.com/2023/day/4)
2 |
--------------------------------------------------------------------------------
/challenges/2023/04-scratchcards/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "13", "input": "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\nCard 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\nCard 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\nCard 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\nCard 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\nCard 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11\n"}
4 | ],
5 | "2": [
6 | {"is": "30", "input": "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\nCard 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\nCard 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\nCard 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\nCard 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\nCard 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11\n"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/challenges/2023/05-ifYouGiveASeedAFertilizer/README.md:
--------------------------------------------------------------------------------
1 | # [Day 5: If You Give A Seed A Fertilizer](https://adventofcode.com/2023/day/5)
2 |
--------------------------------------------------------------------------------
/challenges/2023/05-ifYouGiveASeedAFertilizer/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "35", "input": "seeds: 79 14 55 13\n\nseed-to-soil map:\n50 98 2\n52 50 48\n\nsoil-to-fertilizer map:\n0 15 37\n37 52 2\n39 0 15\n\nfertilizer-to-water map:\n49 53 8\n0 11 42\n42 0 7\n57 7 4\n\nwater-to-light map:\n88 18 7\n18 25 70\n\nlight-to-temperature map:\n45 77 23\n81 45 19\n68 64 13\n\ntemperature-to-humidity map:\n0 69 1\n1 0 69\n\nhumidity-to-location map:\n60 56 37\n56 93 4"}
4 | ],
5 | "2": [
6 | {"is": "46", "input": "seeds: 79 14 55 13\n\nseed-to-soil map:\n50 98 2\n52 50 48\n\nsoil-to-fertilizer map:\n0 15 37\n37 52 2\n39 0 15\n\nfertilizer-to-water map:\n49 53 8\n0 11 42\n42 0 7\n57 7 4\n\nwater-to-light map:\n88 18 7\n18 25 70\n\nlight-to-temperature map:\n45 77 23\n81 45 19\n68 64 13\n\ntemperature-to-humidity map:\n0 69 1\n1 0 69\n\nhumidity-to-location map:\n60 56 37\n56 93 4"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/challenges/2023/06-waitForIt/README.md:
--------------------------------------------------------------------------------
1 | # [Day 6: Wait For It](https://adventofcode.com/2023/day/6)
2 |
--------------------------------------------------------------------------------
/challenges/2023/06-waitForIt/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "288", "input": "Time: 7 15 30\nDistance: 9 40 200\n"}
4 | ],
5 | "2": [
6 | {"is": "71503", "input": "Time: 7 15 30\nDistance: 9 40 200\n"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/challenges/2023/07-camelCards/README.md:
--------------------------------------------------------------------------------
1 | # [Day 7: Camel Cards](https://adventofcode.com/2023/day/7)
2 |
--------------------------------------------------------------------------------
/challenges/2023/07-camelCards/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "6440", "input": "32T3K 765\nT55J5 684\nKK677 28\nKTJJT 220\nQQQJA 483"}
4 | ],
5 | "2": [
6 | {"is": "5905", "input": "32T3K 765\nT55J5 684\nKK677 28\nKTJJT 220\nQQQJA 483"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/challenges/2023/08-hauntedWasteland/README.md:
--------------------------------------------------------------------------------
1 | # [Day 8: Haunted Wasteland](https://adventofcode.com/2023/day/8)
2 |
3 | A generic solution is implemented in commit 208114cb6222064c1a174b69e737c7cd051defa2
--------------------------------------------------------------------------------
/challenges/2023/08-hauntedWasteland/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "2", "input": "RL\n\nAAA = (BBB, CCC)\nBBB = (DDD, EEE)\nCCC = (ZZZ, GGG)\nDDD = (DDD, DDD)\nEEE = (EEE, EEE)\nGGG = (GGG, GGG)\nZZZ = (ZZZ, ZZZ)\n"},
4 | {"is": "6", "input": "LLR\n\nAAA = (BBB, BBB)\nBBB = (AAA, ZZZ)\nZZZ = (ZZZ, ZZZ)\n"}
5 | ],
6 | "2": [
7 | {"is": "6", "input": "LR\n\n11A = (11B, XXX)\n11B = (XXX, 11Z)\n11Z = (11B, XXX)\n22A = (22B, XXX)\n22B = (22C, 22C)\n22C = (22Z, 22Z)\n22Z = (22B, 22B)\nXXX = (XXX, XXX)\n"}
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/challenges/2023/09-mirageMaintenance/README.md:
--------------------------------------------------------------------------------
1 | # [Day 9: Mirage Maintenance](https://adventofcode.com/2023/day/9)
2 |
--------------------------------------------------------------------------------
/challenges/2023/09-mirageMaintenance/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {"is": "114", "input": "0 3 6 9 12 15\n1 3 6 10 15 21\n10 13 16 21 30 45\n"},
4 | {"is": "36", "input": "30 26 24 24 26 30"}
5 | ],
6 | "2": [
7 | {"is": "2", "input": "0 3 6 9 12 15\n1 3 6 10 15 21\n10 13 16 21 30 45\n"},
8 | {"is": "36", "input": "30 26 24 24 26 30"}
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/challenges/2023/10-pipeMaze/README.md:
--------------------------------------------------------------------------------
1 | # [Day 10: Pipe Maze](https://adventofcode.com/2023/day/10)
2 |
--------------------------------------------------------------------------------
/challenges/2023/11-cosmicExpansion/README.md:
--------------------------------------------------------------------------------
1 | # [Day 11: Cosmic Expansion](https://adventofcode.com/2023/day/11)
2 |
--------------------------------------------------------------------------------
/challenges/2023/11-cosmicExpansion/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "374",
5 | "input": "...#......\n.......#..\n#.........\n..........\n......#...\n.#........\n.........#\n..........\n.......#..\n#...#.....\n\n"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/challenges/2023/12-hotSprings/README.md:
--------------------------------------------------------------------------------
1 | # [Day 12: Hot Springs](https://adventofcode.com/2023/day/12)
2 |
3 | Before optimisation: 17.13 seconds for part 1
4 |
5 | 
6 |
7 | After optimisation: 0.80 seconds for part 2
8 |
9 | 
--------------------------------------------------------------------------------
/challenges/2023/12-hotSprings/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "1",
5 | "input": "???.### 1,1,3"
6 | },
7 | {
8 | "is": "4",
9 | "input": ".??..??...?##. 1,1,3"
10 | },
11 | {
12 | "is": "1",
13 | "input": "?#?#?#?#?#?#?#? 1,3,1,6"
14 | },
15 | {
16 | "is": "1",
17 | "input": "????.#...#... 4,1,1"
18 | },
19 | {
20 | "is": "4",
21 | "input": "????.######..#####. 1,6,5"
22 | },
23 | {
24 | "is": "10",
25 | "input": "?###???????? 3,2,1"
26 | },
27 | {
28 | "is": "0",
29 | "input": "#?? 2,1"
30 | }
31 | ],
32 | "2": [
33 | {
34 | "is": "525152",
35 | "input": "???.### 1,1,3\n.??..??...?##. 1,1,3\n?#?#?#?#?#?#?#? 1,3,1,6\n????.#...#... 4,1,1\n????.######..#####. 1,6,5\n?###???????? 3,2,1\n\n"
36 | }
37 | ]
38 | }
--------------------------------------------------------------------------------
/challenges/2023/13-pointOfIncidence/README.md:
--------------------------------------------------------------------------------
1 | # [Day 13: Point of Incidence](https://adventofcode.com/2023/day/13)
2 |
3 | I've got a function that checks vertical lines of symmetry, and to check horizontal ones I just swap the `(x, y)` coords in the grid to `(y, x)` then run it again.
4 |
5 | For each candidate line of symmetry, work out a range that values we need to check (based on which side goes out of bounds first), then for each row in the full height of the grid, count how many rocks are `x` steps away from the line (eg. `.#.|.#.` has 2 rocks 1 step away, assuming the pipe is the line we're checking around).
6 |
7 | For part 1, we just check that no single row has any step within it that doesn't have 0 or 2 rocks.
8 |
9 | For part 2, we make the same check but allow any grid where only a single row fouls that condition. This gives us multiple candidate lines of symmetry for each grid, so we diff it with the as-is case from part 1 and use whatever is new.
--------------------------------------------------------------------------------
/challenges/2023/13-pointOfIncidence/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "405",
5 | "input": "#.##..##.\n..#.##.#.\n##......#\n##......#\n..#.##.#.\n..##..##.\n#.#.##.#.\n\n#...##..#\n#....#..#\n..##..###\n#####.##.\n#####.##.\n..##..###\n#....#..#\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "400",
11 | "input": "#.##..##.\n..#.##.#.\n##......#\n##......#\n..#.##.#.\n..##..##.\n#.#.##.#.\n\n#...##..#\n#....#..#\n..##..###\n#####.##.\n#####.##.\n..##..###\n#....#..#\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/14-parabolicReflectorDish/README.md:
--------------------------------------------------------------------------------
1 | # [Day 14: Parabolic Reflector Dish](https://adventofcode.com/2023/day/14)
2 |
3 | Visualisation exists as `out.mp4`
--------------------------------------------------------------------------------
/challenges/2023/14-parabolicReflectorDish/digits.txt:
--------------------------------------------------------------------------------
1 | xxx
2 | x x
3 | x x
4 | x x
5 | x x
6 | x x
7 | xxx
8 |
9 | x
10 | xxx
11 | x
12 | x
13 | x
14 | x
15 | xxxxx
16 |
17 | xxx
18 | x x
19 | x
20 | x
21 | x
22 | x
23 | xxxxx
24 |
25 | xxx
26 | x x
27 | x
28 | xx
29 | x
30 | x x
31 | xxx
32 |
33 | x
34 | xx
35 | x x
36 | x x
37 | xxxxx
38 | x
39 | x
40 |
41 | xxxxx
42 | x
43 | x
44 | xxxx
45 | x
46 | x x
47 | xxx
48 |
49 | xxx
50 | x x
51 | x
52 | xxxx
53 | x x
54 | x x
55 | xxx
56 |
57 | xxxxx
58 | x
59 | x
60 | x
61 | x
62 | x
63 | x
64 |
65 | xxx
66 | x x
67 | x x
68 | xxx
69 | x x
70 | x x
71 | xxx
72 |
73 | xxx
74 | x x
75 | x x
76 | xxxx
77 | x
78 | x x
79 | xxx
80 |
--------------------------------------------------------------------------------
/challenges/2023/14-parabolicReflectorDish/generate-vis.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -ex
4 |
5 | cat input.txt | python3 vis.py
6 | ffmpeg -y -framerate 30 -pattern_type glob -i 'frames/*.png' -c:v libx264 -pix_fmt yuv420p out.mp4
7 |
--------------------------------------------------------------------------------
/challenges/2023/14-parabolicReflectorDish/out.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2023/14-parabolicReflectorDish/out.mp4
--------------------------------------------------------------------------------
/challenges/2023/14-parabolicReflectorDish/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "136",
5 | "input": "O....#....\nO.OO#....#\n.....##...\nOO.#O....O\n.O.....O#.\nO.#..O.#.#\n..O..#O..O\n.......O..\n#....###..\n#OO..#....\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "64",
11 | "input": "O....#....\nO.OO#....#\n.....##...\nOO.#O....O\n.O.....O#.\nO.#..O.#.#\n..O..#O..O\n.......O..\n#....###..\n#OO..#....\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/15-lensLibrary/README.md:
--------------------------------------------------------------------------------
1 | # [Day 15: Lens Library](https://adventofcode.com/2023/day/15)
2 |
3 | * 2 not 315986
--------------------------------------------------------------------------------
/challenges/2023/15-lensLibrary/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "1320",
5 | "input": "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "145",
11 | "input": "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/16-theFloorWillBeLava/README.md:
--------------------------------------------------------------------------------
1 | # [Day 16: The Floor Will Be Lava](https://adventofcode.com/2023/day/16)
2 |
--------------------------------------------------------------------------------
/challenges/2023/16-theFloorWillBeLava/test.txt:
--------------------------------------------------------------------------------
1 | .|...\....
2 | |.-.\.....
3 | .....|-...
4 | ........|.
5 | ..........
6 | .........\
7 | ..../.\\..
8 | .-.-/..|..
9 | .|....-|.\
10 | ..//.|....
11 |
--------------------------------------------------------------------------------
/challenges/2023/16-theFloorWillBeLava/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "46",
5 | "input": ".|...\\....\n|.-.\\.....\n.....|-...\n........|.\n..........\n.........\\\n..../.\\\\..\n.-.-/..|..\n.|....-|.\\\n..//.|....\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "51",
11 | "input": ".|...\\....\n|.-.\\.....\n.....|-...\n........|.\n..........\n.........\\\n..../.\\\\..\n.-.-/..|..\n.|....-|.\\\n..//.|....\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/17-clumsyCrucible/README.md:
--------------------------------------------------------------------------------
1 | # [Day 17: Clumsy Crucible](https://adventofcode.com/2023/day/17)
2 |
--------------------------------------------------------------------------------
/challenges/2023/17-clumsyCrucible/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "102",
5 | "input": "2413432311323\n3215453535623\n3255245654254\n3446585845452\n4546657867536\n1438598798454\n4457876987766\n3637877979653\n4654967986887\n4564679986453\n1224686865563\n2546548887735\n4322674655533\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "94",
11 | "input": "2413432311323\n3215453535623\n3255245654254\n3446585845452\n4546657867536\n1438598798454\n4457876987766\n3637877979653\n4654967986887\n4564679986453\n1224686865563\n2546548887735\n4322674655533\n\n"
12 | },
13 | {
14 | "is": "71",
15 | "input": "111111111111\n999999999991\n999999999991\n999999999991\n999999999991\n\n"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/challenges/2023/18-lavaductLagoon/README.md:
--------------------------------------------------------------------------------
1 | # [Day 18: Lavaduct Lagoon](https://adventofcode.com/2023/day/18)
2 |
--------------------------------------------------------------------------------
/challenges/2023/18-lavaductLagoon/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "62",
5 | "input": "R 6 (#70c710)\nD 5 (#0dc571)\nL 2 (#5713f0)\nD 2 (#d2c081)\nR 2 (#59c680)\nD 2 (#411b91)\nL 5 (#8ceee2)\nU 2 (#caa173)\nL 1 (#1b58a2)\nU 2 (#caa171)\nR 2 (#7807d2)\nU 3 (#a77fa3)\nL 2 (#015232)\nU 2 (#7a21e3)\n\n"
6 | },
7 | {
8 | "is": "20",
9 | "input": "R 2 (#000000)\nD 1 (#000000)\nR 2 (#000000)\nU 1 (#000000)\nR 2 (#000000)\nD 2 (#000000)\nL 6 (#000000)\nU 2 (#000000)\n"
10 | }
11 | ],
12 | "2": [
13 | {
14 | "is": "952408144115",
15 | "input": "R 6 (#70c710)\nD 5 (#0dc571)\nL 2 (#5713f0)\nD 2 (#d2c081)\nR 2 (#59c680)\nD 2 (#411b91)\nL 5 (#8ceee2)\nU 2 (#caa173)\nL 1 (#1b58a2)\nU 2 (#caa171)\nR 2 (#7807d2)\nU 3 (#a77fa3)\nL 2 (#015232)\nU 2 (#7a21e3)\n\n"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/challenges/2023/19-aplenty/README.md:
--------------------------------------------------------------------------------
1 | # [Day 19: Aplenty](https://adventofcode.com/2023/day/19)
2 |
3 | This is not a problem I expected to be able to first-try part 2 for.
--------------------------------------------------------------------------------
/challenges/2023/19-aplenty/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "19114",
5 | "input": "px{a<2006:qkq,m>2090:A,rfg}\npv{a>1716:R,A}\nlnx{m>1548:A,A}\nrfg{s<537:gd,x>2440:R,A}\nqs{s>3448:A,lnx}\nqkq{x<1416:A,crn}\ncrn{x>2662:A,R}\nin{s<1351:px,qqz}\nqqz{s>2770:qs,m<1801:hdj,R}\ngd{a>3333:R,R}\nhdj{m>838:A,pv}\n\n{x=787,m=2655,a=1222,s=2876}\n{x=1679,m=44,a=2067,s=496}\n{x=2036,m=264,a=79,s=2244}\n{x=2461,m=1339,a=466,s=291}\n{x=2127,m=1623,a=2188,s=1013}\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "167409079868000",
11 | "input": "px{a<2006:qkq,m>2090:A,rfg}\npv{a>1716:R,A}\nlnx{m>1548:A,A}\nrfg{s<537:gd,x>2440:R,A}\nqs{s>3448:A,lnx}\nqkq{x<1416:A,crn}\ncrn{x>2662:A,R}\nin{s<1351:px,qqz}\nqqz{s>2770:qs,m<1801:hdj,R}\ngd{a>3333:R,R}\nhdj{m>838:A,pv}\n\n{x=787,m=2655,a=1222,s=2876}\n{x=1679,m=44,a=2067,s=496}\n{x=2036,m=264,a=79,s=2244}\n{x=2461,m=1339,a=466,s=291}\n{x=2127,m=1623,a=2188,s=1013}\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/20-pulsePropagation/README.md:
--------------------------------------------------------------------------------
1 | # [Day 20: Pulse Propagation](https://adventofcode.com/2023/day/20)
2 |
--------------------------------------------------------------------------------
/challenges/2023/20-pulsePropagation/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "32000000",
5 | "input": "broadcaster -> a, b, c\n%a -> b\n%b -> c\n%c -> inv\n&inv -> a\n\n"
6 | },
7 | {
8 | "is": "11687500",
9 | "input": "broadcaster -> a\n%a -> inv, con\n&inv -> b\n%b -> con\n&con -> output\n"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/challenges/2023/21-stepCounter/README.md:
--------------------------------------------------------------------------------
1 | # [Day 21: Step Counter](https://adventofcode.com/2023/day/21)
2 |
--------------------------------------------------------------------------------
/challenges/2023/21-stepCounter/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "16",
5 | "input": "...........\n.....###.#.\n.###.##..#.\n..#.#...#..\n....#.#....\n.##..S####.\n.##..#...#.\n.......##..\n.##.#.####.\n.##..##.##.\n...........\n\n"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/challenges/2023/22-sandSlabs/README.md:
--------------------------------------------------------------------------------
1 | # [Day 22: Sand Slabs](https://adventofcode.com/2023/day/22)
2 |
--------------------------------------------------------------------------------
/challenges/2023/22-sandSlabs/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "5",
5 | "input": "1,0,1~1,2,1\n0,0,2~2,0,2\n0,2,3~2,2,3\n0,0,4~0,2,4\n2,0,5~2,2,5\n0,1,6~2,1,6\n1,1,8~1,1,9\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "7",
11 | "input": "1,0,1~1,2,1\n0,0,2~2,0,2\n0,2,3~2,2,3\n0,0,4~0,2,4\n2,0,5~2,2,5\n0,1,6~2,1,6\n1,1,8~1,1,9\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/23-aLongWalk/README.md:
--------------------------------------------------------------------------------
1 | # [Day 23: A Long Walk](https://adventofcode.com/2023/day/23)
2 |
3 | Part 2 is *not*:
4 | * 4717 (too low)
5 | * 4826 (too low)
6 | * 5350 (too low)
--------------------------------------------------------------------------------
/challenges/2023/24-neverTellMeTheOdds/README.md:
--------------------------------------------------------------------------------
1 | # [Day 24: Never Tell Me The Odds](https://adventofcode.com/2023/day/24)
2 |
3 | Part 1 is not:
4 | * 1344 (too low)
5 | * 48384 (too high)
6 |
7 | Running this solution requires `z3-solver` to be installed.
--------------------------------------------------------------------------------
/challenges/2023/24-neverTellMeTheOdds/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "2",
5 | "input": "19, 13, 30 @ -2, 1, -2\n18, 19, 22 @ -1, -1, -2\n20, 25, 34 @ -2, -2, -4\n12, 31, 28 @ -1, -2, -1\n20, 19, 15 @ 1, -5, -3\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "47",
11 | "input": "19, 13, 30 @ -2, 1, -2\n18, 19, 22 @ -1, -1, -2\n20, 25, 34 @ -2, -2, -4\n12, 31, 28 @ -1, -2, -1\n20, 19, 15 @ 1, -5, -3\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2023/25-snowverload/README.md:
--------------------------------------------------------------------------------
1 | # [Day 25: Snowverload](https://adventofcode.com/2023/day/25)
2 |
--------------------------------------------------------------------------------
/challenges/2023/25-snowverload/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "54",
5 | "input": "jqt: rhn xhk nvd\nrsh: frs pzl lsr\nxhk: hfx\ncmg: qnr nvd lhk bvb\nrhn: xhk bvb hfx\nbvb: xhk hfx\npzl: lsr hfx nvd\nqnr: nvd\nntq: jqt hfx bvb xhk\nnvd: lhk\nlsr: lhk\nrzs: qnr cmg lsr rsh\nfrs: qnr lhk lsr\n\n"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/challenges/2023/benchmark-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2023/benchmark-graph.png
--------------------------------------------------------------------------------
/challenges/2024/01-historianHysteria/README.md:
--------------------------------------------------------------------------------
1 | # [Day 1: Historian Hysteria](https://adventofcode.com/2024/day/1)
2 |
--------------------------------------------------------------------------------
/challenges/2024/01-historianHysteria/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "11",
5 | "input": "3 4\n4 3\n2 5\n1 3\n3 9\n3 3\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "31",
11 | "input": "3 4\n4 3\n2 5\n1 3\n3 9\n3 3\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/02-redNosedReports/README.md:
--------------------------------------------------------------------------------
1 | # [Day 2: Red Nosed Reports](https://adventofcode.com/2024/day/2)
2 |
--------------------------------------------------------------------------------
/challenges/2024/02-redNosedReports/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "2",
5 | "input": "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "4",
11 | "input": "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/03-mullItOver/README.md:
--------------------------------------------------------------------------------
1 | # [Day 3: Mull It Over](https://adventofcode.com/2024/day/3)
2 |
--------------------------------------------------------------------------------
/challenges/2024/03-mullItOver/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "161",
5 | "input": "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "48",
11 | "input": "xmul(2,4)&mul[3,7]rundon't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/04-ceresSearch/README.md:
--------------------------------------------------------------------------------
1 | # [Day 4: Ceres Search](https://adventofcode.com/2024/day/4)
2 |
3 | Part two is:
4 | * less than 1976
5 | * also, somewhat obviously, less than 1978
6 |
7 | Heatmap of the most overlapped locations
8 |
9 | | Part 1 | Part 2 |
10 | |--------|--------|
11 | |  |  |
--------------------------------------------------------------------------------
/challenges/2024/04-ceresSearch/generate-vis.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -ex
4 |
5 | cat input.txt | PYTHONPATH=../../../ python3 vis.py
6 |
--------------------------------------------------------------------------------
/challenges/2024/04-ceresSearch/heatmap-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2024/04-ceresSearch/heatmap-1.png
--------------------------------------------------------------------------------
/challenges/2024/04-ceresSearch/heatmap-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2024/04-ceresSearch/heatmap-2.png
--------------------------------------------------------------------------------
/challenges/2024/04-ceresSearch/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "18",
5 | "input": "MMMSXXMASM\nMSAMXMSMSA\nAMXSXMAAMM\nMSAMASMSMX\nXMASAMXAMM\nXXAMMXXAMA\nSMSMSASXSS\nSAXAMASAAA\nMAMMMXMMMM\nMXMXAXMASX\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "9",
11 | "input": "MMMSXXMASM\nMSAMXMSMSA\nAMXSXMAAMM\nMSAMASMSMX\nXMASAMXAMM\nXXAMMXXAMA\nSMSMSASXSS\nSAXAMASAAA\nMAMMMXMMMM\nMXMXAXMASX\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/05-printQueue/README.md:
--------------------------------------------------------------------------------
1 | # [Day 5: Print Queue](https://adventofcode.com/2024/day/5)
2 |
--------------------------------------------------------------------------------
/challenges/2024/05-printQueue/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "143",
5 | "input": "47|53\n97|13\n97|61\n97|47\n75|29\n61|13\n75|53\n29|13\n97|29\n53|29\n61|53\n97|53\n61|29\n47|13\n75|47\n97|75\n47|61\n75|61\n47|29\n75|13\n53|13\n\n75,47,61,53,29\n97,61,53,29,13\n75,29,13\n75,97,47,61,53\n61,13,29\n97,13,75,29,47\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "123",
11 | "input": "47|53\n97|13\n97|61\n97|47\n75|29\n61|13\n75|53\n29|13\n97|29\n53|29\n61|53\n97|53\n61|29\n47|13\n75|47\n97|75\n47|61\n75|61\n47|29\n75|13\n53|13\n\n75,47,61,53,29\n97,61,53,29,13\n75,29,13\n75,97,47,61,53\n61,13,29\n97,13,75,29,47\n\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/06-guardGallivant/README.md:
--------------------------------------------------------------------------------
1 | # [Day 6: Guard Gallivant](https://adventofcode.com/2024/day/6)
2 |
3 | Part 2 is:
4 | * higher than 456
5 | * less than 1689
6 |
7 | The first implementation of part 2 took 15 minutes to run.
8 |
9 | * Turning `visited_sequence` in `trace` into a set instead of a list cut this to 60 seconds
10 | * Starting immediately in front of the new obstacle when testing positions to put said new obstacle in cut this to 20 seconds
11 | * Removing a load of maps and type wranging to turn the fully generic `gridutil.add` (and counterparts) into a more limited but much faster function took this to ~16 seconds
12 |
13 | Before:
14 |
15 | ```py
16 | def _coordmap(a: AnyCoordinate, b: AnyCoordinate, fn: Callable) -> AnyCoordinate:
17 | at = type(a)
18 | return at(*map(fn, zip(a, b)))
19 |
20 | def add(a: AnyCoordinate, b: AnyCoordinate) -> AnyCoordinate:
21 | return _coordmap(a, b, lambda x: x[0] + x[1])
22 | ```
23 |
24 | After:
25 |
26 |
27 | ```py
28 | def add(a: Coordinate, b: Coordinate) -> Coordinate:
29 | return Coordinate(a.x + b.x, a.y + b.y)
30 | ```
--------------------------------------------------------------------------------
/challenges/2024/06-guardGallivant/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "41",
5 | "input": "....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...\n\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "6",
11 | "input": "....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/07-bridgeRepair/README.md:
--------------------------------------------------------------------------------
1 | # [Day 7: Bridge Repair](https://adventofcode.com/2024/day/7)
2 |
3 | Part 1 is:
4 | * greater than 450054910499
5 |
6 | Before optimisation (pregenerating then testing operator combiantions using `itertools.product("*+|", length=n)`), run time looks something like this:
7 |
8 | ```
9 | Part 1: min 0.2671 seconds, max 0.2818 seconds, avg 0.2755
10 | Part 2: min 23.2387 seconds, max 24.8753 seconds, avg 23.8805
11 | ```
12 |
13 | It also appeared that using string concatenation as opposed to pure mathematical functions for the concatenation operator was marginally faster in Python.
14 |
15 | After optimisation (recursive solves working backwards through the numbers), the run time looks something like this:
16 |
17 | ```
18 | Part 1: min 0.0214 seconds, max 0.041 seconds, avg 0.0233
19 | Part 2: min 0.0215 seconds, max 0.0273 seconds, avg 0.0229
20 | ```
21 |
22 | The intial version of this solve is in commit `b2fa4b7`.
--------------------------------------------------------------------------------
/challenges/2024/07-bridgeRepair/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "3749",
5 | "input": "190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "11387",
11 | "input": "190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/08-resonantCollinearity/README.md:
--------------------------------------------------------------------------------
1 | # [Day 8: Resonant Collinearity](https://adventofcode.com/2024/day/8)
2 |
3 | Part 1 is:
4 | * less than 298
5 |
6 | This is not a fully generic solution as, in a situation where the differences between x and y dimensions of pairs of coordinates are not coprime, this implementation would skip steps.
7 |
8 | Visualisation exists as `out.mp4`
9 |
--------------------------------------------------------------------------------
/challenges/2024/08-resonantCollinearity/generate-vis.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -ex
4 |
5 | cat input.txt | PYTHONPATH=../../../ python3 vis.py
6 | ffmpeg -y -framerate 30 -pattern_type glob -i 'frames/*.png' -c:v libx264 -pix_fmt yuv420p out.mp4
7 |
--------------------------------------------------------------------------------
/challenges/2024/08-resonantCollinearity/out.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2024/08-resonantCollinearity/out.mp4
--------------------------------------------------------------------------------
/challenges/2024/08-resonantCollinearity/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "14",
5 | "input": "............\n........0...\n.....0......\n.......0....\n....0.......\n......A.....\n............\n............\n........A...\n.........A..\n............\n............\n\n"
6 | },
7 | {
8 | "is": "2",
9 | "input": "..........\n..........\n..........\n....a.....\n..........\n.....a....\n..........\n..........\n..........\n..........\n\n"
10 | },
11 | {
12 | "is": "4",
13 | "input": "..........\n..........\n..........\n....a.....\n........a.\n.....a....\n..........\n..........\n..........\n..........\n"
14 | }
15 | ],
16 | "2": [
17 | {
18 | "is": "34",
19 | "input": "............\n........0...\n.....0......\n.......0....\n....0.......\n......A.....\n............\n............\n........A...\n.........A..\n............\n............\n\n"
20 | },
21 | {
22 | "is": "9",
23 | "input": "T.........\n...T......\n.T........\n..........\n..........\n..........\n..........\n..........\n..........\n..........\n"
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/challenges/2024/09-diskFragmenter/README.md:
--------------------------------------------------------------------------------
1 | # [Day 9: Disk Fragmenter](https://adventofcode.com/2024/day/9)
2 |
3 | Part 2 is:
4 | * less than 6277851188082
5 | 6272188244509
--------------------------------------------------------------------------------
/challenges/2024/09-diskFragmenter/tests.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": [
3 | {
4 | "is": "1928",
5 | "input": "2333133121414131402\n"
6 | }
7 | ],
8 | "2": [
9 | {
10 | "is": "2858",
11 | "input": "2333133121414131402\n"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/challenges/2024/benchmark-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemicro/adventOfCode/569c26b209f4f0a8879cac902fc926f0f9515703/challenges/2024/benchmark-graph.png
--------------------------------------------------------------------------------
/gridutil/__init__.py:
--------------------------------------------------------------------------------
1 | import gridutil.grid
2 | import gridutil.coord
3 |
--------------------------------------------------------------------------------
/runners/buildGo.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | TEMPFILE=$(mktemp)
6 | go build -o "$TEMPFILE" "$1"
7 | echo $TEMPFILE
8 |
--------------------------------------------------------------------------------
/runners/buildKotlin.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | TEMPDIR="$(mktemp -d)"
6 | FNAME=$(basename $1 | sed 's/\.kt$/.jar/')
7 | FULLPATH="$TEMPDIR/$FNAME"
8 | kotlinc "$1" -include-runtime -d "$FULLPATH"
9 | echo $FULLPATH
10 |
--------------------------------------------------------------------------------
/runners/jar.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | java -jar $@
--------------------------------------------------------------------------------
/runners/py.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | PYTHONPATH=. python3 $@
6 |
--------------------------------------------------------------------------------
/templates/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "os"
7 | "strings"
8 | )
9 |
10 | func parse(instr string) any {
11 | return nil
12 | }
13 |
14 | func one(instr string) int {
15 | return -1
16 | }
17 |
18 | func two(instr string) int {
19 | return -1
20 | }
21 |
22 | func main() {
23 | if len(os.Args) < 2 || !(os.Args[1] == "1" || os.Args[1] == "2") {
24 | debug("Missing day argument")
25 | os.Exit(1)
26 | }
27 |
28 | inp, err := io.ReadAll(os.Stdin)
29 | if err != nil {
30 | panic(err)
31 | }
32 | inpStr := strings.TrimSpace(string(inp))
33 |
34 | switch os.Args[1] {
35 | case "1":
36 | fmt.Println(one(inpStr))
37 | case "2":
38 | fmt.Println(two(inpStr))
39 | }
40 | }
41 |
42 | func debug(f string, sub ...any) {
43 | fmt.Fprintf(os.Stderr, f, sub...)
44 | }
45 |
--------------------------------------------------------------------------------
/templates/main.hs:
--------------------------------------------------------------------------------
1 | import System.Environment
2 | import System.Exit
3 | import System.IO
4 | import Data.Maybe
5 |
6 | type ChallengeReturn = String
7 |
8 | one :: String -> ChallengeReturn
9 | one inp = undefined
10 |
11 | two :: String -> ChallengeReturn
12 | two inp = undefined
13 |
14 | main :: IO ()
15 | main = do args <- getArgs
16 | inp <- getContents
17 | _runFn (_selectFn args) inp
18 |
19 | _selectFn :: [String] -> Maybe (String -> ChallengeReturn)
20 | _selectFn ["1"] = Just one
21 | _selectFn ["2"] = Just two
22 | _selectFn _ = Nothing
23 |
24 | _runFn :: Maybe (String -> ChallengeReturn) -> String -> IO ()
25 | _runFn Nothing _ = _debug "Missing or invalid day argument" >> exitWith (ExitFailure 1)
26 | _runFn (Just fn) inp = putStrLn (fn inp) >> exitWith ExitSuccess
27 |
28 | _debug :: String -> IO ()
29 | _debug x = do hPutStrLn stderr x
30 |
--------------------------------------------------------------------------------
/templates/main.kt:
--------------------------------------------------------------------------------
1 | import java.lang.System
2 | import kotlin.system.*
3 | import kotlin.sequences.generateSequence
4 | import kotlin.text.trim
5 |
6 | fun parse(instr: String) {
7 |
8 | }
9 |
10 | fun one(instr: String): Int {
11 | return 0
12 | }
13 |
14 | fun two(instr: String): Int {
15 | return 0
16 | }
17 |
18 | fun main(args: Array) {
19 | if (args.size < 1 || !(args[0] == "1" || args[0] == "2")) {
20 | debug("Missing or invalid day argument")
21 | exitProcess(1)
22 | }
23 | val inp = generateSequence(::readLine).joinToString("\n").trim()
24 | if (args[0] == "1") {
25 | println("${one(inp)}")
26 | } else {
27 | println("${two(inp)}")
28 | }
29 | }
30 |
31 | fun debug(msg: String) {
32 | System.err.println(msg)
33 | }
--------------------------------------------------------------------------------
/templates/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def parse(instr: str) -> None:
5 | return
6 |
7 |
8 | def one(instr: str):
9 | return
10 |
11 |
12 | def two(instr: str):
13 | return
14 |
15 |
16 | def _debug(*args, **kwargs):
17 | kwargs["file"] = sys.stderr
18 | print(*args, **kwargs)
19 |
20 |
21 | if __name__ == "__main__":
22 | if len(sys.argv) < 2 or sys.argv[1] not in ["1", "2"]:
23 | print("Missing day argument", file=sys.stderr)
24 | sys.exit(1)
25 | inp = sys.stdin.read().strip()
26 | if sys.argv[1] == "1":
27 | print(one(inp))
28 | else:
29 | print(two(inp))
--------------------------------------------------------------------------------