diff --git a/2021/three.nim b/2021/three.nim index eca2999..5637f74 100644 --- a/2021/three.nim +++ b/2021/three.nim @@ -1,4 +1,4 @@ -import std/[strutils, sequtils, options, math] +import std/[strutils, sequtils, options, math, parseutils] import ./common const ASCII_ZERO = int('0') @@ -6,18 +6,18 @@ type BitCounter = object zeroes: int ones: int -proc countBits(inputs: seq[string], maybeWidth: Option[int], maybeWindow: Option[int]): seq[BitCounter] = +proc countBits(inputs: seq[string], maybeWidth: Option[int], offset = 0): seq[BitCounter] = let width = maybeWidth.get(inputs[0].len()) - let window = maybeWindow.get(width) - let start = (width - window) - for i in 0.. 0: inc result[i - start].ones - else: inc result[i - start].zeroes + for i in offset.. 0: inc result[outIndex].ones + else: inc result[outIndex].zeroes proc powerConsumption(inputs: seq[string]): int = - let counters = inputs.countBits(none(int), none(int)) + let counters = inputs.countBits(none(int)) let width: Natural = inputs[0].len() for i in 0.. counters[i].zeroes: inc result @@ -26,10 +26,48 @@ proc powerConsumption(inputs: seq[string]): int = result = result * (result xor ((2 ^ width) - 1)) proc lifeSupportRating(inputs: seq[string]): int = - return 0 + let width: Natural = inputs[0].len() + var oxygenRating, co2Rating = 0 + var oxygenCandidates, co2Candidates: seq[int] = toSeq(0..= counters[0].zeroes: '1' else: '0' + echo "OX: ", i, candidates, moreCommon, counters[0] + if counters[0].zeroes == counters[0].ones: + echo "SAME OX" + for j in oxygenCandidates: + if inputs[j][i] == moreCommon: + newOxygenCandidates.add(j) + if newOxygenCandidates.len() == 1: + discard inputs[newOxygenCandidates[0]].parseBin(oxygenRating) + echo "OX DONE" + if co2Rating == 0: + let candidates = co2Candidates.mapIt(inputs[it]) + let counters = countBits(candidates, some(1), i) + let lessCommon: char = if counters[0].zeroes <= counters[0].ones: '0' else: '1' + echo "CO2 ", i, candidates, lessCommon, counters[0] + if counters[0].zeroes == counters[0].ones: + echo "SAME CO2" + for j in co2Candidates: + if inputs[j][i] == lessCommon: + newCo2Candidates.add(j) + if newCo2Candidates.len() == 1: + discard inputs[newCo2Candidates[0]].parseBin(co2Rating) + echo "CO2 DONE" + oxygenCandidates = newOxygenCandidates + co2Candidates = newCo2Candidates + if oxygenRating != 0 and co2Rating != 0: break + echo "OX: ", oxygenRating + echo "CO2: ", co2Rating + return oxygenRating * co2Rating let input = 3.loadInput() -time("countBits part 1"): echo input.powerConsumption() +time("powerConsumption part 1"): echo input.powerConsumption() +time("lifeSupportRating part 2"): echo input.lifeSupportRating() when not defined(release): static: