Commit 15c85b83 authored by Alexander Gehrke's avatar Alexander Gehrke
Browse files

[day9] solution

parent 42e78d51
package aoc2020
import lib.RingBuffer
def day9(input: List[Long]): String =
(
for {
invalid <- findInvalidInInput(input, 25)
range <- findSumRange(input, invalid)
} yield (invalid, range)
).fold("No invalid number"){
case (invalid, (min, max)) =>
s"first invalid: $invalid\nMin/max of sum range: $min / $max\nWeakness (min + max): ${min + max}"
}
def findInvalidInInput(input: List[Long], preambleSize: Int) =
val (preamble, message) = input.splitAt(preambleSize)
findInvalid(RingBuffer(preamble.toVector, preambleSize), message)
def findInvalid(preamble: RingBuffer[Long], message: List[Long]): Option[Long] =
message match {
case h :: t =>
if (preamble.combinations(2).exists(_.sum == h)) findInvalid(preamble :+ h, t)
else Some(h)
case Nil => None
}
def findSumRange(input: List[Long], invalid: Long) =
import math.{min, max}
@annotation.tailrec
def checkHead(remaining: List[Long], sum: Long, minS: Long, maxS: Long): Option[(Long, Long)] =
remaining match {
case Nil => None
case h :: t =>
val nsum = sum + h
if (nsum > invalid) None
else if (nsum == invalid) Some((min(minS, h), max(maxS, h)))
else checkHead(t, nsum, min(minS, h), max(maxS, h))
}
input.tails.collectFirst((checkHead(_, 0L, Long.MaxValue, Long.MinValue)).unlift)
......@@ -10,5 +10,7 @@ package aoc2020
case 6 => input()(day6)
case 7 => input()(day7)
case 8 => input()(day8)
case 9 => input(_.toLong)(day9)
case _ => "No such day implemented"
}
println(out)
package aoc2020.lib
import scala.collection.immutable._
import scala.annotation.alpha
/* Wrap a vector to create a limited size ring buffer */
case class RingBuffer[A](underlying: Vector[A], maxSize: Int) {
/* pass through any methods to the underlying vector, except appending and
* prepending single elements */
export underlying.{ :+ => _, appended => _, +: => _, prepended => _, _ }
inline def full: Boolean = underlying.size == maxSize
//TODO alpha is renamed to targetName in M2 or M3
@alpha("appended") def :+[B >: A](b: B): RingBuffer[B] =
val appendedVec = (if full then underlying.tail else underlying) :+ b
new RingBuffer(appendedVec, maxSize)
@alpha("prepended") def +:[B >: A](b: B): RingBuffer[B] =
val prependedVec = b +: (if full then underlying.init else underlying)
new RingBuffer(prependedVec, maxSize)
}
object RingBuffer {
def apply[A](underlying: Vector[A], maxSize: Int): RingBuffer[A] =
new RingBuffer(
if underlying.size > maxSize then underlying.view.slice(0, maxSize).toVector
else underlying,
maxSize
)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment