un-nest Block enum

This commit is contained in:
Joe Ardent 2025-01-05 16:53:58 -08:00
parent da74a98b8b
commit fc0fd327c3

View file

@ -62,41 +62,29 @@ fn pt1(input: &str) -> usize {
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
enum Block {
Free(FreeBlock),
// size, id
File(FileBlock),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
struct FreeBlock {
size: usize,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
struct FileBlock {
size: usize,
id: usize,
Free { size: usize },
File { size: usize, id: usize },
}
impl Block {
fn is_free(&self) -> Option<usize> {
match self {
Block::Free(s) => Some(s.size),
Block::Free { size } => Some(*size),
_ => None,
}
}
fn size(&self) -> usize {
match self {
Block::Free(block) => block.size,
Block::File(block) => block.size,
Block::Free { size } => *size,
Block::File { size, .. } => *size,
}
}
fn set_size(&mut self, s: usize) {
match self {
Block::Free(block) => block.size = s,
Block::File(block) => block.size = s,
Block::Free { size } => *size = s,
Block::File { size, .. } => *size = s,
}
}
}
@ -112,10 +100,10 @@ fn pt2(input: &str) -> usize {
}
};
if i % 2 == 0 {
let cell = Block::File(FileBlock { size: n, id: i / 2 });
let cell = Block::File { size: n, id: i / 2 };
map.push(cell);
} else {
map.push(Block::Free(FreeBlock { size: n }));
map.push(Block::Free { size: n });
}
}
@ -127,14 +115,14 @@ fn pt2(input: &str) -> usize {
done = true;
}
match map[i] {
Block::Free(_) => {
Block::Free { .. } => {
continue;
}
Block::File(file) => {
if processed.contains(&file.id) {
Block::File { id, .. } => {
if processed.contains(&id) {
continue;
}
processed.insert(file.id);
processed.insert(id);
if move_file(&mut map, i) {
map = compact(&map);
break;
@ -165,7 +153,7 @@ fn move_file(map: &mut Vec<Block>, file_index: usize) -> bool {
let diff = free_size - file_size;
if diff > 0 {
map[file_index].set_size(file_size);
map.insert(j + 1, Block::Free(FreeBlock { size: diff }));
map.insert(j + 1, Block::Free { size: diff });
return true;
}
break;
@ -180,14 +168,14 @@ fn render_map(map: &[Block]) -> Vec<Cell> {
for block in map {
match block {
Block::Free(free) => {
for _ in 0..free.size {
Block::Free { size } => {
for _ in 0..*size {
out.push(Cell::Free);
}
}
Block::File(file) => {
for _ in 0..file.size {
out.push(Cell::Block(file.id));
Block::File { size, id } => {
for _ in 0..*size {
out.push(Cell::Block(*id));
}
}
}
@ -199,14 +187,14 @@ fn render_map(map: &[Block]) -> Vec<Cell> {
impl Display for Block {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Block::Free(FreeBlock { size: s }) => {
Block::Free { size: s } => {
let out = (0..*s).fold(String::new(), |mut out, _| {
let _ = write!(out, ".");
out
});
write!(f, "{out}")
}
Block::File(FileBlock { size: sz, id }) => {
Block::File { size: sz, id } => {
let out = (0..*sz).fold(String::new(), |mut out, _| {
if out.is_empty() {
let _ = write!(out, "{id}");
@ -224,8 +212,8 @@ impl Display for Block {
impl Debug for Block {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Block::Free(s) => write!(f, "free: {}", s.size),
Block::File(b) => write!(f, "{}: {}", b.id, b.size),
Block::Free { size } => write!(f, "free: {}", size),
Block::File { size, id } => write!(f, "{}: {}", id, size),
}
}
}
@ -236,15 +224,15 @@ fn compact(v: &[Block]) -> Vec<Block> {
while i < v.len() {
match v[i] {
Block::File(file) => out.push(Block::File(file)),
Block::Free(free) => {
let mut total = free.size;
Block::File { size, id } => out.push(Block::File { size, id }),
Block::Free { size } => {
let mut total = size;
while let Some(next_free_size) = v.get(i + 1).and_then(|b| b.is_free()) {
total += next_free_size;
i += 1;
}
if total > 0 {
out.push(Block::Free(FreeBlock { size: total }));
out.push(Block::Free { size: total });
}
}
}