Move to subdirectory
This commit is contained in:
parent
c4ae807a5f
commit
c7deb3c71d
47 changed files with 1208 additions and 0 deletions
129
2020/day24/main.swift
Normal file
129
2020/day24/main.swift
Normal file
|
@ -0,0 +1,129 @@
|
|||
import Foundation
|
||||
|
||||
let input = loadData(day: 24)
|
||||
let scanner = Scanner(string: input)
|
||||
scanner.charactersToBeSkipped = nil
|
||||
|
||||
enum Direction: String, CaseIterable {
|
||||
case east = "e"
|
||||
case southEast = "se"
|
||||
case southWest = "sw"
|
||||
case west = "w"
|
||||
case northWest = "nw"
|
||||
case northEast = "ne"
|
||||
}
|
||||
|
||||
extension Scanner {
|
||||
func readDirection() -> Direction? {
|
||||
for dir in Direction.allCases {
|
||||
if string(dir.rawValue) {
|
||||
return dir
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
struct Coord: Hashable {
|
||||
var south: Int
|
||||
var east: Int
|
||||
|
||||
static let zero = Coord(south: 0, east: 0)
|
||||
|
||||
mutating func move(_ direction: Direction) {
|
||||
switch direction {
|
||||
case .east:
|
||||
east += 1
|
||||
case .southEast:
|
||||
south += 1
|
||||
|
||||
case .southWest:
|
||||
south += 1
|
||||
east -= 1
|
||||
|
||||
case .west:
|
||||
east -= 1
|
||||
|
||||
case .northWest:
|
||||
south -= 1
|
||||
|
||||
case .northEast:
|
||||
south -= 1
|
||||
east += 1
|
||||
}
|
||||
}
|
||||
|
||||
func neighbor(_ direction: Direction) -> Coord {
|
||||
var result = self
|
||||
result.move(direction)
|
||||
return result
|
||||
}
|
||||
|
||||
var neighbors: [Coord] {
|
||||
Direction.allCases.map(neighbor)
|
||||
}
|
||||
}
|
||||
|
||||
func readCoordinate() -> Coord {
|
||||
var current = Coord.zero
|
||||
while let direction = scanner.readDirection() {
|
||||
current.move(direction)
|
||||
}
|
||||
precondition(scanner.string("\n"))
|
||||
return current
|
||||
}
|
||||
|
||||
var floor: [Coord: Bool] = [:]
|
||||
var northWestCorner = Coord.zero
|
||||
var southEastCorner = Coord.zero
|
||||
|
||||
|
||||
func expandRange(toInclude coord: Coord) {
|
||||
northWestCorner.east = min(northWestCorner.east, coord.east)
|
||||
northWestCorner.south = min(northWestCorner.south, coord.south)
|
||||
|
||||
southEastCorner.east = max(southEastCorner.east, coord.east)
|
||||
southEastCorner.south = max(southEastCorner.south, coord.south)
|
||||
}
|
||||
|
||||
while !scanner.isAtEnd {
|
||||
let coord = readCoordinate()
|
||||
expandRange(toInclude: coord)
|
||||
|
||||
floor[coord, default: false].toggle()
|
||||
}
|
||||
|
||||
print("part 1:", floor.values.lazy.filter { $0 }.count)
|
||||
|
||||
func step() -> [Coord: Bool] {
|
||||
var result = floor
|
||||
|
||||
for east in (northWestCorner.east - 1)...(southEastCorner.east + 1) {
|
||||
for south in (northWestCorner.south - 1)...(southEastCorner.south + 1) {
|
||||
let coord = Coord(south: south, east: east)
|
||||
|
||||
let isBlack = floor[coord, default: false]
|
||||
|
||||
let blackNeighbors = coord.neighbors
|
||||
.lazy
|
||||
.map { floor[$0, default: false] }
|
||||
.filter { $0 }
|
||||
.count
|
||||
|
||||
if isBlack && (blackNeighbors == 0 || blackNeighbors > 2) {
|
||||
result[coord] = false
|
||||
} else if !isBlack && blackNeighbors == 2 {
|
||||
result[coord] = true
|
||||
expandRange(toInclude: coord)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
for _ in 0..<100 {
|
||||
floor = step()
|
||||
}
|
||||
|
||||
print("part 2:", floor.values.lazy.filter { $0 }.count)
|
Loading…
Add table
Add a link
Reference in a new issue