From abeeee237c0d0f3a65ef5ef6947b188c2c9367fd Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Sat, 16 Dec 2023 18:18:19 +0100 Subject: [PATCH] day 16 puzzle 1 --- README.md | 4 +- src/day16/Mirrors.scala | 10 ++++ src/day16/Puzzle1.scala | 103 ++++++++++++++++++++++++++++++++++ tests/day16/Puzzle1Test.scala | 9 +++ tests_res/day16/input1.txt | 10 ++++ 5 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/day16/Mirrors.scala create mode 100644 src/day16/Puzzle1.scala create mode 100644 tests/day16/Puzzle1Test.scala create mode 100644 tests_res/day16/input1.txt diff --git a/README.md b/README.md index 0e5a444..2c7fb27 100644 --- a/README.md +++ b/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: 28 / 50 +#### Stars: 29 / 50 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | |:------------------:|:-----------------:|:------------------:|:------------------:|:------------------:|:-----------------:|:------------------:| | | | | | 1
:star::star: | 2
:star::star: | 3
:star::star: | | 4
:star::star: | 5
:star::star: | 6
:star::star: | 7
:star::star: | 8
:star::star: | 9
:star::star: | 10
:star::star: | -| 11
:star::star: | 12 | 13
:star::star: | 14
:star::star: | 15
:star::star: | 16 | 17 | +| 11
:star::star: | 12 | 13
:star::star: | 14
:star::star: | 15
:star::star: | 16
:star: | 17 | | 18 | 19 | 20 | 21 | 22 | 23 | 24 | | 25 | | | | | | | \ No newline at end of file diff --git a/src/day16/Mirrors.scala b/src/day16/Mirrors.scala new file mode 100644 index 0000000..a8a57cd --- /dev/null +++ b/src/day16/Mirrors.scala @@ -0,0 +1,10 @@ +package day16 + +object Mirrors extends Enumeration { + type Mirror = Value + val NONE = Value(".") + val DIAGONAL_TL_BR = Value("\\") + val DIAGONAL_BL_TR = Value("/") + val SPLITTER_HOR = Value("-") + val SPLITTER_VER = Value("|") +} diff --git a/src/day16/Puzzle1.scala b/src/day16/Puzzle1.scala new file mode 100644 index 0000000..86d923a --- /dev/null +++ b/src/day16/Puzzle1.scala @@ -0,0 +1,103 @@ +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 Puzzle1 { + 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) + ) + val 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) + energized = 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 solve(path: String): Int = { + loadInput(path) + shootBeam(0, 0, 0) + + var solution: Int = 0 + + for (y: Int <- 0 until height) { + for (x: Int <- 0 until width) { + if (energized(y)(x)) solution += 1 + } + } + + return solution + } + + def main(args: Array[String]): Unit = { + val solution: Int = solve("./res/day16/input1.txt") + println(solution) + } +} diff --git a/tests/day16/Puzzle1Test.scala b/tests/day16/Puzzle1Test.scala new file mode 100644 index 0000000..0306ea9 --- /dev/null +++ b/tests/day16/Puzzle1Test.scala @@ -0,0 +1,9 @@ +package day16 + +import org.scalatest.funsuite.AnyFunSuite + +class Puzzle1Test extends AnyFunSuite { + test("Puzzle1.solve") { + assert(Puzzle1.solve("tests_res/day16/input1.txt") == 46) + } +} diff --git a/tests_res/day16/input1.txt b/tests_res/day16/input1.txt new file mode 100644 index 0000000..c78b2e7 --- /dev/null +++ b/tests_res/day16/input1.txt @@ -0,0 +1,10 @@ +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... \ No newline at end of file