use mino::matrix::{COLUMNS, EMPTY_ROW, FULL_ROW}; use mino::Mat; mod downstacking; pub use downstacking::mystery_mdse; pub fn evaluate(mat: &Mat, pcnt: usize) -> i32 { // TODO: public interface for weights etc. struct Weights { height: i32, i_deps: i32, mdse: i32, pcnt: i32, } const W: Weights = Weights { height: 5, i_deps: 10, mdse: 10, pcnt: 10, }; let mut rating = 0; rating += max_height(mat) * W.height; rating += i_deps(mat) * W.i_deps; rating += mystery_mdse(mat) * W.mdse; rating += (pcnt as i32) * W.pcnt; rating } pub fn max_height(matrix: &Mat) -> i32 { matrix.rows() as i32 } pub fn i_deps(matrix: &Mat) -> i32 { let mut depth = [0u8; COLUMNS as usize]; let mut count = 0; for y in 0..matrix.rows() { // 012345689xxxx // ↑ // _______xxx___ let mut mask = 0b111 << (COLUMNS - 2); // _______x.x___ let mut test = 0b101 << (COLUMNS - 2); for x in (0..COLUMNS).rev() { if matrix.test_row(y, mask, test) { depth[x as usize] += 1; depth[x as usize] %= 4; if depth[x as usize] == 3 { count += 1; } } else { depth[x as usize] = 0; } mask >>= 1; test >>= 1; } } count } pub fn row_trans(matrix: &Mat) -> i32 { let mut prev_row = FULL_ROW; let mut count = 0; for &curr_row in &matrix[..] { count += (curr_row ^ prev_row).count_ones(); prev_row = curr_row; } count += (prev_row ^ EMPTY_ROW).count_ones(); count as i32 } #[cfg(test)] mod test { use super::*; use mino::mat; #[test] fn test_i_deps() { assert_eq!(i_deps(Mat::EMPTY), 0); assert_eq!( i_deps(mat! { "xxxxx...xx"; "xxxxx..xxx"; "xxxxx.xx.x"; "xxxxx.xxxx"; }), 0 ); assert_eq!( i_deps(mat! { "xxx.....xx"; "xxxx..xxxx"; "xxxxx.xxxx"; "x.xxx.xxxx"; }), 0 ); assert_eq!( i_deps(mat! { "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 1 ); assert_eq!( i_deps(mat! { "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 1 ); assert_eq!( i_deps(mat! { "xxxxxxxx.x"; "xxxxxxxx.x"; "xxxxxxxx.x"; "xxxxxxxx.x"; "x.xxxxxxxx"; "x.xxxxxxxx"; "x.xxxxxxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 3, ); assert_eq!( i_deps(mat! { // 6 rows "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 1 ); assert_eq!( i_deps(mat! { // 7 rows "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 2 ); assert_eq!( i_deps(mat! { "x.x......x"; "x.xxx.xxxx"; "x.xxx.xxxx"; "x.xxx.xxxx"; }), 2 ); } #[test] fn test_row_trans() { assert_eq!(row_trans(Mat::EMPTY), 10); assert_eq!( row_trans(mat! { "x........."; "xx........"; "xxx......."; "xxxx......"; "xxxxx....."; "xxxxxx...."; "xxxxxxx..."; "xxxxxxxx.."; "xxxxxxxxx."; "xxxxxxxxxx"; }), 10, ); assert_eq!( row_trans(mat! { "xxxxx.xxxx"; }), 9 + 1, ); assert_eq!( row_trans(mat! { "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; "xxxxx.xxxx"; }), 9 + 1, ); assert_eq!( row_trans(mat! { "xxxxx.xxxx"; "xxxx.Xxxxx"; }), 9 + 2 + 1 ); assert_eq!( row_trans(mat! { "xxxxx.xxx."; "xx....xxxx"; }), 8 + 4 + 4 ); assert_eq!( row_trans(mat! { "xxxx..xxxx"; "xxxx...xxx"; "xxxxx.xxxx"; }), 8 + 1 + 2 + 1, ); } }