Skip to content

Instantly share code, notes, and snippets.

@pakaufmann
Created December 21, 2016 08:23
Show Gist options
  • Save pakaufmann/8c532e007b048ffa44b28724522387eb to your computer and use it in GitHub Desktop.
Save pakaufmann/8c532e007b048ffa44b28724522387eb to your computer and use it in GitHub Desktop.
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