Day 18: Fish use trees for numbers
This commit is contained in:
parent
a702111529
commit
25bc83d011
7
input/2021/day18-sample1.txt
Normal file
7
input/2021/day18-sample1.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[1,2]
|
||||||
|
[[1,2],3]
|
||||||
|
[9,[8,7]]
|
||||||
|
[[1,9],[8,5]]
|
||||||
|
[[[[1,2],[3,4]],[[5,6],[7,8]]],9]
|
||||||
|
[[[9,[3,8]],[[0,9],6]],[[[3,7],[4,9]],3]]
|
||||||
|
[[[[1,3],[5,3]],[[1,3],[8,7]]],[[[4,9],[6,9]],[[8,2],[7,3]]]]
|
2
input/2021/day18-sample2.txt
Normal file
2
input/2021/day18-sample2.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[[[[4,3],4],4],[7,[[8,4],9]]]
|
||||||
|
[1,1]
|
1
input/2021/day18-sample3.txt
Normal file
1
input/2021/day18-sample3.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[[[[1,1],[2,2]],[3,3]],[4,4]]
|
1
input/2021/day18-sample4.txt
Normal file
1
input/2021/day18-sample4.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[[[[3,0],[5,3]],[4,4]],[5,5]]
|
1
input/2021/day18-sample5.txt
Normal file
1
input/2021/day18-sample5.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[[[[5,0],[7,4]],[5,5]],[6,6]]
|
10
input/2021/day18-sample6.txt
Normal file
10
input/2021/day18-sample6.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]
|
||||||
|
[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]
|
||||||
|
[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]
|
||||||
|
[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]
|
||||||
|
[7,[5,[[3,8],[1,4]]]]
|
||||||
|
[[2,[2,2]],[8,[8,1]]]
|
||||||
|
[2,9]
|
||||||
|
[1,[[[9,3],9],[[9,0],[0,7]]]]
|
||||||
|
[[[5,[7,4]],7],1]
|
||||||
|
[[[[4,2],2],6],[8,7]]
|
10
input/2021/day18-sample7.txt
Normal file
10
input/2021/day18-sample7.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||||
|
[[[5,[2,8]],4],[5,[[9,9],0]]]
|
||||||
|
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
|
||||||
|
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
|
||||||
|
[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
|
||||||
|
[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
|
||||||
|
[[[[5,4],[7,7]],8],[[8,3],8]]
|
||||||
|
[[9,3],[[9,9],[6,[4,9]]]]
|
||||||
|
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
|
||||||
|
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
|
100
input/2021/day18.txt
Normal file
100
input/2021/day18.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
[[[[2,8],[4,6]],[[2,4],[9,4]]],[[[0,6],[4,6]],[1,6]]]
|
||||||
|
[7,[[5,7],1]]
|
||||||
|
[[[[8,8],7],5],[[[5,6],1],6]]
|
||||||
|
[[[8,5],[[0,0],[4,9]]],[2,8]]
|
||||||
|
[7,[[5,2],[[3,0],[7,7]]]]
|
||||||
|
[[6,[6,8]],[3,[5,2]]]
|
||||||
|
[6,[[[8,9],[9,9]],[3,8]]]
|
||||||
|
[[[1,[0,2]],[7,[3,0]]],8]
|
||||||
|
[[9,6],6]
|
||||||
|
[[[2,3],1],[9,[3,7]]]
|
||||||
|
[5,[[[5,8],3],9]]
|
||||||
|
[[[[8,8],3],[2,2]],[2,3]]
|
||||||
|
[[[4,9],3],[[[7,3],8],5]]
|
||||||
|
[[[3,5],[3,7]],[[[9,7],9],[9,[7,8]]]]
|
||||||
|
[[7,1],8]
|
||||||
|
[0,[[[6,8],[1,1]],[1,[5,8]]]]
|
||||||
|
[[[[2,2],[9,5]],[0,[1,0]]],[4,[[2,4],4]]]
|
||||||
|
[[[[2,5],[7,3]],[7,6]],[[6,[4,4]],[3,8]]]
|
||||||
|
[[3,[[7,9],2]],[[0,[4,4]],[[6,9],9]]]
|
||||||
|
[[[7,7],[[1,4],[1,6]]],[7,[[6,3],6]]]
|
||||||
|
[[0,8],[[[1,6],2],4]]
|
||||||
|
[[0,[[2,7],[0,4]]],[[[3,8],[7,7]],5]]
|
||||||
|
[[[[9,9],[1,3]],[9,[4,3]]],[[[3,4],[6,4]],1]]
|
||||||
|
[[[9,[0,9]],[2,[7,6]]],[2,[[1,9],[3,3]]]]
|
||||||
|
[[4,[5,6]],[[[1,5],6],[[1,5],[5,2]]]]
|
||||||
|
[1,[[3,[2,1]],5]]
|
||||||
|
[[4,[3,8]],[3,[6,3]]]
|
||||||
|
[[7,1],[[3,[6,0]],[5,[1,1]]]]
|
||||||
|
[[8,7],[[[0,1],[2,6]],[5,[4,7]]]]
|
||||||
|
[9,[[[1,6],[8,9]],[6,6]]]
|
||||||
|
[4,9]
|
||||||
|
[[[[0,8],[8,5]],9],[7,[1,3]]]
|
||||||
|
[[[[8,5],0],[[4,6],4]],[8,4]]
|
||||||
|
[[[[8,9],8],[[3,1],[7,6]]],2]
|
||||||
|
[[[[6,3],0],[2,[4,8]]],[[[0,3],[3,5]],4]]
|
||||||
|
[0,[[9,[0,6]],5]]
|
||||||
|
[[[[1,9],[2,7]],[[4,0],[9,9]]],[[8,[3,6]],[3,4]]]
|
||||||
|
[[[[0,7],[8,4]],1],[[8,3],[[3,5],[8,0]]]]
|
||||||
|
[[[[3,5],4],[0,9]],[[[1,7],5],[9,[8,0]]]]
|
||||||
|
[[[8,[6,8]],[[3,7],[0,8]]],[[[5,2],[1,7]],[9,5]]]
|
||||||
|
[[[[5,1],[0,7]],4],[0,4]]
|
||||||
|
[[[[9,8],[3,9]],[[0,6],3]],[[[9,1],[8,7]],2]]
|
||||||
|
[[9,[[0,3],6]],[[3,4],[[8,9],5]]]
|
||||||
|
[[1,[1,8]],[[6,[4,2]],1]]
|
||||||
|
[7,[[1,[5,2]],[[9,7],0]]]
|
||||||
|
[0,[8,6]]
|
||||||
|
[1,4]
|
||||||
|
[[8,[4,1]],[[[4,0],[0,0]],[7,[3,4]]]]
|
||||||
|
[2,[[1,[1,8]],[[3,4],1]]]
|
||||||
|
[[8,[[1,2],[3,1]]],[[[4,4],[7,9]],1]]
|
||||||
|
[[4,[0,[6,4]]],[9,[0,[1,2]]]]
|
||||||
|
[[6,[3,1]],[[7,8],[8,[2,5]]]]
|
||||||
|
[[[2,[3,3]],[[6,4],[9,4]]],[[[1,5],[7,4]],[0,6]]]
|
||||||
|
[[[[8,0],3],[[4,0],3]],[[7,5],4]]
|
||||||
|
[[[2,[4,3]],[[2,1],5]],1]
|
||||||
|
[[[8,1],[0,4]],[9,[[1,4],[9,0]]]]
|
||||||
|
[[[5,0],[[7,7],9]],[[6,[6,2]],7]]
|
||||||
|
[[[[5,9],0],[[4,6],[3,8]]],[6,[6,5]]]
|
||||||
|
[[[6,[7,8]],[5,3]],[[3,[6,5]],[[8,7],[4,7]]]]
|
||||||
|
[[9,[[8,7],4]],[[[6,3],0],[[2,3],[5,9]]]]
|
||||||
|
[[[[1,8],6],1],[[[7,8],4],[7,2]]]
|
||||||
|
[[[[7,1],[6,2]],[[7,8],2]],0]
|
||||||
|
[[[4,5],[0,3]],[[2,4],1]]
|
||||||
|
[[[9,1],7],[[[8,8],[0,7]],[8,0]]]
|
||||||
|
[[5,[[7,5],[7,5]]],[3,[4,8]]]
|
||||||
|
[[7,[1,0]],[[3,[1,5]],0]]
|
||||||
|
[[[5,1],[[5,2],[7,3]]],[[7,[3,9]],9]]
|
||||||
|
[5,[1,[[9,9],[3,0]]]]
|
||||||
|
[[2,0],[9,[6,[3,3]]]]
|
||||||
|
[[[[0,4],[4,8]],[[1,9],[5,8]]],[[[7,0],5],[5,1]]]
|
||||||
|
[[[[1,5],[9,2]],[6,[3,6]]],[4,[1,[1,5]]]]
|
||||||
|
[[[[1,4],[4,6]],[[5,5],[3,5]]],[[[7,1],4],[[0,7],4]]]
|
||||||
|
[[6,[3,5]],1]
|
||||||
|
[8,[[1,[0,7]],[[2,5],6]]]
|
||||||
|
[[[[1,6],3],[[9,7],9]],[[7,8],3]]
|
||||||
|
[[[[9,9],[2,0]],0],[1,4]]
|
||||||
|
[[[[1,3],[5,1]],[[0,4],2]],0]
|
||||||
|
[[3,2],[7,[[9,3],8]]]
|
||||||
|
[[9,0],[4,[[8,7],[5,5]]]]
|
||||||
|
[[[[7,4],8],[[4,4],1]],9]
|
||||||
|
[[9,[[7,9],1]],[[[6,5],7],[[2,5],2]]]
|
||||||
|
[7,2]
|
||||||
|
[[[6,6],[[9,4],4]],6]
|
||||||
|
[[1,[[5,0],3]],[5,[4,4]]]
|
||||||
|
[[[3,2],[[4,6],6]],[[3,[9,5]],[[0,2],[4,6]]]]
|
||||||
|
[5,[[0,[3,0]],[7,[7,9]]]]
|
||||||
|
[[[[0,4],[1,5]],4],[8,[[4,7],8]]]
|
||||||
|
[[[[9,1],0],0],4]
|
||||||
|
[[[[8,4],[4,2]],[9,[1,7]]],[6,3]]
|
||||||
|
[2,[[[8,3],2],[[3,1],8]]]
|
||||||
|
[[[[9,0],[7,8]],[[2,7],[0,3]]],[[[8,5],3],[9,[6,8]]]]
|
||||||
|
[[[[8,9],[9,1]],[4,[0,1]]],[[[7,8],2],2]]
|
||||||
|
[[[[2,2],[4,1]],[2,[2,8]]],[[[6,5],1],9]]
|
||||||
|
[[[[3,0],7],7],[[[9,3],7],4]]
|
||||||
|
[[[[7,5],1],3],[[[0,7],7],[[2,6],[9,9]]]]
|
||||||
|
[[[[5,2],8],[9,[8,8]]],[2,[[0,8],[5,6]]]]
|
||||||
|
[[[[7,7],[1,2]],[6,6]],[8,[5,8]]]
|
||||||
|
[[7,[4,[8,9]]],[[4,[7,2]],8]]
|
||||||
|
[[[6,4],[7,7]],[[[3,7],0],[0,1]]]
|
||||||
|
[[1,[5,9]],[8,[4,6]]]
|
|
@ -2,5 +2,104 @@ package de.qwertyuiop.aoc.`2021`
|
||||||
|
|
||||||
import de.qwertyuiop.aoc.lib.*
|
import de.qwertyuiop.aoc.lib.*
|
||||||
import cats.*, cats.implicits.given
|
import cats.*, cats.implicits.given
|
||||||
|
import atto.*, Atto.*
|
||||||
|
|
||||||
def day18(using InputSource): Unit = ???
|
def day18(using InputSource): Unit =
|
||||||
|
import Snailfish.*
|
||||||
|
val lines = input()
|
||||||
|
val snumbers = lines.map(i => snailfishNumber.parseOnly(i).option.get)
|
||||||
|
val result = snumbers.tail.foldLeft(snumbers.head)(_ + _)
|
||||||
|
//val sum = Pair(snumbers(0), snumbers(1))
|
||||||
|
//tryExplode(sum)
|
||||||
|
//println(reduce(snailfishNumber.parseOnly("[[[[0,7],4],[7,[[8,4],9]]],[1,1]]").option.get))
|
||||||
|
println(s"Reduced: $result")
|
||||||
|
println(s"Magnitude: ${result.magnitude}")
|
||||||
|
|
||||||
|
val maxMag = snumbers.combinations(2).map{ case List(a, b) => (a + b).magnitude max (b + a).magnitude }.max
|
||||||
|
println(s"maximum: $maxMag")
|
||||||
|
|
||||||
|
|
||||||
|
enum Dir:
|
||||||
|
case L, R
|
||||||
|
extension (d: Dir)
|
||||||
|
def opposite: Dir = if d == Dir.L then Dir.R else Dir.L
|
||||||
|
|
||||||
|
|
||||||
|
trait SnailfishNumber:
|
||||||
|
def replace(path: List[Dir], elem: SnailfishNumber): SnailfishNumber =
|
||||||
|
modify(path)(_ => elem)
|
||||||
|
|
||||||
|
def modify(path: List[Dir])(f: SnailfishNumber => SnailfishNumber): SnailfishNumber =
|
||||||
|
(this, path) match
|
||||||
|
case (Pair(l, r), Dir.L :: Nil) => Pair(f(l), r)
|
||||||
|
case (Pair(l, r), Dir.R :: Nil) => Pair(l, f(r))
|
||||||
|
case (Pair(l, r), Dir.L :: rest) => Pair(l.modify(rest)(f), r)
|
||||||
|
case (Pair(l, r), Dir.R :: rest) => Pair(l, r.modify(rest)(f))
|
||||||
|
case (snailnum, _) => f(snailnum) // either Lit or end of path
|
||||||
|
|
||||||
|
def magnitude: Int =
|
||||||
|
this match
|
||||||
|
case Pair(l, r) => l.magnitude * 3 + r.magnitude * 2
|
||||||
|
case Lit(x) => x
|
||||||
|
|
||||||
|
infix def +(right: SnailfishNumber): SnailfishNumber =
|
||||||
|
Snailfish.reduce(Pair(this, right))
|
||||||
|
|
||||||
|
case class Lit(value: Int) extends SnailfishNumber:
|
||||||
|
override def toString = s"$value"
|
||||||
|
case class Pair(left: SnailfishNumber, right: SnailfishNumber) extends SnailfishNumber:
|
||||||
|
override def toString = s"[$left,$right]"
|
||||||
|
|
||||||
|
object Snailfish:
|
||||||
|
|
||||||
|
def snailfishNumber: Parser[SnailfishNumber] =
|
||||||
|
(
|
||||||
|
int.map(Lit.apply) ||
|
||||||
|
squareBrackets(
|
||||||
|
(snailfishNumber <~ char(',')) ~ snailfishNumber
|
||||||
|
).map(Pair.apply.tupled)
|
||||||
|
).map(_.merge)
|
||||||
|
|
||||||
|
|
||||||
|
def reduce(sn: SnailfishNumber): SnailfishNumber =
|
||||||
|
tryExplode(sn).orElse(trySplit(sn)).map(reduce).getOrElse(sn)
|
||||||
|
|
||||||
|
def trySplit(sn: SnailfishNumber): Option[SnailfishNumber] =
|
||||||
|
sn match
|
||||||
|
case Pair(l, r) =>
|
||||||
|
trySplit(l).map(newL => Pair(newL, r))
|
||||||
|
.orElse(trySplit(r).map(newR => Pair(l, newR)))
|
||||||
|
case Lit(x) if x < 10 => None
|
||||||
|
case Lit(x) => Some(Pair(Lit(x / 2), Lit(x / 2 + x % 2)))
|
||||||
|
|
||||||
|
|
||||||
|
def tryExplode(sn: SnailfishNumber): Option[SnailfishNumber] =
|
||||||
|
def findPath(path: List[Dir], depth: Int, elem: SnailfishNumber): Option[(List[Dir], Int, Int)] = elem match
|
||||||
|
case Pair(l, r) if depth < 4 =>
|
||||||
|
val left = findPath(Dir.L :: path, depth + 1, l)
|
||||||
|
if left.nonEmpty then left
|
||||||
|
else findPath(Dir.R :: path, depth + 1, r)
|
||||||
|
case Pair(Lit(l),Lit(r)) => (path.reverse, l, r).some
|
||||||
|
case Lit(_) => None
|
||||||
|
|
||||||
|
def nextNeighbour(dir: Dir, path: List[Dir]): Option[List[Dir]] =
|
||||||
|
val rpath = path.reverse
|
||||||
|
val pos = rpath.indexOf(dir.opposite)
|
||||||
|
if pos < 0 then None
|
||||||
|
else
|
||||||
|
val (pre, _ :: post) = rpath.splitAt(pos)
|
||||||
|
Some((pre.map(_ => dir.opposite) ++ (dir:: post)).reverse)
|
||||||
|
|
||||||
|
def add(value: Int, dir: Dir)(snail: SnailfishNumber) : SnailfishNumber = snail match
|
||||||
|
case Lit(x) => Lit(x + value)
|
||||||
|
case Pair(l, r) =>
|
||||||
|
if dir == Dir.R then Pair(l, add(value, dir)(r))
|
||||||
|
else Pair(add(value, dir)(l), r)
|
||||||
|
|
||||||
|
findPath(List(), 0, sn).map { (path, l, r) =>
|
||||||
|
val zeroed = sn.replace(path, Lit(0))
|
||||||
|
val left = nextNeighbour(Dir.L, path)
|
||||||
|
val right = nextNeighbour(Dir.R, path)
|
||||||
|
val leftAdded = left.map(p => zeroed.modify(p)(add(l, Dir.R))).getOrElse(zeroed)
|
||||||
|
right.map(p => leftAdded.modify(p)(add(r, Dir.L))).getOrElse(leftAdded)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue