Snippet

advent_of_code/2024_9.rb
Code:
# Advent of Code 2024, Day 9: Disk Fragmenter

# https://adventofcode.com/2024/day/9

require_relative './helpers.rb'

def lfi(d, ix = d.size - 1)
  ix -= 1 until d[ix] != nil
  return ix
end

def fbi(d, ix = 0)
  ix += 1 until d[ix] == nil
  return ix
end

def part_one(d)
  [lfi(d), fbi(d)].as { |f, b| d[f], d[b] = d[b], d[f] } until lfi(d) == fbi(d) - 1
  d.compact.map.with_index { |n, i| n * i }.sum
end

def part_two(d, last)
  last.downto(0).each { |id|
    s, f, b = d.count(id), d.find_index(id), -1
    d.size.times { |i| (b = i; break) if d[i, s].compact == [] }
    next if (b < 0) || (f < b)
    d[f, s], d[b, s] = d[b, s], d[f, s]
  }
  d.map.with_index { |n, i| (n ? n : 0) * i }.sum
end

def solve(data)
  id = -1
  data = data[0].chars.map.with_index { |n, i| [i.odd? ? nil : id += 1] * n.to_i }.flatten
  [part_one(data.dup), part_two(data.dup, id)]
end

puts solve(get_dataset(year: 2024, day: 9, type: 'example'))
puts solve(get_dataset(year: 2024, day: 9, type: 'example_2'))
# puts solve(get_dataset(year: 2024, day: 9, type: 'input'))
Output:
1928
2858
60
132