hehe done
This commit is contained in:
commit
2fd7581b47
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -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"
|
|
@ -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]
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue