code quality: downstacking.rs
This commit is contained in:
parent
d564bc25af
commit
71efd222eb
|
@ -21,9 +21,10 @@ pub fn mystery_mdse(init_mat: &Mat) -> i32 {
|
||||||
debug_assert!(!res_ys.is_empty(), "{res_ys:?}");
|
debug_assert!(!res_ys.is_empty(), "{res_ys:?}");
|
||||||
|
|
||||||
let res = &mut mat[res_ys];
|
let res = &mut mat[res_ys];
|
||||||
|
// determine pieces needed to fill residue by filling them
|
||||||
if let Some((_x0, _y0, area)) = flood_fill(res) {
|
if let Some((_x0, _y0, area)) = flood_fill(res) {
|
||||||
// estimate pieces needed to fill residue, and then fill them
|
// min number of pieces = ceil(area/4)
|
||||||
let res_pc = (area + 3) / 4; // = ceil(area/4)
|
let res_pc = (area + 3) / 4;
|
||||||
|
|
||||||
// add to total count, but dampen by iteration count; residue cleared later on
|
// add to total count, but dampen by iteration count; residue cleared later on
|
||||||
// most likely has blocks contributed to it by attempts to clear in earlier
|
// most likely has blocks contributed to it by attempts to clear in earlier
|
||||||
|
@ -54,39 +55,42 @@ pub fn mystery_mdse(init_mat: &Mat) -> i32 {
|
||||||
/// 1 xxxxxxxx.x
|
/// 1 xxxxxxxx.x
|
||||||
/// 0 xx..xxxxxx
|
/// 0 xx..xxxxxx
|
||||||
///
|
///
|
||||||
/// Given this stack, `residue` returns the range `2..=3`. The hole found is in row 1
|
/// Given this stack, `residue` returns the range `2..4`. The hole found is in row 1
|
||||||
/// column 8, and there are two rows of residue above it. Note that the hole in row 0
|
/// column 8, and there are two rows of residue above it. Note that the hole in row 0
|
||||||
/// columns 2-3 is also a valid hole, but row 1 is found first because it is on a higher
|
/// columns 2-3 is also a valid hole, but row 1 is found first because it is on a higher
|
||||||
/// row.
|
/// row.
|
||||||
fn residue(mat: &Mat) -> Option<Range<i16>> {
|
fn residue(mat: &Mat) -> Option<Range<i16>> {
|
||||||
let mut y = mat.rows();
|
// find hole that is covered
|
||||||
let mut prev_row = EMPTY_ROW; // = mat[y]
|
let mut mask;
|
||||||
|
|
||||||
// find garbage row
|
let mut y0 = mat.rows();
|
||||||
let mask = loop {
|
let mut prev_row = EMPTY_ROW; // = mat[y]
|
||||||
if y == 0 {
|
loop {
|
||||||
|
if y0 == 0 {
|
||||||
// hit the bottom
|
// hit the bottom
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let curr_row = mat[y - 1];
|
let curr_row = mat[y0 - 1];
|
||||||
let mask = prev_row & !curr_row;
|
|
||||||
// for some bit i, prev_row[i] == 1 && curr_row[i] == 0
|
// for some bit i, prev_row[i] == 1 && curr_row[i] == 0
|
||||||
|
mask = prev_row & !curr_row;
|
||||||
if mask != 0 {
|
if mask != 0 {
|
||||||
break mask;
|
break;
|
||||||
}
|
}
|
||||||
y -= 1;
|
|
||||||
|
y0 -= 1;
|
||||||
prev_row = curr_row;
|
prev_row = curr_row;
|
||||||
};
|
}
|
||||||
|
|
||||||
// find top of residue
|
// find top of residue
|
||||||
let y0 = y;
|
let mut y1 = y0;
|
||||||
let y1 = loop {
|
loop {
|
||||||
let curr_row = mat[y];
|
let curr_row = mat[y1];
|
||||||
if curr_row & mask == 0 {
|
if curr_row & mask == 0 {
|
||||||
break y;
|
break;
|
||||||
}
|
}
|
||||||
y += 1;
|
y1 += 1;
|
||||||
};
|
}
|
||||||
|
|
||||||
Some(y0..y1)
|
Some(y0..y1)
|
||||||
}
|
}
|
||||||
|
@ -98,6 +102,9 @@ fn residue(mat: &Mat) -> Option<Range<i16>> {
|
||||||
fn flood_fill(rows: &mut [u16]) -> Option<(i16, i16, u32)> {
|
fn flood_fill(rows: &mut [u16]) -> Option<(i16, i16, u32)> {
|
||||||
fn init(rows: &[u16]) -> Option<(i16, i16)> {
|
fn init(rows: &[u16]) -> Option<(i16, i16)> {
|
||||||
for (y, row) in rows.iter().enumerate() {
|
for (y, row) in rows.iter().enumerate() {
|
||||||
|
// trailing_ones() finds some unoccipied cell in `row`. if the row is full
|
||||||
|
// then this return 16 (since there are 16 bits in the row representation
|
||||||
|
// type).
|
||||||
let x = row.trailing_ones();
|
let x = row.trailing_ones();
|
||||||
if x < 16 {
|
if x < 16 {
|
||||||
return Some((x as i16, y as i16));
|
return Some((x as i16, y as i16));
|
||||||
|
@ -107,10 +114,12 @@ fn flood_fill(rows: &mut [u16]) -> Option<(i16, i16, u32)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flood(rows: &mut [u16], x: i16, y: i16) -> u32 {
|
fn flood(rows: &mut [u16], x: i16, y: i16) -> u32 {
|
||||||
|
// test if (x,y) is OOB
|
||||||
if x < 0 || y < 0 || (y as usize) >= rows.len() {
|
if x < 0 || y < 0 || (y as usize) >= rows.len() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to fill in (x,y)
|
||||||
let idx = y as usize;
|
let idx = y as usize;
|
||||||
let mask = 1 << x;
|
let mask = 1 << x;
|
||||||
if rows[idx] & mask != 0 {
|
if rows[idx] & mask != 0 {
|
||||||
|
@ -128,7 +137,6 @@ fn flood_fill(rows: &mut [u16]) -> Option<(i16, i16, u32)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (x0, y0) = init(rows)?;
|
let (x0, y0) = init(rows)?;
|
||||||
|
|
||||||
Some((x0, y0, flood(rows, x0, y0)))
|
Some((x0, y0, flood(rows, x0, y0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue