Orient all pieces rotations to 0 0 to resolve #1 and clean up.

main
felixm 2023-10-19 14:03:19 +02:00
parent 367cda9e27
commit 17984773d7
5 changed files with 535 additions and 438 deletions

111
src/field.rs Normal file
View File

@ -0,0 +1,111 @@
use crate::pattern::{AbsCoord, Pattern};
use colored::{Color, Colorize};
use std::fmt;
/// A Field is a list of available (empty) coordinates.
#[derive(Debug, Clone)]
pub struct Field {
width: u32,
height: u32,
pub empty_coords: Vec<AbsCoord>,
patterns: Vec<(AbsCoord, Pattern)>,
}
impl Field {
pub fn new(width: u32, height: u32) -> Self {
let mut empty_coords = Vec::new();
for y in 0..height {
for x in 0..width {
empty_coords.push(AbsCoord { x, y });
}
}
Self {
width,
height,
empty_coords,
patterns: Vec::new(),
}
}
pub fn add_pattern(&mut self, location: &AbsCoord, pattern: &Pattern) -> bool {
// Convert the pattern's relative coordinates to absolute coordinates
let abs_coords: Option<Vec<_>> = pattern
.coords
.iter()
.map(|rel_coord| location.add(rel_coord))
.collect();
match abs_coords {
Some(abs_coords) => {
if abs_coords
.iter()
.all(|abs_coord| self.empty_coords.contains(abs_coord))
{
self.empty_coords
.retain(|empty_coord| !abs_coords.contains(empty_coord));
self.patterns.push((location.clone(), pattern.clone()));
true
} else {
false
}
}
None => false,
}
}
pub fn fits(&self, location: &AbsCoord, pattern: &Pattern) -> bool {
let abs_coords: Option<Vec<_>> = pattern
.coords
.iter()
.map(|rel_coord| location.add(rel_coord))
.collect();
match abs_coords {
Some(abs_coords) => {
if abs_coords
.iter()
.all(|abs_coord| self.empty_coords.contains(abs_coord))
{
true
} else {
false
}
}
None => false,
}
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut grid = vec![
vec![' '.to_string().color(Color::White); self.width as usize];
self.height as usize
];
let colors = vec![
Color::Red,
Color::Green,
Color::Yellow,
Color::Blue,
Color::Magenta,
Color::Cyan,
Color::White,
Color::Black,
];
for (index, (location, pattern)) in self.patterns.iter().enumerate() {
let color = colors[index % colors.len()]; // This makes sure we loop back to the start if there are more patterns than colors.
for rel_coord in &pattern.coords {
let abs_coord = location.add(rel_coord).unwrap();
grid[abs_coord.y as usize][abs_coord.x as usize] = '#'.to_string().color(color);
}
}
for row in grid.iter() {
for cell in row.iter() {
write!(f, "{}", cell)?;
}
writeln!(f)?;
}
Ok(())
}
}

View File

