From 2a68c5ff26249a7f59fc3d1893e9fec9d3bae5a1 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Sat, 25 Dec 2021 16:10:40 +0100 Subject: [PATCH] Day 24 (Slooow) --- AoC21.xcodeproj/project.pbxproj | 99 +++++++ day24.swift | 453 ++++++++++++++++++++++++++++++++ 2 files changed, 552 insertions(+) create mode 100644 day24.swift diff --git a/AoC21.xcodeproj/project.pbxproj b/AoC21.xcodeproj/project.pbxproj index d15ff6e..81f2578 100644 --- a/AoC21.xcodeproj/project.pbxproj +++ b/AoC21.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 26132D372774C886004F0228 /* day23.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26132D2B2774C871004F0228 /* day23.swift */; }; 26132D382774C886004F0228 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; }; + 26132D482775D6A5004F0228 /* day24.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26132D472775D6A5004F0228 /* day24.swift */; }; + 26132D492775D6AC004F0228 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; }; 2615545A276A6C2C00374D18 /* day14.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155459276A6C2C00374D18 /* day14.swift */; }; 2615545B276A6C3200374D18 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; }; 26155468276A6D0A00374D18 /* day15.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155467276A6D0A00374D18 /* day15.swift */; }; @@ -55,6 +57,15 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 26132D3E2775D68D004F0228 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 26155450276A6C1C00374D18 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -213,6 +224,8 @@ /* Begin PBXFileReference section */ 26132D2B2774C871004F0228 /* day23.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = day23.swift; sourceTree = ""; }; 26132D302774C87D004F0228 /* Day23 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day23; sourceTree = BUILT_PRODUCTS_DIR; }; + 26132D402775D68D004F0228 /* Day24 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day24; sourceTree = BUILT_PRODUCTS_DIR; }; + 26132D472775D6A5004F0228 /* day24.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = day24.swift; sourceTree = ""; }; 26155452276A6C1C00374D18 /* Day14 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day14; sourceTree = BUILT_PRODUCTS_DIR; }; 26155459276A6C2C00374D18 /* day14.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = day14.swift; sourceTree = ""; }; 26155460276A6CF700374D18 /* Day15 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day15; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -258,6 +271,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 26132D3D2775D68D004F0228 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 2615544F276A6C1C00374D18 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -383,6 +403,7 @@ 263BA594275E974800839C92 = { isa = PBXGroup; children = ( + 26132D472775D6A5004F0228 /* day24.swift */, 26132D2B2774C871004F0228 /* day23.swift */, 2680ECFB27732A9400CAB23C /* day22.swift */, 2680ECE22771D82400CAB23C /* day21.swift */, @@ -427,6 +448,7 @@ 2680ECE72771D82F00CAB23C /* Day21 */, 2680ECF427732A8300CAB23C /* Day22 */, 26132D302774C87D004F0228 /* Day23 */, + 26132D402775D68D004F0228 /* Day24 */, ); name = Products; sourceTree = ""; @@ -451,6 +473,23 @@ productReference = 26132D302774C87D004F0228 /* Day23 */; productType = "com.apple.product-type.tool"; }; + 26132D3F2775D68D004F0228 /* Day24 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 26132D462775D68D004F0228 /* Build configuration list for PBXNativeTarget "Day24" */; + buildPhases = ( + 26132D3C2775D68D004F0228 /* Sources */, + 26132D3D2775D68D004F0228 /* Frameworks */, + 26132D3E2775D68D004F0228 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Day24; + productName = Day24; + productReference = 26132D402775D68D004F0228 /* Day24 */; + productType = "com.apple.product-type.tool"; + }; 26155451276A6C1C00374D18 /* Day14 */ = { isa = PBXNativeTarget; buildConfigurationList = 26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */; @@ -754,6 +793,10 @@ 26132D2F2774C87D004F0228 = { CreatedOnToolsVersion = 13.2.1; }; + 26132D3F2775D68D004F0228 = { + CreatedOnToolsVersion = 13.2.1; + LastSwiftMigration = 1320; + }; 26155451276A6C1C00374D18 = { CreatedOnToolsVersion = 13.1; LastSwiftMigration = 1310; @@ -849,6 +892,7 @@ 2680ECE62771D82F00CAB23C /* Day21 */, 2680ECF327732A8300CAB23C /* Day22 */, 26132D2F2774C87D004F0228 /* Day23 */, + 26132D3F2775D68D004F0228 /* Day24 */, ); }; /* End PBXProject section */ @@ -863,6 +907,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 26132D3C2775D68D004F0228 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 26132D492775D6AC004F0228 /* common.swift in Sources */, + 26132D482775D6A5004F0228 /* day24.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 2615544E276A6C1C00374D18 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1043,6 +1096,43 @@ }; name = Release; }; + 26132D442775D68D004F0228 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 722B335UM5; + ENABLE_HARDENED_RUNTIME = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 26132D452775D68D004F0228 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 722B335UM5; + ENABLE_HARDENED_RUNTIME = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; 26155456276A6C1C00374D18 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1701,6 +1791,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 26132D462775D68D004F0228 /* Build configuration list for PBXNativeTarget "Day24" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 26132D442775D68D004F0228 /* Debug */, + 26132D452775D68D004F0228 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/day24.swift b/day24.swift new file mode 100644 index 0000000..c94013c --- /dev/null +++ b/day24.swift @@ -0,0 +1,453 @@ +import Foundation + +@main +struct Day24: Puzzle { + + func run() { + let program = readInput() + + var alus: [(Alu, min: Int, max: Int)] = [(Alu(), 0, 0)] + + for instruction in program { + if case .inp(let register) = instruction { + buildNextAlus(&alus, register: register) + } else { + for index in alus.indices { + alus[index].0.run(instruction) + } + } + } + + let serialNumbers = alus + .lazy + .filter { $0.0[Alu.resultRegister] == 0 } + + print("Part 1:", serialNumbers.map(\.max).max()!) + print("Part 2:", serialNumbers.map(\.min).min()!) + } + + func buildNextAlus(_ alus: inout [(Alu, min: Int, max: Int)], register: RegisterId) { + var table: [Alu: Int] = [:] + + var newAlus: [(Alu, Int, Int)] = [] + + for digit: Alu.Register in 1...9 { + for (alu, oldMin, oldMax) in alus { + var alu = alu + alu[register] = digit + let newMin = oldMin * 10 + Int(digit) + let newMax = oldMax * 10 + Int(digit) + + if let index = table[alu] { + newAlus[index].1 = min(newAlus[index].1, newMin) + newAlus[index].2 = max(newAlus[index].2, newMax) + } else { + table[alu] = newAlus.count + newAlus.append((alu, newMin, newMax)) + } + } + } + + print("Alu count", newAlus.count) + alus = newAlus + } + + func readInput() -> [Instruction] { + let scanner = Scanner(string: input) + var program: [Instruction] = [] + while !scanner.isAtEnd { + program.append(scanner.instruction()) + } + return program + } + +} + + +struct Alu: Hashable { + static let resultRegister: RegisterId = 3 + typealias Register = Int + var w: Register = 0 + var x: Register = 0 + var y: Register = 0 + var z: Register = 0 + + func getValue(_ operand: Operand) -> Register { + switch operand { + case .register(let registerId): + return self[registerId] + case .number(let int): + return Register(int) + } + } + + subscript(register: RegisterId) -> Register { + _read { + switch register { + case 0: yield w + case 1: yield x + case 2: yield y + case 3: yield z + default: fatalError() + } + } + + _modify { + switch register { + case 0: yield &w + case 1: yield &x + case 2: yield &y + case 3: yield &z + default: fatalError() + } + } + + } + + mutating func run(_ instruction: Instruction) { + switch instruction { + case .inp: + break + + case .add(let registerId, let operand): + self[registerId] += getValue(operand) + + case .mul(let registerId, let operand): + self[registerId] *= getValue(operand) + + case .div(let registerId, let operand): + self[registerId] /= getValue(operand) + + case .mod(let registerId, let operand): + self[registerId] %= getValue(operand) + + case .eql(let registerId, let operand): + self[registerId] = (self[registerId] == getValue(operand)) ? 1 : 0 + } + } + +} + +typealias RegisterId = Int + +enum Operand { + case register(RegisterId) + case number(Int) +} + +enum Instruction { + case inp(RegisterId) + case add(RegisterId, Operand) + case mul(RegisterId, Operand) + case div(RegisterId, Operand) + case mod(RegisterId, Operand) + case eql(RegisterId, Operand) +} + +extension Scanner { + func register() -> RegisterId? { + + if scanString("w") != nil { + return 0 + } + + if scanString("x") != nil { + return 1 + } + + if scanString("y") != nil { + return 2 + } + + if scanString("z") != nil { + return 3 + } + + return nil + } + + func operand() -> Operand { + if let register = register() { + return .register(register) + } + + if let int = scanInt() { + return .number(int) + } + + fatalError() + } + + func instruction() -> Instruction { + guard let command = scanUpToCharacters(from: .whitespaces), + let target = register() + else { + fatalError() + } + + switch command { + case "inp": return .inp(target) + case "add": return .add(target, operand()) + case "mul": return .mul(target, operand()) + case "div": return .div(target, operand()) + case "mod": return .mod(target, operand()) + case "eql": return .eql(target, operand()) + default: fatalError() + } + } +} + +let input = """ +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 8 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 15 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 13 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 2 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -10 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 1 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -3 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 5 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 10 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 12 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 6 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 1 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 12 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 9 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 14 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -2 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -9 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 2 +mul y x +add z y +"""