-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Michał Kleszczyński
committed
Dec 9, 2024
1 parent
b495aba
commit 9ec8407
Showing
4 changed files
with
122 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { readFileSync } from 'node:fs' | ||
|
||
import { runExamples, runSolution } from '@magiczne/advent-of-code-ts-core/aoc' | ||
|
||
const EMPTY = -1 | ||
|
||
const part1 = (data: ReadonlyArray<number>): number => { | ||
let currentFileId = 0 | ||
const disk: Array<number> = [] | ||
|
||
for (let i = 0; i < data.length; i++) { | ||
const isEmpty = i % 2 !== 0 | ||
const value = isEmpty ? EMPTY : currentFileId | ||
|
||
disk.push(...Array.from({ length: data[i] }, _ => value)) | ||
|
||
if (!isEmpty) { | ||
currentFileId++ | ||
} | ||
} | ||
|
||
for (let i = disk.length - 1; i >= 0; i--) { | ||
if (disk[i] === EMPTY || disk.indexOf(EMPTY) > i) { | ||
continue | ||
} | ||
|
||
disk[disk.indexOf(EMPTY)] = disk[i] | ||
disk[i] = EMPTY | ||
} | ||
|
||
return disk.reduce((acc, item, index) => { | ||
if (item === EMPTY) { | ||
return acc | ||
} | ||
|
||
return acc + index * item | ||
}, 0) | ||
} | ||
|
||
const part2 = (data: ReadonlyArray<number>): number => { | ||
let currentFileId = 0 | ||
let disk: Array<{ id: number; length: number }> = data.map((item, index) => { | ||
const isEmpty = index % 2 !== 0 | ||
const id = isEmpty ? EMPTY : currentFileId++ | ||
|
||
if (isEmpty) { | ||
return { id, length: item } | ||
} | ||
|
||
return { | ||
id, | ||
length: item, | ||
} | ||
}) | ||
|
||
for (let i = currentFileId - 1; i >= 0; i--) { | ||
const fileIndex = disk.findIndex(block => block.id === i) | ||
const freeSpaceIndex = disk.findIndex(block => block.id === EMPTY && block.length >= disk[fileIndex].length) | ||
|
||
if (freeSpaceIndex === -1 || fileIndex < freeSpaceIndex) { | ||
continue | ||
} | ||
|
||
if (disk[freeSpaceIndex].length > disk[fileIndex].length) { | ||
disk = [ | ||
...disk.slice(0, freeSpaceIndex), | ||
{ id: disk[fileIndex].id, length: disk[fileIndex].length }, | ||
{ id: EMPTY, length: disk[freeSpaceIndex].length - disk[fileIndex].length }, | ||
...disk.slice(freeSpaceIndex + 1), | ||
] | ||
disk[fileIndex + 1].id = EMPTY | ||
} else if (disk[freeSpaceIndex].length === disk[fileIndex].length) { | ||
disk[freeSpaceIndex].id = disk[fileIndex].id | ||
disk[fileIndex].id = EMPTY | ||
} | ||
} | ||
|
||
// There may be places with two empty blocks next to each other, we need to compact them | ||
for (let j = 0; j < disk.length - 1; j++) { | ||
if (disk[j].id == EMPTY && disk[j + 1].id == EMPTY) { | ||
disk = [...disk.slice(0, j), { id: EMPTY, length: disk[j].length + disk[j + 1].length }, ...disk.slice(j + 2)] | ||
|
||
j-- | ||
} | ||
} | ||
|
||
return disk.reduce( | ||
(acc, block) => { | ||
if (block.id === EMPTY) { | ||
return { | ||
blockId: acc.blockId + block.length, | ||
checksum: acc.checksum, | ||
} | ||
} | ||
|
||
return { | ||
blockId: acc.blockId + block.length, | ||
checksum: | ||
acc.checksum + | ||
Array.from({ length: block.length }, (_, index) => { | ||
return block.id * (index + acc.blockId) | ||
}).reduce((blockAcc, value) => blockAcc + value, 0), | ||
} | ||
}, | ||
{ blockId: 0, checksum: 0 }, | ||
).checksum | ||
} | ||
|
||
const reader = (file: string): ReadonlyArray<number> => { | ||
return readFileSync(file, 'utf-8') | ||
.trim() | ||
.split('') | ||
.map(item => { | ||
return parseInt(item, 10) | ||
}) | ||
} | ||
|
||
runExamples(2024, '09', reader, part1, part2) | ||
runSolution(2024, '09', reader, part1, part2) |
Oops, something went wrong.