Skip to content

Commit 711cd1f

Browse files
committed
day7 done bitch
1 parent 24c8f10 commit 711cd1f

File tree

5 files changed

+201
-5
lines changed

5 files changed

+201
-5
lines changed

Sources/AdventOfCode.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ let allChallenges: [any AdventDay] = [
88
Day04(),
99
Day05(),
1010
Day06(),
11+
Day07(),
1112
]
1213

1314
@main

Sources/Day06.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ struct Day06: AdventDay {
141141

142142
func part2() -> Int {
143143
var count = 0
144-
let obstacles = guardPatrol().obstacles
144+
let (_, steps, obstacles) = guardPatrol()
145145

146146
var newObstacles: [Coord] = [Coord]()
147147
for (offset, candidates) in obstacles.windows(ofCount: 4).enumerated() {
@@ -154,14 +154,16 @@ struct Day06: AdventDay {
154154
if offset > 4 {
155155

156156
// TODO: this is not right
157-
for (idx, elem) in obstacles[0...0].enumerated() {
157+
for (idx, elem) in obstacles[0...offset].enumerated() {
158158
print("trying", idx, elem)
159159
let wrappedOffset = offset % 4
160160
c[3] = elem
161161
if let coord = isAValidLoop(wrappedOffset: wrappedOffset, c: c) {
162-
count += 1
163-
newObstacles.append(coord)
164-
print(c)
162+
if steps.contains(coord) {
163+
count += 1
164+
newObstacles.append(coord)
165+
print(c)
166+
}
165167
}
166168
}
167169

Sources/Day07.swift

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import Algorithms
2+
3+
struct Calibration {
4+
var result: Int
5+
var values: [Int]
6+
}
7+
extension Calibration {
8+
init<S: StringProtocol>(from line: S) {
9+
let parts = line.split(separator: ":")
10+
result = Int(parts[0]) ?? 0
11+
values = parts[1].integers()
12+
}
13+
}
14+
extension Calibration: CustomStringConvertible {
15+
var description: String {
16+
"\(self.result): \(self.values.map {String($0)}.joined(separator: " "))"
17+
}
18+
}
19+
20+
struct Day07: AdventDay {
21+
var calibrations: [Calibration]
22+
init(data: String) {
23+
calibrations = data.lines().map { Calibration(from: $0) }
24+
}
25+
26+
func isValidCalibration(_ calibration: Calibration) -> Bool {
27+
// early return
28+
if calibration.values.count == 1 {
29+
return calibration.result == calibration.values[0]
30+
}
31+
// generate all operators permutations using a cartesian product method
32+
let allPermutations = product(["+", "*"], repeated: calibration.values.count - 1)
33+
for ops in allPermutations {
34+
var res = calibration.values[0]
35+
let products = zip(ops, calibration.values[1..<calibration.values.count])
36+
for (op, value) in products {
37+
if op == "+" {
38+
res += value
39+
}
40+
if op == "*" {
41+
res *= value
42+
}
43+
}
44+
// print(calibration, "->", res)
45+
if res == calibration.result {
46+
47+
// early from the loop
48+
return true
49+
}
50+
}
51+
// none of the permutations allowed to get the expected result
52+
return false
53+
}
54+
55+
func part1() -> Int {
56+
let possibleCalibrations = calibrations.filter {
57+
isValidCalibration($0)
58+
}
59+
60+
return possibleCalibrations.map { $0.result }.sum
61+
}
62+
63+
func isValidCalibration2(_ calibration: Calibration) -> Bool {
64+
// early return
65+
if calibration.values.count == 1 {
66+
return calibration.result == calibration.values[0]
67+
}
68+
// generate all operators permutations using a cartesian product method
69+
let allPermutations = product(["+", "*", "||"], repeated: calibration.values.count - 1)
70+
for ops in allPermutations {
71+
var res = calibration.values[0]
72+
let products = zip(ops, calibration.values[1..<calibration.values.count])
73+
for (op, value) in products {
74+
if op == "+" {
75+
res += value
76+
}
77+
if op == "*" {
78+
res *= value
79+
}
80+
if op == "||" {
81+
res = Int(String(res) + String(value)) ?? 0
82+
}
83+
}
84+
// print(calibration, "->", res)
85+
if res == calibration.result {
86+
87+
// early from the loop
88+
return true
89+
}
90+
}
91+
// none of the permutations allowed to get the expected result
92+
return false
93+
}
94+
95+
func part2() -> Int {
96+
let possibleCalibrations = calibrations.filter { calibration in
97+
if isValidCalibration(calibration) {
98+
return true
99+
} else {
100+
return isValidCalibration2(calibration)
101+
}
102+
}
103+
104+
return possibleCalibrations.map { $0.result }.sum
105+
}
106+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/// An iterator-sequence for the Cartesian product of multiple sequences of the same type.
2+
/// See `product(_:)`.
3+
public struct CartesianProduct<S: Sequence>: IteratorProtocol, Sequence {
4+
5+
private let sequences: [S]
6+
private var iterators: [S.Iterator]
7+
private var currentValues: [S.Iterator.Element] = []
8+
9+
fileprivate init(_ sequences: [S]) {
10+
self.sequences = sequences
11+
self.iterators = sequences.map { $0.makeIterator() }
12+
}
13+
14+
public mutating func next() -> [S.Iterator.Element]? {
15+
guard !currentValues.isEmpty else {
16+
var firstValues: [S.Iterator.Element] = []
17+
for index in iterators.indices {
18+
guard let value = iterators[index].next() else {
19+
return nil
20+
}
21+
firstValues.append(value)
22+
}
23+
currentValues = firstValues
24+
return firstValues
25+
}
26+
27+
for index in currentValues.indices.reversed() {
28+
if let value = iterators[index].next() {
29+
currentValues[index] = value
30+
return currentValues
31+
}
32+
33+
guard index != 0 else {
34+
return nil
35+
}
36+
37+
iterators[index] = sequences[index].makeIterator()
38+
currentValues[index] = iterators[index].next()!
39+
}
40+
41+
return currentValues
42+
}
43+
}
44+
45+
/// Returns an iterator-sequence for the Cartesian product of the sequence repeated with itself a number of times.
46+
/// ```
47+
/// let values = product([1, 2, 3], repeated: 2)
48+
/// // Equivalent to product([1, 2, 3], [1, 2, 3])
49+
/// ```
50+
/// - Parameters:
51+
/// - sequence: The sequence from which to compute the product.
52+
/// - repeated: The number of times to repeat the sequence with itself in computing the product.
53+
/// - Returns: An iterator-sequence for the Cartesian product of the sequence repeated with itself a number of times.
54+
public func product<S: Sequence>(_ sequence: S, repeated: Int) -> CartesianProduct<S> {
55+
let sequences = Array(repeating: sequence, count: repeated)
56+
return CartesianProduct(sequences)
57+
}

Tests/Day07.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Testing
2+
3+
@testable import aoc
4+
5+
@Suite("Day07")
6+
struct Day07Tests {
7+
let testData = """
8+
190: 10 19
9+
3267: 81 40 27
10+
83: 17 5
11+
156: 15 6
12+
7290: 6 8 6 15
13+
161011: 16 10 13
14+
192: 17 8 14
15+
21037: 9 7 18 13
16+
292: 11 6 16 20
17+
"""
18+
19+
@Test("part1")
20+
func testPart1() async throws {
21+
let challenge = Day07(data: testData)
22+
#expect(challenge.part1() == 3749)
23+
}
24+
25+
@Test("part2")
26+
func testPart2() async throws {
27+
let challenge = Day07(data: testData)
28+
#expect(challenge.part2() == 11387)
29+
}
30+
}

0 commit comments

Comments
 (0)