Created
December 4, 2023 13:11
-
-
Save doeixd/b5ab68857bc183a441b841cd768053f4 to your computer and use it in GitHub Desktop.
day3.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let isTest = Deno.args.join('').match(/test\d?/)?.[0] | |
if (isTest && !/\d/.test(isTest.split('').at(-1))) isTest += '1' | |
let file = await Deno.readTextFile(`./${isTest || `input`}`) | |
file = file.trim('').split('\n') | |
let valid_parts_acc = 0 | |
let gear_acc = 0 | |
let part_number_map = {} | |
let gears = [] | |
for (let line_idx in file) { | |
line_idx = +line_idx | |
part_number_map[line_idx] ||= {} | |
let line = file[line_idx] | |
let part_numbers = [] | |
for (let char_idx in line) { | |
char_idx = +char_idx | |
let char = line[char_idx] | |
let char_is_digit = /\d/.test(char) | |
let prev_char_is_digit = /\d/.test(line[char_idx - 1]) | |
let is_start_of_part_number = char_is_digit && !prev_char_is_digit | |
let is_tail_of_part_number = char_is_digit && prev_char_is_digit | |
if (is_start_of_part_number) part_numbers.push({ digits: [char], start: char_idx }) | |
if (is_tail_of_part_number) part_numbers.at(-1).digits.push(char) | |
let is_gear = char == '*' | |
if (is_gear) gears.push({ char_idx, line_idx }) | |
} | |
for (let part_number of part_numbers) { | |
for (let i = part_number.start; i < (part_number.digits.length + part_number.start); i++) { | |
part_number_map[line_idx][i] = part_number | |
} | |
let box_lines = make_get_box(line_idx)(part_number.start, part_number.digits.length) | |
let has_special = /[^\d\.]/ | |
let part_number_int = parseInt(part_number.digits.join('')) | |
let is_vaild_part_number = box_lines | |
.map(l => has_special.test(l)) | |
.some(l => l) | |
if (is_vaild_part_number) valid_parts_acc += part_number_int | |
} | |
} | |
for (let gear of gears) { | |
let box_lines = make_get_box(gear.line_idx)(gear.char_idx, 1, true).flat() | |
let adjecent_parts = new Set() | |
for (let { box_line_idx, box_char_idx } of box_lines) { | |
let part = part_number_map?.[box_line_idx]?.[box_char_idx] | |
part && adjecent_parts.add(part) | |
} | |
if (adjecent_parts.size !== 2) continue; | |
adjecent_parts = Array.from(adjecent_parts).map(l => parseInt(l.digits.join(''))) | |
let ratio = (adjecent_parts[0]) * (adjecent_parts[1]) | |
gear_acc += ratio | |
} | |
console.log(valid_parts_acc) | |
console.log() | |
console.log(gear_acc) | |
function make_get_box(line_idx) { | |
let previous_line = file?.[line_idx - 1] || '' | |
let line = file[line_idx] | |
let next_line = file?.[line_idx + 1] || '' | |
return function get_box(start, len = 1, just_indexes = false) { | |
let box_start = start == 0 ? 0 : start - 1 | |
let number_end = len + start | |
let box_end = (number_end) == line.length ? line.length : (number_end) + 1 | |
let lines = [previous_line, line, next_line] | |
.map(l => l.slice(box_start, box_end)) | |
if (just_indexes) { | |
return lines.map((box_chars, box_line_idx) => { | |
let sub = box_line_idx == 0 ? 1 : box_line_idx == 1 ? 0 : -1 | |
let real_line_idx = Math.min(Math.max(line_idx - sub, 0), file.length - 1) | |
let box_chars_idx = Array.from(box_chars).map((_box_char, box_char_idx) => { | |
return box_char_idx + box_start | |
}) | |
return box_chars_idx.map(box_char_idx => { | |
return { box_line_idx: real_line_idx, box_char_idx } | |
}) | |
}) | |
} | |
return lines | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
day4