hehe done

This commit is contained in:
Alie 2023-07-15 23:33:44 +02:00
commit 2fd7581b47
4 changed files with 148 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "figure-solver"
version = "0.1.0"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "figure-solver"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

132
src/main.rs Normal file
View File

@ -0,0 +1,132 @@
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Tile {
White,
Pink,
Blue,
Yellow,
None,
}
impl ToString for Tile {
fn to_string(&self) -> String {
match self {
Tile::White => "w",
Tile::Pink => "p",
Tile::Blue => "b",
Tile::Yellow => "y",
Tile::None => " ",
}
.to_string()
}
}
impl From<char> for Tile {
fn from(c: char) -> Self {
match c {
'w' => Tile::White,
'b' => Tile::Blue,
'p' => Tile::Pink,
'y' => Tile::Yellow,
' ' => Tile::None,
_ => panic!("Wrong tile"),
}
}
}
type Field = Vec<Vec<Tile>>;
fn main() {
let field = vec!["wwbyb", "ywwyw", "wwbbw", "pypby", "pyppw"];
let field: Field = field
.iter()
.map(|l| l.chars().map(|c| Tile::from(c)).collect::<Vec<_>>())
.collect();
let mut cache: HashMap<_, _> = HashMap::new();
println!("{:?}", less_turns(&field, 0, vec![], &mut cache));
}
fn less_turns(field: &Field, depth: u32, steps: Vec<usize>, cache: &mut HashMap<Field, (u32, Vec<usize>)>) -> (u32, Vec<usize>) {
if winned(field){return (depth, steps);}
if let Some(res) = cache.get(field){
if res.0 <= depth{
return res.clone();
}
}
let row = &field.len() - 1;
let mut results = vec![];
for col in 0..row + 1 {
let selected_color: Tile = field[row][col];
if selected_color != Tile::None {
let mut steps = steps.clone();
steps.push(col);
results.push(less_turns(&calculate_turn(&field, col), depth + 1, steps, cache));
}
}
let result = results.iter().min_by_key(|(d, _)| d).unwrap();
cache.insert(field.clone(), result.clone());
result.clone()
}
fn propagate_click(mut field: Field, row: usize, column: usize, color: Tile) -> Field {
if field.get(row).is_none() || field[row].get(column).is_none() || field[row][column] != color {
return field;
}
field[row][column] = Tile::None;
field = if row > 0 {
propagate_click(field, row - 1, column, color)
} else {
field
};
field = if row < usize::MAX {
propagate_click(field, row + 1, column, color)
} else {
field
};
field = if column > 0 {
propagate_click(field, row, column - 1, color)
} else {
field
};
field = if column < usize::MAX {
propagate_click(field, row, column + 1, color)
} else {
field
};
field
}
fn calculate_turn(field: &Field, column: usize) -> Field {
let mut field = field.clone();
let row = &field.len() - 1;
let selected_color: Tile = field[row][column];
field = propagate_click(field, row, column, selected_color);
for i in 0..field[row].len() {
let mut stack: Vec<Tile> = vec![];
for j in 0..field.len() {
stack.push(field[j][i]);
}
stack = stack
.iter()
.filter(|tile| **tile != Tile::None)
.rev()
.chain(stack.iter().filter(|tile| **tile == Tile::None))
.map(|t| *t)
.collect();
for j in 0..field.len() {
field[j][i] = stack.pop().expect("input and output should equal");
}
}
field
}
fn winned(field: &Field) -> bool {
field
.iter()
.map(|l| l.iter())
.flatten()
.filter(|t| **t != Tile::None)
.count()
<= 0
}