-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday6.swift
79 lines (70 loc) · 2.38 KB
/
day6.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//
// day6.swift
// aoc
//
// Created by Greg Titus on 12/5/24.
//
import Foundation
import RegexBuilder
func daySix(_ contents: String) -> Int {
struct Square {
var directions = 0
var visited: Bool { directions != 0 }
var barrier = false
init(_ c: Character) {
switch c {
case "^":
directions = (1 << Direction.up.rawValue)
case "#":
barrier = true
default:
break
}
}
}
var grid = Grid(contents: contents, mapping: { Square($0) })
let start = grid.indices.first(where: { grid[$0].visited })!
// guard walks, returning false if stepping out of the grid, or true if in a loop
func newBarrierWalk(_ grid: inout Grid<Square>, from start: Position, in d: Direction) -> Bool {
var position = start
var direction = d
while true {
let next = position.direction(direction)
guard grid.valid(index: next) else { return false }
if grid[next].barrier {
direction = direction.turnClockwise()
if (grid[position].directions & (1 << direction.rawValue)) != 0 { return true }
grid[position].directions |= (1 << direction.rawValue)
} else {
position = next
}
}
}
// original walk
var placedAlready: Set<Position> = [start]
func walk(_ grid: inout Grid<Square>, start: Grid<Square>.Index = start) -> Int {
var result = 0
var position = start
var direction = Direction.up
while true {
let next = position.direction(direction)
guard grid.valid(index: next) else { return result }
if grid[next].barrier {
direction = direction.turnClockwise()
grid[position].directions |= (1 << direction.rawValue)
} else {
let ifTurned = direction.turnClockwise()
if !placedAlready.contains(next) {
placedAlready.insert(next)
var copy = Grid(copy: grid)
copy[next].barrier = true
if newBarrierWalk(©, from: position, in: ifTurned) {
result += 1
}
}
position = next
}
}
}
return walk(&grid)
}