diff --git a/2021/3.ts b/2021/3.ts index 2e7551c..7e4ca2a 100644 --- a/2021/3.ts +++ b/2021/3.ts @@ -3,8 +3,42 @@ const input = await collectArray(await inputLines("3")); type SubmarineCommand = ["forward", number] | ["up", number] | ["down", number]; +type Counters = [zeroCount: number, oneCount: number][]; + const ASCII_ZERO = "0".charCodeAt(0); + +function countBits( + input: string[], + width?: number, + windowWidth?: number, +): Counters { + if (!width) width = input[0].length; + if (!windowWidth) windowWidth = width; + const counter: Counters = Array.from(Array(width), (_) => [0, 0]); + for (const l of input) { + for (let i = width - windowWidth; i < width; i++) { + const val = l.charCodeAt(i) - ASCII_ZERO; + counter[i][val]++; + } + } + return counter; +} + export function part1(input: string[]): number { + const width = input[0].length; + const counter = countBits(input); + const ones = [...Array(width).keys()].reduce((acc, i) => + acc += (counter[i][1] >= counter[i][0]) ? (1 << i) : 0 + ); + // xor with a mask the same size as the width to get the zeroes value + console.log("oz:", ones); + return ones * (ones ^ (Math.pow(2, width) - 1)); +} + +await measureDuration(() => console.log("Part 1", part1(input))); + +export function part2(input: string[]): number { + // I hate this. const width = input[0].length; const counter = Array.from(Array(width), (_) => [0, 0]); for (const l of input) { @@ -13,20 +47,52 @@ export function part1(input: string[]): number { counter[i][val]++; } } - let ones = 0; + let oxyGenRating = null; + let coScrubRating = null; + let oxyGenCandidates = input.slice(0); + let coScrubCandidates = input.slice(0); for (let i = 0; i < width; i++) { - if (counter[i][1] >= counter[i][0]) ones++; - ones = ones << 1; + const newOxyGenCandidates: string[] = []; + const newCoScrubCandidates: string[] = []; + // console.log(counter[i]); + const moreCommon = (counter[i][1] > counter[i][0] ? 1 : 0).toString(); + // console.log(i, width, moreCommon); + if (!oxyGenRating) { + for (const binnum of oxyGenCandidates) { + if (binnum[i] == moreCommon) newOxyGenCandidates.push(binnum); + } + if (newOxyGenCandidates.length == 1) { + oxyGenRating = parseInt(newOxyGenCandidates[0], 2); + /* + console.log( + "Oxygen Generator Rating:", + oxyGenRating, + oxyGenCandidates, + newOxyGenCandidates, + ); + */ + } else oxyGenCandidates = newOxyGenCandidates; + // console.log(oxyGenCandidates); + } + if (!coScrubRating) { + for (const binnum of coScrubCandidates) { + if (binnum[i] != moreCommon) newCoScrubCandidates.push(binnum); + } + if (newCoScrubCandidates.length == 1) { + coScrubRating = parseInt(newCoScrubCandidates[0], 2); + /* + console.log( + "CO2 Scrubber Rating:", + coScrubRating, + coScrubCandidates, + newCoScrubCandidates, + ); + */ + } else coScrubCandidates = newCoScrubCandidates; + // console.log(coScrubCandidates); + } } - ones = ones >> 1; - const zeroes = ones ^ (Math.pow(2, width) - 1); // xor with a mask the same size as the width - return ones * zeroes; + return (oxyGenRating || 0) * (coScrubRating || 0); } -await measureDuration(() => console.log("Part 1", part1(input))); - -export function part2(input: string[]): number { - return 0; -} - -await measureDuration(() => console.log("Part 2", part2(input))); +// await measureDuration(() => console.log("Part 2", part2(input))); diff --git a/2021/three.nim b/2021/three.nim new file mode 100644 index 0000000..eca2999 --- /dev/null +++ b/2021/three.nim @@ -0,0 +1,51 @@ +import std/[strutils, sequtils, options, math] +import ./common + +const ASCII_ZERO = int('0') +type BitCounter = object + zeroes: int + ones: int + +proc countBits(inputs: seq[string], maybeWidth: Option[int], maybeWindow: Option[int]): 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 + +proc powerConsumption(inputs: seq[string]): int = + let counters = inputs.countBits(none(int), none(int)) + let width: Natural = inputs[0].len() + for i in 0.. counters[i].zeroes: inc result + result = result shl 1 + result = result shr 1 + result = result * (result xor ((2 ^ width) - 1)) + +proc lifeSupportRating(inputs: seq[string]): int = + return 0 + +let input = 3.loadInput() +time("countBits part 1"): echo input.powerConsumption() + +when not defined(release): + static: + let testInput = @[ + "00100", + "11110", + "10110", + "10111", + "10101", + "01111", + "00111", + "11100", + "10000", + "11001", + "00010", + "01010", + ] + doAssert testInput.powerConsumption() == 198 + doAssert testInput.lifeSupportRating() == 230