Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Created February 19, 2021 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sungkmi/7a34570efa4d17a0f0ee2434d9034963 to your computer and use it in GitHub Desktop.
Save sungkmi/7a34570efa4d17a0f0ee2434d9034963 to your computer and use it in GitHub Desktop.
package sungkmi.aoc2020.day11
enum PositionState:
case Empty, Occufied, Floor
type Layout = IndexedSeq[IndexedSeq[PositionState]]
extension [A](is: IndexedSeq[A])
def get(n: Int): Option[A] = if 0 <= n && n < is.size then Some(is(n)) else None
extension (l: Layout)
def apply(r: Int, c: Int): Option[PositionState] = for
row <- l.get(r)
column <- row.get(c)
yield column
def neighborOf(r: Int, c: Int): Seq[PositionState] = for
i <- -1 to 1
j <- -1 to 1 if i!=0 || j!=0
state <- apply(r + i, c + j).toSeq
yield state
@annotation.tailrec
def getVisibleSeat(r: Int, c: Int, dr: Int, dc: Int): Option[PositionState] =
apply(r + dr, c + dc) match
case None => None
case Some(PositionState.Floor) => getVisibleSeat(r + dr, c + dc, dr, dc)
case Some(state) => Some(state)
def allVisibleSeats(r: Int, c: Int): Seq[PositionState] = for
i <- -1 to 1
j <- -1 to 1 if i!=0 || j!=0
state <- getVisibleSeat(r, c, i, j).toSeq
yield state
def countOccufied: Int = l.map(_.count(_ == PositionState.Occufied)).sum
def countNeighborOccupation(r: Int, c: Int): Int =
neighborOf(r, c).count(_ == PositionState.Occufied)
def countVisibleOccupation(r: Int, c: Int): Int =
allVisibleSeats(r, c).count(_ == PositionState.Occufied)
def step: Layout = l.zipWithIndex.map:
case (row, r) => row.zipWithIndex.map:
case (PositionState.Empty, c) if countNeighborOccupation(r, c) == 0 =>
PositionState.Occufied
case (PositionState.Occufied, c) if countNeighborOccupation(r, c) >= 4 =>
PositionState.Empty
case (state, c) => state
def step2: Layout = l.zipWithIndex.map:
case (row, r) => row.zipWithIndex.map:
case (PositionState.Empty, c) if countVisibleOccupation(r, c) == 0 =>
PositionState.Occufied
case (PositionState.Occufied, c) if countVisibleOccupation(r, c) >= 5 =>
PositionState.Empty
case (state, c) => state
def getMap: String = l.map:
_.map:
case PositionState.Empty => 'L'
case PositionState.Occufied => '#'
case PositionState.Floor => '.'
.mkString
.mkString("\n")
def converged(step: Layout => Layout): Option[Layout] =
val Max: Int = 10000000
@annotation.tailrec
def loop(count: Int, last: Layout): Option[Layout] =
val next = step(last)
if next == last then Some(last) else loop(count + 1, next)
loop(0, l)
def occupationEndup: Option[Int] = converged(_.step).map(_.countOccufied)
def occupationEndup2: Option[Int] = converged(_.step2).map(_.countOccufied)
def parse(inputString: String): Layout = inputString.split("\n").map:
line => line.map:
case 'L' => PositionState.Empty
case '#' => PositionState.Occufied
case '.' => PositionState.Floor
.toIndexedSeq
.toIndexedSeq
@main def part1: Unit =
val ans = parse(input).occupationEndup
println(ans)
@main def part2: Unit =
val ans = parse(input).occupationEndup2
println(ans)
//lazy val input: String = """
package sungkmi.aoc2020.day11
class Day11Test extends munit.FunSuite {
val layouts = Seq("""L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL""",
"""#.##.##.##
#######.##
#.#.#..#..
####.##.##
#.##.##.##
#.#####.##
..#.#.....
##########
#.######.#
#.#####.##""",
"""#.LL.L#.##
#LLLLLL.L#
L.L.L..L..
#LLL.LL.L#
#.LL.LL.LL
#.LLLL#.##
..L.L.....
#LLLLLLLL#
#.LLLLLL.L
#.#LLLL.##""",
"""#.##.L#.##
#L###LL.L#
L.#.#..#..
#L##.##.L#
#.##.LL.LL
#.###L#.##
..#.#.....
#L######L#
#.LL###L.L
#.#L###.##""",
"""#.#L.L#.##
#LLL#LL.L#
L.L.L..#..
#LLL.##.L#
#.LL.LL.LL
#.LL#L#.##
..L.L.....
#L#LLLL#L#
#.LLLLLL.L
#.#L#L#.##""",
"""#.#L.L#.##
#LLL#LL.L#
L.#.L..#..
#L##.##.L#
#.#L.LL.LL
#.#L#L#.##
..L.L.....
#L#L##L#L#
#.LLLLLL.L
#.#L#L#.##""",
)
test("Step #1") {
assertEquals(parse(layouts(0)).step, parse(layouts(1)))
}
test("Step #2") {
assertEquals(parse(layouts(1)).step, parse(layouts(2)))
}
test("Step #3") {
assertEquals(parse(layouts(2)).step, parse(layouts(3)))
}
test("Step #4") {
assertEquals(parse(layouts(3)).step, parse(layouts(4)))
}
test("Step #5") {
assertEquals(parse(layouts(4)).step, parse(layouts(5)))
}
test("occupationEndup") {
assertEquals(parse(layouts(0)).occupationEndup, Some(37))
}
test("occupationEndup2") {
assertEquals(parse(layouts(0)).occupationEndup2, Some(26))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment