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)]
|
#[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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue