Skip to content

Instantly share code, notes, and snippets.

@pakaufmann
Created December 9, 2016 09:11
Show Gist options
  • Save pakaufmann/7fd4ef83a4b11121d7bf58619d13c91f to your computer and use it in GitHub Desktop.
Save pakaufmann/7fd4ef83a4b11121d7bf58619d13c91f to your computer and use it in GitHub Desktop.
object Day9 extends Challenge {
override def runFirst(): Unit = {
val compressed = loadFile("day9.txt").mkString
println(decompress(compressed))
}
override def runSecond(): Unit = {
val compressed = loadFile("day9.txt").mkString
println(decompress(compressed, v2 = true))
}
def decompress(compressed: String, v2: Boolean = false): Long = {
val decompressed = (compressed + " ").foldLeft(Decompressed.empty) {
case (d@Decompressed(_, None), '(') =>
d.newMarker
case (d@Decompressed(_, Some(m@Marker(_, Some(_), None))), ')') =>
d.setMarker(m.newSeq)
case (d@Decompressed(output, marker), c) =>
marker match {
case None =>
d.copy(output = output + 1)
case Some(m@Marker(_, None, _)) if c.isDigit =>
d.setMarker(m.addRemaining(c.asDigit))
case Some(m@Marker(_, None, _)) if c == 'x' =>
d.setMarker(m.addRepeat(0))
case Some(m@Marker(_, Some(_), None)) if c.isDigit =>
d.setMarker(m.addRepeat(c.asDigit))
case Some(m@Marker(remaining, Some(_), Some(s))) if remaining > 0 =>
d.setMarker(m.copy(remaining - 1, sequence = Some(s.append(c))))
case Some(Marker(_, Some(repeat), Some(s))) =>
val v2Repeated = if (v2) decompress(s.toString, v2) * repeat else s.toString.length * repeat
val (newOutput, marker) = c match {
case '(' =>
(output + v2Repeated, Some(Marker.initial))
case _ =>
(output + v2Repeated + 1, None)
}
d.copy(newOutput, marker)
}
}
decompressed.output - 1
}
}
case class Marker(remaining: Int, repeat: Option[Int], sequence: Option[StringBuilder]) {
def addRepeat(i: Int): Marker = repeat match {
case Some(e) => this.copy(repeat = Some(e * 10 + i))
case None => this.copy(repeat = Some(i))
}
def newSeq: Marker = this.copy(sequence = Some(new StringBuilder("")))
def addRemaining(r: Int): Marker = this.copy(remaining = remaining * 10 + r)
}
object Marker {
def initial = Marker(0, None, None)
}
case class Decompressed(output: Long, marker: Option[Marker]) {
def newMarker: Decompressed = this.copy(marker = Some(Marker.initial))
def setMarker(marker: Marker): Decompressed = this.copy(marker = Some(marker))
}
object Decompressed {
def empty = Decompressed(0, None)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment