day 16 puzzle 2
This commit is contained in:
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @@ -5,11 +5,11 @@ This repo contains my attempt at this year's Advent of Code (2023) | ||||
| I will try and do some problems (probably not all of them) in Scala | ||||
|  | ||||
| ## Progress: | ||||
| #### Stars: 29 / 50 | ||||
| |        Mon         |        Tue        |        Wed         |        Thu         |        Fri         |        Sat        |        Sun         | | ||||
| |:------------------:|:-----------------:|:------------------:|:------------------:|:------------------:|:-----------------:|:------------------:| | ||||
| |                    |                   |                    |                    | 1<br>:star::star:  | 2<br>:star::star: | 3<br>:star::star:  | | ||||
| | 4<br>:star::star:  | 5<br>:star::star: | 6<br>:star::star:  | 7<br>:star::star:  | 8<br>:star::star:  | 9<br>:star::star: | 10<br>:star::star: | | ||||
| | 11<br>:star::star: |        12         | 13<br>:star::star: | 14<br>:star::star: | 15<br>:star::star: |   16<br>:star:    |         17         | | ||||
| |         18         |        19         |         20         |         21         |         22         |        23         |         24         | | ||||
| |         25         |                   |                    |                    |                    |                   |                    | | ||||
| #### Stars: 30 / 50 | ||||
| |        Mon         |        Tue        |        Wed         |        Thu         |        Fri         |        Sat         |        Sun         | | ||||
| |:------------------:|:-----------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:| | ||||
| |                    |                   |                    |                    | 1<br>:star::star:  | 2<br>:star::star:  | 3<br>:star::star:  | | ||||
| | 4<br>:star::star:  | 5<br>:star::star: | 6<br>:star::star:  | 7<br>:star::star:  | 8<br>:star::star:  | 9<br>:star::star:  | 10<br>:star::star: | | ||||
| | 11<br>:star::star: |        12         | 13<br>:star::star: | 14<br>:star::star: | 15<br>:star::star: | 16<br>:star::star: |         17         | | ||||
| |         18         |        19         |         20         |         21         |         22         |         23         |         24         | | ||||
| |         25         |                   |                    |                    |                    |                    |                    | | ||||
							
								
								
									
										136
									
								
								src/day16/Puzzle2.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/day16/Puzzle2.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| package day16 | ||||
|  | ||||
| import day16.Mirrors.{DIAGONAL_BL_TR, DIAGONAL_TL_BR, Mirror, NONE, SPLITTER_HOR, SPLITTER_VER} | ||||
|  | ||||
| import scala.collection.mutable.ArrayBuffer | ||||
| import scala.io.{BufferedSource, Source} | ||||
|  | ||||
| object Puzzle2 { | ||||
|   var mirrors: Array[Array[Mirror]] = Array.empty | ||||
|   var energized: Array[Array[Boolean]] = Array.empty | ||||
|   var width: Int = 0 | ||||
|   var height: Int = 0 | ||||
|   val OFFSETS: Array[(Int, Int)] = Array( | ||||
|     (1, 0), (0, 1), (-1, 0), (0, -1) | ||||
|   ) | ||||
|   var path: ArrayBuffer[(Int, Int, Int)] = new ArrayBuffer() | ||||
|  | ||||
|   def loadInput(path: String): Unit = { | ||||
|     val source: BufferedSource = Source.fromFile(path) | ||||
|     val lines: Array[String] = source.getLines().toArray | ||||
|  | ||||
|     height = lines.length | ||||
|     width = if (height == 0) 0 else lines(0).length | ||||
|     mirrors = Array.ofDim(height, width) | ||||
|  | ||||
|     for ((line: String, y: Int) <- lines.zipWithIndex) { | ||||
|       for ((c: Char, x: Int) <- line.zipWithIndex) { | ||||
|         val mirror: Mirror = Mirrors.withName(""+c) | ||||
|         mirrors(y)(x) = mirror | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     source.close() | ||||
|   } | ||||
|  | ||||
|   def shootBeam(startX: Int, startY: Int, startDir: Int): Unit = { | ||||
|     if (startX < 0 || startX >= width || startY < 0 || startY >= height) return | ||||
|     var x: Int = startX | ||||
|     var y: Int = startY | ||||
|     var dir: Int = startDir | ||||
|     var continue: Boolean = true | ||||
|     do { | ||||
|       if (path.contains((x, y, dir))) return | ||||
|       path.addOne((x, y, dir)) | ||||
|  | ||||
|       energized(y)(x) = true | ||||
|  | ||||
|       mirrors(y)(x) match { | ||||
|         case NONE => {} | ||||
|         case DIAGONAL_TL_BR => { | ||||
|           dir = Math.floorDiv(dir, 2)*2 + 1 - (dir % 2) | ||||
|         } | ||||
|         case DIAGONAL_BL_TR => { | ||||
|           dir = 3 - dir | ||||
|         } | ||||
|         case SPLITTER_HOR => { | ||||
|           if (dir % 2 == 1) { | ||||
|             continue = false | ||||
|             shootBeam(x+1, y, 0) | ||||
|             shootBeam(x-1, y, 2) | ||||
|           } | ||||
|         } | ||||
|         case SPLITTER_VER => { | ||||
|           if (dir % 2 == 0) { | ||||
|             continue = false | ||||
|             shootBeam(x, y+1, 1) | ||||
|             shootBeam(x, y-1, 3) | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (continue) { | ||||
|         val offset: (Int, Int) = OFFSETS(dir) | ||||
|         x += offset._1 | ||||
|         y += offset._2 | ||||
|       } | ||||
|  | ||||
|       if (x < 0 || x >= width) continue = false | ||||
|       if (y < 0 || y >= height) continue = false | ||||
|     } while (continue) | ||||
|   } | ||||
|  | ||||
|   def countEnergized(): Int = { | ||||
|     var count: Int = 0 | ||||
|     for (y: Int <- 0 until height) { | ||||
|       for (x: Int <- 0 until width) { | ||||
|         if (energized(y)(x)) count += 1 | ||||
|       } | ||||
|     } | ||||
|     return count | ||||
|   } | ||||
|  | ||||
|   def clearEnergized(): Unit = { | ||||
|     energized = Array.ofDim(height, width) | ||||
|     path.clear() | ||||
|   } | ||||
|  | ||||
|   def solve(path: String): Int = { | ||||
|     loadInput(path) | ||||
|  | ||||
|     var solution: Int = 0 | ||||
|     val totalSteps: Int = (width + height)*2 | ||||
|  | ||||
|     for (y: Int <- 0 until height) { | ||||
|       print(f"\r${2.0*y/totalSteps*100}%.2f%%") | ||||
|       clearEnergized() | ||||
|       shootBeam(0, y, 0) | ||||
|       solution = Math.max(solution, countEnergized()) | ||||
|  | ||||
|       print(f"\r${(2.0*y+1)/totalSteps*100}%.2f%%") | ||||
|       clearEnergized() | ||||
|       shootBeam(width-1, y, 1) | ||||
|       solution = Math.max(solution, countEnergized()) | ||||
|     } | ||||
|  | ||||
|     for (x: Int <- 0 until width) { | ||||
|       print(f"\r${(2.0*x+height*2)/totalSteps*100}%.2f%%") | ||||
|       clearEnergized() | ||||
|       shootBeam(x, 0, 1) | ||||
|       solution = Math.max(solution, countEnergized()) | ||||
|  | ||||
|       print(f"\r${(2.0*x+height*2+1)/totalSteps*100}%.2f%%") | ||||
|       clearEnergized() | ||||
|       shootBeam(x, height-1, 3) | ||||
|       solution = Math.max(solution, countEnergized()) | ||||
|     } | ||||
|     println("100%") | ||||
|  | ||||
|     return solution | ||||
|   } | ||||
|  | ||||
|   def main(args: Array[String]): Unit = { | ||||
|     val solution: Int = solve("./res/day16/input1.txt") | ||||
|     println(solution) | ||||
|   } | ||||
| } | ||||
							
								
								
									
										9
									
								
								tests/day16/Puzzle2Test.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/day16/Puzzle2Test.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package day16 | ||||
|  | ||||
| import org.scalatest.funsuite.AnyFunSuite | ||||
|  | ||||
| class Puzzle2Test extends AnyFunSuite { | ||||
|   test("Puzzle2.solve") { | ||||
|     assert(Puzzle2.solve("tests_res/day16/input1.txt") == 51) | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user