Skip to content

Commit 4a8dfd7

Browse files
committed
day2 part1
1 parent a697c8a commit 4a8dfd7

File tree

3 files changed

+110
-1
lines changed

3 files changed

+110
-1
lines changed

Sources/AdventOfCode.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import ArgumentParser
22

33
// Add each new day implementation to this array:
44
let allChallenges: [any AdventDay] = [
5-
Day01()
5+
Day01(),
6+
Day02(),
67
]
78

89
@main

Sources/Day02.swift

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Algorithms
2+
3+
struct Report {
4+
var value: [Int]
5+
6+
}
7+
extension Report {
8+
init(_ data: Substring) {
9+
value = data.split(separator: " ").map { v in Int(v) ?? 0 }
10+
}
11+
}
12+
13+
func spreadsWell(_ value: Int) -> Bool {
14+
abs(value) <= 3 && abs(value) >= 1
15+
}
16+
17+
struct ReportAnalyzer {
18+
19+
func isSafe(report: Report, damped: Bool = false) -> Bool {
20+
// all values are either increasing or decreasing
21+
let diffs = report.value.adjacentPairs().map { (one, two) in
22+
two - one
23+
}
24+
let order = diffs.grouped { v in
25+
if v < 0 {
26+
return "desc"
27+
}
28+
if v > 0 {
29+
return "asc"
30+
}
31+
return "none"
32+
}
33+
let spread = diffs.filter { spreadsWell($0) }
34+
35+
let isSafe = order.count == 1 && spread.count == diffs.count
36+
if damped {
37+
38+
let orderIsOffByOne =
39+
order.count == 2
40+
&& (order["desc", default: []].count == 1 || order["asc", default: []].count == 1)
41+
// let spreadIsOffByOne = spread.count == diffs.count - 1
42+
let spreadDefect = diffs.firstIndex { spreadsWell($0) == false }
43+
if let defect = spreadDefect {
44+
print(defect, report.value)
45+
return ReportAnalyzer().isSafe(
46+
report: Report(
47+
value: report.value.filter {
48+
$0 == report.value[defect + 1]
49+
}))
50+
}
51+
// print("\(report): safe (\(isSafe)) order (\(orderIsOffByOne)) spread (\(spreadIsOffByOne))")
52+
return isSafe || orderIsOffByOne
53+
}
54+
55+
return isSafe
56+
}
57+
}
58+
59+
struct Day02: AdventDay {
60+
// Save your data in a corresponding text file in the `Data` directory.
61+
var data: String
62+
63+
var reports: [Report] {
64+
data.split(separator: "\n").map { Report($0) }
65+
}
66+
67+
func part1() -> Int {
68+
reports.map { ReportAnalyzer().isSafe(report: $0) }.filter { $0 }.count
69+
}
70+
71+
func part2() -> Int {
72+
reports.map { ReportAnalyzer().isSafe(report: $0, damped: true) }.filter { $0 }.count
73+
74+
}
75+
}

Tests/Day02.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Testing
2+
3+
@testable import aoc
4+
5+
@Suite("Day02")
6+
struct Day02Tests {
7+
let testData = """
8+
7 6 4 2 1
9+
1 2 7 8 9
10+
9 7 6 2 1
11+
1 3 2 4 5
12+
8 6 4 4 1
13+
1 3 6 7 9
14+
"""
15+
16+
@Test("report analyzer")
17+
func name() async throws {
18+
#expect(Report("7 6 4 2 1").value == [7, 6, 4, 2, 1])
19+
#expect(ReportAnalyzer().isSafe(report: Report("7 6 4 2 1")) == true)
20+
}
21+
22+
@Test("part1")
23+
func testPart1() async throws {
24+
let challenge = Day02(data: testData)
25+
#expect(challenge.part1() == 2)
26+
}
27+
28+
@Test("part2")
29+
func testPart2() async throws {
30+
let challenge = Day02(data: testData)
31+
#expect(challenge.part2() == 4)
32+
}
33+
}

0 commit comments

Comments
 (0)