diff --git a/2016/Sources/AdventOfCode.swift b/2016/Sources/AdventOfCode.swift index 3276e89..8278a5a 100644 --- a/2016/Sources/AdventOfCode.swift +++ b/2016/Sources/AdventOfCode.swift @@ -5,6 +5,7 @@ let allChallenges: [any AdventDay] = [ Day01(), Day02(), Day03(), + Day04(), ] @main diff --git a/2016/Sources/Day04.swift b/2016/Sources/Day04.swift new file mode 100644 index 0000000..429f343 --- /dev/null +++ b/2016/Sources/Day04.swift @@ -0,0 +1,54 @@ +import Foundation +import Collections + +private typealias KeyValuePair = (k: Character, v: Int) + +struct Day04: AdventDay { + let data: String + + func part1() -> Int { + return data.matches(of: /([a-z-]+)-(\d+)\[([a-z]+)]/) + .reduce(0) { sum, match in + let (_, name, id, checksum) = match.output + + let counts = Dictionary( + uniqueKeysWithValues: name.uniqued() + .filter { $0.isLetter } + .map { c in (c, name.count(where: { $0 == c })) } + ) + + let actualChecksum = counts.keys + .sorted() + .sorted(by: { counts[$0]! > counts[$1]! }) + .prefix(5) + + return if actualChecksum.elementsEqual(checksum) { + sum + Int(id)! + } else { + sum + } + } + } + + func part2() -> Int { + let asciiStart = Int(Character("a").asciiValue!) + + return data.matches(of: /([a-z-]+)-(\d+)\[([a-z]+)]/) + .map { match in + let (_, name, id, _) = match.output + + let decrypted = name.split(separator: "-") + .map { word in + String( + word.map { letter in + Character(UnicodeScalar((Int(letter.asciiValue!) - asciiStart + Int(id)!) % 26 + asciiStart)!) + } + ) + } + .joined(separator: " ") + + return (decrypted, Int(id)!) + } + .first(where: { $0.0 == "northpole object storage" })!.1 + } +} diff --git a/2016/Tests/Day04Tests.swift b/2016/Tests/Day04Tests.swift new file mode 100644 index 0000000..b9f3a6c --- /dev/null +++ b/2016/Tests/Day04Tests.swift @@ -0,0 +1,16 @@ +import Testing + +@testable import AoC2016 + +struct Day04Tests { + let testData = """ + aaaaa-bbb-z-y-x-123[abxyz] + a-b-c-d-e-f-g-h-987[abcde] + not-a-real-room-404[oarel] + totally-real-room-200[decoy] + """ + + @Test func testPart1() throws { + #expect(try Day04(data: testData).part1() == 1514) + } +}