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