@ -1,422 +1,12 @@
use std::fmt;
use colored::{Color, Colorize};
#[derive(Debug, PartialEq, Clone)]
struct RelCoord {
x: u32,
y: u32,
}
#[derive(Debug, PartialEq, Clone)]
struct AbsCoord {
x: u32,
y: u32,
}
impl AbsCoord {
fn add(&self, offset: &RelCoord) -> Self {
Self {
x: self.x + offset.x,
y: self.y + offset.y,
}
}
}
#[derive(Debug, PartialEq, Clone)]
struct Pattern {
coords: Vec<RelCoord>
}
impl fmt::Display for Pattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Determine the bounding box for the pattern.
let max_x = self.coords.iter().map(|coord| coord.x).max().unwrap_or(0);
let max_y = self.coords.iter().map(|coord| coord.y).max().unwrap_or(0);
// Initialize a 2D grid to hold the pattern representation.
let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize];
// Place the blocks of the pattern onto the grid.
for coord in &self.coords {
grid[coord.y as usize][coord.x as usize] = '#';
}
// Convert the 2D grid to a string.
for row in grid.iter() {
for cell in row.iter() {
write!(f, "{}", cell)?;
}
writeln!(f)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
struct Piece {
name: String,
patterns: Vec<Pattern>
}
impl Piece {
#[allow(dead_code)]
pub fn hero () -> Self {
let coords_vert = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 0, y: 1},
RelCoord {x: 0, y: 2},
RelCoord {x: 0, y: 3},
];
let coords_hori = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 1, y: 0},
RelCoord {x: 2, y: 0},
RelCoord {x: 3, y: 0},
];
Self {
name: "Hero".to_string(),
patterns: vec![
Pattern { coords: coords_vert },
Pattern { coords: coords_hori },
]
}
}
#[allow(dead_code)]
pub fn teewee () -> Self {
let coords_up = vec![
RelCoord {x: 1, y: 0},
RelCoord {x: 0, y: 1},
RelCoord {x: 1, y: 1},
RelCoord {x: 2, y: 1},
];
let coords_right = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 0, y: 1},
RelCoord {x: 0, y: 2},
RelCoord {x: 1, y: 1},
];
let coords_down = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 1, y: 0},
RelCoord {x: 2, y: 0},
RelCoord {x: 1, y: 1},
];
let coords_left = vec![
RelCoord {x: 0, y: 1},
RelCoord {x: 1, y: 0},
RelCoord {x: 1, y: 1},
RelCoord {x: 1, y: 2},
];
Self {
name: "Teewee".to_string(),
patterns: vec![
Pattern { coords: coords_up },
Pattern { coords: coords_right },
Pattern { coords: coords_down },
Pattern { coords: coords_left },
]
}
}
#[allow(dead_code)]
pub fn blue_ricky() -> Self {
let coords_upright = vec![
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 1, y: 2 },
RelCoord { x: 0, y: 2 },
];
let coords_right = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 2, y: 1 },
];
let coords_downright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 1, y: 0 },
];
let coords_left = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 2, y: 1 },
];
Self {
name: "Blue Ricky".to_string(),
patterns: vec![
Pattern { coords: coords_upright },
Pattern { coords: coords_right },
Pattern { coords: coords_downright },
Pattern { coords: coords_left },
]
}
}
#[allow(dead_code)]
pub fn orange_ricky() -> Self {
let coords_upright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 1, y: 2 },
];
let coords_right = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 0, y: 1 },
];
let coords_downright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 1, y: 2 },
];
let coords_left = vec![
RelCoord { x: 2, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 2, y: 1 },
];
Self {
name: "Orange Ricky".to_string(),
patterns: vec![
Pattern { coords: coords_upright },
Pattern { coords: coords_right },
Pattern { coords: coords_downright },
Pattern { coords: coords_left },
]
}
}
#[allow(dead_code)]
pub fn smashboy() -> Self {
let coords = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
];
Self {
name: "Smashboy".to_string(),
patterns: vec![
Pattern { coords },
]
}
}
#[allow(dead_code)]
pub fn cleveland_z () -> Self {
let flat = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 1, y: 0},
RelCoord {x: 1, y: 1},
RelCoord {x: 2, y: 1},
];
let upright = vec![
RelCoord {x: 1, y: 0},
RelCoord {x: 1, y: 1},
RelCoord {x: 0, y: 1},
RelCoord {x: 0, y: 2},
];
Self {
name: "Cleveland Z".to_string(),
patterns: vec![
Pattern { coords: flat },
Pattern { coords: upright },
]
}
}
#[allow(dead_code)]
pub fn rhode_island_z () -> Self {
let flat = vec![
RelCoord {x: 0, y: 1},
RelCoord {x: 1, y: 0},
RelCoord {x: 1, y: 1},
RelCoord {x: 2, y: 0},
];
let upright = vec![
RelCoord {x: 0, y: 0},
RelCoord {x: 0, y: 1},
RelCoord {x: 1, y: 1},
RelCoord {x: 1, y: 2},
];
Self {
name: "Rhode Island Z".to_string(),
patterns: vec![
Pattern { coords: flat },
Pattern { coords: upright },
]
}
}
}
impl fmt::Display for Piece {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:\n\n", self.name.red())?;
for pattern in self.patterns.iter() {
write!(f, "{}\n", pattern)?;
}
Ok(())
}
}
/// A Field is a list of available (empty) coordinates.
#[derive(Debug, Clone)]
struct Field {
width: u32,
height: u32,
empty_coords: Vec<AbsCoord>,
patterns: Vec<(AbsCoord, Pattern)>,
}
impl Field {
pub fn new(width: u32, height: u32) -> Self {
let mut empty_coords = Vec::new();
for x in 0..width {
for y in 0..height {
empty_coords.push(AbsCoord { x: x, y: y });
}
}
Self { width, height, empty_coords, patterns: Vec::new() }
}
fn add_pattern(&mut self, location: &AbsCoord, pattern: &Pattern) -> bool {
// Convert the pattern's relative coordinates to absolute coordinates
let abs_coords: Vec<_> = pattern.coords.iter().map(|rel_coord| location.add(rel_coord)).collect();
if abs_coords.iter().all(|abs_coord| self.empty_coords.contains(abs_coord)) {
self.empty_coords.retain(|empty_coord| !abs_coords.contains(empty_coord));
self.patterns.push((location.clone(), pattern.clone()));
true
} else {
false
}
}
fn fits(&self, location: &AbsCoord, pattern: &Pattern) -> bool {
let abs_coords: Vec<_> = pattern.coords.iter().map(|rel_coord| location.add(rel_coord)).collect();
if abs_coords.iter().all(|abs_coord| self.empty_coords.contains(abs_coord)) {
true
} else {
false
}
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut grid = vec![vec![' '.to_string().color(Color::White); self.width as usize]; self.height as usize];
let colors = vec![Color::Red, Color::Green, Color::Yellow, Color::Blue, Color::Magenta, Color::Cyan, Color::White, Color::Black];
for (index, (location, pattern)) in self.patterns.iter().enumerate() {
let color = colors[index % colors.len()]; // This makes sure we loop back to the start if there are more patterns than colors.
for rel_coord in &pattern.coords {
let abs_coord = location.add(rel_coord);
grid[abs_coord.y as usize][abs_coord.x as usize] = '#'.to_string().color(color);
}
}
for row in grid.iter() {
for cell in row.iter() {
write!(f, "{}", cell)?;
}
writeln!(f)?;
}
Ok(())
}
}
mod field;
mod pattern;
mod piece;
#[cfg(test)]
mod tests {
use crate::AbsCoord;
use crate::Field;
use crate::Piece;
use crate::solve;
mod tests;
#[test]
fn test_add_pattern() {
let mut field = Field::new(3, 3);
assert_eq!(field.add_pattern(&AbsCoord {x: 0, y: 0 }, &Piece::blue_ricky().patterns[0]), true);
assert_eq!(field.add_pattern(&AbsCoord {x: 0, y: 0 }, &Piece::blue_ricky().patterns[1]), false);
}
#[test]
fn test_solve_no_pieces() {
let field = Field::new(5, 5);
let pieces = vec![];
let result = solve(field, pieces);
assert!(result.is_none());
}
#[test]
fn test_solve_no_space() {
let field = Field::new(0, 0);
let pieces = vec![
Piece::smashboy(),
];
let result = solve(field, pieces);
assert!(result.is_none());
}
#[test]
fn test_solve_base_case() {
let field = Field::new(0, 0);
let pieces = vec![];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_solve_four_smashboys() {
let field = Field::new(4, 4);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_two_two_one() {
let field = Field::new(4, 5);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::blue_ricky(),
Piece::blue_ricky(),
Piece::hero(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_two_two_one_fail() {
let field = Field::new(4, 5);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::blue_ricky(),
Piece::orange_ricky(),
Piece::hero(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
}
use field::Field;
use piece::Piece;
fn solve(field: Field, pieces: Vec<Piece>) -> Option<Field> {
if field.empty_coords.is_empty() {
@ -429,7 +19,7 @@ fn solve(field: Field, pieces: Vec<Piece>) -> Option<Field> {
return None;
}
for empty_coord in &field.empty_coords.as_slice()[0..2] {
for empty_coord in &field.empty_coords {
for (piece_index, piece) in pieces.iter().enumerate() {
for pattern in &piece.patterns {
if field.fits(&empty_coord, &pattern) {
@ -439,7 +29,7 @@ fn solve(field: Field, pieces: Vec<Piece>) -> Option<Field> {
new_field.add_pattern(&empty_coord, &pattern);
match solve(new_field, new_pieces) {
Some(field) => return Some(field),
None => {},
None => {}
}
}
}
@ -449,32 +39,35 @@ fn solve(field: Field, pieces: Vec<Piece>) -> Option<Field> {
}
fn main() {
let field = Field::new(6, 6);
let field = Field::new(8, 7);
// All pieces as reference:
// Piece::cleveland_z(), // -_
// Piece::rhode_island_z(), // _-
// Piece::teewee(), // _|_
// Piece::hero(), // ____
// Piece::orange_ricky(), // ___|
// Piece::blue_ricky(), // |___
// Piece::smashboy(), // o
let pieces = vec![
Piece::cleveland_z(), // -_
Piece::cleveland_z(), // -_
Piece::cleveland_z(), // -_
Piece::orange_ricky(), // ___|
Piece::orange_ricky(), // ___|
Piece::blue_ricky(), // |___
Piece::blue_ricky(), // |___
Piece::hero(), // ----
Piece::hero(), // ----
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::teewee(),
Piece::teewee(),
// Piece::cleveland_z(), // -_
// Piece::rhode_island_z(), // _-
// Piece::teewee(),
// Piece::hero(),
// Piece::orange_ricky(), // ___|
// Piece::blue_ricky(), // |___
// Piece::smashboy(),
Piece::teewee(),
Piece::teewee(),
Piece::cleveland_z(), // -_
Piece::rhode_island_z(), // _-
Piece::orange_ricky(), // ___|
Piece::blue_ricky(), // |___
];
let result = solve(field, pieces);
match result {
Some(field) => println!("{}", field),
None => println!("No solution",)
None => println!("No solution",),
};
// for piece in &pieces {
// print!("{}", piece);
// }
}

53
src/pattern.rs Normal file
View File

@ -0,0 +1,53 @@
use std::fmt;
#[derive(Debug, PartialEq, Clone)]
pub struct RelCoord {
pub x: i32,
pub y: i32,
}
#[derive(Debug, PartialEq, Clone)]
pub struct AbsCoord {
pub x: u32,
pub y: u32,
}
impl AbsCoord {
pub fn add(&self, offset: &RelCoord) -> Option<Self> {
Some(Self {
x: ((self.x as i32) + offset.x).try_into().ok()?,
y: ((self.y as i32) + offset.y).try_into().ok()?,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Pattern {
pub coords: Vec<RelCoord>,
}
impl fmt::Display for Pattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Determine the bounding box for the pattern.
let max_x = self.coords.iter().map(|coord| coord.x).max().unwrap_or(0);
let max_y = self.coords.iter().map(|coord| coord.y).max().unwrap_or(0);
// Initialize a 2D grid to hold the pattern representation.
let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize];
// Place the blocks of the pattern onto the grid.
for coord in &self.coords {
grid[coord.y as usize][coord.x as usize] = '#';
}
// Convert the 2D grid to a string.
for row in grid.iter() {
for cell in row.iter() {
write!(f, "{}", cell)?;
}
writeln!(f)?;
}
Ok(())
}
}

235
src/piece.rs Normal file
View File

@ -0,0 +1,235 @@
use crate::pattern::{Pattern, RelCoord};
use colored::Colorize;
use std::fmt;
#[derive(Debug, Clone)]
pub struct Piece {
name: String,
pub patterns: Vec<Pattern>,
}
impl Piece {
#[allow(dead_code)]
pub fn hero() -> Self {
let coords_vert = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 0, y: 3 },
];
let coords_hori = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 3, y: 0 },
];
Self {
name: "Hero".to_string(),
patterns: vec![
Pattern {
coords: coords_vert,
},
Pattern {
coords: coords_hori,
},
],
}
}
#[allow(dead_code)]
pub fn teewee() -> Self {
let coords_up = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: -1, y: 1 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 1 },
];
let coords_right = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 1, y: 1 },
];
let coords_down = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 1, y: 1 },
];
let coords_left = vec![
RelCoord { x: -1, y: 1 },
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
];
Self {
name: "Teewee".to_string(),
patterns: vec![
Pattern { coords: coords_up },
Pattern {
coords: coords_right,
},
Pattern {
coords: coords_down,
},
Pattern {
coords: coords_left,
},
],
}
}
#[allow(dead_code)]
pub fn blue_ricky() -> Self {
let coords_upright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: -1, y: 2 },
];
let coords_right = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 2, y: 1 },
];
let coords_downright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 1, y: 0 },
];
let coords_left = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 2, y: 1 },
];
Self {
name: "Blue Ricky".to_string(),
patterns: vec![
Pattern {
coords: coords_upright,
},
Pattern {
coords: coords_right,
},
Pattern {
coords: coords_downright,
},
Pattern {
coords: coords_left,
},
],
}
}
#[allow(dead_code)]
pub fn orange_ricky() -> Self {
let coords_upright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 2 },
RelCoord { x: 1, y: 2 },
];
let coords_right = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 2, y: 0 },
RelCoord { x: 0, y: 1 },
];
let coords_downright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 1, y: 2 },
];
let coords_left = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: -1, y: 1 },
RelCoord { x: -2, y: 1 },
];
Self {
name: "Orange Ricky".to_string(),
patterns: vec![
Pattern {
coords: coords_upright,
},
Pattern {
coords: coords_right,
},
Pattern {
coords: coords_downright,
},
Pattern {
coords: coords_left,
},
],
}
}
#[allow(dead_code)]
pub fn smashboy() -> Self {
let coords = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
];
Self {
name: "Smashboy".to_string(),
patterns: vec![Pattern { coords }],
}
}
#[allow(dead_code)]
pub fn cleveland_z() -> Self {
let flat = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 2, y: 1 },
];
let upright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: -1, y: 1 },
RelCoord { x: -1, y: 2 },
];
Self {
name: "Cleveland Z".to_string(),
patterns: vec![Pattern { coords: flat }, Pattern { coords: upright }],
}
}
#[allow(dead_code)]
pub fn rhode_island_z() -> Self {
let flat = vec![
RelCoord { x: -1, y: 1 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 0, y: 0 },
RelCoord { x: 1, y: 0 },
];
let upright = vec![
RelCoord { x: 0, y: 0 },
RelCoord { x: 0, y: 1 },
RelCoord { x: 1, y: 1 },
RelCoord { x: 1, y: 2 },
];
Self {
name: "Rhode Island Z".to_string(),
patterns: vec![Pattern { coords: flat }, Pattern { coords: upright }],
}
}
}
impl fmt::Display for Piece {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:\n\n", self.name.red())?;
for pattern in self.patterns.iter() {
write!(f, "{}\n", pattern)?;
}
Ok(())
}
}

