un-nest Block enum
This commit is contained in:
parent
da74a98b8b
commit
fc0fd327c3
1 changed files with 27 additions and 39 deletions
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue