Skip to content

Commit d3ec2e8

Browse files
committed
wip
1 parent d01a870 commit d3ec2e8

File tree

7 files changed

+149
-32
lines changed

7 files changed

+149
-32
lines changed

Sources/Day04.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Algorithms
22

3-
func searchInNeighbors(pos: Coord, _ grid: Grid) -> [Coord] {
4-
pos.fullNeighbors.included(in: grid).filter { n in
3+
func searchInNeighbors(pos: Coord, _ grid: Grid<Character>) -> [Coord] {
4+
grid.filter(allInside: pos.fullNeighbors).filter { n in
55
grid[n] == "M"
66
}
77
}
88

9-
func isMAS(pos: Coord, _ grid: Grid) -> Bool {
9+
func isMAS(pos: Coord, _ grid: Grid<Character>) -> Bool {
1010
let candidates = pos.cornerNeighbors
11-
if (candidates.allSatisfy { $0.isInside(grid: grid) }) {
11+
if grid.filter(allInside: candidates).count == 4 {
1212
let l = candidates.map { grid[$0] }.compactMap { $0 }
1313
let letterSet = Set(l)
1414
// same letter can not be on opposite side
@@ -17,7 +17,7 @@ func isMAS(pos: Coord, _ grid: Grid) -> Bool {
1717
return false
1818
}
1919

20-
func isWhole(pos: Coord, inDir: Coord, grid: Grid) -> Bool {
20+
func isWhole(pos: Coord, inDir: Coord, grid: Grid<Character>) -> Bool {
2121
let aPos = pos + inDir
2222
let sPos = aPos + inDir
2323
if let aValue = grid[aPos], let sValue = grid[sPos] {
@@ -27,12 +27,12 @@ func isWhole(pos: Coord, inDir: Coord, grid: Grid) -> Bool {
2727
}
2828

2929
struct Day04: AdventDay {
30-
var grid: Grid
30+
var grid: Grid<Character>
3131
init(data: String) {
3232
grid = Grid(from: data)
3333
}
3434

35-
func countAllWhere(letter search: Character, predicate: (Coord, Grid) -> Bool) -> Int {
35+
func countAllWhere(letter search: Character, predicate: (Coord, Grid<Character>) -> Bool) -> Int {
3636
grid.raw.enumerated().map { (y, line) in
3737
line.enumerated().map { (x, letter) in
3838
if letter == search {

Sources/Day06.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct Guard {
2828
}
2929

3030
struct Day06: AdventDay {
31-
var grid: Grid
31+
var grid: Grid<Character>
3232
init(data: String) {
3333
grid = Grid(from: data)
3434
}
@@ -38,7 +38,7 @@ struct Day06: AdventDay {
3838
var steps: [Coord] = [Coord]()
3939
var obstacles: [Coord] = [Coord]()
4040
var officer = Guard(pos: grid.firstCoord(of: "^")!, direction: .North)
41-
while officer.pos.isInside(grid: grid) {
41+
while grid.includes(coord: officer.pos) {
4242
// save position
4343
locations.insert(officer.pos)
4444

@@ -64,7 +64,7 @@ struct Day06: AdventDay {
6464
func doesComeBack(step: Coord) -> Bool {
6565
var officer = Guard(pos: grid.firstCoord(of: "^")!, direction: .North)
6666
var locations: [Coord] = [Coord]()
67-
while officer.pos.isInside(grid: grid) {
67+
while grid.includes(coord: officer.pos) {
6868
locations.append(officer.pos)
6969

7070
// move the guard

Sources/Day10.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Algorithms
22

33
struct Day10: AdventDay {
4-
var grid: Grid
4+
var grid: Grid<Character>
55

66
init(data: String) {
77
grid = Grid(from: data)

Sources/Day12.swift

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import Algorithms
2+
3+
struct Field {
4+
var id: Character
5+
var area: Int = 1
6+
var perimeter: Int = 0
7+
var coords: [Coord] = [Coord]()
8+
9+
func compute() -> Int {
10+
area * perimeter
11+
}
12+
13+
mutating func visited(coord: Coord) {
14+
coords.append(coord)
15+
}
16+
}
17+
extension Field {
18+
init(id: Character) {
19+
self.id = id
20+
area = 1
21+
perimeter = 0
22+
}
23+
}
24+
25+
struct Day12: AdventDay {
26+
var grid: Grid<Character>
27+
28+
init(data: String) {
29+
grid = Grid(from: data)
30+
}
31+
32+
func exploreField(from pos: Coord, id: Character, field oldField: Field) -> Field {
33+
var field = oldField
34+
field.visited(coord: pos)
35+
field.area += 1
36+
// explore the grid
37+
for neighbor in pos.crossNeighbors {
38+
print("checking for", neighbor)
39+
if let candidate = grid[neighbor] {
40+
if candidate == id {
41+
print("we are together")
42+
// same value means we have a new area tile
43+
return exploreField(from: neighbor, id: id, field: field)
44+
} else {
45+
print("someone else")
46+
// this is a frontier
47+
field.perimeter += 1
48+
}
49+
} else {
50+
print("grid boundary")
51+
// this is the frontier of the grid
52+
field.perimeter += 1
53+
}
54+
}
55+
return field
56+
}
57+
58+
func part1() -> Int {
59+
60+
var record = [Coord: Bool]()
61+
var fields = [Field]()
62+
for y in 0..<grid.height {
63+
for x in 0..<grid.width {
64+
let currentPos = Coord(x: x, y: y)
65+
print(currentPos)
66+
// position has already been visited
67+
guard record[currentPos] == nil else {
68+
print("already visited")
69+
continue
70+
}
71+
72+
if let gridValue = grid[currentPos] {
73+
// start a new field
74+
print("starting a new field")
75+
let field = exploreField(
76+
from: currentPos, id: gridValue, field: Field(id: gridValue))
77+
fields.append(field)
78+
field.coords.forEach { s in
79+
record[s] = true
80+
}
81+
print("-------", field)
82+
}
83+
}
84+
}
85+
return fields.map { $0.compute() }.sum
86+
}
87+
88+
func part2() -> Int {
89+
0
90+
}
91+
}

Sources/Helpers/Coord.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ struct Coord {
3636
var fullNeighbors: [Coord] {
3737
self.cornerNeighbors + self.crossNeighbors
3838
}
39-
40-
func isInside(grid: Grid) -> Bool {
41-
self.x >= 0 && self.x <= grid.width - 1 && self.y >= 0 && self.y <= grid.height - 1
42-
}
43-
4439
}
4540

4641
extension Coord: Equatable {}
@@ -89,9 +84,3 @@ extension Coord {
8984
return Self(x: lhs.x * rhs, y: lhs.y * rhs)
9085
}
9186
}
92-
93-
extension Array where Array.Element == Coord {
94-
func included(in grid: Grid) -> Self {
95-
self.filter { $0.isInside(grid: grid) }
96-
}
97-
}

Sources/Helpers/Grid.swift

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
struct Grid {
2-
typealias Element = Character
3-
1+
struct Grid<Element: Sendable> {
42
var raw: [[Element]]
53

64
// dimensions
@@ -12,7 +10,7 @@ struct Grid {
1210
}
1311

1412
subscript(_ coord: Coord) -> Element? {
15-
if coord.isInside(grid: self) {
13+
if self.includes(coord: coord) {
1614
return raw[coord.y][coord.x]
1715
}
1816
return nil
@@ -21,9 +19,21 @@ struct Grid {
2119
subscript(col: Int, row: Int) -> Element {
2220
raw[row][col]
2321
}
22+
23+
func includes(coord: Coord) -> Bool {
24+
coord.x >= 0 && coord.x <= self.width - 1 && coord.y >= 0 && coord.y <= self.height - 1
25+
}
26+
27+
func filter(allInside: [Coord]) -> [Coord] {
28+
allInside.filter { self.includes(coord: $0) }
29+
}
2430
}
2531

26-
extension Grid {
32+
extension Grid: Sendable {
33+
34+
}
35+
36+
extension Grid where Element == Character {
2737
/// creates a Grid of characters from a multiline string
2838
init(from data: String) {
2939
self.raw = data.lines().map { Array($0) }
@@ -36,11 +46,7 @@ extension Grid {
3646
}.joined(by: "\n"))
3747
}
3848

39-
func includes(coord: Coord) -> Bool {
40-
coord.x >= 0 && coord.x <= self.width - 1 && coord.y >= 0 && coord.y <= self.height - 1
41-
}
42-
43-
func firstCoord(of char: Character) -> Coord? {
49+
func firstCoord(of char: Element) -> Coord? {
4450
let index = self.raw.flatMap { $0 }.firstIndex(of: char)
4551
if let index = index {
4652
let x = index % self.width

Tests/Day12.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import Testing
2+
3+
@testable import aoc
4+
5+
@Suite("Day12")
6+
struct Day12Tests {
7+
let testData = """
8+
RRRRIICCFF
9+
RRRRIICCCF
10+
VVRRRCCFFF
11+
VVRCCCJFFF
12+
VVVVCJJCFE
13+
VVIVCCJJEE
14+
VVIIICJJEE
15+
MIIIIIJJEE
16+
MIIISIJEEE
17+
MMMISSJEEE
18+
"""
19+
20+
@Test("part1")
21+
func testPart1() async throws {
22+
let challenge = Day12(data: testData)
23+
#expect(challenge.part1() == 1930)
24+
}
25+
26+
@Test("part2")
27+
func testPart2() async throws {
28+
let challenge = Day12(data: testData)
29+
#expect(challenge.part2() == 0)
30+
}
31+
}

0 commit comments

Comments
 (0)