Created
December 9, 2016 09:11
-
-
Save pakaufmann/7fd4ef83a4b11121d7bf58619d13c91f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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