From f49a645bc509f67ab738775b2ccd6ab45e45a33f Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 15 Dec 2024 13:52:14 +0000 Subject: [PATCH] Day 15 --- src/main/kotlin/utils/Point.kt | 20 ++++ src/main/kotlin/y2024/day15/Day15.kt | 142 +++++++++++++++++++++++ src/main/kotlin/y2024/day15/input.txt | Bin 0 -> 22592 bytes src/test/kotlin/y2024/day15/Day15Test.kt | 16 +++ 4 files changed, 178 insertions(+) create mode 100644 src/main/kotlin/y2024/day15/Day15.kt create mode 100644 src/main/kotlin/y2024/day15/input.txt create mode 100644 src/test/kotlin/y2024/day15/Day15Test.kt diff --git a/src/main/kotlin/utils/Point.kt b/src/main/kotlin/utils/Point.kt index 529dd70..c28291f 100644 --- a/src/main/kotlin/utils/Point.kt +++ b/src/main/kotlin/utils/Point.kt @@ -48,6 +48,14 @@ data class Point(val x: Int, val y: Int) { copy(x = x + it.x, y = y + it.y) } + fun getNeighbour(direction: Char): Point = when (direction) { + '^' -> n + '>' -> e + 'v' -> s + '<' -> w + else -> error("Unknown direction: $direction") + } + operator fun plus(other: Point) = Point(other.x + x, other.y + y) operator fun minus(other: Point) = Point(x - other.x, y - other.y) @@ -77,6 +85,18 @@ fun Map.traverse(block: (Point, T?) -> Unit) { } } +fun Map.printGrid(default: Char = '.') { + val width = maxOf { it.key.x } + val height = maxOf { it.key.y } + + repeat(height.inc()) { y -> + repeat(width.inc()) { x -> + print(getOrDefault(Point(x, y), default)) + } + println() + } +} + fun pointsInArea(point1: Point, point2: Point): List { val (minY, maxY) = listOf(point1.y, point2.y).sorted() val (minX, maxX) = listOf(point1.x, point2.x).sorted() diff --git a/src/main/kotlin/y2024/day15/Day15.kt b/src/main/kotlin/y2024/day15/Day15.kt new file mode 100644 index 0000000..47ffed6 --- /dev/null +++ b/src/main/kotlin/y2024/day15/Day15.kt @@ -0,0 +1,142 @@ +package y2024.day15 + +import utils.Point +import utils.getInputFile +import utils.toPointGrid + +fun main() { + println("Part one: " + Day15.solvePartOne()) + println("Part two: " + Day15.solvePartTwo()) +} + +object Day15 { + + private val instructions: CharArray + private val gridInput: List + + init { + val (gridInput, instructionInput) = getInputFile(this::class.java.packageName, example = false) + .readText() + .split("\n\n") + .map { it.split("\n") } + instructions = instructionInput.joinToString("").toCharArray() + this.gridInput = gridInput + } + + fun solvePartOne(): Long { + val grid = gridInput.toPointGrid().toMutableMap() + var robot = grid.entries.find { it.value == '@' }!!.key + + instructions.forEach { direction -> + val movement = generateSequence(robot.getNeighbour(direction).takeUnless { grid.isWall(it) }) { lastPos -> + if (grid[lastPos] == '.') return@generateSequence null + lastPos.getNeighbour(direction).takeUnless { grid.isWall(it) } + }.toList() + if (movement.isNotEmpty() && movement.any { grid[it] == '.' }) { + grid[robot] = '.' + robot = movement.first() + grid[robot] = '@' + + if (movement.size > 1) { + grid[movement.last()] = 'O' + } + } + } + + return grid + .filterValues { it == 'O' } + .keys + .sumOf { (x, y) -> x + y * 100L } + } + + fun solvePartTwo(): Long { + val grid = gridInput.map { + it.map { c -> + when (c) { + '@' -> "@." + 'O' -> "[]" + else -> "$c$c" + } + }.joinToString(separator = "") + }.toPointGrid().toMutableMap() + var robot = grid.entries.find { it.value == '@' }!!.key + val horizontalMoves = listOf('<', '>') + + instructions.forEach ins@{ direction -> + val nextPos = if (direction in horizontalMoves) { + // Horizontal logic is just the same as P1 + val movement = generateSequence(robot.getNeighbour(direction).takeUnless { grid.isWall(it) }) { lastPos -> + if (grid[lastPos] == '.') return@generateSequence null + lastPos.getNeighbour(direction).takeUnless { grid.isWall(it) } + }.toList() + if (movement.isEmpty() || grid[movement.last()] != '.') return@ins + movement + .reversed() + .windowed(2) + .forEach { (a, b) -> + grid[a] = grid[b]!! + } + movement.first() + } else { + // Vertical logic needs to account for larger boxes... + val movingBoxes = mutableSetOf>() + val searchBoxes = mutableSetOf>() + val nextPos = robot.getNeighbour(direction).takeUnless { grid.isWall(it) } ?: return@ins + + if (grid.isBox(nextPos)) { + searchBoxes += grid.fullBox(nextPos) + } + + while (searchBoxes.isNotEmpty()) { + val nextBox = searchBoxes.first() + val nextLeft = nextBox.first.getNeighbour(direction) + val nextRight = nextBox.second.getNeighbour(direction) + + if (grid.isWall(nextLeft) || grid.isWall(nextRight)) return@ins // Box will move into a wall, instruction is impossible, exit + + if (grid.isBox(nextLeft)) { + searchBoxes += grid.fullBox(nextLeft) + } + if (grid.isBox(nextRight)) { + searchBoxes += grid.fullBox(nextRight) + } + + movingBoxes += nextBox + searchBoxes -= nextBox + } + + movingBoxes + .onEach { (bl, br) -> + // Mark all moving box spaces as empty + grid[bl] = '.' + grid[br] = '.' + } + .forEach { (bl, br) -> + // Update all new box positions + grid[bl.getNeighbour(direction)] = '[' + grid[br.getNeighbour(direction)] = ']' + } + + nextPos + } + + // Move robot + grid[robot] = '.' + robot = nextPos + grid[robot] = '@' + } + + return grid + .filterValues { it == '[' } + .keys + .sumOf { (x, y) -> x + y * 100L } + } + + private fun Map.isWall(point: Point) = get(point) == '#' + private fun Map.isBox(point: Point) = get(point) == '[' || get(point) == ']' + private fun Map.fullBox(point: Point) = when (get(point)) { + '[' -> point to point.e + ']' -> point.w to point + else -> error("No a box point") + } +} diff --git a/src/main/kotlin/y2024/day15/input.txt b/src/main/kotlin/y2024/day15/input.txt new file mode 100644 index 0000000000000000000000000000000000000000..c350f670f240d8df56add732676d725a6fafaaaa GIT binary patch literal 22592 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≫#`}9jxNht4(1=vPdSFt(`L{-U1CpxcTEBoCC;SVNzxPxmbsasiGb>hS3a?xGTdxl& zBk9H;m$v&_;ZF-Lw7b|0DCUEd;f1Q`K_s0^=nQ1* zXZoXC(=Zb%FxvtRuYfBr&0l;CkC~1rT%Uq&2|0;19MsFUj9KBX!OxHnDD{dw#$jqN z94j%2Lt2a=4pr>(K>0D{2Fm9Z;%>j*9yUt zU1>-7$LR_{Z=<1550lf;YC{D|_!+aY+>NIff>s_7>;U3vH0tJ}u5)gM`QLzQOZYE4cHnUQ za)we&!N6Odf%*6e7z0-GRz{HaarqOu@V&@6_#VLgMvHUdX83vbZWk{`0WoI#Wk{d) zx*;-Ywg=`?jLfxE_(Z)IgL~G1mzQ|F5B1H1XZW;mDpo|FVe@bk1BFLnne)zt5k}`I zJ3BoPgyjUyu9_(a{Ck;58D)bkNjwm%0l_x zqDKblO`ME6&pC|DEcYTJxb#@%7gn3xWt&fG@w#(=diGv*H8!GWCn8H1*^YQLoJ`N< z6HCGiOK1|FCrLeeb7s~9HfGJbB)CoxBKP&OA8-QfTqfg46r2Gi7~1E>!efUY9eL3V z7bpBvM;IBCgDeX0po1ShdQ|}(GR6zEwa9#=J>rzF%%HkjGvfwY+8kd2&*F;^;AXnQ zX3rX=xgL3fEz_{mH=|U2WhH4A9>|w(@J`7-za7IcBxMZQt%@)E3pJ&*=hk5{Q?4Yq zYatr;NGcLQpZ`HhlA*Z#~TTv5~eAmW+MJxll`z!4i`q0Qkdt8#rGn}ssXs+vCF%d^ByLdf~wsNcdg zPzoKts?IybUy(+mEA&FXR&MAdGa2l(yp|CbP#JK(1`~aVj2LJ#du5#vaApLahfW4$ z%1|iRaxQiMBWV}|G(6qpEus|3P*IS}%#pl(<;Odi_hg=L4Vr^F5`Z~$Mm1a3yw13R zt3ZMT5~7Xw$4^wuR9W<|VHb>7#3SrnmsotBGj64E8zg@eL_R^AlGOPt#mcM>#|SYM zBH9JI{g2O_PP(^Hw@R>RvR9-a=JC_uo8e!a@5%^I_{d=v3E;hCl`aXEt1vE#455{3 zp=;4@7-FN#zEZ&l& zGktlo{_ng$P2b}XBWB@C>F|{x07Ey&(3&^K$7CCy~AZ>-X{BBq9>r2{car-;?@m#jn^`Z z1_kbU-k_cC_IAqu99EWCpCT2A4-dt|YXrobt*E{JB>+;uo?cemEE6OR8dy>UXal=H z!#V6fG=!CFOas$i1$ry~Mx6qyu9ONN+ODNZlpU3_)0CFQAud#xu!K#Sd5)?r41GU( zNcx^@#%FaAh#ap{!EA1#lQ2*DigmYPN6uljYI}`XP^YN0%rIhv=dt^{!GLrn{=%FR zslrz9e3S^a9jAX7>Q_|?Bg+NB2J0OXCboq6s`lXr*5%~gW8|7e`Ce``lqG*ZlDoCh ztFeK=B|$|-+#j0kgrpDdL-!zw*7gLzGeKoDyQ95jo6YKweJA`T9plCF+YnivfCxYLZ8ao}DWi6`)#t+slXY2q)iIsNYgl%~P&uD&i0MzpWd9{nMe z5wZBB8j9r1b^DtBdhI07*Pl`*Y38-n%{k_vH}0 zr}-$G2i%O^L(WQL?5w_XgGSq_)tA|(Z}E4(gxK=@*|d1TGXAKE_iyDnbhWdigdFY| z_o?iwo@>jJ!e+5aZU_CCbk`|~z}}9dsamz4FbHu)l7pG@gRQsdc^EL^mdSD)F1z^? zHFkxu479bzIMAWJa`c%VDpC@kg=gA^<}j+gWOu7)1P8}~4jAuyz6&1U-;jEqjN1T6 zPZJ`LpggTmv%f*|S%M+AJ48+w6@(svAOt!*K*i;s-7Kwpcf(5s@3+YFxz1dAz@(sL z)(~B8F#+!d#JVeT^+db%Y&~9b_m{5Co=<279dUX+=xonH4wef7MjG`eWx$5x!B>$D zY9a8CEY5V+3*=3Be<#UaQyOO45RHd&xxW8UZ)_5(L@e6kLt429t|CS%BC+Ki9MscX zD+)y8SkNztz79IjN;XF6oS@L^a2<0$fj=9Ml^i2}@Gs?qgs4L#>%#PlkiU67G=F9X z^^$S}JsNoc%B_-g*O%qsjpf_nQby7D*$&Bg#Uhy*7!b~KtxSz`TbpLn+D^{9+#C`h zDvi_!@IKoaa3lzvz0P_`27k@Z8V({Kk1sV)f2@u#k~sF=A{hvPTamXaiFLM);QC>N zVldAaLeDp%5hwAJn+Y4(!{;#E{@x(2oXYjDz?dfwHb}%xy=QyqT;PH0?J~;0)q5@# z(zHjo1*8f6DW+CNaU!5RK&&=+ZCy4dzN3htwMKzK3#ee6++T>#IpPkbq$KJF+|l4u z74a+l>sC{QYQ>Ac-^J+w*#E7o879n#DaE5IA1a3^b-702?1Deao@^%XUZ+D$Y^F+h zm2Wjb4&}!n#v%kyh~lH%H@<=bR>zw~OVve;=ltWv0rA)S@4OXv3x8uJ# z1GI!8gr^C>m@Hald(ey<$bh@kkfI~HNgop~vt^Q6)tx9Pud2jCM;_Os=OK6j!yKZs zK0g}^tM{DetF)#CWz>G1F3{B~*H;(207rDqg#%Q7v~L{3xB|=zi2-or>I$KF{+A27 zkey4Cb87JBjZ{y*?cw-tNZw=9+Rii9SrN*LvK0PW6^L-*jBQ|nci{}4RCD)sCZW0} z23p_$p9;N|gWxZJeS9c9C7O**(jG!`6PMI$%}j@vS)f`5$ z9()xKcmUBNH_pC+6Jc4Hmu<04>vA1~PsyLU_yxeNi5w9>Q>EjKDLt1d;eJ{~LaNOd z)Bn!%78&Fp^ocK#=ND{#dZ+QRSf@bzFyG_-Sy5{l6ro~7BX8`U7to7K21KZI>Hz~F z+6D)aI{ZUF-;!*6OfPnBMB_|9R6)TIP8~2MfmwjBIFR4%nUQ*usY;FsG!hXLb4Bg; z9R2L-_V-cwZwKU!oAOJt+>FtbqLhDJ6~^yR%61psh;6%~+5^2nug!y6vd!_ir#Jvm z488}DuvMVxj&?tK*!U8+j%3Yum;TG@XL*OOU``IyO7WoUm!3e4O0no-RI&n&hoIWC zgpxx~_jdn;a)Y#L=lKDR_j5hhAh2|8G=D|~w$s1Oc5&iSAq$e31HJZ40StbtV9_aX zroj6$6%W|HTNXSllzv=oWwhs!4sr{$Pz?gy+>0(_1}h*$(>?6{pSobRPt|9)!<_S5RN=S?&|VlQ4PKT2l|7h^cuof0B)M^rKjxcGi{|2|52S10 zcWj-?+#aJ_@SG;Gi_b{eu>Eb^?O$q0JtUB^L)*Gruod1vgkWf)ZHcnU9=-=A6Ul1| z^72X%d{nAN_jCri;VQhru1;JES{Hq^eUYMxcW}rVye)(Y=gvMBkua9x?ASemV!q#c zQONMub1%yAa21GZic}t*FcNiA0eHEkqTBTQ-{>7dfE?)TOlcnZ1tGUFLde3#jCG3z z))ddhi70Ss>B``60A1-2%>sy$Q^v(!xyLKAu(n=~e2c_O|w`nabmw|Sx z#sqbBGi5`11&oGN%e)pM4iJ5a+LUlPfB+_;6tr=F`j=q}8@9mLb``|H^bx@d4{7SS zCw}#pYguM-cqHr~qbw*KSTv|ryhApjK^L|-avztlSi?ooOu+^pNRh2jo6X;w^dk4X zQB>%?>jjH`x_5^fs0lTc$jjd6CF*35b^Z4cD9al#^TJoF%hlYM3U(zVv*RhF_S${; z1V0bDf1W$6tFq}n2B2j8Hf4a9I?+b(E%zc!IBelACf~kEZ0sisxSnBNw^x{=F|)n3 zf6{7Sny+9MAUnpHHv#!_|{7e5afFmG*4~9-KjD>D6vKf^{Rr{l9gU}Wb?_*+Z{|l z*(eE82j61=8&9`X?sNZ_LFI})DG?Qw3_JG`U?6O&KD*3j<$E_nJUv=6MZ`-3F#TV& z%%$%kM#GB|Nl&G146C{gTZlj5vjo4+8Hvz%aUvchyOg&_695-el&PPvQUC(3Yw2I# zCw1hArVhRV|9ME!W?fqWq!vB*(jz_LpPn`qNx!m`T8fE#ou*7xQqdH+wK;N`=iEa! zFaz;6YDBxQ{c6mgP!C$W3H2yuetL1D0R=a^Q&eR;5UV4X?vZ^JI6A(WvlQ3(wue#P z7hy)^h0}J8y&T)Y5N2|^}1P+VjBM}357qq*1QCw>z3p~ zdq3XEc7NDCQQs%RR(`zgo>YKLf!@)|Qyx;G2xp`bNjtm=w>$eM<-`G7f;5kL5xB+_ zGw;apZcamXx#>n=2KsQLQ2=kX-F6m?JroS<0evT8?PSIMJnv*}J({?kAy$sjIy_yy zf;Vs|jC5Q^FLS-(+hK_QR$^$7EnDKdk9^KlDuWeB!>fil-aKTNw`5Tvp2}Pal3q_R z*#n`Vg@_cE)?K-fnh7SDvk7&O8H@J5R0FmSay$t(KWAFB@c5W?pOjG(Sp3KcTgzv# zW`AUMm@noHac$<_MkslFsA-ZZLDn=sD;J(uk?(W^57W(DGSA;JNo&-8dW;cPL`+nE zLr5%YLL;{2I(lQ>+2snpBR)auH2?E>q({$D(*MKpw&f|}4H_?~P^*Cm*=oV&ofxa> zExQwvnUbZoYETnAqfqyRE-Al6PO#~~ zvHG#YacgD^pk_1tv!yNLmC8_QboHV?Xv2+>Tw8|nSNyV~2<^bXY3TLS$}jGFQ9Jz0 zQ>86w20-8(u-H6g8;3dB(d!5U5~K-{>GEu-{i;X<<=23Zs48#m&kmI8228~*SGgj`cZq0{ z$NJEHmaw`i3tC6O7SoB?_K9QXv?_|({c*ut4RZ!JB|QDp=lz?-1xRTY9}Ewg_=lt(_5C;9XXY5|C0RhQgU_Cn zLr)+d-~k7=w%ac*qa^$1H8b)h>DUC5X4T@dptvlPh*S)-Z=ec8-Q@T}{Api6>1BY{$KzeBo0+I(Bux|JodUG~=D{R#ZZ_Cmx)kp`xCkPZ~ zXdEt}zRSKBxJP~}v(@^=pTHK*#|PTfeuW%ot)c3Wxp6^JSiz{bHyC4DGKSA$Vt}{d zsa40#>v{T7PHNI$EWg4pON+<=FNca~JZA^;!LcR@dYooGg`Kw4e z`seD1)!_%hPnlAepgq_^HHkbqB>-6wTLg3p>*82_bV(dSZ~Hef0Q>3(>iaD6=7%En zhj5%V6>wvy*xqOwoW-w>a3*2=q`y5eg<(dL&b5;wpTB@;*E>q<1fOT0f(ny7N(Y)X z< zRkdxcgMJ}>;`e?*b9F46`NCysXkP&l6xy*SbklSnwk$|qt5>=@GPb!(Fk`eRl${Y@SAukj7)2wx! zT+51vM63K=Ry0)2YKNt@dENB0EiiatP3xun06Pc2Sa`Tb(OPyak)IMQ&PBy))GJx& zMGh6b6MlY>%a`q=Baw**8hB$9_9q^XH%>oHHIGX-P{!%5N*qABhSp2_fs=dqmh%GB zXGq*Qzd5ox7+C((n=-~c7)ne-sA0O=Ir<=*V7=s{_XV=9+gssJYI-r0SI1-i9x9OE zhf^t_-_hzx?)?bx4dh|I@SY1&C!ow#DLcxwH>>H(b2#jR?4c*CG9?7_`~XtzXP4y< zL?5D$!4aiCcHn^Yp*K-BcvO9O!QmQYK6u)`Yur?}Sbz`%bs=tz1UJ^+_VQL*T%cWu z4qz-hs~UXTT!2eNNfF;ezgcvml5*QA);G0nGGlOV1sDlqA9?90UTing@6LtpAj1N~ zD+*?@ViFTFkweK*p}69pSUvDK)szJ%q3m2Zrq!YUWxuy7K(N`gDFZEz7LmDSsQ#_N ztV`)gcWutZzxoX13|=#|QdO@jS^+a}(;aXy{xI)ioPNDipur zHiPm6zc2NI;ipA{y<_y#G=K&ACmT=xZ80F*ZC%>Kbmidum*JhR)jpjty-HkSrzKR{ znV=ChcPZ!FaMh(aIluDKw@@CKv2BwcQA-+(HnFMtEUVNJnzt&c$;$~7OQK=HPJcnm z0Julg@TM}dx!W5g7zS<-m!yPdmL5#=PiZ3Kt8}7&Bkq+=b7YP{XzWsXq0f}60+8LI z(xuW!MK8MvpfrwLY=!Zq60~1IcLj*54VItH=avlB@P?K1>7i7T}?9;4lf zYNx(f+uD=khaHej!1G-IKTq*(sr=T+@)odUt9FT0E@2ZMSQBq4PKdYqRi178@>Ab{^3lWkYTpvbDi8MZ^%(fgBadL literal 0 HcmV?d00001 diff --git a/src/test/kotlin/y2024/day15/Day15Test.kt b/src/test/kotlin/y2024/day15/Day15Test.kt new file mode 100644 index 0000000..ae085a3 --- /dev/null +++ b/src/test/kotlin/y2024/day15/Day15Test.kt @@ -0,0 +1,16 @@ +package y2024.day15 + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +internal class Day15Test { + @Test + fun solvePartOne() { + assertEquals(1487337, Day15.solvePartOne()) + } + + @Test + fun solvePartTwo() { + assertEquals(1521952, Day15.solvePartTwo()) + } +}