Created
December 21, 2016 08:23
-
-
Save pakaufmann/8c532e007b048ffa44b28724522387eb 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 Day21 extends Challenge { | |
override def runFirst(): Unit = { | |
val instructions = parseInstructions(loadFile("day21.txt").getLines().toSeq).toList | |
val scrambled = instructions.foldLeft("abcdefgh") { (pw, instruction) => | |
instruction match { | |
case SwapPosition(from, to) => | |
pw.updated(to, pw(from)).updated(from, pw(to)) | |
case SwapLetter(char1, char2) => | |
pw.replace(char1, '_').replace(char2, char1).replace('_', char2) | |
case RotateBased(char) => | |
val index = pw.indexOf(char) | |
rotate(pw, if(index >= 4) index + 2 else index + 1) | |
case Rotate(steps, false) => | |
rotate(pw, steps) | |
case Rotate(steps, true) => | |
rotate(pw.reverse, steps).reverse | |
case Reverse(from, to) => | |
val toReverse = pw.slice(from, to + 1) | |
pw.replace(toReverse, toReverse.reverse) | |
case Move(from, to) => | |
val toMove = pw(from) | |
val (part1, part2) = pw.replace(toMove.toString, "").splitAt(to) | |
part1 + toMove + part2 | |
} | |
} | |
println(scrambled) | |
} | |
private def rotate(pw: String, steps: Int) = { | |
val by = steps % pw.length | |
val (part1, part2) = pw.splitAt(pw.length - by) | |
part2 + part1 | |
} | |
override def runSecond(): Unit = { | |
val instructions = parseInstructions(loadFile("day21.txt").getLines().toSeq).toList | |
val unscrambled = instructions.reverse.foldLeft("fbgdceah") { (pw, instruction) => | |
instruction match { | |
case SwapPosition(to, from) => | |
pw.updated(to, pw(from)).updated(from, pw(to)) | |
case SwapLetter(char1, char2) => | |
pw.replace(char1, '_').replace(char2, char1).replace('_', char2) | |
case RotateBased(char) => | |
val index = pw.indexOf(char) | |
val rotatedBy = Iterator.from(0).find { step => | |
val indexAtStep = if(index - step < 0) pw.length + (index - step) else index - step | |
val rotatedBy = if(indexAtStep >= 4) indexAtStep + 2 else indexAtStep + 1 | |
rotatedBy % pw.length == step | |
}.get | |
rotate(pw.reverse, rotatedBy).reverse | |
case Rotate(steps, false) => | |
rotate(pw.reverse, steps).reverse | |
case Rotate(steps, true) => | |
rotate(pw, steps) | |
case Reverse(from, to) => | |
val toReverse = pw.slice(from, to + 1) | |
pw.replace(toReverse, toReverse.reverse) | |
case Move(to, from) => | |
val toMove = pw(from) | |
val (part1, part2) = pw.replace(toMove.toString, "").splitAt(to) | |
part1 + toMove + part2 | |
} | |
} | |
println(unscrambled) | |
} | |
private def parseInstructions(lines: Seq[String]) = { | |
lines | |
.map(_.split(" ") match { | |
case Array("swap", "position", from, _, _, to) => | |
SwapPosition(from.toInt, to.toInt) | |
case Array("swap", "letter", char1, _, _, char2) => | |
SwapLetter(char1(0), char2(0)) | |
case Array("rotate", "based", _, _, _, _, char) => | |
RotateBased(char(0)) | |
case Array("rotate", dir, steps, _) => | |
Rotate(steps.toInt, dir == "left") | |
case Array("reverse", _, from, _, to) => | |
Reverse(from.toInt, to.toInt) | |
case Array("move", _, from, _, _, to) => | |
Move(from.toInt, to.toInt) | |
}) | |
} | |
sealed trait Instruction | |
case class SwapPosition(from: Int, to: Int) extends Instruction | |
case class SwapLetter(char1: Char, char2: Char) extends Instruction | |
case class Rotate(steps: Int, left: Boolean) extends Instruction | |
case class RotateBased(char: Char) extends Instruction | |
case class Reverse(from: Int, to: Int) extends Instruction | |
case class Move(from: Int, to: Int) extends Instruction | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment