Skip to content

Commit 1f17728

Browse files
committed
Use 4 bool arrays
1 parent 6f740b7 commit 1f17728

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

16.swift

+29-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ while let line = readLine() {
33
grid.append(items(line))
44
}
55

6+
let ny = grid.count
7+
let nx = grid.first?.count ?? 0
8+
69
var f = energized(by: Beam(x: 0, y: 0, d: .r))
710
var m = edges().map({ energized(by: $0) }).max() ?? 0
811
print(f, m)
@@ -14,7 +17,7 @@ enum Item: Character {
1417
func items(_ s: String) -> [Item] { s.compactMap { Item(rawValue: $0) } }
1518
func item(at beam: Beam) -> Item { grid[beam.y][beam.x] }
1619

17-
enum Direction { case l, r, u, d }
20+
enum Direction: Int { case l, r, u, d }
1821

1922
struct Beam: Hashable {
2023
let x, y: Int
@@ -46,20 +49,40 @@ struct Beam: Hashable {
4649
var reflectD: Beam { Beam(x: x, y: y + 1, d: .d) }
4750
}
4851

52+
typealias Visited = [[Bool]]
53+
4954
func energized(by beam: Beam) -> Int {
50-
var visited = Set<Beam>()
55+
// It is much faster to use 4 arrays (one for each direction) to keep track
56+
// of visited beams instead of a Set<Beam>().
57+
var visited: [Visited] = Array(
58+
repeating: Array(repeating: Array(repeating: false, count: nx), count: ny),
59+
count: 4)
60+
5161
trace(beam: beam, visited: &visited)
52-
return Set(visited.map({ [$0.x, $0.y] })).count
62+
63+
var count = 0
64+
for y in 0..<ny {
65+
for x in 0..<nx {
66+
for d in 0..<4 {
67+
if visited[d][y][x] {
68+
count += 1
69+
break
70+
}
71+
}
72+
}
73+
}
74+
return count
5375
}
5476

55-
func trace(beam: Beam, visited: inout Set<Beam>) {
77+
func trace(beam: Beam, visited: inout [Visited]) {
5678
var (beam, bt) = (beam, beam)
5779
var next: [Beam] = []
5880

5981
while isInBounds(beam) {
60-
if !visited.insert(beam).inserted {
82+
if visited[beam.d.rawValue][beam.y][beam.x] {
6183
break
6284
}
85+
visited[beam.d.rawValue][beam.y][beam.x] = true
6386

6487
switch item(at: beam) {
6588
case .vbar where beam.isHorizontal:
@@ -93,13 +116,10 @@ func trace(beam: Beam, visited: inout Set<Beam>) {
93116
func isInBounds(_ beam: Beam) -> Bool {
94117
let x = beam.x
95118
let y = beam.y
96-
return x >= 0 && x < grid[0].count && y >= 0 && y < grid.count
119+
return x >= 0 && x < nx && y >= 0 && y < ny
97120
}
98121

99122
func edges() -> [Beam] {
100-
let ny = grid.count
101-
let nx = grid.first?.count ?? 0
102-
103123
var result: [Beam] = []
104124
for y in 0..<ny {
105125
result.append(Beam(x: 0, y: y, d: .r))

0 commit comments

Comments
 (0)