From d07dd395e10ddb9f43f5bf04881c593545d49ef6 Mon Sep 17 00:00:00 2001 From: Soren Date: Sun, 2 Dec 2018 21:43:32 -0800 Subject: [PATCH] Day 3 --- aoc/src/main/scala/aoc/y2018/Day03.scala | 72 ++++++++++++++++++++++ aoc/src/main/scala/aoc/y2018/package.scala | 3 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 aoc/src/main/scala/aoc/y2018/Day03.scala diff --git a/aoc/src/main/scala/aoc/y2018/Day03.scala b/aoc/src/main/scala/aoc/y2018/Day03.scala new file mode 100644 index 0000000..c35df6a --- /dev/null +++ b/aoc/src/main/scala/aoc/y2018/Day03.scala @@ -0,0 +1,72 @@ +package aoc.y2018 + +import aoc.Day + +object Day03 extends Day { + + import fastparse._, SingleLineWhitespace._ + + case class Claim(id: Int, pos: (Int, Int), size: (Int, Int)) + + def numParser[_: P]: P[Int] = P(CharIn("0-9").rep(1).!).map(_.toInt) + def idParser[_: P]: P[Int] = P("#" ~ numParser) + def coordParser[_: P]: P[(Int, Int)] = P(numParser ~ "," ~ numParser) + def dimensParser[_: P]: P[(Int, Int)] = P(numParser ~ "x" ~ numParser) + def claimParser[_: P]: P[Claim] = P(idParser ~ "@" ~ coordParser ~ ":" ~ dimensParser).map { + case (id, coords, dimens) => Claim(id, coords, dimens) + } + def claimsParser[_: P]: P[List[Claim]] = P(claimParser.rep(1, "\n"./)).map(_.toList) + + def getClaims(input: String): List[Claim] = { + val Parsed.Success(claims, _) = parse(input, claimsParser(_)) + claims + } + + def insideRange(c: (Int, Int), p: (Int, Int), s: (Int, Int)): Boolean = { + (c, p, s) match { + case ((cx, cy), (px, py), (sw, sh)) => + cx >= px && + cx < px + sw && + cy >= py && + cy < py + sh + } + } + + def mapSection[A](l: List[List[A]], p: (Int, Int), s: (Int, Int), f: A => A): List[List[A]] = { + val coordinated = l.zipWithIndex.map { case (n, i) => n.zipWithIndex.map { case (e, y) => (e, y, i) } } + val mapped = coordinated.map(_.map { case (e, y, x) => if(insideRange((x, y), p, s)) f(e) else e }) + mapped + } + + def maxSize(c: List[Claim]): (Int, Int) = { + (c.map { + case Claim(_, (x, _), (w, _)) => x + w + }.max, c.map { + case Claim(_, (_, y), (_, h)) => y + h + }.max) + } + + override def part1(input: String): String = { + val claims = getClaims(input) + val (highestW, highestH) = maxSize(claims) + val starting: List[List[Int]] = List.fill(highestW)(List.fill(highestH)(0)) + val finished = claims.foldLeft(starting)((acc, cc) => { + mapSection(acc, cc.pos, cc.size, (i: Int) => i + 1) + }) + finished.flatten.count(_ > 1).toString + } + + override def part2(input: String): String = { + val claims = getClaims(input) + val (highestW, highestH) = maxSize(claims) + val starting: List[List[List[Int]]] = List.fill(highestW)(List.fill(highestH)(List())) + val finished = claims.foldLeft(starting)((acc, cc) => { + mapSection(acc, cc.pos, cc.size, (e: List[Int]) => cc.id :: e) + }) + val all = finished.flatten + val oneInhabitant = all.filter(_.size == 1).map(_.head).toSet + val solitary = oneInhabitant.filter(i => all.filter(_.contains(i)).forall(_.size == 1)) + solitary.head.toString + } + +} diff --git a/aoc/src/main/scala/aoc/y2018/package.scala b/aoc/src/main/scala/aoc/y2018/package.scala index f6136fe..a02dc3d 100644 --- a/aoc/src/main/scala/aoc/y2018/package.scala +++ b/aoc/src/main/scala/aoc/y2018/package.scala @@ -4,7 +4,8 @@ package object y2018 extends Year { override def days: Map[String, Day] = Map( "1" -> Day01, - "2" -> Day02 + "2" -> Day02, + "3" -> Day03, ) }