...
 
Commits (3)
......@@ -3,5 +3,22 @@ package is.kow.adventofcode._2019
object Main extends App {
val p3 = new Puzzle3
println("Failed Attempt 1:")
val p3Start = System.currentTimeMillis()
println(s"DISTANCE: ${p3.distance("input.txt")}")
println(s"Cheapest path: ${p3.cheapestRoute("input.txt")}")
val p3End = System.currentTimeMillis()
val p32 = new Puzzle3Try2
val p32Start = System.currentTimeMillis()
val distance = Puzzle3Loader.process("input.txt", p32.distanceFromCenter)
val cheapest = Puzzle3Loader.process("input.txt", p32.shortestPath)
val p32End = System.currentTimeMillis()
println("Attempt 2:")
println(s"Distance: $distance -- Cheapest: $cheapest")
println(s"Original: ${(p3End - p3Start) / 1000}")
println(s"new: ${(p32End - p32Start) / 1000}")
}
......@@ -17,12 +17,8 @@ class Puzzle3 {
val wire1Path = wirePath(wire1String.split(",").toList).reverse
println()
val wire2Path = wirePath(wire2String.split(",").toList).reverse
println("WIRE 1: " + wire1Path)
println("WIRE 2: " + wire2Path)
//Find all the intersections
val points: List[Point] = wire1Path.iterator.flatMap { wire1 =>
//See if it intersects with any wire, and get that point
......@@ -34,9 +30,8 @@ class Puzzle3 {
//Don't count 0,0
val intersections = points.drop(1)
println("Intersecting points: " + intersections)
val distances = intersections.map(manhattanDistance(Point(0, 0), _));
val distances = intersections.map(manhattanDistance(Point(0, 0), _))
val smallest = distances.foldLeft(distances.head) { (acc, v) =>
if (v < acc) {
v
......@@ -51,6 +46,55 @@ class Puzzle3 {
}
}
def cheapestRoute(resource: String): Int = {
//load from resource
val source = Source.fromResource(resource)
try {
//Two lines
val lines = source.getLines().toList
val wire1String = lines.head
val wire2String = lines.tail.head
val wire1Path = wirePath(wire1String.split(",").toList).reverse
val wire2Path = wirePath(wire2String.split(",").toList).reverse
//Find all the intersections
val points: List[Point] = wire1Path.iterator.flatMap { wire1 =>
//See if it intersects with any wire, and get that point
wire2Path.map { wire2 =>
wire1.intersects2(wire2)
}.filter(_.isDefined)
.map(_.get)
}.toList
//Don't count 0,0
val intersections = points.drop(1)
val distances = intersections.map { point =>
pointPath(wire1Path, point) + pointPath(wire2Path, point)
}
val smallest = distances.foldLeft(distances.head) { (acc, v) =>
if (v < acc) {
v
} else {
acc
}
}
smallest
}
finally {
source.close()
}
}
private def pointPath(wire: List[Wire], dest: Point): Int = {
//Get all points
val path = wire.flatMap(_.points).distinct.map(Point(_)).takeWhile(_ != dest)
path.length
}
private def manhattanDistance(p: Point, q: Point): Int = {
Math.abs(p.x - q.x) + Math.abs(p.y - q.y)
}
......@@ -75,7 +119,6 @@ class Puzzle3 {
case right(dist) =>
Wire(startPoint, startPoint.copy(x = startPoint.x + dist.toInt))
}
println(s"${ops.head}: ${wire}")
//Got a wire, accumulate it, and get point
mapPath(wire :: acc, wire.end, ops.tail)
}
......
package is.kow.adventofcode._2019
import scala.io.Source
object Puzzle3Loader {
def process(resource: String, operation: (String, String) => Int): Int = {
val source = Source.fromResource(resource)
try {
val lines = source.getLines().toList
val wire1 = lines.head
val wire2 = lines.tail.head
operation(wire1, wire2)
} finally {
source.close()
}
}
}
package is.kow.adventofcode._2019
class Puzzle3Try2 {
def distanceFromCenter(wire1: String, wire2: String): Int = {
val wire1Points = wireStringToPoints(wire1)
val wire2Points = wireStringToPoints(wire2)
val intersections = wire1Points.intersect(wire2Points)
intersections.foldLeft(Int.MaxValue) { (acc, point) =>
val dist = manhattanDistance(Point(0, 0), point)
if (dist < acc) {
dist
} else {
acc
}
}
}
private def manhattanDistance(p: Point, q: Point): Int = {
Math.abs(p.x - q.x) + Math.abs(p.y - q.y)
}
def shortestPath(wire1: String, wire2: String): Int = {
val wire1Points = wireStringToPoints(wire1)
val wire2Points = wireStringToPoints(wire2)
val intersections = wire1Points.intersect(wire2Points)
intersections.foldLeft(Int.MaxValue) { (acc, point) =>
val dist = wire1Points.indexOf(point) + wire2Points.indexOf(point) + 2
if (dist < acc) dist else acc
}
}
private def wireStringToPoints(wire: String): List[Point] = {
val up = raw"U([0-9]+)".r
val down = raw"D([0-9]+)".r
val left = raw"L([0-9]+)".r
val right = raw"R([0-9]+)".r
wire.split(",").foldLeft(List.empty[Point]) { (acc, op) =>
val lastPoint = if (acc.isEmpty) {
Point(0, 0)
} else {
acc.last
}
val newLine = op match {
case up(dist) => (1 to dist.toInt).map(y => lastPoint.copy(y = lastPoint.y + y))
case down(dist) => (1 to dist.toInt).map(y => lastPoint.copy(y = lastPoint.y - y))
case right(dist) => (1 to dist.toInt).map(x => lastPoint.copy(x = lastPoint.x + x))
case left(dist) => (1 to dist.toInt).map(x => lastPoint.copy(x = lastPoint.x - x))
}
acc ++ newLine
}
}
}
......@@ -22,17 +22,29 @@ case class Wire(start: Point, end: Point) {
end.x to start.x
}
range.map(x =>
val path = range.map(x =>
(x, start.y)
).toList
)
val items = if (start.x < end.x) {
path
} else {
path.reverse
}
items.toList
} else {
val range = if (start.y < end.y) {
start.y to end.y
} else {
end.y to start.y
}
range.map(y =>
(start.x, y)).toList
val pre = range.map(y =>
(start.x, y))
val finished = if (start.y < end.y) {
pre
} else {
pre.reverse
}
finished.toList
}
}
......
......@@ -10,6 +10,7 @@ case class Wires(wire1: List[String], wire2: List[String], distance: Int)
class Puzzle3Spec extends AnyFunSpec {
def p3 = new Puzzle3
def p32 = new Puzzle3Try2
describe("Day 3 Part 1") {
List(
......@@ -22,6 +23,27 @@ class Puzzle3Spec extends AnyFunSpec {
assert(p3.distance(resource) == expected)
}
it(s"for input $resource expects $expected for version 2") {
assert(Puzzle3Loader.process(resource, p32.distanceFromCenter) == expected)
}
}
}
}
describe("Day 3 part 2") {
List(
("test1.txt", 30),
("test2.txt", 610),
("test3.txt", 410)
).foreach {
case (resource, expected) => {
it(s"for input ${resource}, expect $expected path") {
assert(p3.cheapestRoute(resource) == expected)
}
it(s"for input $resource expects $expected for version 2") {
assert(Puzzle3Loader.process(resource, p32.shortestPath) == expected)
}
}
}
}
......