Compare commits
3 Commits
24e925c27d
...
9e2aca403f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e2aca403f | ||
|
|
4c675c3ffe | ||
|
|
eee695007d |
@@ -11,7 +11,8 @@ val solvers = Map[Int, Solver](
|
||||
6 -> Day06,
|
||||
7 -> Day07,
|
||||
8 -> Day08,
|
||||
9 -> Day09
|
||||
9 -> Day09,
|
||||
10 -> Day10
|
||||
)
|
||||
|
||||
def runSolver(solver: Solver, input: os.Path): Unit =
|
||||
|
||||
@@ -8,33 +8,47 @@ object Day07 extends Solver(7):
|
||||
while m * 10 <= b do m *= 10
|
||||
a * (m * 10) + b
|
||||
|
||||
def deconcat(a: Long, b: Long): Option[Long] =
|
||||
val b_len = Math.log10(b).floor.toLong + 1
|
||||
if (a % Math.pow(10, b_len).toLong == b)
|
||||
then Some(a / Math.pow(10, b_len).toLong)
|
||||
else None
|
||||
|
||||
class Searcher(target: Long, nums: Vector[Long], elephants: Boolean):
|
||||
def search(acc: Long = nums(0), pos: Int = 1): Boolean =
|
||||
if (pos >= nums.length) return acc == target
|
||||
if (acc > target) return false
|
||||
search(acc + nums(pos), pos + 1)
|
||||
|| search(acc * nums(pos), pos + 1)
|
||||
|| (elephants && search(concat(acc, nums(pos)), pos + 1))
|
||||
|| search(acc * nums(pos), pos + 1)
|
||||
|| (elephants && search(concat(acc, nums(pos)), pos + 1))
|
||||
|
||||
class Tester(nums: Vector[Long], elephants: Boolean):
|
||||
def test(target: Long, pos: Int = nums.length - 1): Boolean =
|
||||
if pos == 0 then return target == nums(0)
|
||||
if target <= 0 then return false
|
||||
test(target - nums(pos), pos - 1)
|
||||
|| (target % nums(pos) == 0 && test(target / nums(pos), pos - 1))
|
||||
|| (elephants && deconcat(target, nums(pos)).exists(test(_, pos - 1)))
|
||||
|
||||
def check(target: Long, nums: Vector[Long], thirdElephant: Boolean): Boolean =
|
||||
if nums.contains(0)
|
||||
then Searcher(target, nums, thirdElephant).search()
|
||||
else Tester(nums, thirdElephant).test(target)
|
||||
|
||||
def run(input: os.ReadablePath): (Timings, Solution) =
|
||||
val REGEX = """(\d+): (.*)""".r
|
||||
val (pre_time, in) = timed {
|
||||
os.read.lines(input).map {
|
||||
case REGEX(value, rest) => (value.toLong, longs(rest))
|
||||
}.toVector
|
||||
os.read
|
||||
.lines(input)
|
||||
.map { case REGEX(value, rest) => (value.toLong, longs(rest)) }
|
||||
.toVector
|
||||
}
|
||||
|
||||
val (p1_time, p1_solution) = timed {
|
||||
in
|
||||
.filter((target, nums) => Searcher(target, nums, false).search())
|
||||
.map(_.head)
|
||||
.sum
|
||||
in.filter(p => check(p._1, p._2, false)).map(_.head).sum
|
||||
}
|
||||
|
||||
val (p2_time, p2_solution) = timed {
|
||||
in
|
||||
.filter((target, nums) => Searcher(target, nums, true).search())
|
||||
.map(_.head)
|
||||
.sum
|
||||
in.filter(p => check(p._1, p._2, true)).map(_.head).sum
|
||||
}
|
||||
|
||||
(
|
||||
|
||||
@@ -1,42 +1,39 @@
|
||||
package dev.ctsk.aoc.days
|
||||
|
||||
import dev.ctsk.aoc._
|
||||
import scala.collection.mutable.PriorityQueue
|
||||
import scala.math.Ordered.orderingToOrdered
|
||||
import dev.ctsk.aoc.*
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
|
||||
object Day09 extends Solver(9):
|
||||
implicit def ord: Ordering[Record] = Ordering.by(-_.offset)
|
||||
|
||||
implicit def ord: Ordering[Record] = Ordering.by(-1 * _.offset)
|
||||
case class Record(offset: Int, size: Int, id: Int):
|
||||
def checksum: Long = id.toLong * (size * offset + size * (size - 1) / 2)
|
||||
|
||||
case class GapMap(
|
||||
data: Map[Int, PriorityQueue[Record]]
|
||||
):
|
||||
case class GapMap(data: Map[Int, mutable.PriorityQueue[Record]]):
|
||||
def relocate(record: Record): Record =
|
||||
val bucket = data.view
|
||||
.filter((gapSize, gaps) => gapSize >= record.size && gaps.nonEmpty)
|
||||
.minByOption(_._2.head.offset)
|
||||
.maxByOption(_._2.head)
|
||||
|
||||
bucket match
|
||||
case None => record
|
||||
case Some((gapSize, gaps)) =>
|
||||
val gap = gaps.dequeue()
|
||||
if gap.offset >= record.offset then return record
|
||||
val remaining = gapSize - record.size
|
||||
if remaining > 0 then
|
||||
data(remaining)
|
||||
.enqueue(Record(gap.offset + record.size, remaining, gap.id))
|
||||
val rest = gapSize - record.size
|
||||
if rest > 0 then
|
||||
data(rest).enqueue(Record(gap.offset + record.size, rest, -1))
|
||||
Record(gap.offset, record.size, record.id)
|
||||
|
||||
def part1(input: Array[Int]): Long =
|
||||
val materialized = input.zipWithIndex.flatMap((x, i) =>
|
||||
if i % 2 == 0 then Iterator.fill(x.toInt)(i / 2)
|
||||
else Iterator.fill(x.toInt)(-1)
|
||||
if i % 2 == 0
|
||||
then Iterator.fill(x)(i / 2)
|
||||
else Iterator.fill(x)(-1)
|
||||
)
|
||||
|
||||
@tailrec def compact(l: Int = 0, r: Int = materialized.length - 1): Unit =
|
||||
@tailrec
|
||||
def compact(l: Int = 0, r: Int = materialized.length - 1): Unit =
|
||||
if l >= r then return ()
|
||||
if materialized(l) != -1 then return compact(l + 1, r)
|
||||
if materialized(r) == -1 then return compact(l, r - 1)
|
||||
@@ -48,19 +45,19 @@ object Day09 extends Solver(9):
|
||||
|
||||
def part2(input: Array[Int]): Long =
|
||||
val offsets = input.scanLeft(0)(_ + _).toArray
|
||||
val records =
|
||||
input.zipWithIndex.zip(offsets).map { case ((value, index), offset) =>
|
||||
if index % 2 == 0
|
||||
then Record(offset, value, index / 2)
|
||||
else Record(offset, value, -1)
|
||||
}
|
||||
|
||||
val (gaps, files) = records.partition(_.id == -1)
|
||||
val (gaps, files) = input.zip(offsets).zipWithIndex.partitionMap {
|
||||
case ((value, offset), index) =>
|
||||
if index % 2 == 0
|
||||
then Right(Record(offset, value, index / 2))
|
||||
else Left(Record(offset, value, -1))
|
||||
}
|
||||
|
||||
val gapMap = GapMap(
|
||||
gaps.groupBy(_.size).mapValues(PriorityQueue.from(_)).toMap
|
||||
gaps.groupBy(_.size).view.mapValues(mutable.PriorityQueue.from).toMap
|
||||
)
|
||||
|
||||
files.reverse.map(gapMap.relocate(_)).map(_.checksum).sum
|
||||
files.reverse.map(gapMap.relocate).map(_.checksum).sum
|
||||
|
||||
def run(input: os.ReadablePath): (Timings, Solution) =
|
||||
val disk = os.read.lines(input)(0).map(_.asDigit).toArray
|
||||
|
||||
46
aoc/src/dev/ctsk/aoc/days/Day10.scala
Normal file
46
aoc/src/dev/ctsk/aoc/days/Day10.scala
Normal file
@@ -0,0 +1,46 @@
|
||||
package dev.ctsk.aoc.days
|
||||
|
||||
import dev.ctsk.aoc._
|
||||
import dev.ctsk.aoc.Direction._
|
||||
|
||||
object Day10 extends Solver(10):
|
||||
type Input = (Grid[Char], Seq[Point])
|
||||
|
||||
def pre(input: os.ReadablePath): Input =
|
||||
val grid = Grid(os.read.lines(input).map(_.toArray).toArray)
|
||||
val zero = grid.find(_ == '0').toSeq
|
||||
(grid, zero)
|
||||
|
||||
def step(
|
||||
grid: Grid[Char],
|
||||
start: Seq[(Point, Point)],
|
||||
height: Int
|
||||
): Seq[(Point, Point)] =
|
||||
(for
|
||||
(p, origin) <- start
|
||||
a <- Seq(Up, Down, Left, Right)
|
||||
if grid(a(p)).exists(_.asDigit == height)
|
||||
yield (a(p), origin))
|
||||
|
||||
def part1(input: Input): Int =
|
||||
val (grid, zero) = input
|
||||
(1 to 9)
|
||||
.foldLeft(zero.zip(zero)) { case (acc, h) => step(grid, acc, h) }
|
||||
.distinct
|
||||
.size
|
||||
|
||||
def part2(input: Input): Int =
|
||||
val (grid, zero) = input
|
||||
(1 to 9)
|
||||
.foldLeft(zero.zip(zero)) { case (acc, h) => step(grid, acc, h) }
|
||||
.size
|
||||
|
||||
def run(input: os.ReadablePath): (Timings, Solution) =
|
||||
val (pre_time, (grid, zero)) = timed { pre(input) }
|
||||
val (p1_time, p1_solution) = timed { part1((grid, zero)) }
|
||||
val (p2_time, p2_solution) = timed { part2((grid, zero)) }
|
||||
|
||||
(
|
||||
Timings(pre_time, p1_time, p2_time),
|
||||
Solution(Int.box(p1_solution), Int.box(p2_solution))
|
||||
)
|
||||
2
data/10.ans
Normal file
2
data/10.ans
Normal file
@@ -0,0 +1,2 @@
|
||||
638
|
||||
1289
|
||||
50
data/10.in
Normal file
50
data/10.in
Normal file
@@ -0,0 +1,50 @@
|
||||
14567892107654348943218769016567650154541210421036
|
||||
03456783298993267654309458122168743243450344323145
|
||||
12567654456780154327812367433059804012769455410234
|
||||
03498012349876065016901056544965418765898766708943
|
||||
12345101212145076545411034545878329658981055899854
|
||||
09876876705034187632110123656789421047432765988765
|
||||
67878965896123298901001656743078431236598894012034
|
||||
50965014387654567650012349856127340012367653213125
|
||||
41234321298347656543243492347833458903458743404987
|
||||
30087430178298343650156781016942167812769252985676
|
||||
21196567069121243761056432679851043212890101679854
|
||||
33203498451080252852347841589765654301285234521763
|
||||
14512432347890161943210950432106567610106501430012
|
||||
01693501036543270856102167645656788943217432567897
|
||||
32789672321015389987343078938765497654998549879898
|
||||
45679987410234578101256560129812321067801456734787
|
||||
03478756500187665432107452121901054328982340125676
|
||||
12568767891098987013898943030810167017654321010210
|
||||
21079458910127698123965436945107878988901267124378
|
||||
30980349821034787654876327876716901210985458095469
|
||||
45671210136765693454761016329825432345671329186954
|
||||
12789800345876548763876125419434501654510413277843
|
||||
03543211238989439012985630308765898746701204567832
|
||||
14623400141232323101234521678906567239874343236901
|
||||
25710519850541014143219834567611452108965650145690
|
||||
76897678769650001054301712106320143210345789036781
|
||||
87678989678742112363212601235431234321276988325432
|
||||
90549876349233678478004592347842389123489676710876
|
||||
21632305256104569589123487656965476016512369856945
|
||||
52301014107012345670149874565456365017603450747832
|
||||
65490123458912396501234563432147454328214921632401
|
||||
86985432167905487654341012563038901039309834521321
|
||||
97876789001856778761232127678127612398712701100410
|
||||
89810678012760869890103238999210543125625632234509
|
||||
76701549013451987217876434785695610034534548765678
|
||||
05432432174012987301987325654780123435210159854789
|
||||
12980120985123673458986510783279234987346543123898
|
||||
43878921976034562567603412892168765679857012010187
|
||||
34565437852178901070412103601001410012768001921236
|
||||
45430566543065012181543014580432321003459122876545
|
||||
50121098767654327892678877698569457654219433468904
|
||||
23292145678954218983019988087658768894308596567812
|
||||
14587239010563007654128679112565489765107687656521
|
||||
05674678323472167659436543203474321087230156785430
|
||||
96983565401089898748540987654589321098543243896543
|
||||
87874328992396701037621296562105465407698012565432
|
||||
78765017687478632128760345673456978312789801478521
|
||||
29653078596569543019656921087567889213456700329650
|
||||
12532169430430156010567892193610367804765410418789
|
||||
03445678321321060123456543012323458912894321001678
|
||||
Reference in New Issue
Block a user