Complete much more of y2017
This commit is contained in:
parent
8c9f95fe2c
commit
ea871d612e
5 changed files with 148 additions and 8 deletions
|
@ -22,13 +22,7 @@ object Day10 extends Day {
|
|||
last
|
||||
}
|
||||
|
||||
override def part1(input: String): String = {
|
||||
val shifts = input.split(',').map(_.toInt).toList
|
||||
val last = runShifts(shifts)
|
||||
(last.head * last.tail.head).toString
|
||||
}
|
||||
|
||||
override def part2(input: String): String = {
|
||||
def knotHash(input: String): String = {
|
||||
val magic = List(17, 31, 73, 47, 23)
|
||||
val codes = input.map(_.toInt) ++ magic
|
||||
val shifts = List.fill(64)(codes).flatten
|
||||
|
@ -39,4 +33,14 @@ object Day10 extends Day {
|
|||
hexed.mkString
|
||||
}
|
||||
|
||||
override def part1(input: String): String = {
|
||||
val shifts = input.split(',').map(_.toInt).toList
|
||||
val last = runShifts(shifts)
|
||||
(last.head * last.tail.head).toString
|
||||
}
|
||||
|
||||
override def part2(input: String): String = {
|
||||
knotHash(input)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
34
aoc/src/main/scala/aoc/y2017/Day13.scala
Normal file
34
aoc/src/main/scala/aoc/y2017/Day13.scala
Normal file
|
@ -0,0 +1,34 @@
|
|||
package aoc.y2017
|
||||
|
||||
import aoc.Day
|
||||
|
||||
object Day13 extends Day {
|
||||
|
||||
import fastparse._, SingleLineWhitespace._
|
||||
|
||||
def parseNumber[_: P]: P[Int] = P(CharIn("0-9").rep(1).!).map(_.toInt)
|
||||
def parseScanner[_: P]: P[(Int, Int)] = P(parseNumber ~ ": " ~ parseNumber)
|
||||
def parseScanners[_: P]: P[Map[Int, Int]] = P(parseScanner.rep(1, "\n")).map(Map(_: _*))
|
||||
|
||||
def scannerAtStart(time: Int, range: Int): Boolean = (time % (2 * (range - 1))) == 0
|
||||
|
||||
def scanners(input: String): Map[Int, Int] = parse(input, parseScanners(_)).get.value
|
||||
def severity(scanners: Map[Int, Int], delay: Int): Int = scanners.collect {
|
||||
case (index, range) if scannerAtStart(index + delay, range) => index * range
|
||||
}.sum
|
||||
|
||||
override def part1(input: String): String = {
|
||||
severity(scanners(input), delay = 0).toString
|
||||
}
|
||||
|
||||
override def part2(input: String): String = {
|
||||
val parsedScanners = scanners(input)
|
||||
lazy val packetDelays: LazyList[Int] = LazyList.from(0)
|
||||
lazy val tripSeverities = packetDelays.map(delay => (delay, severity(parsedScanners, delay)))
|
||||
val avoidanceDelay = tripSeverities.indexWhere {
|
||||
case (delay, severity) => severity == 0 && delay % (2 * (parsedScanners(0) - 1)) != 0
|
||||
}
|
||||
avoidanceDelay.toString
|
||||
}
|
||||
|
||||
}
|
51
aoc/src/main/scala/aoc/y2017/Day14.scala
Normal file
51
aoc/src/main/scala/aoc/y2017/Day14.scala
Normal file
|
@ -0,0 +1,51 @@
|
|||
package aoc.y2017
|
||||
|
||||
import aoc.Day
|
||||
|
||||
object Day14 extends Day {
|
||||
|
||||
def getRows(input: String): Seq[BigInt] = {
|
||||
val keyStrings = (0 to 127).map(row => s"$input-$row")
|
||||
val knotHashes = keyStrings.map(Day10.knotHash)
|
||||
knotHashes.map(BigInt(_, 16))
|
||||
}
|
||||
|
||||
override def part1(input: String): String = {
|
||||
val bigInts = getRows(input)
|
||||
val bits = bigInts.map(_.bitCount).sum
|
||||
bits.toString
|
||||
}
|
||||
|
||||
override def part2(input: String): String = {
|
||||
val bigInts = getRows(input)
|
||||
val disk = bigInts.toVector.map { bigInt =>
|
||||
(0 to bigInt.bitLength).toVector.map(bigInt.testBit).padTo(128, false).take(128)
|
||||
}
|
||||
type GroupedDisk = Vector[Vector[Option[Int]]]
|
||||
val numberBlocks: GroupedDisk = disk.zipWithIndex.map {
|
||||
case (row, y) => row.zipWithIndex.map {
|
||||
case (true, x) => Some(y * 128 + x)
|
||||
case (false, _) => None
|
||||
}
|
||||
}
|
||||
def simplifyGroups(disk: GroupedDisk): GroupedDisk = {
|
||||
disk.zipWithIndex.map {
|
||||
case (row, y) => row.zipWithIndex.map {
|
||||
case (None, _) => None
|
||||
case (Some(g), x) =>
|
||||
val left = if(x > 0) disk(y)(x - 1) else None
|
||||
val right = if(x < 127) disk(y)(x + 1) else None
|
||||
val up = if(y > 0) disk(y - 1)(x) else None
|
||||
val down = if(y < 127) disk(y + 1)(x) else None
|
||||
Vector(Some(g), left, right, up, down).collect { case Some(v) => v }.minOption
|
||||
}
|
||||
}
|
||||
}
|
||||
lazy val defrags: LazyList[GroupedDisk] = numberBlocks #:: defrags.map(simplifyGroups)
|
||||
val (simplest, _) = defrags.zipWithIndex.takeWhile {
|
||||
case (thisPass, index) => index < 1 || defrags(index - 1) != thisPass
|
||||
}.last
|
||||
simplest.flatten.collect { case Some(g) => g }.groupBy(identity).size.toString
|
||||
}
|
||||
|
||||
}
|
48
aoc/src/main/scala/aoc/y2017/Day15.scala
Normal file
48
aoc/src/main/scala/aoc/y2017/Day15.scala
Normal file
|
@ -0,0 +1,48 @@
|
|||
package aoc.y2017
|
||||
|
||||
import aoc.Day
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
object Day15 extends Day {
|
||||
|
||||
import fastparse._, NoWhitespace._
|
||||
|
||||
def parseNumber[_: P]: P[Int] = P(CharIn("0-9").rep(1).!).map(_.toInt)
|
||||
def parseGenerator[_: P](name: String): P[Int] = P("Generator " ~ name ~ " starts with " ~ parseNumber)
|
||||
def parseGenerators[_: P]: P[(Int, Int)] = P(parseGenerator("A") ~ "\n" ~ parseGenerator("B"))
|
||||
|
||||
@tailrec def step(number: Int, multiplier: Int, forceMultiple: Int = 1): Int = {
|
||||
val product = number.toLong * multiplier.toLong
|
||||
val remainder = (product % Int.MaxValue).toInt
|
||||
if(remainder % forceMultiple != 0) step(remainder, multiplier, forceMultiple)
|
||||
else remainder
|
||||
}
|
||||
|
||||
@tailrec def go(genANum: Int, genBNum: Int, genAMult: Int, genBMult: Int, forceMultipleA: Int = 1, forceMultipleB: Int = 1, left: Int = 40_000_000, sum: Int = 0): Int = {
|
||||
if(left < 0) sum
|
||||
else {
|
||||
val nextA = step(genANum, genAMult, forceMultipleA)
|
||||
val nextB = step(genBNum, genBMult, forceMultipleB)
|
||||
val nextLeft = left - 1
|
||||
val nextSum = if(((nextA ^ nextB) & ((1 << 16) - 1)) == 0) sum + 1 else sum
|
||||
go(nextA, nextB, genAMult, genBMult, forceMultipleA, forceMultipleB, nextLeft, nextSum)
|
||||
}
|
||||
}
|
||||
|
||||
def run(input: String, pairs: Int, forceMultiple: Boolean): Int = {
|
||||
val genAMult = 16807
|
||||
val genBMult = 48271
|
||||
val (genAStart, genBStart) = parse(input, parseGenerators(_)).get.value
|
||||
go(genAStart, genBStart, genAMult, genBMult, if(forceMultiple) 4 else 1, if(forceMultiple) 8 else 1, pairs)
|
||||
}
|
||||
|
||||
override def part1(input: String): String = {
|
||||
run(input, pairs = 40_000_000, forceMultiple = false).toString
|
||||
}
|
||||
|
||||
override def part2(input: String): String = {
|
||||
run(input, pairs = 5_000_000, forceMultiple = true).toString
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,10 @@ package object y2017 extends Year {
|
|||
"10" -> Day10,
|
||||
"11" -> Day11,
|
||||
"12" -> Day12,
|
||||
"25" -> Day25
|
||||
"13" -> Day13,
|
||||
"14" -> Day14,
|
||||
"15" -> Day15,
|
||||
"25" -> Day25,
|
||||
)
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue