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