mosredna

AoC 2024 day 9

Dec 9th, 2024 (edited)
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 2.94 KB | Source Code | 0 0
  1. const fs = require("fs")
  2.  
  3. const input = fs.readFileSync(__dirname + (process.argv.includes("--test") ? "/test.txt" : "/input.txt"), "utf8").trim()
  4.  
  5. const parseDiskBlocks = (data) => {
  6.     const diskBlocks = []
  7.     let fileId = 0,
  8.         isFile = true
  9.  
  10.     for (const length of data) {
  11.         const len = +length
  12.         diskBlocks.push(...Array(len).fill(isFile ? fileId : "."))
  13.         if (isFile) fileId++
  14.         isFile = !isFile
  15.     }
  16.  
  17.     return diskBlocks
  18. }
  19.  
  20. const computeChecksum = (diskBlocks) =>
  21.     diskBlocks.reduce((checksum, block, index) => checksum + (block !== "." ? index * block : 0), 0)
  22.  
  23. const compactDisk = (diskBlocks) => {
  24.     let left = 0,
  25.         right = diskBlocks.length - 1
  26.  
  27.     while (left < diskBlocks.length && diskBlocks[left] !== ".") left++
  28.     while (right > left) {
  29.         while (right > left && diskBlocks[right] === ".") right--
  30.         if (right <= left) break
  31.         ;[diskBlocks[left], diskBlocks[right]] = [diskBlocks[right], "."]
  32.         while (left < diskBlocks.length && diskBlocks[left] !== ".") left++
  33.         right--
  34.     }
  35.  
  36.     return diskBlocks
  37. }
  38.  
  39. const part1 = (data) => {
  40.     const diskBlocks = parseDiskBlocks(data)
  41.     const compacted = compactDisk(diskBlocks)
  42.     return computeChecksum(compacted)
  43. }
  44.  
  45. const part2 = (data) => {
  46.     const diskBlocks = parseDiskBlocks(data)
  47.     const files = []
  48.     const freeSpans = []
  49.  
  50.     diskBlocks.forEach((block, i) => {
  51.         if (block !== ".") {
  52.             files[block] ??= { id: block, size: 0, positions: [] }
  53.             files[block].positions.push(i)
  54.             files[block].size++
  55.         } else if (!freeSpans.length || freeSpans.at(-1).end + 1 !== i) {
  56.             freeSpans.push({ start: i, end: i, size: 1 })
  57.         } else {
  58.             freeSpans.at(-1).end++
  59.             freeSpans.at(-1).size++
  60.         }
  61.     })
  62.  
  63.     files.reverse().forEach((file) => {
  64.         if (!file) return
  65.  
  66.         const { size, positions } = file
  67.         const fileStartPos = positions[0]
  68.         const targetSpan = freeSpans.find((span) => span.size >= size && span.end < fileStartPos)
  69.  
  70.         if (targetSpan) {
  71.             positions.forEach((pos) => (diskBlocks[pos] = "."))
  72.             for (let i = 0; i < size; i++) {
  73.                 diskBlocks[targetSpan.start + i] = file.id
  74.             }
  75.  
  76.             if (targetSpan.size === size) {
  77.                 freeSpans.splice(freeSpans.indexOf(targetSpan), 1)
  78.             } else {
  79.                 targetSpan.start += size
  80.                 targetSpan.size -= size
  81.             }
  82.  
  83.             freeSpans.push({
  84.                 start: fileStartPos,
  85.                 end: fileStartPos + size - 1,
  86.                 size
  87.             })
  88.         }
  89.     })
  90.  
  91.     return computeChecksum(diskBlocks)
  92. }
  93.  
  94. console.time("Part 1 Time")
  95. console.log("Part 1:", part1(input))
  96. console.timeEnd("Part 1 Time")
  97.  
  98. console.time("Part 2 Time")
  99. console.log("Part 2:", part2(input))
  100. console.timeEnd("Part 2 Time")
  101.  
Advertisement
Add Comment
Please, Sign In to add comment