Skip to content

Commit 375c76b

Browse files
committed
Year 2019 Day 10
1 parent b5a3fd2 commit 375c76b

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,4 @@ Entries for the annual [Advent of Code](https://adventofcode.com/) challenge, wr
7777
| 7 | [Amplification Circuit](https://adventofcode.com/2019/day/7) | [Source](src/main/scala/AdventOfCode2019/Day07.scala) |
7878
| 8 | [Space Image Format](https://adventofcode.com/2019/day/8) | [Source](src/main/scala/AdventOfCode2019/Day08.scala) |
7979
| 9 | [Sensor Boost](https://adventofcode.com/2019/day/9) | [Source](src/main/scala/AdventOfCode2019/Day09.scala) |
80+
| 10 | [Monitoring Station](https://adventofcode.com/2019/day/10) | [Source](src/main/scala/AdventOfCode2019/Day10.scala) |
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
....#.....#.#...##..........#.......#......
2+
.....#...####..##...#......#.........#.....
3+
.#.#...#..........#.....#.##.......#...#..#
4+
.#..#...........#..#..#.#.......####.....#.
5+
##..#.................#...#..........##.##.
6+
#..##.#...#.....##.#..#...#..#..#....#....#
7+
##...#.............#.#..........#...#.....#
8+
#.#..##.#.#..#.#...#.....#.#.............#.
9+
...#..##....#........#.....................
10+
##....###..#.#.......#...#..........#..#..#
11+
....#.#....##...###......#......#...#......
12+
.........#.#.....#..#........#..#..##..#...
13+
....##...#..##...#.....##.#..#....#........
14+
............#....######......##......#...#.
15+
#...........##...#.#......#....#....#......
16+
......#.....#.#....#...##.###.....#...#.#..
17+
..#.....##..........#..........#...........
18+
..#.#..#......#......#.....#...##.......##.
19+
.#..#....##......#.............#...........
20+
..##.#.....#.........#....###.........#..#.
21+
...#....#...#.#.......#...#.#.....#........
22+
...####........#...#....#....#........##..#
23+
.#...........#.................#...#...#..#
24+
#................#......#..#...........#..#
25+
..#.#.......#...........#.#......#.........
26+
....#............#.............#.####.#.#..
27+
.....##....#..#...........###........#...#.
28+
.#.....#...#.#...#..#..........#..#.#......
29+
.#.##...#........#..#...##...#...#...#.#.#.
30+
#.......#...#...###..#....#..#...#.........
31+
.....#...##...#.###.#...##..........##.###.
32+
..#.....#.##..#.....#..#.....#....#....#..#
33+
.....#.....#..............####.#.........#.
34+
..#..#.#..#.....#..........#..#....#....#..
35+
#.....#.#......##.....#...#...#.......#.#..
36+
..##.##...........#..........#.............
37+
...#..##....#...##..##......#........#....#
38+
.....#..........##.#.##..#....##..#........
39+
.#...#...#......#..#.##.....#...#.....##...
40+
...##.#....#...........####.#....#.#....#..
41+
...#....#.#..#.........#.......#..#...##...
42+
...##..............#......#................
43+
........................#....##..#........#
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package AdventOfCode2019
2+
3+
object Day10:
4+
case class Point(x: Int, y: Int):
5+
def to(other: Point): Line = Line(y - other.y, other.x - x, x * other.y - other.x * y)
6+
7+
case class Line(a: Int, b: Int, c: Int):
8+
def distance(p: Point): Int = a * p.x + b * p.y + c
9+
def normal(p: Point): Line = Line(b, -a, a * p.y - b * p.x)
10+
11+
def parse(input: Seq[String]): Set[Point] =
12+
val height = input.size
13+
val width = input.head.size
14+
val points = for y <- 0 until height; x <- 0 until width if input(y)(x) == '#' yield Point(x, y)
15+
points.toSet
16+
17+
def countVisible(points: Set[Point]): Set[(Point, Int)] =
18+
points.map { origin =>
19+
val visible = groupByLine(points, origin).values.map { points =>
20+
val distances = points.values
21+
distances.count(_ < 0).min(1) + distances.count(_ > 0).min(1)
22+
}
23+
origin -> visible.sum
24+
}
25+
26+
def groupByLine(points: Set[Point], origin: Point): Map[Line, Map[Point, Int]] =
27+
(points - origin).foldLeft(Map.empty[Line, List[Point]]) { (lines, point) =>
28+
lines.keys.find(_.distance(point) == 0) match
29+
case Some(line) => lines.updated(line, point :: lines(line))
30+
case None => lines.updated(origin.to(point), List(point))
31+
}
32+
.map { (line, points) =>
33+
val normal = line.normal(origin)
34+
line -> points.zip(points.map(normal.distance)).toMap
35+
}
36+
37+
def orderedClockwise(quadrant: Int, origin: Point, points: Set[Point]): Map[(Int, Int, Int), Point] =
38+
groupByLine(points, origin).flatMap { case (line, distances) =>
39+
val toLeft = points.count(point => line.distance(point) < 0)
40+
val inOrder = distances.values.toSeq.sorted.zipWithIndex.toMap
41+
distances.map((point, distance) => (inOrder(distance), quadrant, toLeft) -> point)
42+
}
43+
44+
def part1(input: Seq[String]): Int =
45+
val points = parse(input)
46+
val (origin, visible) = countVisible(points).maxBy(_._2)
47+
visible
48+
49+
def part2(input: Seq[String]): Int =
50+
val points = parse(input)
51+
val (origin, visible) = countVisible(points).maxBy(_._2)
52+
53+
val topRight = orderedClockwise(0, origin, points.filter(p => p.x >= origin.x && p.y < origin.y))
54+
val bottomRight = orderedClockwise(1, origin, points.filter(p => p.x > origin.x && p.y >= origin.y))
55+
val bottomLeft = orderedClockwise(2, origin, points.filter(p => p.x <= origin.x && p.y > origin.y))
56+
val topLeft = orderedClockwise(3, origin, points.filter(p => p.x < origin.x && p.y <= origin.y))
57+
58+
val all = topRight ++ bottomRight ++ bottomLeft ++ topLeft
59+
val key = all.keys.toSeq.sorted.apply(199)
60+
val result = all(key)
61+
62+
100 * result.x + result.y
63+
end part2
64+
65+
def main(args: Array[String]): Unit =
66+
val data = io.Source.fromResource("AdventOfCode2019/Day10.txt").getLines().toSeq
67+
println(part1(data))
68+
println(part2(data))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package AdventOfCode2019
2+
3+
import org.scalatest.funsuite.AnyFunSuite
4+
5+
class Day10Suite extends AnyFunSuite:
6+
val sample = Seq(
7+
".#..##.###...#######",
8+
"##.############..##.",
9+
".#.######.########.#",
10+
".###.#######.####.#.",
11+
"#####.##.#.##.###.##",
12+
"..#####..#.#########",
13+
"####################",
14+
"#.####....###.#.#.##",
15+
"##.#################",
16+
"#####.##.###..####..",
17+
"..######..##.#######",
18+
"####.##.####...##..#",
19+
".#####..#.######.###",
20+
"##...#.##########...",
21+
"#.##########.#######",
22+
".####.#.###.###.#.##",
23+
"....##.##.###..#####",
24+
".#.#.###########.###",
25+
"#.#.#.#####.####.###",
26+
"###.##.####.##.#..##")
27+
28+
test("Part 1 should handle sample input correctly") {
29+
assert(Day10.part1(sample) == 210)
30+
}
31+
32+
test("Part 2 should handle sample input correctly") {
33+
assert(Day10.part2(sample) == 802)
34+
}

0 commit comments

Comments
 (0)