Day6.scala (2843B)
1 import scala.annotation.tailrec 2 def day6_pt1(input: Iterator[String]): Int = 3 val lst = input.toList 4 val pos = lst.zipWithIndex.find((s, y) => s.contains("^")).map((s, y) => (s.indexOf('^'), y)).get 5 val grid = updated(lst, pos, '.') 6 val grid2 = do_follow(grid, pos, '^') 7 grid2.map(line => line.count(ch => ch == 'X')).sum 8 9 @tailrec() 10 def do_follow(grid: List[String], pos: (Int,Int), dir: Char): List[String] = 11 val grid2 = updated(grid, pos, 'X') 12 val pos2 = next_pos(pos, dir) 13 val (x2, y2) = pos2 14 if (oob(grid2, pos2)) { 15 return grid2 16 } 17 if (grid_at(grid2, pos2) == '#') { 18 val dir2 = next_dir(dir) 19 do_follow(grid2, pos, dir2) 20 } else { 21 do_follow(grid2, pos2, dir) 22 } 23 24 def day6_pt2(input: Iterator[String]): Int = 25 val lst = input.toList 26 val pos = lst.zipWithIndex.find((s, y) => s.contains("^")).map((s, y) => (s.indexOf('^'), y)).get 27 val grid = updated(lst, pos, '.') 28 val grid2 = do_follow(grid, pos, '^') 29 List.range(0, grid.size).flatMap(y => List.range(0, grid(0).size).map(x => (x, y))) 30 .filter(block => block != pos) // Can't add a block where the guard currenly is... 31 .filter(block => grid_at(grid2, block) == 'X') // only bother testing locations the guard actually visited; otherwise it's an ineffective block 32 .filter(block => { 33 val res = do_follow3(updated(grid, block, '#'), pos, '^', Set()) 34 println(s"Testing new block at $block: $res") 35 res 36 }) 37 .size 38 39 @tailrec() 40 def do_follow3(grid: List[String], pos: (Int,Int), dir: Char, hist: Set[((Int,Int), Char)]): Boolean = 41 if (hist.contains(pos, dir)) { 42 return true 43 } 44 val pos2 = next_pos(pos, dir) 45 if (oob(grid, pos2)) { 46 return false 47 } 48 49 if (grid_at(grid, pos2) == '#') { 50 do_follow3(grid, pos, next_dir(dir), hist + ((pos, dir))) 51 } else { 52 do_follow3(grid, pos2, dir, hist + ((pos, dir))) 53 } 54 55 // def print(grid: List[String]): Unit = 56 // grid.foreach(line => println(line)) 57 58 def grid_at(grid: List[String], pos: (Int, Int)): Char = 59 grid(pos(1)).charAt(pos(0)) 60 61 def updated(grid: List[String], pos: (Int,Int), replacement: Char): List[String] = 62 val (x, y) = pos 63 return grid.updated(y, grid(y).updated(x, replacement)) 64 65 def next_pos(pos: (Int,Int), dir: Char): (Int,Int) = 66 dir match 67 case '^' => (pos(0), pos(1)-1) 68 case '>' => (pos(0)+1, pos(1)) 69 case 'v' => (pos(0), pos(1)+1) 70 case '<' => (pos(0)-1, pos(1)) 71 72 def next_dir(dir: Char): Char = 73 dir match 74 case '^' => '>' 75 case '>' => 'v' 76 case 'v' => '<' 77 case '<' => '^' 78 79 def oob(grid: List[String], pos: (Int,Int)): Boolean = 80 val (x, y) = pos 81 x < 0 || y < 0 || x >= grid(0).size || y >= grid.size