Initial version of Talos Solver
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
45
.vscode/launch.json
vendored
Normal file
45
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug executable 'talos_solver'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"--bin=talos_solver",
|
||||
"--package=talos_solver"
|
||||
],
|
||||
"filter": {
|
||||
"name": "talos_solver",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in executable 'talos_solver'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--bin=talos_solver",
|
||||
"--package=talos_solver"
|
||||
],
|
||||
"filter": {
|
||||
"name": "talos_solver",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
171
Cargo.lock
generated
Normal file
171
Cargo.lock
generated
Normal file
@@ -0,0 +1,171 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6"
|
||||
dependencies = [
|
||||
"is-terminal",
|
||||
"lazy_static",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "talos_solver"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "talos_solver"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
colored = "2.0"
|
||||
480
src/main.rs
Normal file
480
src/main.rs
Normal file
@@ -0,0 +1,480 @@
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::AbsCoord;
|
||||
use crate::Field;
|
||||
use crate::Piece;
|
||||
use crate::solve;
|
||||
|
||||
#[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());
|
||||
}
|
||||
}
|
||||
|
||||
fn solve(field: Field, pieces: Vec<Piece>) -> Option<Field> {
|
||||
if field.empty_coords.is_empty() {
|
||||
if pieces.is_empty() {
|
||||
return Some(field);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else if pieces.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
for empty_coord in &field.empty_coords.as_slice()[0..2] {
|
||||
for (piece_index, piece) in pieces.iter().enumerate() {
|
||||
for pattern in &piece.patterns {
|
||||
if field.fits(&empty_coord, &pattern) {
|
||||
let mut new_field: Field = field.clone();
|
||||
let mut new_pieces = pieces.clone();
|
||||
new_pieces.remove(piece_index);
|
||||
new_field.add_pattern(&empty_coord, &pattern);
|
||||
match solve(new_field, new_pieces) {
|
||||
Some(field) => return Some(field),
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let field = Field::new(6, 6);
|
||||
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::teewee(),
|
||||
Piece::teewee(),
|
||||
// Piece::cleveland_z(), // -_
|
||||
// Piece::rhode_island_z(), // _-
|
||||
// Piece::teewee(),
|
||||
// Piece::hero(),
|
||||
// Piece::orange_ricky(), // ___|
|
||||
// Piece::blue_ricky(), // |___
|
||||
// Piece::smashboy(),
|
||||
];
|
||||
let result = solve(field, pieces);
|
||||
match result {
|
||||
Some(field) => println!("{}", field),
|
||||
None => println!("No solution",)
|
||||
};
|
||||
|
||||
// for piece in &pieces {
|
||||
// print!("{}", piece);
|
||||
// }
|
||||
}
|
||||
Reference in New Issue
Block a user