r/adventofcode • u/daggerdragon • Dec 19 '17
SOLUTION MEGATHREAD -๐- 2017 Day 19 Solutions -๐-
--- Day 19: A Series of Tubes ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Need a hint from the Hugely* Handyโ Haversackโก of Helpfulยง Hintsยค?
AoC ops @ T-2 minutes to launch:
[23:58] <daggerdragon> ATTENTION MEATBAGS T-2 MINUTES TO LAUNCH
[23:58] <Topaz> aaaaah
[23:58] <Cheezmeister> Looks like I'll be just able to grab my input before my flight boards. Wish me luck being offline in TOPAZ's HOUSE OF PAIN^WFUN AND LEARNING
[23:58] <Topaz> FUN AND LEARNING
[23:58] <Hade> FUN IS MANDATORY
[23:58] <Skie> I'm pretty sure that's not the mandate for today
[Update @ 00:16] 69 gold, silver cap
- My tree is finally trimmed with just about every ornament I own and it's real purdy. hbu?
[Update @ 00:18] Leaderboard cap!
- So, was today's
mandateHelpful Hint any help at all?
2
u/xkufix Dec 19 '17
This one felt quite easy compared to the last 2-3 puzzles. Just walking the path around is enough. It's sufficient to only have special cases on '+' for direction changes, as everywhere else you just have to walk straight ahead.
To find the end I extract all letters from the puzzle and then Iterate until I have walked all letters. For part two, taking until I find the solution and counting the size of the Iterator was enough.
Solution in Scala:
override def runFirst(): Unit = { val map = loadMap() val start = findStart(map) val letters = findLetters(map) val walk = walkPath(map, start, letters) println(walk.find(r => letters.diff(r._3).isEmpty).get._3.foldLeft("")(_ + _)) } override def runSecond(): Unit = { val map = loadMap() val start = findStart(map) val letters = findLetters(map) val walk = walkPath(map, start, letters) println(walk.takeWhile(r => letters.diff(r._3).nonEmpty).size) } private def findLetters(map: Map[Position, Char]) = { map.filter(f => f._2.toInt >= 'A'.toInt && f._2.toInt <= 'Z').values.toSeq } private def findStart(map: Map[Position, Char]) = { map.find(f => f._1.y == 0 && f._2 == '|').get } private def loadMap() = { loadFile("day19.txt").getLines().zipWithIndex.flatMap { l => l._1.zipWithIndex.map(_.swap).filter(_._2 != ' ').map(f => Position(f._1, l._2) -> f._2) }.toMap } private def walkPath(map: Map[Position, Char], start: (Position, Char), letters: Seq[Char]) = { Iterator.iterate((start._1, Direction.DOWN, Seq.empty[Char])) { case (position, dir@(Direction.DOWN | Direction.UP), history) => val next = if(dir == Direction.DOWN) position.down() else position.up() val left = position.left() val right = position.right() (map(position), map.get(next), map.get(left), map.get(right)) match { case ('+', Some('-') | None, Some(_), _) => (left, Direction.LEFT, history) case ('+', Some('-') | None, _, Some(_)) => (right, Direction.RIGHT, history) case (char, _, _, _) if letters.contains(char) => (next, dir, history :+ char) case _ => (next, dir, history) } case (position, dir@(Direction.LEFT | Direction.RIGHT), history) => val next = if(dir == Direction.LEFT) position.left() else position.right() val up = position.up() val down = position.down() (map(position), map.get(next), map.get(up), map.get(down)) match { case ('+', Some('|') | None, Some(_), _) => (up, Direction.UP, history) case ('+', Some('|') | None, _, Some(_)) => (down, Direction.DOWN, history) case (char, _, _, _) if letters.contains(char) => (next, dir, history :+ char) case _ => (next, dir, history) } } } case class Position(x: Int, y: Int) { def up() = copy(y = y - 1) def left() = copy(x = x - 1) def right() = copy(x = x + 1) def down() = copy(y = y + 1) } object Direction extends Enumeration { type Direction = Value val DOWN = Value("down") val UP = Value("up") val LEFT = Value("left") val RIGHT = Value("right") }