From 1393ed13d6a9747645a8e0546cab540c51b62dee Mon Sep 17 00:00:00 2001 From: Fred Ulrich <9284621+fulrich@users.noreply.github.com> Date: Wed, 14 Dec 2022 13:11:49 -0500 Subject: [PATCH] Solution for Day 14 --- src/main/resources/day14_cave_system | 148 ++++++++++++++++++ .../ulrichs/aoc/core/algebra/Coordinate.scala | 13 ++ .../ca/ulrichs/aoc/core/algebra/Grid.scala | 20 +-- .../core/algebra/pathing/PathFinding.scala | 1 - .../ulrichs/aoc/core/input/InputParsing.scala | 5 +- .../aoc/island/waterfall/CaveSystem.scala | 74 +++++++++ .../ulrichs/aoc/core/algebra/GridTest.scala | 2 +- .../aoc/island/waterfall/CaveSystemTest.scala | 34 ++++ 8 files changed, 282 insertions(+), 15 deletions(-) create mode 100644 src/main/resources/day14_cave_system create mode 100644 src/main/scala/ca/ulrichs/aoc/island/waterfall/CaveSystem.scala create mode 100644 src/test/scala/ca/ulrichs/aoc/island/waterfall/CaveSystemTest.scala diff --git a/src/main/resources/day14_cave_system b/src/main/resources/day14_cave_system new file mode 100644 index 0000000..0ba6ba3 --- /dev/null +++ b/src/main/resources/day14_cave_system @@ -0,0 +1,148 @@ +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +516,113 -> 521,113 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +529,82 -> 533,82 +541,157 -> 545,157 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +512,111 -> 517,111 +538,154 -> 542,154 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +523,76 -> 527,76 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +511,82 -> 515,82 +514,79 -> 518,79 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +514,85 -> 518,85 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +532,85 -> 536,85 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +535,151 -> 539,151 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +526,85 -> 530,85 +497,50 -> 497,51 -> 512,51 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +509,113 -> 514,113 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +538,148 -> 542,148 +492,17 -> 496,17 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +541,145 -> 545,145 +497,50 -> 497,51 -> 512,51 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +550,154 -> 554,154 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +520,79 -> 524,79 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +517,63 -> 517,64 -> 524,64 -> 524,63 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +532,154 -> 536,154 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +521,117 -> 521,118 -> 531,118 -> 531,117 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +547,157 -> 551,157 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +521,117 -> 521,118 -> 531,118 -> 531,117 +517,63 -> 517,64 -> 524,64 -> 524,63 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +523,82 -> 527,82 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +495,15 -> 499,15 +553,157 -> 557,157 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +498,17 -> 502,17 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +547,151 -> 551,151 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +504,17 -> 508,17 +544,148 -> 548,148 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +523,113 -> 528,113 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +535,157 -> 539,157 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +498,13 -> 502,13 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +526,79 -> 530,79 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +521,117 -> 521,118 -> 531,118 -> 531,117 +541,151 -> 545,151 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +532,134 -> 532,136 -> 530,136 -> 530,142 -> 542,142 -> 542,136 -> 536,136 -> 536,134 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +519,111 -> 524,111 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +529,157 -> 533,157 +511,101 -> 511,103 -> 504,103 -> 504,106 -> 517,106 -> 517,103 -> 513,103 -> 513,101 +501,15 -> 505,15 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +508,85 -> 512,85 +520,85 -> 524,85 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +517,76 -> 521,76 +517,82 -> 521,82 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +523,69 -> 523,70 -> 530,70 +520,73 -> 524,73 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +544,154 -> 548,154 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +511,54 -> 511,56 -> 504,56 -> 504,61 -> 520,61 -> 520,56 -> 515,56 -> 515,54 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +515,109 -> 520,109 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +517,63 -> 517,64 -> 524,64 -> 524,63 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 +523,69 -> 523,70 -> 530,70 +528,131 -> 528,121 -> 528,131 -> 530,131 -> 530,127 -> 530,131 -> 532,131 -> 532,124 -> 532,131 -> 534,131 -> 534,126 -> 534,131 +501,98 -> 501,93 -> 501,98 -> 503,98 -> 503,97 -> 503,98 -> 505,98 -> 505,90 -> 505,98 -> 507,98 -> 507,92 -> 507,98 -> 509,98 -> 509,94 -> 509,98 -> 511,98 -> 511,93 -> 511,98 +489,45 -> 489,38 -> 489,45 -> 491,45 -> 491,38 -> 491,45 -> 493,45 -> 493,40 -> 493,45 -> 495,45 -> 495,39 -> 495,45 -> 497,45 -> 497,43 -> 497,45 -> 499,45 -> 499,43 -> 499,45 -> 501,45 -> 501,36 -> 501,45 +489,20 -> 489,24 -> 483,24 -> 483,32 -> 495,32 -> 495,24 -> 492,24 -> 492,20 +521,170 -> 521,163 -> 521,170 -> 523,170 -> 523,160 -> 523,170 -> 525,170 -> 525,165 -> 525,170 -> 527,170 -> 527,168 -> 527,170 -> 529,170 -> 529,169 -> 529,170 -> 531,170 -> 531,169 -> 531,170 -> 533,170 -> 533,160 -> 533,170 diff --git a/src/main/scala/ca/ulrichs/aoc/core/algebra/Coordinate.scala b/src/main/scala/ca/ulrichs/aoc/core/algebra/Coordinate.scala index 5a813a7..bdd85ed 100644 --- a/src/main/scala/ca/ulrichs/aoc/core/algebra/Coordinate.scala +++ b/src/main/scala/ca/ulrichs/aoc/core/algebra/Coordinate.scala @@ -1,5 +1,7 @@ package ca.ulrichs.aoc.core.algebra +import ca.ulrichs.aoc.core.input.InputParsing + case class Coordinate(x: Int, y: Int): def +(coordinate: Coordinate): Coordinate = Coordinate(x = coordinate.x + x, y = coordinate.y + y) def -(coordinate: Coordinate): Coordinate = Coordinate(x = coordinate.x - x, y = coordinate.y - y) @@ -28,6 +30,14 @@ case class Coordinate(x: Int, y: Int): lazy val surrounding: Seq[Coordinate] = adjacent ++ diagonal + def to(coordinate: Coordinate): Seq[Coordinate] = coordinate match{ + case Coordinate(targetX, targetY) if targetX == x => buildRange(y, targetY).map(newY => copy(y = newY)) + case Coordinate(targetX, targetY) if targetY == y => buildRange(x, targetX).map(newX => copy(x = newX)) + case _ => throw IllegalArgumentException(s"Can only create as range of Coordinates on a straight axis: $this -> $coordinate.") + } + + private def buildRange(start: Int, end: Int): Range = if start < end then start to end else (end to start).reverse + override def toString: String = s"($x, $y)" object Coordinate: @@ -43,6 +53,9 @@ object Coordinate: case _ => throw IllegalArgumentException(s"Cannot build a Coordinate from $input") } + given InputParsing[Coordinate] with + def parse(input: String): Coordinate = Coordinate.parse(input) + given Conversion[(Int, Int), Coordinate] with def apply(tuple: (Int, Int)): Coordinate = Coordinate(tuple._1, tuple._2) diff --git a/src/main/scala/ca/ulrichs/aoc/core/algebra/Grid.scala b/src/main/scala/ca/ulrichs/aoc/core/algebra/Grid.scala index 7766a69..0b523fc 100644 --- a/src/main/scala/ca/ulrichs/aoc/core/algebra/Grid.scala +++ b/src/main/scala/ca/ulrichs/aoc/core/algebra/Grid.scala @@ -1,6 +1,8 @@ package ca.ulrichs.aoc.core.algebra -case class Grid[+A](private val points: Map[Coordinate, A]): +import scala.collection.immutable.HashMap + +case class Grid[+A](private val points: HashMap[Coordinate, A]): lazy val maximumColumn = keys.map(_.x).max lazy val maximumRow = keys.map(_.y).max @@ -46,7 +48,7 @@ case class Grid[+A](private val points: Map[Coordinate, A]): (Grid(left), Grid(right)) } - def mapValues[B](f: A => B): Grid[B] = Grid(points.view.mapValues(f).toMap) + def mapValues[B](f: A => B): Grid[B] = Grid(HashMap.from(points.view.mapValues(f))) def mapKeys(f: Coordinate => Coordinate): Grid[A] = Grid(points.map { case(coordinate, value) => f(coordinate) -> value }) def dropColumn(column: Int): Grid[A] = Grid(points.collect { @@ -72,12 +74,13 @@ case class Grid[+A](private val points: Map[Coordinate, A]): def transformAt[B >: A](positions: Seq[Coordinate])(f: B => B): Grid[B] = if positions.isEmpty then this - else Grid( - positions.foldLeft(Map.from[Coordinate, B](points)) { case (accumulation, key) => accumulation.get(key) match { + else + val newPoints = positions.foldLeft(Map.from[Coordinate, B](points)) { case (accumulation, key) => accumulation.get(key) match { case Some(value) => accumulation.updated[B](key, f(value)) case None => accumulation } } - ) + + Grid(HashMap.from(newPoints)) def merge[B >: A](other: Grid[B]): Grid[B] = Grid(points ++ other.points) def merge[B >: A](grid: Grid[B])(f: (B, B) => B): Grid[B] = Grid( @@ -100,7 +103,7 @@ case class Grid[+A](private val points: Map[Coordinate, A]): println(toString(stringify, default)) object Grid: - def apply[A](input: Seq[(Coordinate, A)]): Grid[A] = Grid(input.toMap) + def apply[A](input: Seq[(Coordinate, A)]): Grid[A] = Grid(HashMap.from(input)) def parse[A](input: Seq[String])(parser: (Coordinate, Char) => A): Grid[A] = Grid( input.zipWithIndex.flatMap { (row, y) => @@ -110,13 +113,12 @@ object Grid: } ) - def fromCoordinates[A](input: Seq[String], default: A)(fill: Coordinate => A): Grid[A] = { - val coordinates = input.map(Coordinate.parse) + def fromCoordinates[A](coordinates: Seq[Coordinate], default: A)(fill: Coordinate => A): Grid[A] = { val width = coordinates.map(_.x).max + 1 val height = coordinates.map(_.y).max + 1 create(width = width, height = height) { coordinate => - coordinates.find(_ == coordinate).map(fill).getOrElse(default) + coordinates.find(_ == coordinate).map(fill).getOrElse(default) } } diff --git a/src/main/scala/ca/ulrichs/aoc/core/algebra/pathing/PathFinding.scala b/src/main/scala/ca/ulrichs/aoc/core/algebra/pathing/PathFinding.scala index 206475f..27480f5 100644 --- a/src/main/scala/ca/ulrichs/aoc/core/algebra/pathing/PathFinding.scala +++ b/src/main/scala/ca/ulrichs/aoc/core/algebra/pathing/PathFinding.scala @@ -3,7 +3,6 @@ package ca.ulrichs.aoc.core.algebra.pathing import ca.ulrichs.aoc.core.algebra.Coordinate import ca.ulrichs.aoc.core.algebra.grid.Grid - import scala.collection.{mutable, *} import scala.util.control.Breaks.{break, breakable} diff --git a/src/main/scala/ca/ulrichs/aoc/core/input/InputParsing.scala b/src/main/scala/ca/ulrichs/aoc/core/input/InputParsing.scala index 79de5ba..2386bae 100644 --- a/src/main/scala/ca/ulrichs/aoc/core/input/InputParsing.scala +++ b/src/main/scala/ca/ulrichs/aoc/core/input/InputParsing.scala @@ -1,6 +1,6 @@ package ca.ulrichs.aoc.core.input -import ca.ulrichs.aoc.core.algebra.{Coordinate, RangeHelpers} +import ca.ulrichs.aoc.core.algebra.RangeHelpers trait InputParsing[A]: def parse(input: String): A @@ -17,6 +17,3 @@ object InputParsing: given InputParsing[Range] with def parse(input: String): Range = RangeHelpers.parse(input) - - given InputParsing[Coordinate] with - def parse(input: String): Coordinate = Coordinate.parse(input) diff --git a/src/main/scala/ca/ulrichs/aoc/island/waterfall/CaveSystem.scala b/src/main/scala/ca/ulrichs/aoc/island/waterfall/CaveSystem.scala new file mode 100644 index 0000000..a5f0d80 --- /dev/null +++ b/src/main/scala/ca/ulrichs/aoc/island/waterfall/CaveSystem.scala @@ -0,0 +1,74 @@ +package ca.ulrichs.aoc.island.waterfall + +import ca.ulrichs.aoc.core.algebra.Coordinate +import ca.ulrichs.aoc.core.algebra.grid.Grid +import ca.ulrichs.aoc.core.input.SourceInput +import ca.ulrichs.aoc.core.input.StringParsing.* +import ca.ulrichs.aoc.island.waterfall.CaveSystem.SandStart + +import scala.annotation.tailrec + +case class CaveSystem(grid: Grid[Char]): + lazy val sandUnits: Seq[Coordinate] = grid.findAll('o') + + lazy val afterSandfall: CaveSystem = sandFall(SandStart, grid) + + @tailrec + final def sandFall(sand: Coordinate, innerGrid: Grid[Char]): CaveSystem = { + val availableSpots = (innerGrid.at(sand.down), innerGrid.at(sand.downLeft), innerGrid.at(sand.downRight)) + val maxY = Seq(sand.down, sand.downLeft, sand.downLeft).map(_.y).max + // val maxX = Seq(sand.down, sand.downLeft, sand.downLeft).map(_.x).max + + if maxY >= innerGrid.dimensions.height then return CaveSystem(innerGrid) + // if maxX >= innerGrid.width then return CaveSystem(innerGrid) + + availableSpots match { + case (Some('.'), _, _) => sandFall(sand.down, innerGrid) + case (_, Some('.'), _) => sandFall(sand.downLeft, innerGrid) + case (_, _, Some('.')) => sandFall(sand.downRight, innerGrid) + case _ => + if sand == SandStart then CaveSystem(innerGrid.updated(SandStart, 'o')) + else sandFall(SandStart, innerGrid.updated(sand, 'o')) + } + } + + +object CaveSystem: + val SandStart: Coordinate = Coordinate(500, 0) + + def parse(input: SourceInput): CaveSystem = { + val all = input.asSeq[String].flatMap { rawRockLine => + val coordinateRangeList = rawRockLine.split(" -> ").map(_.as[Coordinate]) + + coordinateRangeList.foldLeft(Seq.empty[Coordinate]) { + case (Nil, target) => Seq(target) + case (head :: Nil, target) => head to target + case (init :+ last, target) => init ++ (last to target) + } + } + + val grid = Grid.fromCoordinates(all)(value => if all.contains(value) then '#' else '.').updated(SandStart, '+') + CaveSystem(grid) + } + + def parseWithFloor(input: SourceInput): CaveSystem = { + val coordinateRanges: Seq[Seq[Coordinate]] = input.asSeq[String].map(_.split(" -> ").map(_.as[Coordinate])) + + val coordinates: Seq[Coordinate] = coordinateRanges.flatMap { coordinateList => + coordinateList.foldLeft(Seq.empty[Coordinate]) { + case (Nil, target) => Seq(target) + case (head :: Nil, target) => head to target + case (init :+ last, target) => init ++ (last to target) + } + } + + val maxX = coordinates.map(_.x).max + val floorY = coordinates.map(_.y).max + 2 + + val floorToSandStart = (floorY - SandStart.y) + val floor = Coordinate(SandStart.x - floorToSandStart, floorY) to Coordinate(SandStart.x + floorToSandStart, floorY) + val all = coordinates ++ floor :+ SandStart + + val grid = Grid.fromCoordinates(all)(value => if all.contains(value) then '#' else '.').updated(SandStart, '+') + CaveSystem(grid) + } diff --git a/src/test/scala/ca/ulrichs/aoc/core/algebra/GridTest.scala b/src/test/scala/ca/ulrichs/aoc/core/algebra/GridTest.scala index 72f89f9..18bd846 100644 --- a/src/test/scala/ca/ulrichs/aoc/core/algebra/GridTest.scala +++ b/src/test/scala/ca/ulrichs/aoc/core/algebra/GridTest.scala @@ -119,7 +119,7 @@ class GridTest extends AnyFunSuite with LoneElement: } test("Can create a grid given a list of coordinates") { - val grid = Grid.fromCoordinates(Seq("3, 3", "5, 5"), default = 0)(_.x) + val grid = Grid.fromCoordinates(Seq(Coordinate(3, 3), Coordinate(5, 5)), default = 0)(_.x) grid.height shouldBe 6 grid.width shouldBe 6 diff --git a/src/test/scala/ca/ulrichs/aoc/island/waterfall/CaveSystemTest.scala b/src/test/scala/ca/ulrichs/aoc/island/waterfall/CaveSystemTest.scala new file mode 100644 index 0000000..a81cbb6 --- /dev/null +++ b/src/test/scala/ca/ulrichs/aoc/island/waterfall/CaveSystemTest.scala @@ -0,0 +1,34 @@ +package ca.ulrichs.aoc.island.waterfall + +import ca.ulrichs.aoc.core.input.SourceInput +import org.scalatest.* +import matchers.should.Matchers.* +import org.scalatest.funsuite.AnyFunSuite + +class CaveSystemTest extends AnyFunSuite: + val exampleSource = SourceInput( + "498,4 -> 498,6 -> 496,6", + "503,4 -> 502,4 -> 502,9 -> 494,9" + ) +// test("Can parse the ranges of rocks into a Cave System") { +// CaveSystem.parseWithFloor(exampleSource).afterSandfall.grid.print((c, v) => v.toString) +// CaveSystem.parseWithFloor(exampleSource).afterSandfall.sandUnits.length shouldBe 93 +// } + + test("Can find when the cave system fills up for a real cave system with a floor") { + val source = SourceInput.fromResource("day14_cave_system") + val afterSandfall = CaveSystem.parseWithFloor(source).afterSandfall + + afterSandfall.grid.print((c, v) => v.toString) + afterSandfall.sandUnits.length shouldBe 28145 + } + +// test("Do some sandfall") { +// CaveSystem.parse(exampleSource).afterSandfall.grid.print((c, v) => v.toString) +// CaveSystem.parse(exampleSource).afterSandfall.sandUnits.length shouldBe 24 +// } +// +// test("Do some sandfall for real") { +// val source = SourceInput.fromResource("day14_cave_system") +// CaveSystem.parse(source).afterSandfall.sandUnits.length shouldBe 24 +// }