Complete much more of y2017

This commit is contained in:
Aly 2019-12-03 23:24:41 -08:00
parent 8c9f95fe2c
commit ea871d612e
5 changed files with 148 additions and 8 deletions

View file

@ -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)
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View file

@ -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,
)
}