105
src/tests.rs Normal file
View File

@ -0,0 +1,105 @@
use crate::pattern::AbsCoord;
use crate::solve;
use crate::Field;
use crate::Piece;
#[test]
fn test_add_pattern() {
let mut field = Field::new(3, 3);
assert_eq!(
field.add_pattern(&AbsCoord { x: 0, y: 0 }, &Piece::blue_ricky().patterns[0]),
false
);
assert_eq!(
field.add_pattern(&AbsCoord { x: 0, y: 0 }, &Piece::blue_ricky().patterns[1]),
true
);
}
#[test]
fn test_solve_no_pieces() {
let field = Field::new(5, 5);
let pieces = vec![];
let result = solve(field, pieces);
assert!(result.is_none());
}
#[test]
fn test_solve_no_space() {
let field = Field::new(0, 0);
let pieces = vec![Piece::smashboy()];
let result = solve(field, pieces);
assert!(result.is_none());
}
#[test]
fn test_solve_base_case() {
let field = Field::new(0, 0);
let pieces = vec![];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_solve_four_smashboys() {
let field = Field::new(4, 4);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_two_two_one() {
let field = Field::new(4, 5);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::blue_ricky(),
Piece::blue_ricky(),
Piece::hero(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_two_two_one_fail() {
let field = Field::new(4, 5);
let pieces = vec![
Piece::smashboy(),
Piece::smashboy(),
Piece::blue_ricky(),
Piece::orange_ricky(),
Piece::hero(),
];
let result = solve(field, pieces);
assert!(result.is_some());
}
#[test]
fn test_eight_seven() {
let field = Field::new(8, 7);
let pieces = vec![
Piece::hero(), // ----
Piece::hero(), // ----
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::smashboy(),
Piece::teewee(),
Piece::teewee(),
Piece::teewee(),
Piece::teewee(),
Piece::cleveland_z(), // -_
Piece::rhode_island_z(), // _-
Piece::orange_ricky(), // ___|
Piece::blue_ricky(), // |___
];
let result = solve(field, pieces);
assert!(result.is_some());
}