Skip to content

Commit

Permalink
Day 09
Browse files Browse the repository at this point in the history
  • Loading branch information
yitsushi committed Dec 10, 2021
1 parent 09731c5 commit 10b3015
Show file tree
Hide file tree
Showing 13 changed files with 579 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cmd/aoc2021/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/yitsushi/advent-of-code-2021/days/day06"
"github.com/yitsushi/advent-of-code-2021/days/day07"
"github.com/yitsushi/advent-of-code-2021/days/day08"
"github.com/yitsushi/advent-of-code-2021/days/day09"
)

func withDays(month puzzle.Month) puzzle.Month {
Expand All @@ -22,6 +23,7 @@ func withDays(month puzzle.Month) puzzle.Month {
month.Register(6, &day06.Solver{})
month.Register(7, &day07.Solver{})
month.Register(8, &day08.Solver{})
month.Register(9, &day09.Solver{})

return month
}
12 changes: 12 additions & 0 deletions days/day09/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package day09

import "fmt"

// OutOfBoundError happens when we want to reach a position ouside of the map.
type OutOfBoundError struct {
Index int
}

func (e OutOfBoundError) Error() string {
return fmt.Sprintf("out of bound error: %d", e.Index)
}
5 changes: 5 additions & 0 deletions days/day09/fixtures/example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
2199943210
3987894921
9856789892
8767896789
9899965678
100 changes: 100 additions & 0 deletions days/day09/fixtures/input
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
8754399998765678934569897649898767987432123986543213567997681024589763459854327895454567899979876567
9865989879854578923998789438789656795421013499854101278976542137678954598765456964323456789768995456
1979879965913569899878679626598947987532194987653232389898756398889865679876587953212457899656789345
0999767894301346798767568917467898998999989998754343499769877479996986789987678943103998988545999156
9875658789212457899653498902345789989987978999875454678956998567895397898998789653239899876839878997
2984545678923498987732497893459898679876867899986568789545459789954298967899898764349768995424456989
1973123789434589876521256789767986598765458998797678899632349895432109456789909865997659789312349979
9862012578955678965410345789979895439897346789698989998921234999543212367898919979876545689101298864
7653223467896799876321235899998754320989477897569099987892545898767323498987898998765435679232987743
8868434578987899965434345678959965439876568999432129876989656799875456999456997898765323578949896542
9876545699198978976745676789349878545987679998764598765679767899876567894359876987653214789898785621
5987676789019567898956897899956989787898989999975987654568978999987879945298765698775623456789654310
3298798993123458999498969999899996999929497899986798923589989998798989932129854349986737687899794322
2129899986548899992359356789798765678912345678997976534678999987689999893998743234598898788929876533
3348998997656789989467969899659978799323567789989998645689999874578999789897654345689949899434987545
5656987898767899878979899998743989976539678999978909897898979953489987656799765656792125989695997657
6879876789888989867999789897654599987898989999868912998997567892198986545698976768921014568989898798
8989865678999876548987678789765679099987899898756793569989998989987665434567897979432123459879789899
9498654569643987656996545678978789129876989654345679699879899878998543212367998989543456998767689998
4349865678954598987894323489989899298765678973216789989765679869898664323458999297677679877654568997
3239876789985699898965412345996998989874567892101234978954398756789775434567893139798899965433699976
4109987899876987679876103457895987879983459989235349867895987645678996755678921029929989954321788965
3298998965998976569954323568999876767892598768976798658999876535869899876989432198939767895434567893
4397899893219987698765454567897965656991698657997899545699965423456789987897543987898956789567789912
6976976789909998789896566788945694547789987645789999434589876534787895898998659876787645678998992101
9965865667897899890987989999896983234679876535678998545678987645678974799329969865486536789999543322
8754323458976899921298991556789975135798765323456987678789999876899753689919899986321017899987678433
9843212357894567893989632345899989245899986434567898989899876987976974567898798765432128989999989994
9954301348943656789876546786999895346953497565778949799998764398975965689998659986554534678998998789
9865412367892347998987697997899765456932987678899235678929865459989878789987643987866545799567897678
1996537569901456987898989998939876767891299899910123799219876567897999891987654598977656892456789567
0989987678912367896999878999212987978910123992391234942109998678986579910199799679198787891367993456
9878999899953567895698767898923498989521345679989349899298769999975437921988978989019898942478902567
8767899989879789934989656987994989995432656789778997678965459889876556899876567899999999543589323478
9657789875999892129878549876789879876543467898656789498976797679987987898765456789879987674696534567
9545678954569954298765432345689756997654578909947992347897987568899898949993234898968698985897647688
8434567893498765459986321235799842398767678919899743456999876456789789234989148897657569697898798799
7545798932349876578996410134999921269878789998789654567899765347898698949878956789543454598999899912
8786899543467987889987821235689543459989899886599995698998654236987567896967899898432123999898965301
9897999964878998999998642547898654567993998765457889789879764345897678985756789987645239899767993212
6989989895989979479899753457929865788901989654345679998769865456789799864347999897656798778456789323
4579876789998768366789876569019879899899876545234567899656976577892987643238998789978989563348995434
3398765678929854255899989678923989976789985432125678932987987698921098432159876567899765431237896545
2129654569919867134989999989434599965691096421034789321398999789993298541099965467909876210176989766
1019993457899773235678998996545699894989297533145895435459799899989987693989876378919986321245678997
2298789967899654547999997987699989792165987654256789945997689998878998989878987459998765432346799789
3987679899998765659531986798988777689014598765468899899886599987567899878767898567899878643456789678
9876545788999878967999994339876566579923459876979956789765498765468998764356789679932989987567994599
8765434567894989879878789212965452467894567988989245999854329878312349875457898789641094597679999689
9965325789912399989865678909854321378995678999297457898763219885101256988768949896532123498789878993
9978412892109989998754567898765210135789789980196568999874598764312345999879235987643435679893467892
8989523993298678998653278999879321245678999871987979698765679984323679893989123498754545678942378901
7995436789396545698764345699875432356789498762398989549896893986654598782393234569767657899321999992
6789545678989434579975456789986743456789219654569991239989921098765697654459945679898968998939889989
5678967899678924569996567897399865767898999765678989998878932129976798765667897789959979987998775678
4567898934569319698789978965246978978987878976789679876767893239987899986899939893244598976899654678
2458979320178998987678989954358989989876767987898789765456789398698912399996547992123497865678943789
1278965491389987896567898765467999998965656898959898654345678976569699498989956789019986564989654894
2367896989499896985456789876569878987654548789349999875234567895434578997879899892198765473699879932
3456789878998765674367898988998767996543237678998998692123458954325678986567798943999654312579989321
4767898769987654561234567899987856789542123567897987543254569543212349895454687959876543201467898730
5978997658998963210123679901976545878953234689995498954345678969101998765343456799987875412345679641
6789899867899654721234569219875634767894645789789599898758789998929876543212345689998964323456789432
9896799978939875674348678939994323456789656898678988789869899987999987672101234578998765537577997545
9985989989012987786759789998963213697898767956569876679979989876989899865216795789569876646989798986
9874578992124598999899899987954325989999998943498865567899879765679766994345678995459987658994679987
8763469789235789921932999896899476978999989432976543456799854323456954986776899212398799869543456798
7542345678945699892921298765778999869689976569877331357898763210567893098987942101987689978954569899
9321234567896798759893987654567897654567897698765210237999895432378932199798994299876579989765678912
5456347698997987645789199873456789543456998799854325446789976556489653987649789978765467899879889923
6565456789999765434679297632347997654868949989965436556892989667689769999735699866212345999989999899
7676567997898652123589986544459899765689939878976787667921998789799898989129789754323456789992345798
8798678956789843254678987676598798976789898769987898989939879899899987678998998765458578998921959897
9899989767898764567889998787987687897999797659899969396899965910979876567887999896567699987899899986
1932199878969975678999989899895456798998678645779954245789874321256975453456789987779789876799799875
0193998999456989789998776987678347989997576534667895345699765432346965322345678998989998765678678964
1989897632357899899889645987563239867976434323456987456798976543499876410238789879997897654234567973
2979789543468921998765439765432153458985321012667896567987997654987654321234894569876789543123457899
9865698954599893987656023986549012369876432523678987679876889765698766432457943498765679764034598978
9764567895987759876543234797898137478987675434567898798765679896789879745567892987654567932125899568
8643786789876545987654345698996546789198786545678979898664589987899987656678979699843457897236789346
6532345678985432399895456789987857994019897656799567997543468998998998767799764598764598976347895459
7653567989876531569979967891098968943235998768923456985432377999987549878894643469975689765456789568
9765678998983210998767898962239979654459999879436569876621456789896432989943012979896799876568998779
9876789467974329899879999543478989795998987989999978986532567896795321299932199898789899987879999889
7987994359865439789989397654567899989787895699888899986543478965989432349893989747678989998999899998
6798987212976798698993298776678999878576996898777789987654567894678943498789767634599878999986788976
7999876434987977567979999897899898756455989989665568998765678923499854598678954523989769798765667895
8987987565699765454567896998956796544234769876533457899876789765789767898789763219979945698754656789
9876598978798754323478965449349897932123456965412345678987892976799899989999854998767824598743445678
4989499989899998454589986321298989891015569654323456889798901987899989878899969876543213987652134567
2398989990999997567995975410987677789234698765434568997659213499967879965799989987632101298543245898
1987679891298997678954986829876566689345689876987678989998994569656567894678998996545212349654456789
9876566789987898789993497845985434578956890998999799679886989798743459965699987989694393498766567899
8765465698765699897989598956987316789897921989878954599765678999995998977789896578976989999897878989
9943344987654987945678999767999402356789549976767893987654569899889897989899765467899878789998989879
8432123498743495434389899879873212345898798865656899998543654698767786999987674356898765699019698768
7643234898767894321235789998764325476789897654345788999652123598654645898797543237899654578924569978
9654655679879985410134567899865445567899986545234567898761024696543234789643210123978976689635678989
8765678799989876621245789999876786798998765432123456789432123987654345698775431234569987796545689999
34 changes: 34 additions & 0 deletions days/day09/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package day09

import (
"bufio"
"io"
)

// Solver is the main solver.
type Solver struct {
input CaveMap
}

const (
asciiShift = 48
)

// SetInput receives the input and parses its content.
func (d *Solver) SetInput(input io.Reader) error {
scanner := bufio.NewScanner(input)
d.input = newCaveMap()

for scanner.Scan() {
text := scanner.Text()
line := []int{}

for _, character := range text {
line = append(line, int(character-asciiShift))
}

d.input.AddLayer(line)
}

return nil
}
23 changes: 23 additions & 0 deletions days/day09/input_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package day09_test

import (
"bytes"
"io/ioutil"
"testing"

"github.com/stretchr/testify/assert"
"github.com/yitsushi/advent-of-code-2021/days/day09"
test "github.com/yitsushi/go-aoc/testing"
)

func TestSolver_SetInput(t *testing.T) {
example, err := test.LoadFixture("example")
if !assert.NoError(t, err) {
return
}

day := day09.Solver{}
err = day.SetInput(ioutil.NopCloser(bytes.NewReader(example)))

assert.NoError(t, err)
}
60 changes: 60 additions & 0 deletions days/day09/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package day09

import (
"fmt"
"sort"

"github.com/yitsushi/go-aoc/math"
"github.com/yitsushi/go-aoc/perf"
)

// Part1 for this day.
func (d *Solver) Part1() (string, error) {
defer perf.Duration(perf.Track("Part1"))

result := 0

for _, location := range d.input.FindLowPoints() {
if value, err := d.input.Position(location); err == nil {
result += value + 1
}
}

return fmt.Sprintf("%d", result), nil
}

// Part2 for this day.
func (d *Solver) Part2() (string, error) {
defer perf.Duration(perf.Track("Part2"))

basinSizes := []int{}

for _, sink := range d.input.FindLowPoints() {
basin := append(d.input.WhoCanFlowHere(sink), sink)
basinSizes = append(basinSizes, len(removeDuplicateValues(basin)))
}

sort.Slice(basinSizes, func(i, j int) bool {
return basinSizes[i] > basinSizes[j]
})

result := basinSizes[0] * basinSizes[1] * basinSizes[2]

return fmt.Sprintf("%d", result), nil
}

func removeDuplicateValues(input []math.Vector2DInt) []math.Vector2DInt {
keys := make(map[interface{}]bool)
list := []math.Vector2DInt{}

for _, entry := range input {
hash := entry.Hash()
if _, value := keys[hash]; !value {
keys[hash] = true

list = append(list, entry)
}
}

return list
}
142 changes: 142 additions & 0 deletions days/day09/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package day09

import (
"github.com/yitsushi/go-aoc/math"
)

const (
topValue = 9
)

// CaveMap is the map of the cave.
type CaveMap struct {
layers [][]int
}

func newCaveMap() CaveMap {
return CaveMap{layers: [][]int{}}
}

// AddLayer to the map.
func (c *CaveMap) AddLayer(line []int) {
c.layers = append(c.layers, line)
}

// Layers of the map.
func (c CaveMap) Layers() [][]int {
return c.layers
}

// Layer of the map.
func (c CaveMap) Layer(n int) ([]int, error) {
if n < 0 || n >= len(c.layers) {
return []int{}, OutOfBoundError{Index: n}
}

return c.layers[n], nil
}

// Position value on the map.
func (c CaveMap) Position(coord math.Vector2DInt) (int, error) {
targetRow, err := c.Layer(coord.Y)
if err != nil {
return -1, err
}

if coord.X < 0 || coord.X >= len(targetRow) {
return -1, OutOfBoundError{Index: coord.X}
}

return targetRow[coord.X], nil
}

// Adjacents positions.
func (c CaveMap) Adjacents(coord math.Vector2DInt) []math.Vector2DInt {
result := []math.Vector2DInt{}

targets := []math.Vector2DInt{
{X: 0, Y: 1},
{X: 0, Y: -1},
{X: 1, Y: 0},
{X: -1, Y: 0},
}

for _, target := range targets {
if _, err := c.Position(coord.Add(target)); err == nil {
result = append(result, coord.Add(target))
}
}

return result
}

// IsLowest checks if all adjacents are higher or not.
func (c CaveMap) IsLowest(coord math.Vector2DInt) bool {
value, err := c.Position(coord)
if err != nil {
return false
}

for _, adjacent := range c.Adjacents(coord) {
adjacentValue, err := c.Position(adjacent)
if err != nil {
continue
}

if adjacentValue <= value {
return false
}
}

return true
}

// FindLowPoints returns with all the positions where it's the lowest based
// on its adjacent positions.
func (c CaveMap) FindLowPoints() []math.Vector2DInt {
result := []math.Vector2DInt{}

for idy, line := range c.Layers() {
for idx := range line {
if c.IsLowest(math.Vector2DInt{Y: idy, X: idx}) {
result = append(
result,
math.Vector2DInt{X: idx, Y: idy},
)
}
}
}

return result
}

// WhoCanFlowHere walks up on the map from a point to discover basins.
func (c CaveMap) WhoCanFlowHere(coord math.Vector2DInt) []math.Vector2DInt {
result := []math.Vector2DInt{}

value, err := c.Position(coord)
if err != nil {
return result
}

for _, target := range c.Adjacents(coord) {
targetValue, err := c.Position(target)
if err != nil {
continue
}

if targetValue == topValue {
continue
}

if targetValue > value {
result = append(result, target)
}
}

for _, target := range result {
result = append(result, c.WhoCanFlowHere(target)...)
}

return result
}
Loading

0 comments on commit 10b3015

Please sign in to comment.