From 882f238ec9f6f3710ff83e52d19361cae63c8a3a Mon Sep 17 00:00:00 2001 From: nmcb Date: Sat, 14 Feb 2026 10:04:29 +0100 Subject: [PATCH] add runtime checks --- 2015/src/main/scala/aoc2015/Day07.scala | 3 +-- 2015/src/main/scala/aoc2015/Day13.scala | 3 +-- 2016/src/main/scala/aoc2016/Day01.scala | 6 ++--- 2016/src/main/scala/aoc2016/Day04.scala | 3 +-- 2016/src/main/scala/aoc2016/Day21.scala | 9 +++----- 2016/src/main/scala/aoc2016/Day23.scala | 14 +++++------- 2017/src/main/scala/aoc2017/Day22.scala | 3 +-- 2018/src/main/scala/aoc2018/Day06.scala | 3 +-- 2018/src/main/scala/aoc2018/Day07.scala | 3 +-- 2018/src/main/scala/aoc2018/Day13.scala | 6 ++--- 2019/src/main/scala/aoc2019/Day06.scala | 3 +-- 2019/src/main/scala/aoc2019/Day08.scala | 3 +-- 2019/src/main/scala/aoc2019/Day13.scala | 4 ++-- 2019/src/main/scala/aoc2019/Day23.scala | 3 +-- 2019/src/main/scala/aoc2019/Day24.scala | 12 +++++----- 2019/src/main/scala/aoc2019/cpu/CPU.scala | 9 +++----- 2020/src/main/scala/aoc2020/Day03.scala | 3 +-- 2020/src/main/scala/aoc2020/Day04.scala | 14 ++++++------ 2020/src/main/scala/aoc2020/Day06.scala | 5 ++-- 2020/src/main/scala/aoc2020/Day07.scala | 3 +-- 2020/src/main/scala/aoc2020/Day08.scala | 3 +-- 2020/src/main/scala/aoc2020/Day09.scala | 11 ++++----- 2020/src/main/scala/aoc2020/Day12.scala | 28 ++++++++++------------- 2020/src/main/scala/aoc2020/Day14.scala | 6 ++--- 2021/src/main/scala/aoc2021/Day10.scala | 3 +-- 2021/src/main/scala/aoc2021/Day16.scala | 3 +-- 2021/src/main/scala/aoc2021/vector.scala | 6 ++--- 2022/src/main/scala/aoc2022/Day02.scala | 6 ++--- 2022/src/main/scala/aoc2022/Day05.scala | 3 +-- 2022/src/main/scala/aoc2022/Day07.scala | 2 +- 2022/src/main/scala/aoc2022/Day10.scala | 3 +-- 2022/src/main/scala/aoc2022/Day14.scala | 3 +-- 2022/src/main/scala/aoc2022/Day19.scala | 3 +-- 2022/src/main/scala/aoc2022/Day21.scala | 3 +-- 2022/src/main/scala/aoc2022/Day24.scala | 8 +++---- 2022/src/main/scala/aoc2022/Day25.scala | 3 +-- 2023/src/main/scala/aoc2023/Day04.scala | 3 +-- 2023/src/main/scala/aoc2023/Day07.scala | 11 ++++----- 2023/src/main/scala/aoc2023/Day08.scala | 3 +-- 2023/src/main/scala/aoc2023/Day12.scala | 3 +-- 2023/src/main/scala/aoc2023/Day16.scala | 4 +--- 2023/src/main/scala/aoc2023/Day18.scala | 6 ++--- 2023/src/main/scala/aoc2023/Day24.scala | 8 ++++--- 2024/src/main/scala/aoc2024/Day02.scala | 13 +++++------ 2024/src/main/scala/aoc2024/Day15.scala | 11 +++++---- 2024/src/main/scala/aoc2024/Day17.scala | 6 ++--- 2025/src/main/scala/aoc2025/Day06.scala | 3 +-- 47 files changed, 112 insertions(+), 165 deletions(-) diff --git a/2015/src/main/scala/aoc2015/Day07.scala b/2015/src/main/scala/aoc2015/Day07.scala index a938dde..49d24fb 100644 --- a/2015/src/main/scala/aoc2015/Day07.scala +++ b/2015/src/main/scala/aoc2015/Day07.scala @@ -30,13 +30,12 @@ object Day07 extends AoC: def solve(rules: Vector[Rule], wire: Wire, setWireB: Option[Int] = None): Int = @tailrec def fold(rules: Seq[Rule], env: Env = Map.empty): Int = - env.get(wire) match + env.get(wire).runtimeChecked match case Some(v) => v case None => rules match case rule +: rest => rule.call(env) match case Some(v) => fold(rest, env.updated(rule.ret, v)) case None => fold(rest :+ rule, env) - case _ => sys.error(s"undefined wire=$wire") val puzzleInput: Vector[Rule] = setWireB.map(v => Val(v, "b") +: rules.filterNot(_.ret == "b")).getOrElse(rules) fold(puzzleInput) diff --git a/2015/src/main/scala/aoc2015/Day13.scala b/2015/src/main/scala/aoc2015/Day13.scala index eb7785b..5ac42a6 100644 --- a/2015/src/main/scala/aoc2015/Day13.scala +++ b/2015/src/main/scala/aoc2015/Day13.scala @@ -27,9 +27,8 @@ object Day13 extends AoC: val n1 = List(setting.init.last, setting.last, setting.head) val n2 = List(setting.last, setting.head, setting.tail.head) (n1 :: n2 :: setting.sliding(3).toList) - .map: + .collect: case List(nl, name, nr) => name -> List(nl, nr) - case _ => sys.error("expected a list of size 3") .toMap def happiness(name: String): Int = diff --git a/2016/src/main/scala/aoc2016/Day01.scala b/2016/src/main/scala/aoc2016/Day01.scala index 75c80ee..6a7e59d 100644 --- a/2016/src/main/scala/aoc2016/Day01.scala +++ b/2016/src/main/scala/aoc2016/Day01.scala @@ -20,7 +20,7 @@ object Day01 extends AoC: x.abs + y.abs infix def process(cmd: Cmd): Vector[Ikke] = - (dir, cmd.turn) match + (dir, cmd.turn).runtimeChecked match case (N, 'L') => (1 to cmd.dist).map(dist => copy(x = x - dist, dir = W)).toVector case (E, 'L') => (1 to cmd.dist).map(dist => copy(y = y + dist, dir = N)).toVector case (S, 'L') => (1 to cmd.dist).map(dist => copy(x = x + dist, dir = E)).toVector @@ -29,7 +29,6 @@ object Day01 extends AoC: case (E, 'R') => (1 to cmd.dist).map(dist => copy(y = y - dist, dir = S)).toVector case (S, 'R') => (1 to cmd.dist).map(dist => copy(x = x - dist, dir = W)).toVector case (W, 'R') => (1 to cmd.dist).map(dist => copy(y = y + dist, dir = N)).toVector - case _ => sys.error("boom!") object Ikke: @@ -43,11 +42,10 @@ object Day01 extends AoC: @tailrec def twice(test: Vector[Ikke], visited: Vector[Ikke]): Option[Ikke] = - test match + test.runtimeChecked match case Vector() => None case h +: t if visited.exists(ikke => ikke.x == h.x && ikke.y == h.y) => Some(h) case _ +: t => twice(t, visited) - case _ => sys.error("boom!") val next = path.last.process(commands.head) if twice(next, path).nonEmpty then twice(next, path).get else solve(commands.tail :+ commands.head, path :++ next) diff --git a/2016/src/main/scala/aoc2016/Day04.scala b/2016/src/main/scala/aoc2016/Day04.scala index a48f523..24afee4 100644 --- a/2016/src/main/scala/aoc2016/Day04.scala +++ b/2016/src/main/scala/aoc2016/Day04.scala @@ -14,9 +14,8 @@ object Day04 extends AoC: underlying.filter(_.isDigit).toInt def checksum: String = - underlying match + underlying.runtimeChecked match case s"$nameAndId[$checksum]" => checksum - case _ => sys.error(s"no checksum: $underlying") def isValid: Boolean = diff --git a/2016/src/main/scala/aoc2016/Day21.scala b/2016/src/main/scala/aoc2016/Day21.scala index 5e6fa70..b4759da 100644 --- a/2016/src/main/scala/aoc2016/Day21.scala +++ b/2016/src/main/scala/aoc2016/Day21.scala @@ -42,7 +42,7 @@ object Day21 extends AoC: s.patch(x, "", 1).patch(y, s.charAt(x).toString, 0) infix def scramble(s: String): String = - this match + this.runtimeChecked match case SwapPosition(x, y) => s.swapPosition(x, y) case SwapLetter(a, b) => s.swapLetter(a, b) case Rotate("left", n) => s.rotateLeft(n) @@ -50,10 +50,9 @@ object Day21 extends AoC: case RotateByPosition(a) => s.rotateByPositionRight(a) case ReverseByPosition(x, y) => s.reverseByPosition(x, y) case Move(x, y) => s.move(x, y) - case _ => sys.error("boom!") infix def unscramble(s: String): String = - this match + this.runtimeChecked match case SwapPosition(x, y) => s.swapPosition(x, y) case SwapLetter(a, b) => s.swapLetter(a, b) case Rotate("left", n) => s.rotateRight(n) @@ -61,21 +60,19 @@ object Day21 extends AoC: case RotateByPosition(a) => s.rotateByPositionLeft(a) case ReverseByPosition(x, y) => s.reverseByPosition(x, y) case Move(x, y) => s.move(y, x) - case _ => sys.error("boom!") import Operation.* val operations: Vector[Operation] = lines - .map: + .collect: case s"swap position $x with position $y" => SwapPosition(x.toInt, y.toInt) case s"swap letter $a with letter $b" => SwapLetter(a.head, b.head) case s"rotate based on position of letter $a" => RotateByPosition(a.head) case s"rotate $d $n $plural" => Rotate(d, n.toInt) case s"reverse positions $x through $y" => ReverseByPosition(x.toInt, y.toInt) case s"move position $x to position $y" => Move(x.toInt, y.toInt) - case s: String => sys.error(s"match error: '$s'") override lazy val answer1: String = operations.foldLeft("abcdefgh")((s, o) => o.scramble(s)) diff --git a/2016/src/main/scala/aoc2016/Day23.scala b/2016/src/main/scala/aoc2016/Day23.scala index 827b126..a57ec67 100644 --- a/2016/src/main/scala/aoc2016/Day23.scala +++ b/2016/src/main/scala/aoc2016/Day23.scala @@ -24,10 +24,10 @@ object Day23 extends AoC: case r: Register => registers.getOrElse(r, 0) case v: Value => v - def update(register: Operand, operand: Operand, f: Value => Value = identity): Registers = - if register.isRegister then - val value = (f compose registers.valueOf)(operand) - registers.updated(register.toRegister, value) + def update(target: Operand, source: Operand, f: Value => Value = identity): Registers = + if target.isRegister then + val value = (f compose registers.valueOf)(source) + registers.updated(target.toRegister, value) else registers @@ -74,16 +74,14 @@ object Day23 extends AoC: def toggle(offset: Operand): Vector[Option[Instruction]] = val index = pc + registers.valueOf(offset) if instructions.indices.contains(index) then - instructions.updated(index, instructions(index) match + val update = instructions(index).runtimeChecked match case None => None case Some(CPY(o, r)) => Some(JNZ(o, r)) case Some(INC(r)) => Some(DEC(r)) case Some(DEC(r)) => Some(INC(r)) case Some(JNZ(o, v)) => Some(CPY(o, v)) case Some(TGL(x)) => Some(INC(x)) - //Part 2 - case _ => sys.error("boom!") - ) + instructions.updated(index, update) else instructions diff --git a/2017/src/main/scala/aoc2017/Day22.scala b/2017/src/main/scala/aoc2017/Day22.scala index 65ebb62..e467ca5 100644 --- a/2017/src/main/scala/aoc2017/Day22.scala +++ b/2017/src/main/scala/aoc2017/Day22.scala @@ -74,10 +74,9 @@ object Day22 extends AoC: .flatMap: (row,y) => row .zipWithIndex - .map: + .collect: case ('#',x) => Pos.of(x,y) -> Infected case ('.',x) => Pos.of(x,y) -> Clean - case ( c ,_) => sys.error(s"unexpected char=$c") .toMap .withDefaultValue(Clean) diff --git a/2018/src/main/scala/aoc2018/Day06.scala b/2018/src/main/scala/aoc2018/Day06.scala index 4f10da2..5324601 100644 --- a/2018/src/main/scala/aoc2018/Day06.scala +++ b/2018/src/main/scala/aoc2018/Day06.scala @@ -29,10 +29,9 @@ object Day06 extends AoC: val closest: Vector[(Pos,Pos)] = positions.flatMap: p => coordinates.map(c => (c, c.manhattanDistance(p))) - .sortBy(_.distance).take(2) match + .sortBy(_.distance).take(2).runtimeChecked match case a +: b +: _ if a.distance == b.distance => None case a +: _ => Some(p,a.coordinate) - case _ => sys.error(s"no distance found for position: $p") val areas: Map[Pos,Int] = closest.groupMapReduce((_,c) => c)((_,_) => 1)(_+_) diff --git a/2018/src/main/scala/aoc2018/Day07.scala b/2018/src/main/scala/aoc2018/Day07.scala index a006d19..39e40ec 100644 --- a/2018/src/main/scala/aoc2018/Day07.scala +++ b/2018/src/main/scala/aoc2018/Day07.scala @@ -41,9 +41,8 @@ object Day07 extends AoC: val steps: Vector[(Char,Char)] = def parser(s: String): (Char,Char) = - s match + s.runtimeChecked match case s"Step $first must be finished before step $second can begin." => (first.head, second.head) - case _ => sys.error("boom!") lines.map(parser) override lazy val answer1: String = solve(steps, timer = _ => 1, parallelization = 1).right.mkString("") diff --git a/2018/src/main/scala/aoc2018/Day13.scala b/2018/src/main/scala/aoc2018/Day13.scala index 27748e1..9f579a5 100644 --- a/2018/src/main/scala/aoc2018/Day13.scala +++ b/2018/src/main/scala/aoc2018/Day13.scala @@ -10,7 +10,7 @@ object Day13 extends AoC: extension (d: Dir) infix def follow(c: Char): Dir = - (d, c) match + (d, c).runtimeChecked match case (_, '|') | (_, '-') => d case (N, '/') => E case (E, '/') => N @@ -20,7 +20,6 @@ object Day13 extends AoC: case (E, '\\') => S case (S, '\\') => E case (W, '\\') => N - case _ => sys.error(s"unable to follow dir=$d, char=$c") infix def turn(turn: Turn): Dir = (d, turn) match @@ -56,11 +55,10 @@ object Day13 extends AoC: def move(grid: Grid): Cart = val c = grid.charAt(pos step dir) - c match + c.runtimeChecked match case Some('|') | Some('-') => copy(pos = pos step dir) case Some('/') | Some('\\') => copy(pos = pos step dir, dir = dir follow c.get) case Some('+') => copy(pos = pos step dir, dir = dir turn atIntersection, atIntersection = atIntersection.next) - case _ => sys.error(s"unexpected char at pos=$pos, char=$c") val (grid: Grid, carts: Vector[Cart]) = val matrix = lines.map(_.toVector) diff --git a/2019/src/main/scala/aoc2019/Day06.scala b/2019/src/main/scala/aoc2019/Day06.scala index f6ae91d..9b9d913 100644 --- a/2019/src/main/scala/aoc2019/Day06.scala +++ b/2019/src/main/scala/aoc2019/Day06.scala @@ -40,10 +40,9 @@ object Day06 extends AoC: @tailrec def path(l: Vector[Name], r: Vector[Name]): Vector[Name] = - (l,r) match + (l,r).runtimeChecked match case (l1 +: l2 +: _ , r1 +: r2 +: _) if l1 == r1 && l2 == r2 => path(l.tail, r.tail) case (l1 +: _ , r1 +: _ ) if l1 == r1 => l.reverse ++ r.tail - case _ => sys.error(s"unmatched l=$l, r=$r") override lazy val answer1: Int = planets.map(orbits).map(_.length).sum override lazy val answer2: Int = path(pathToCom("YOU"), pathToCom("SAN")).length diff --git a/2019/src/main/scala/aoc2019/Day08.scala b/2019/src/main/scala/aoc2019/Day08.scala index d983744..9168ad3 100644 --- a/2019/src/main/scala/aoc2019/Day08.scala +++ b/2019/src/main/scala/aoc2019/Day08.scala @@ -69,11 +69,10 @@ object Day08 extends AoC: extension (dig: Dig) def digitToPix: Pix = - dig match + dig.runtimeChecked match case 0 => Black case 1 => White case 2 => Trans - case _ => sys.error("boom") def stack(top: Layer[Pix], bot: Layer[Pix]): Layer[Pix] = top.zip(bot).map((t,b) => b.stack(t)) diff --git a/2019/src/main/scala/aoc2019/Day13.scala b/2019/src/main/scala/aoc2019/Day13.scala index 23be620..1fa7362 100644 --- a/2019/src/main/scala/aoc2019/Day13.scala +++ b/2019/src/main/scala/aoc2019/Day13.scala @@ -25,8 +25,8 @@ object Day13 extends AoC: extension (outputs: LazyList[Value]) def render: Map[Location,Tile] = outputs.grouped(3).foldLeft(Map.empty[Location,Tile]): - case (result, LazyList(x,y,id)) => result + (Location(x,y) -> Tile.fromId(id)) - case output => sys.error(s"invalid output: $output") + case (result, LazyList(x, y, id)) => result + (Location(x, y) -> Tile.fromId(id)) + case output => sys.error(s"invalid output: $output") val program: Mem = Mem.parse(input) diff --git a/2019/src/main/scala/aoc2019/Day23.scala b/2019/src/main/scala/aoc2019/Day23.scala index 645122a..bbeda26 100644 --- a/2019/src/main/scala/aoc2019/Day23.scala +++ b/2019/src/main/scala/aoc2019/Day23.scala @@ -23,8 +23,7 @@ object Day23 extends AoC: val nextInput = if cpu.stdin.nonEmpty then in else Seq.empty - run match - case None => sys.error(s"unexpected halt") + run.runtimeChecked match case Some(cpu, None) => State(cpu, nextInput, out) case Some(cpu, Some(value)) => State(cpu, nextInput, out :+ value) diff --git a/2019/src/main/scala/aoc2019/Day24.scala b/2019/src/main/scala/aoc2019/Day24.scala index e366e5a..cc87e2b 100644 --- a/2019/src/main/scala/aoc2019/Day24.scala +++ b/2019/src/main/scala/aoc2019/Day24.scala @@ -23,12 +23,12 @@ object Day24 extends AoC: case Area(5, y, amount) => Set(Area(3, 2, amount - 1)) case Area(x, -1, amount) => Set(Area(2, 1, amount - 1)) case Area(x, 5, amount) => Set(Area(2, 3, amount - 1)) - case Area(2, 2, amount) => area match - case Area(2, 1, amount) => Set.tabulate(5)(x => Area(x, 0, amount + 1)) - case Area(2, 3, amount) => Set.tabulate(5)(x => Area(x, 4, amount + 1)) - case Area(1, 2, amount) => Set.tabulate(5)(y => Area(0, y, amount + 1)) - case Area(3, 2, amount) => Set.tabulate(5)(y => Area(4, y, amount + 1)) - case _ => sys.error(s"illegal area: $area") + case Area(2, 2, amount) => + area.runtimeChecked match + case Area(2, 1, amount) => Set.tabulate(5)(x => Area(x, 0, amount + 1)) + case Area(2, 3, amount) => Set.tabulate(5)(x => Area(x, 4, amount + 1)) + case Area(1, 2, amount) => Set.tabulate(5)(y => Area(0, y, amount + 1)) + case Area(3, 2, amount) => Set.tabulate(5)(y => Area(4, y, amount + 1)) case other => Set(other) def step(grid: Set[Area], neighbours: Area => Seq[Area]): Set[Area] = diff --git a/2019/src/main/scala/aoc2019/cpu/CPU.scala b/2019/src/main/scala/aoc2019/cpu/CPU.scala index 201fca5..ab6eed8 100644 --- a/2019/src/main/scala/aoc2019/cpu/CPU.scala +++ b/2019/src/main/scala/aoc2019/cpu/CPU.scala @@ -35,17 +35,15 @@ case class CPU(mem: Mem, stdin: LazyList[Value] = LazyList.empty, ip: Pointer = def paramMode(offset: Int): Int = ((value(0) / math.pow(10, 2 + offset).toInt) % 10).toInt def read(offset: Int): Value = - paramMode(offset) match + paramMode(offset).runtimeChecked match case 0 => mem(param(offset).toInt) case 1 => param(offset) case 2 => mem((base + param(offset)).toInt) - case _ => sys.error(s"illegal parameter read mode ${paramMode(offset)}") def write(offset: Int, value: Value): Mem = - paramMode(offset) match + paramMode(offset).runtimeChecked match case 0 => mem.set(param(offset).toInt, value) case 2 => mem.set((base + param(offset)).toInt, value) - case _ => sys.error(s"illegal parameter write mode ${paramMode(offset)}") def withInput(input: Value*): CPU = copy(stdin = input.to(LazyList)) @@ -54,7 +52,7 @@ case class CPU(mem: Mem, stdin: LazyList[Value] = LazyList.empty, ip: Pointer = copy(stdin = input) def executeOne: Option[State] = - opcode match + opcode.runtimeChecked match case 1 => Some((copy(mem = write(2, read(0) + read(1)), ip = ip + 4), None)) case 2 => Some((copy(mem = write(2, read(0) * read(1)), ip = ip + 4), None)) case 3 => Option.when(stdin.nonEmpty)(copy(mem = write(0, stdin.head), ip = ip + 2, stdin = stdin.tail), None) @@ -65,7 +63,6 @@ case class CPU(mem: Mem, stdin: LazyList[Value] = LazyList.empty, ip: Pointer = case 8 => Some((copy(mem = write(2, if (read(0) == read(1)) 1 else 0), ip = ip + 4), None)) case 9 => Some((copy(ip = ip + 2, base = base + read(0).toInt), None)) case 99 => None - case _ => sys.error(s"unknown opcode $opcode") def outputs: LazyList[Value] = LazyList.unfold(this)(_.executeOne.map(_.swap)).flatten diff --git a/2020/src/main/scala/aoc2020/Day03.scala b/2020/src/main/scala/aoc2020/Day03.scala index 5eff82e..2f8dddb 100644 --- a/2020/src/main/scala/aoc2020/Day03.scala +++ b/2020/src/main/scala/aoc2020/Day03.scala @@ -16,11 +16,10 @@ object Day03 extends AoC: def walk(dx: Int, dy: Int): Long = @tailrec def step(x: Int, y: Int, acc: Long = 0): Long = - sample(x, y) match + sample(x, y).runtimeChecked match case None => acc case Some('.') => step(x + dx, y + dy, acc) case Some('#') => step(x + dx, y + dy, acc + 1) - case _ => sys.error(s"boom: x=$x,y=$y,dx=$dx,dy=$dy") step(dx,dy) val forest: Forest = Forest(lines.map(_.toVector)) diff --git a/2020/src/main/scala/aoc2020/Day04.scala b/2020/src/main/scala/aoc2020/Day04.scala index d40b9e1..dbffe43 100644 --- a/2020/src/main/scala/aoc2020/Day04.scala +++ b/2020/src/main/scala/aoc2020/Day04.scala @@ -5,23 +5,23 @@ import scala.io.* object Day04 extends AoC: - type Passport = Map[String,String] + type Passport = Map[String, String] object Passport: val empty: Passport = - Map.empty[String,String] + Map.empty[String, String] val passports: Vector[Passport] = - lines.foldLeft(Vector(Passport.empty)): (acc,line) => + lines.foldLeft(Vector(Passport.empty)): (result, line) => line.split(' ') match case Array("") => - Passport.empty +: acc + Passport.empty +: result case line: Array[String] => val update = line.map(_.split(':')).map(kv => kv(0) -> kv(1)).toMap - (update ++ acc.head) +: acc.tail + (update ++ result.head) +: result.tail - def valYear(key: String, min: Int, max: Int)(passport: Passport): Boolean = - passport.get(key).exists(year => year.toInt >= min && year.toInt <= max) + def valYear(key: String, min: Int, max: Int)(p: Passport): Boolean = + p.get(key).exists(year => year.toInt >= min && year.toInt <= max) def valHgt(p: Passport): Boolean = p.get("hgt").exists: height => diff --git a/2020/src/main/scala/aoc2020/Day06.scala b/2020/src/main/scala/aoc2020/Day06.scala index 2647b05..67f3078 100644 --- a/2020/src/main/scala/aoc2020/Day06.scala +++ b/2020/src/main/scala/aoc2020/Day06.scala @@ -3,15 +3,14 @@ package aoc2020 import nmcb.* object Day06 extends AoC: - - + val answers: Vector[Vector[String]] = lines.foldLeft(Vector(Vector.empty[String])): case (result, line) if line.nonEmpty => (line +: result.head) +: result.tail case (result, _) => Vector.empty[String] +: result def chars(list: Vector[String]): String = - list.fold("")(_+_).distinct + list.mkString("").distinct override lazy val answer1: Int = answers.map(chars).map(_.length).sum override lazy val answer2: Int = answers.map(grp => grp.fold(chars(grp))(_ intersect _).length).sum diff --git a/2020/src/main/scala/aoc2020/Day07.scala b/2020/src/main/scala/aoc2020/Day07.scala index 762b65b..66c13df 100644 --- a/2020/src/main/scala/aoc2020/Day07.scala +++ b/2020/src/main/scala/aoc2020/Day07.scala @@ -38,10 +38,9 @@ object Day07 extends AoC: bags.filter(b => b.from == from && b.to.isDefined).map(b => b.to.get -> b.count) def solve2(inner: Vector[(Color,Int)], result: Int = 0): Int = - inner match + inner.runtimeChecked match case Vector() => result case (child,count) +: cs => solve2(cs, result + count + count * solve2(childrenOf(child))) - case _ => sys.error("boom!") override lazy val answer1: Int = bags.solve1(bags.parentsOf("shinygold")).distinct.size diff --git a/2020/src/main/scala/aoc2020/Day08.scala b/2020/src/main/scala/aoc2020/Day08.scala index b5cda93..1e9c40e 100644 --- a/2020/src/main/scala/aoc2020/Day08.scala +++ b/2020/src/main/scala/aoc2020/Day08.scala @@ -53,10 +53,9 @@ object Day08 extends AoC: def patch(program: Program): Program = def patchLine(line: Int): Program = - program(line) match + program(line).runtimeChecked match case Instruction("nop", arg) => program.updated(line, Instruction("jmp", arg)) case Instruction("jmp", arg) => program.updated(line, Instruction("nop", arg)) - case Instruction(op, arg) => sys.error(s"invalid op=$op, arg=$arg") VM(program).run(debug = true) .trace diff --git a/2020/src/main/scala/aoc2020/Day09.scala b/2020/src/main/scala/aoc2020/Day09.scala index 580d07e..3292e0a 100644 --- a/2020/src/main/scala/aoc2020/Day09.scala +++ b/2020/src/main/scala/aoc2020/Day09.scala @@ -12,13 +12,10 @@ object Day09 extends AoC: def solve1(preamble: Vector[Long], inbound: Vector[Long]): Long = @tailrec def go(todo: Vector[Long], prem: Vector[Long] = preamble): Long = - todo match - case test +: rest => - if prem.combinations(2).map(_.sum).contains(test) then - go(rest, prem.drop(1) :+ test) - else - test - case _ => sys.error("boom") + if prem.combinations(2).map(_.sum).contains(todo.head) then + go(todo.tail, prem.drop(1) :+ todo.head) + else + todo.head go(inbound) def solve2(inbound: Vector[Long], sum: Long): Option[Long] = diff --git a/2020/src/main/scala/aoc2020/Day12.scala b/2020/src/main/scala/aoc2020/Day12.scala index 464b95f..f9fc15c 100644 --- a/2020/src/main/scala/aoc2020/Day12.scala +++ b/2020/src/main/scala/aoc2020/Day12.scala @@ -16,7 +16,7 @@ object Day12 extends AoC: @tailrec private final def turn(current: Char, direction: Char, by: Int): Char = - if (by == 0) current else (current,direction) match + if (by == 0) current else (current, direction).runtimeChecked match case ('N','R') => turn('E', direction, by - 90) case ('E','R') => turn('S', direction, by - 90) case ('S','R') => turn('W', direction, by - 90) @@ -25,34 +25,31 @@ object Day12 extends AoC: case ('E','L') => turn('N', direction, by - 90) case ('S','L') => turn('E', direction, by - 90) case ('W','L') => turn('S', direction, by - 90) - case _ => sys.error(s"two faced=${(current,direction)}") - infix def perform(a: Action): Ship = - a.code match + a.code.runtimeChecked match case 'N' => copy(y = y + a.by) case 'S' => copy(y = y - a.by) case 'E' => copy(x = x + a.by) case 'W' => copy(x = x - a.by) case 'L' | 'R' => copy(face = turn(face, a.code, a.by)) - case 'F' => face match - case 'N' => copy(y = y + a.by) - case 'S' => copy(y = y - a.by) - case 'E' => copy(x = x + a.by) - case 'W' => copy(x = x - a.by) - case _ => sys.error(s"flat on its face=$face") - case _ => sys.error(s"code contains a error='${a.code}'") + case 'F' => + face.runtimeChecked match + case 'N' => copy(y = y + a.by) + case 'S' => copy(y = y - a.by) + case 'E' => copy(x = x + a.by) + case 'W' => copy(x = x - a.by) def manhattan: Int = x.abs + y.abs case class WayPoint(x: Int, y: Int): - @tailrec private final def turn(current: Char, by: Int, x0: Int = x, y0: Int = y): WayPoint = - if by == 0 then copy(x = x0, y = y0) else current match + @tailrec + final def turn(current: Char, by: Int, x0: Int = x, y0: Int = y): WayPoint = + if by == 0 then copy(x = x0, y = y0) else current.runtimeChecked match case 'R' => turn(current, by - 90, y0, 0 - x0) case 'L' => turn(current, by - 90, 0 - y0, x0) - case _ => sys.error(s"code contains a coding error='$current'") def perform(a: Action): WayPoint = a.code match @@ -65,10 +62,9 @@ object Day12 extends AoC: case class WayPointedShip(x: Int = 0, y: Int = 0, wp: WayPoint = WayPoint(10, 1)): infix def perform(a: Action): WayPointedShip = - a.code match + a.code.runtimeChecked match case 'N' | 'S' | 'E' | 'W' | 'L' | 'R' => copy(wp = wp.perform(a)) case 'F' => copy(x = x + wp.x * a.by, y = y + wp.y * a.by) - case _ => sys.error(s"code contains a coding error='${a.code}'") def manhattan: Int = x.abs + y.abs diff --git a/2020/src/main/scala/aoc2020/Day14.scala b/2020/src/main/scala/aoc2020/Day14.scala index c32dce4..7877f52 100644 --- a/2020/src/main/scala/aoc2020/Day14.scala +++ b/2020/src/main/scala/aoc2020/Day14.scala @@ -35,7 +35,7 @@ object Day14 extends AoC: case (('X',b), lsb) => "" + b + lsb case (('1',_), lsb) => "" + '1' + lsb case (('0',_), lsb) => "" + '0' + lsb - case err => sys.error(s"boom: $err"), + case err => sys.error(s"boom: $err"), radix = 2 ) @@ -46,12 +46,12 @@ object Day14 extends AoC: case (('X',_),lsb) => "" + 'X' + lsb case (('1',_),lsb) => "" + '1' + lsb case (('0',b),lsb) => "" + b + lsb - case err => sys.error(s"boom: $err") + case err => sys.error(s"boom: $err") .foldRight(List.empty[String]): case ('X',acc) => if acc.nonEmpty then acc.flatMap(n => List("0" + n, "1" + n)) else List("0", "1") case ('1',acc) => if acc.nonEmpty then acc.map(n => "1" + n) else List("1") case ('0',acc) => if acc.nonEmpty then acc.map(n => "0" + n) else List("0") - case err => sys.error(s"boom: $err") + case err => sys.error(s"boom: $err") .map(string => new UInt36(string, 2)) override def toString: String = diff --git a/2021/src/main/scala/aoc2021/Day10.scala b/2021/src/main/scala/aoc2021/Day10.scala index a99d889..6e3857b 100644 --- a/2021/src/main/scala/aoc2021/Day10.scala +++ b/2021/src/main/scala/aoc2021/Day10.scala @@ -44,12 +44,11 @@ object Day10 extends AoC: override lazy val answer1: Long = lines .flatMap(incomplete) - .map: + .collect: case ')' => 3L case ']' => 57L case '}' => 1197L case '>' => 25137L - case c => sys.error(s"invalid char: $c") .groupMapReduce(identity)(identity)(_ + _) .values .sum diff --git a/2021/src/main/scala/aoc2021/Day16.scala b/2021/src/main/scala/aoc2021/Day16.scala index 49bea62..796293e 100644 --- a/2021/src/main/scala/aoc2021/Day16.scala +++ b/2021/src/main/scala/aoc2021/Day16.scala @@ -105,10 +105,9 @@ object Day16 extends AoC: @tailrec def go(groups: Vector[Vector[Bit]], acc: Vector[Group] = Vector.empty): (Vector[Group], Vector[Bit]) = - groups match + groups.runtimeChecked match case bits +: rest if Group.isLast(bits) => (acc :+ Group(bits), rest.flatten) case bits +: rest => go(rest, acc :+ Group(bits)) - case _ => sys.error("no last group") go(rest.grouped(5).toVector) diff --git a/2021/src/main/scala/aoc2021/vector.scala b/2021/src/main/scala/aoc2021/vector.scala index f9d2260..c28f1a9 100644 --- a/2021/src/main/scala/aoc2021/vector.scala +++ b/2021/src/main/scala/aoc2021/vector.scala @@ -25,9 +25,8 @@ package aoc2021 Vec(x.toString, y.toString) def parse(s: String): Vec = - s match + s.runtimeChecked match case VecLit(x, y) => Vec(x, y) - case _ => sys.error(s"does not match ${VecLit.regex} : '$s'") val origin: Vec = Vec(0, 0) @@ -62,9 +61,8 @@ package aoc2021 Vec3(x.toString, y.toString, z.toString) def parse(s: String): Vec3 = - s match + s.runtimeChecked match case Vec3Lit(x, y, z) => Vec3(x, y, z) - case _ => sys.error(s"does not match ${Vec3Lit.regex} : '$s'") val origin: Vec3 = Vec3(0, 0, 0) diff --git a/2022/src/main/scala/aoc2022/Day02.scala b/2022/src/main/scala/aoc2022/Day02.scala index 870e363..6abcdcc 100644 --- a/2022/src/main/scala/aoc2022/Day02.scala +++ b/2022/src/main/scala/aoc2022/Day02.scala @@ -8,7 +8,7 @@ object Day02 extends AoC: case s"$p1 $p2" => (p1.head,p2.head) def score1(p1: Char, p2: Char): Int = - (p1,p2) match + (p1, p2).runtimeChecked match case ('A','X') => 1 + 3 case ('A','Y') => 2 + 6 case ('A','Z') => 3 + 0 @@ -18,10 +18,9 @@ object Day02 extends AoC: case ('C','X') => 1 + 6 case ('C','Y') => 2 + 0 case ('C','Z') => 3 + 3 - case _ => sys.error(s"illegal chars: ($p1,$p2)") def score2(p1: Char, p2: Char): Int = - (p1,p2) match + (p1, p2).runtimeChecked match case ('A','X') => 3 + 0 case ('A','Y') => 1 + 3 case ('A','Z') => 2 + 6 @@ -31,7 +30,6 @@ object Day02 extends AoC: case ('C','X') => 2 + 0 case ('C','Y') => 3 + 3 case ('C','Z') => 1 + 6 - case _ => sys.error(s"illegal chars: ($p1,$p2)") override lazy val answer1: Int = codes.map(score1).sum diff --git a/2022/src/main/scala/aoc2022/Day05.scala b/2022/src/main/scala/aoc2022/Day05.scala index 5cbd19a..7be9161 100644 --- a/2022/src/main/scala/aoc2022/Day05.scala +++ b/2022/src/main/scala/aoc2022/Day05.scala @@ -22,9 +22,8 @@ object Day05 extends AoC: val columnSize: Int = - lines.filter(isLabelLine) match + lines.filter(isLabelLine).runtimeChecked match case Vector(cols) => cols.split(' ').last.toInt - case _ => sys.error("multiple label lines") def crateExtractor(line: String)(idx: Int): Option[Char] = Try(line.charAt(1 + idx * 4)) match diff --git a/2022/src/main/scala/aoc2022/Day07.scala b/2022/src/main/scala/aoc2022/Day07.scala index bffb80c..8cd40b1 100644 --- a/2022/src/main/scala/aoc2022/Day07.scala +++ b/2022/src/main/scala/aoc2022/Day07.scala @@ -48,7 +48,7 @@ object Day07 extends AoC: lazy val fileSystem: FileSystem = import Path.* stdout - .foldLeft(FileSystem.empty)((sys,line) => + .foldLeft(FileSystem.empty)((sys, line) => line match case DirLine(name) => sys.copy(ds = sys.ds :+ flatten(sys.cur :+ name)) case FileLine(name, size) => sys.copy(fs = sys.fs :+ File(flatten(sys.cur :+ name), size)) diff --git a/2022/src/main/scala/aoc2022/Day10.scala b/2022/src/main/scala/aoc2022/Day10.scala index ae6cc7d..8400c57 100644 --- a/2022/src/main/scala/aoc2022/Day10.scala +++ b/2022/src/main/scala/aoc2022/Day10.scala @@ -24,11 +24,10 @@ object Day10 extends AoC: val sync: Seq[Int] = List(20, 60, 100, 140, 180, 220).map(_ - 1) def nextCycle: CPU = - is match + is.runtimeChecked match case Nop +: rest => CPU( rest, cycle + 1, x ) case Add(v, 2) +: rest => CPU(Add(v,1) +: rest, cycle + 1, x ) case Add(v, 1) +: rest => CPU( rest, cycle + 1, x + v) - case _ => sys.error("boom!") val signalStrength: Int = x * (cycle + 1) diff --git a/2022/src/main/scala/aoc2022/Day14.scala b/2022/src/main/scala/aoc2022/Day14.scala index fc866ad..09976a2 100644 --- a/2022/src/main/scala/aoc2022/Day14.scala +++ b/2022/src/main/scala/aoc2022/Day14.scala @@ -33,10 +33,9 @@ object Day14 extends AoC: @tailrec def positions(path: Vector[Pos], result: Vector[Pos] = Vector.empty): Vector[Pos] = - path match + path.runtimeChecked match case _ +: Vector() => result case from +: to +: rest => positions(to +: rest, result :++ segment(from, to)) - case _ => sys.error("boom!") paths.foldLeft(Vector.empty[Pos])((rocks, path) => rocks :++ positions(path)).distinct diff --git a/2022/src/main/scala/aoc2022/Day19.scala b/2022/src/main/scala/aoc2022/Day19.scala index 1ec9951..b285441 100644 --- a/2022/src/main/scala/aoc2022/Day19.scala +++ b/2022/src/main/scala/aoc2022/Day19.scala @@ -72,12 +72,11 @@ object Day19 extends AoC: actions.flatten def build(action: Build): Robot = - action match + action.runtimeChecked match case OreRobot => Robot(Ore) case ClayRobot => Robot(Clay) case ObsidianRobot => Robot(Obsidian) case GeodeRobot => Robot(Geode) - case Nothing => sys.error("boom robot!") @tailrec def produce(robots: Vector[Robot], stash: MaterialStash): MaterialStash = diff --git a/2022/src/main/scala/aoc2022/Day21.scala b/2022/src/main/scala/aoc2022/Day21.scala index aa46448..8069e7d 100644 --- a/2022/src/main/scala/aoc2022/Day21.scala +++ b/2022/src/main/scala/aoc2022/Day21.scala @@ -48,11 +48,10 @@ object Day21 extends AoC: @targetName("eq") def |=|(rhs: Result): Result = - (lhs, rhs) match + (lhs, rhs).runtimeChecked match case (ll: Long, ro: Lazy) => ro(ll) case (lo: Lazy, rl: Long) => lo(rl) case (ll: Long, rl: Long) if rl == ll => rl - case _ => sys.error("boom!") type Defer = Name => Result type Deferrable = Defer => Result diff --git a/2022/src/main/scala/aoc2022/Day24.scala b/2022/src/main/scala/aoc2022/Day24.scala index decf34f..4400340 100644 --- a/2022/src/main/scala/aoc2022/Day24.scala +++ b/2022/src/main/scala/aoc2022/Day24.scala @@ -70,7 +70,7 @@ object Day24 extends AoC: def nextBlizzardChar(streamField: Field[(Char,Char,Char,Char)])(x: Int, y: Int): Char = val count = countBlizzards(streamField)(x: Int, y: Int) val (uc,dc,lc,rc) = streamField(y)(x) - count match + count.runtimeChecked match case 0 => OpenChar case 1 if uc == UpChar => UpChar case 1 if dc == DownChar => DownChar @@ -79,9 +79,8 @@ object Day24 extends AoC: case 2 => '2' case 3 => '3' case 4 => '4' - case _ => sys.error("more than 4 blizzards in one field pos") - val futureStreamField: Field[(Char,Char,Char,Char)] = + val futureStreamField: Field[(Char, Char, Char, Char)] = (for { y <- 0 until sizeY x <- 0 until sizeX @@ -93,9 +92,8 @@ object Day24 extends AoC: val futureField: Field[Char] = val buffer: Array[Array[Char]] = Array.fill(sizeY, sizeX)(Field.OpenChar) - for (y <- 0 until sizeY ; x <- 0 until sizeX) { + for y <- 0 until sizeY ; x <- 0 until sizeX do buffer(y)(x) = nextBlizzardChar(futureStreamField)(x, y) - } buffer.map(_.toVector).toVector type Paths = Set[Pos] diff --git a/2022/src/main/scala/aoc2022/Day25.scala b/2022/src/main/scala/aoc2022/Day25.scala index 6eb9dcf..5b3066a 100644 --- a/2022/src/main/scala/aoc2022/Day25.scala +++ b/2022/src/main/scala/aoc2022/Day25.scala @@ -27,9 +27,8 @@ object Day25 extends AoC: val Powers: Long = 5 def fromChar(c: Char): Digit = - c match + c.runtimeChecked match case '2' | '1' | '0' | '-' | '=' => Digit(c) - case _ => sys.error(s"boom: '$c'") case class Number(digits: List[Digit]): diff --git a/2023/src/main/scala/aoc2023/Day04.scala b/2023/src/main/scala/aoc2023/Day04.scala index a2013aa..b9dbc83 100644 --- a/2023/src/main/scala/aoc2023/Day04.scala +++ b/2023/src/main/scala/aoc2023/Day04.scala @@ -24,9 +24,8 @@ object Day04 extends AoC: def ints(s: String): Vector[Int] = s.trim.split("\\s+").map(_.toInt).toVector - s match + s.runtimeChecked match case s"Card $id: $winning | $mine" => Card(id.trim.toInt, ints(winning), ints(mine)) - case _ => sys.error(s"unmatched: $s") val cards: Map[Int,Card] = lines.map(Card.fromString).map(c => c.id -> c).toMap diff --git a/2023/src/main/scala/aoc2023/Day07.scala b/2023/src/main/scala/aoc2023/Day07.scala index 28ad3ea..b8a9dd8 100644 --- a/2023/src/main/scala/aoc2023/Day07.scala +++ b/2023/src/main/scala/aoc2023/Day07.scala @@ -87,20 +87,19 @@ object Day07 extends AoC: combinations.grouped(8).map(_.map(cs => strengths(cs).max).max).max private def strengths(hand: Cards): List[Strength] = + @tailrec def loop(todo: List[(Card, Int)], found: List[Strength] = List.empty): List[Strength] = - todo match + todo.runtimeChecked match case Nil => found.sorted case (d, 5) :: rest => loop(rest, FiveOfAKind :: found) case (d, 4) :: rest => loop(rest, FourOfAKind :: found) case (d, 3) :: rest => loop(rest, ThreeOfAKind :: found) case (d, 2) :: rest => - found match + found.runtimeChecked match case Nil => loop(rest, Pair :: found) case Pair :: _ => loop(rest, TwoPair :: found.tail) case ThreeOfAKind :: _ => loop(rest, FullHouse :: found.tail) - case _ => sys.error(s"illegal state: found=$found, todo=$todo") case (d, 1) :: rest => loop(rest, High :: found) - case _ => sys.error(s"illegal state: $todo") val countedCards = hand.groupMapReduce(identity)(_ => 1)(_ + _).toList.sortBy(_.right).reverse loop(countedCards).reverse @@ -112,12 +111,12 @@ object Day07 extends AoC: (a: Hand, b: Hand) => val highs = strength(a) compare strength(b) if highs != 0 then highs else + @tailrec def highest(as: Cards, bs: Cards): Int = - (as, bs) match + (as, bs).runtimeChecked match case (ha :: ra, hb :: rb) if (ha compare hb) == 0 => highest(ra, rb) case (ha :: ra, hb :: rb) => ha compare hb case (Nil, Nil) => 0 - case (_,_) => sys.error(s"could not compare: $as with $bs") highest(a.cards, b.cards) object Hand: diff --git a/2023/src/main/scala/aoc2023/Day08.scala b/2023/src/main/scala/aoc2023/Day08.scala index bab9b95..b4265c7 100644 --- a/2023/src/main/scala/aoc2023/Day08.scala +++ b/2023/src/main/scala/aoc2023/Day08.scala @@ -15,10 +15,9 @@ object Day08 extends AoC: case class Network(directions: Directions, nodes: Nodes): def step(from: String, direction: Char): String = - direction match + direction.runtimeChecked match case 'L' => nodes.getOrElse(from, sys.error(s"no step left from: $from")).left case 'R' => nodes.getOrElse(from, sys.error(s"no step right from: $from")).right - case _ => sys.error(s"invalid direction: $direction") @tailrec final def pathTo(exit: String => Boolean, from: String, directions: Directions, path: String = ""): String = diff --git a/2023/src/main/scala/aoc2023/Day12.scala b/2023/src/main/scala/aoc2023/Day12.scala index c6ceb14..ef8527f 100644 --- a/2023/src/main/scala/aoc2023/Day12.scala +++ b/2023/src/main/scala/aoc2023/Day12.scala @@ -22,7 +22,7 @@ object Day12 extends AoC: private def solve(mask: String, lengths: List[Int]): Long = cache.getOrElseUpdate((mask, lengths), - (mask, lengths) match + (mask, lengths).runtimeChecked match case (_, Nil) if mask.contains('#') => 0 case (_, Nil) => 1 case ("", _ :: _) => 0 @@ -39,7 +39,6 @@ object Day12 extends AoC: case _ => 0 case (s"#$tail", _ :: _) => 0 case (s"?$tail", _) => solve(s".$tail", lengths) + solve(s"#$tail", lengths) - case _ => sys.error(s"illegal state: mask=$mask, lengths=$lengths") ) lazy val arrangements: Long = diff --git a/2023/src/main/scala/aoc2023/Day16.scala b/2023/src/main/scala/aoc2023/Day16.scala index 43b6c35..2db4c07 100644 --- a/2023/src/main/scala/aoc2023/Day16.scala +++ b/2023/src/main/scala/aoc2023/Day16.scala @@ -16,7 +16,7 @@ object Day16 extends AoC: private def advance(p: Pos, d: Dir): List[(Pos,Dir)] = val result: List[(Pos,Dir)] = - (tile(p), d) match + (tile(p), d).runtimeChecked match case ('.', N) => List(p.step(N) -> N) case ('.', E) => List(p.step(E) -> E) case ('.', S) => List(p.step(S) -> S) @@ -42,8 +42,6 @@ object Day16 extends AoC: case ('\\', S) => List(p.step(E) -> E) case ('\\', W) => List(p.step(N) -> N) - case _ => sys.error(s"advancing: p=$p, d=$d") - result.filter((p,_) => p.x >= 0 && p.y >= 0 && p.x < sizeX && p.y < sizeY) private def trace(start: Pos, direction: Dir): Set[(Pos,Dir)] = diff --git a/2023/src/main/scala/aoc2023/Day18.scala b/2023/src/main/scala/aoc2023/Day18.scala index 686f692..8988e08 100644 --- a/2023/src/main/scala/aoc2023/Day18.scala +++ b/2023/src/main/scala/aoc2023/Day18.scala @@ -29,20 +29,18 @@ object Day18 extends AoC: extension (p: Pos) infix def move1(op: Op): Vector[Pos] = - op match + op.runtimeChecked match case Op('U', length) => Vector.tabulate(length)(dy => (x = p.x, y = p.y - dy - 1)) case Op('D', length) => Vector.tabulate(length)(dy => (x = p.x, y = p.y + dy + 1)) case Op('L', length) => Vector.tabulate(length)(dx => (x = p.x - dx - 1, y = p.y)) case Op('R', length) => Vector.tabulate(length)(dx => (x = p.x + dx + 1, y = p.y)) - case Op(dir, length) => sys.error(s"invalid dir=$dir, length=$length") infix def move2(op: Op): Pos = - op match + op.runtimeChecked match case Op('U', length) => (x = p.x, y = p.y - length) case Op('D', length) => (x = p.x, y = p.y + length) case Op('L', length) => (x = p.x - length, y = p.y) case Op('R', length) => (x = p.x + length, y = p.y) - case Op(dir, length) => sys.error(s"invalid dir=$dir, length=$length") diff --git a/2023/src/main/scala/aoc2023/Day24.scala b/2023/src/main/scala/aoc2023/Day24.scala index 9d52cd1..9fc2a21 100644 --- a/2023/src/main/scala/aoc2023/Day24.scala +++ b/2023/src/main/scala/aoc2023/Day24.scala @@ -322,10 +322,12 @@ object Day24 extends AoC: object Stone: def fromString(s: String): Stone = - s match + s.runtimeChecked match case s"$x, $y, $z @ $vx, $vy, $vz" => - Stone(Vec(x.trim.toLong, y.trim.toLong, z.trim.toLong), Vec(vx.trim.toLong, vy.trim.toLong, vz.trim.toLong)) - case _ => sys.error(s"input error: '$s'") + Stone( + location = Vec( x.trim.toLong, y.trim.toLong, z.trim.toLong), + velocity = Vec(vx.trim.toLong, vy.trim.toLong, vz.trim.toLong) + ) case class Vec(x: Long, y: Long, z: Long): def +(that: Vec): Vec = Vec(x + that.x, y + that.y, z + that.z) diff --git a/2024/src/main/scala/aoc2024/Day02.scala b/2024/src/main/scala/aoc2024/Day02.scala index d4e060d..98eea69 100644 --- a/2024/src/main/scala/aoc2024/Day02.scala +++ b/2024/src/main/scala/aoc2024/Day02.scala @@ -4,15 +4,14 @@ import nmcb.* object Day02 extends AoC: - private case class Report(levels: Seq[Int]): + private case class Report(levels: Vector[Int]): - private lazy val differences: Seq[Int] = + private lazy val differences: Vector[Int] = levels .sliding(2) - .map: - case Seq(l, r) => r - l - case d => sys.error(s"boom: $d") - .toSeq + .collect: + case Vector(l, r) => r - l + .toVector private lazy val isIncreasing: Boolean = differences.forall(d => d >= 0) @@ -33,7 +32,7 @@ object Day02 extends AoC: withOneLevelRemoved.count(_.isSafe) > 0 - private val reports: Seq[Report] = lines.map(s => Report(s.split(' ').map(_.toInt).toSeq)) + private val reports: Vector[Report] = lines.map(s => Report(s.split(' ').map(_.toInt).toVector)) override lazy val answer1: Int = reports.count(_.isSafe) override lazy val answer2: Int = reports.count(r => r.isSafe || r.isSafeWithOneLevelRemoved) diff --git a/2024/src/main/scala/aoc2024/Day15.scala b/2024/src/main/scala/aoc2024/Day15.scala index e5d346b..9add515 100644 --- a/2024/src/main/scala/aoc2024/Day15.scala +++ b/2024/src/main/scala/aoc2024/Day15.scala @@ -84,12 +84,15 @@ object Day15 extends AoC: Grid(updatedAndCleaned) def resize: Grid = + def map(p: Pos, from: Char, to: Char) = + Map((x = p.x * 2, y = p.y) -> from, (x = (p.x * 2) + 1, y = p.y) -> to) + Grid( grid.flatMap: - case (p,'#') => Map((x = p.x * 2, y = p.y) -> '#', (x = (p.x * 2) + 1, y = p.y) -> '#') - case (p,'.') => Map((x = p.x * 2, y = p.y) -> '.', (x = (p.x * 2) + 1, y = p.y) -> '.') - case (p,'O') => Map((x = p.x * 2, y = p.y) -> '[', (x = (p.x * 2) + 1, y = p.y) -> ']') - case (p,'@') => Map((x = p.x * 2, y = p.y) -> '@', (x = (p.x * 2) + 1, y = p.y) -> '.') + case (p,'#') => map(p, '#', '#') + case (p,'.') => map(p, '.', '.') + case (p,'O') => map(p, '[', ']') + case (p,'@') => map(p, '@', '.') case (p, c ) => sys.error(s"invalid element: p=$p, c=$c") ) diff --git a/2024/src/main/scala/aoc2024/Day17.scala b/2024/src/main/scala/aoc2024/Day17.scala index 161a636..0a73532 100644 --- a/2024/src/main/scala/aoc2024/Day17.scala +++ b/2024/src/main/scala/aoc2024/Day17.scala @@ -23,18 +23,17 @@ object Day17 extends AoC: if halts then this else read.run def combo: Long = - operand match + operand.runtimeChecked match case 0 | 1 | 2 | 3 => operand case 4 => a case 5 => b case 6 => c - case _ => sys.error(s"Invalid combo operand: $operand") def literal: Long = operand def read: CPU = - opcode match + opcode.runtimeChecked match case 0 => copy(a = a >> combo, ip = ip + 2) case 1 => copy(b = b ^ literal, ip = ip + 2) case 2 => copy(b = combo & 0x07, ip = ip + 2) @@ -43,7 +42,6 @@ object Day17 extends AoC: case 5 => copy(out = (out << 3) + (combo & 0x07), ip = ip + 2) case 6 => copy(b = a >> combo, ip = ip + 2) case 7 => copy(c = a >> combo, ip = ip + 2) - case _ => sys.error(s"Invalid r.performed: ip=$ip, inst=${program(ip)}") @tailrec final def display(current: Long, result: String = ""): String = diff --git a/2025/src/main/scala/aoc2025/Day06.scala b/2025/src/main/scala/aoc2025/Day06.scala index ccfa461..ce3357d 100644 --- a/2025/src/main/scala/aoc2025/Day06.scala +++ b/2025/src/main/scala/aoc2025/Day06.scala @@ -5,10 +5,9 @@ import nmcb.* object Day06 extends AoC: def calculate(operators: Vector[Char], operands: Vector[Vector[Long]]): Vector[Long] = - operators.zip(operands).map: + operators.zip(operands).collect: case ('+', operands) => operands.sum case ('*', operands) => operands.product - case (o, _) => sys.error(s"unknown operator: $o") def solve1(lines: Vector[String]): Vector[Long] = val operands = lines.init.map(_.split("\\s+").filter(_.nonEmpty).map(_.toLong)).transpose