Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active January 14, 2022 12:37
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sungkmi/b8798b695ddd8aadef706b062e2aa718 to your computer and use it in GitHub Desktop.
package lascala.aoc2021.day1_10.day5
opaque type Diagram = Map[(Int, Int), Int]
extension (d: Diagram)
def countValue(cond: Int => Boolean): Int = d.values.count(cond)
object Diagram:
def fromPoints(points: Seq[(Int, Int)]): Diagram =
points.foldLeft(Map.empty[(Int, Int), Int].withDefaultValue(0)) {
case (d, (x, y)) => d.updated((x, y), d((x, y)) + 1)
}
def parse(s: String): Diagram =
val points: Seq[(Int, Int)] = s.split("\n").map(Line.parse).flatMap{
case Some(Line.Diagonal(_, _, _, _)) => Seq.empty
case Some(line) => line.toPoints
case None => Seq.empty
}
fromPoints(points)
end parse
def parseWithDiagonal(s: String): Diagram =
val points: Seq[(Int, Int)] = s.split("\n").map(Line.parse).flatMap{
case Some(line) => line.toPoints
case None => Seq.empty
}
fromPoints(points)
end parseWithDiagonal
end Diagram
sealed trait Line
extension (l: Line)
def toPoints: Seq[(Int, Int)] = l match
case Line.Horizontal(x0, x1, y) =>
(x0 to x1).map(x => (x, y))
case Line.Vertical(y0, y1, x) =>
(y0 to y1).map(y => (x, y))
case Line.Diagonal(x0, y0, x1, y1) =>
def points(i: Int, f: Int): List[Int] =
(if i <= f then i to f else i to f by -1).toList
points(x0, x1) `zip` points(y0, y1)
end toPoints
end extension
object Line:
final case class Horizontal(x0: Int, x1: Int, y: Int) extends Line
final case class Vertical(y0: Int, y1: Int, x: Int) extends Line
final case class Diagonal(x0: Int, y0: Int, x1: Int, y1: Int) extends Line
def parse(s: String): Option[Line] =
val Array(x0, y0, x1, y1) = for
pointString <- s.split(" -> ")
point <- pointString.split(",").map(_.toInt)
yield point
if x0 == x1 then Some(Vertical(y0 min y1, y0 max y1, x0))
else if y0 == y1 then Some(Horizontal(x0 min x1, x0 max x1, y0))
else if (x1 - x0).abs == (y1 - y0).abs then Some(Diagonal(x0, y0, x1, y1))
else None
end parse
end Line
def solve1(s: String): BigInt =
val diagram = Diagram.parse(s)
diagram.countValue(_ >= 2)
end solve1
def solve2(s: String): BigInt =
val diagram = Diagram.parseWithDiagonal(s)
diagram.countValue(_ >= 2)
end solve2
@main def part1: Unit =
val ans = solve1(input)
println(ans)
@main def part2: Unit =
val ans = solve2(input)
println(ans)
//val input = """556,286 -> 341,71
package lascala.aoc2021.day1_10.day5
import minitest.SimpleTestSuite
import hedgehog.minitest.HedgehogSupport
import hedgehog.*
object Day5Test extends SimpleTestSuite with HedgehogSupport:
val testInput = """0,9 -> 5,9
8,0 -> 0,8
9,4 -> 3,4
2,2 -> 2,1
7,0 -> 7,4
6,4 -> 2,0
0,9 -> 2,9
3,4 -> 1,4
0,0 -> 8,8
5,5 -> 8,2"""
example("day5 - solve1") {
solve1(testInput) ==== 5
}
example("day5 - solve2") {
solve2(testInput) ==== 12
}
end Day5Test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment