Skip to content

Commit

Permalink
FREEZE.indexed
Browse files Browse the repository at this point in the history
  • Loading branch information
lgarron committed Oct 5, 2024
1 parent 03faa8c commit 1633f72
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 68 deletions.
22 changes: 15 additions & 7 deletions src/rs/scramble/puzzles/cube2x2x2.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use cubing::{alg::Alg, puzzles::cube2x2x2_kpuzzle};

use crate::{_internal::AlwaysValid, scramble::{
puzzles::static_move_list::{add_random_suffixes_from, static_parsed_opt_list},
randomize::PieceZeroConstraint,
scramble_search::FilteredSearch,
}};
use crate::{
_internal::AlwaysValid,
scramble::{
puzzles::static_move_list::{add_random_suffixes_from, static_parsed_opt_list},
randomize::PieceZeroConstraint,
scramble_search::FilteredSearch,
},
};

use super::{
super::randomize::{
Expand All @@ -17,14 +20,19 @@ pub fn scramble_2x2x2() -> Alg {
let kpuzzle = cube2x2x2_kpuzzle();

#[allow(non_snake_case)] // Move meanings are case sensitive.
let mut filtered_search_L_B_D =
FilteredSearch::<AlwaysValid>::new(kpuzzle, generators_from_vec_str(vec!["L", "B", "D"]), None);
let mut filtered_search_L_B_D = FilteredSearch::<AlwaysValid>::new(
kpuzzle,
generators_from_vec_str(vec!["L", "B", "D"]),
None,
kpuzzle.default_pattern(),
);

#[allow(non_snake_case)] // Move meanings are case sensitive.
let mut filtered_search_U_L_F_R = FilteredSearch::<AlwaysValid>::new(
kpuzzle,
generators_from_vec_str(vec!["U", "L", "F", "R"]),
None,
kpuzzle.default_pattern(),
);

loop {
Expand Down
9 changes: 7 additions & 2 deletions src/rs/scramble/puzzles/cube3x3x3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ impl Default for Scramble3x3x3TwoPhase {
fn default() -> Self {
let kpuzzle = cube3x3x3_centerless_kpuzzle().clone();
let generators = generators_from_vec_str(vec!["U", "L", "F", "R", "B", "D"]);
let filtering_idfs = basic_idfs(&kpuzzle, generators.clone(), Some(32));
let filtering_idfs = basic_idfs(
&kpuzzle,
generators.clone(),
Some(32),
kpuzzle.default_pattern(),
);

let phase1_target_pattern = cube3x3x3_centerless_g1_target_kpattern().clone();
let phase1_idfs = idfs_with_target_pattern(
Expand Down Expand Up @@ -119,7 +124,7 @@ impl Scramble3x3x3TwoPhase {
};

let phase1_alg = {
let phase1_search_pattern = mask(pattern, &self.phase1_target_pattern);
let phase1_search_pattern = mask(pattern, &self.phase1_target_pattern).unwrap();

self.phase1_idfs
.search(
Expand Down
61 changes: 56 additions & 5 deletions src/rs/scramble/puzzles/mask_pattern.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
use cubing::kpuzzle::KPattern;
use std::cmp::min;

pub(crate) fn mask(source_pattern: &KPattern, mask_pattern: &KPattern) -> KPattern {
use cubing::kpuzzle::{KPattern, OrientationWithMod};

use crate::scramble::PuzzleError;

pub(crate) fn mask(
source_pattern: &KPattern,
mask_pattern: &KPattern,
) -> Result<KPattern, PuzzleError> {
let mut masked_pattern = mask_pattern.clone();
for orbit_info in source_pattern.kpuzzle().orbit_info_iter() {
for i in 0..orbit_info.num_pieces {
let old_piece = source_pattern.get_piece(orbit_info, i);
let old_piece_mapped = mask_pattern.get_piece(orbit_info, old_piece);
masked_pattern.set_piece(orbit_info, i, old_piece_mapped);
let orientation_with_mod = source_pattern.get_orientation_with_mod(orbit_info, i);
masked_pattern.set_orientation_with_mod(orbit_info, i, orientation_with_mod);

let source_orientation_with_mod =
source_pattern.get_orientation_with_mod(orbit_info, i);
let mask_orientation_with_mod = mask_pattern.get_orientation_with_mod(orbit_info, i);

if mask_orientation_with_mod.orientation != 0 {
return Err(PuzzleError {
description: "Masks cannot currently have piece orientation".to_owned(),
});
};

dbg!("1");

let source_mod = source_orientation_with_mod.orientation_mod;
let source_mod = if source_mod == 0 {
orbit_info.num_orientations
} else {
source_mod
};
dbg!("2");

let mask_mod = mask_orientation_with_mod.orientation_mod;
let mask_mod = if mask_mod == 0 {
orbit_info.num_orientations
} else {
mask_mod
};
dbg!("3", mask_mod, source_mod);

if source_mod % mask_mod != 0 && mask_mod % source_mod != 0 {
return Err(PuzzleError {
description: "Incompatible orientation mod in mask".to_owned(),
});
};

let masked_mod = min(source_mod, mask_mod);
let orientation_with_mod = OrientationWithMod {
orientation: source_orientation_with_mod.orientation % masked_mod,
orientation_mod: if masked_mod == orbit_info.num_orientations {
0
} else {
masked_mod
},
};

masked_pattern.set_orientation_with_mod(orbit_info, i, &orientation_with_mod);
}
}
masked_pattern
Ok(masked_pattern)
}
135 changes: 92 additions & 43 deletions src/rs/scramble/puzzles/square1.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use cubing::alg::{parse_alg, Alg};
use cubing::alg::{parse_alg, parse_move, Alg, Move};
use rand::seq::SliceRandom;
use rand::thread_rng;

use crate::{_internal::CheckPattern, scramble::randomize::PieceZeroConstraint};
use crate::{
_internal::{AlwaysValid, CheckPattern},
scramble::{
randomize::{basic_parity, PieceZeroConstraint},
scramble_search::FilteredSearch,
},
};

use super::{
super::{
Expand All @@ -15,8 +21,6 @@ use super::{
mask_pattern::mask,
};

struct Square1SlicableChecker;

const SLOTS_THAT_ARE_BEFORE_SLICES: [u8; 4] = [5, 11, 17, 23];
// const LOWER_CORNER_CUBE_SLOTS: [u8; 4] = [0, 3, 6, 9, 13, 16, 19, 22];

Expand Down Expand Up @@ -54,6 +58,8 @@ const WEDGE_TYPE_LOOKUP: [WedgeType; 24] = [
WedgeType::CornerUpper,
];

struct Square1SlicableChecker;

impl CheckPattern for Square1SlicableChecker {
fn is_valid(pattern: &cubing::kpuzzle::KPattern) -> bool {
let orbit_info = &pattern.kpuzzle().data.ordered_orbit_info[0];
Expand All @@ -75,34 +81,36 @@ impl CheckPattern for Square1SlicableChecker {
}
}

// impl CheckPattern for Square1CubeShapeChecker {
// fn is_valid(pattern: &cubing::kpuzzle::KPattern) -> bool {
// let orbit_info = &pattern.kpuzzle().data.ordered_orbit_info[0];
// assert_eq!(orbit_info.name.0, "WEDGES");

// for i in [0, 1, 2, 11, 12, 13] {
// let value = unsafe {
// pattern
// .packed_orbit_data()
// .get_raw_piece_or_permutation_value(orbit_info, i)
// };

// for j in [3, 6, 9] {
// if value
// != unsafe {
// pattern
// .packed_orbit_data()
// .get_raw_piece_or_permutation_value(orbit_info, i + j)
// }
// {
// return false;
// }
// }
// }

// true
// }
// }
struct Square1CubeShapeChecker;

impl CheckPattern for Square1CubeShapeChecker {
fn is_valid(pattern: &cubing::kpuzzle::KPattern) -> bool {
let orbit_info = &pattern.kpuzzle().data.ordered_orbit_info[0];
assert_eq!(orbit_info.name.0, "WEDGES");

for i in [0, 1, 2, 11, 12, 13] {
let value = unsafe {
pattern
.packed_orbit_data()
.get_raw_piece_or_permutation_value(orbit_info, i)
};

for j in [3, 6, 9] {
if value
!= unsafe {
pattern
.packed_orbit_data()
.get_raw_piece_or_permutation_value(orbit_info, i + j)
}
{
return false;
}
}
}

true
}
}

pub fn scramble_square1() -> Alg {
let kpuzzle = square1_unbandaged_kpuzzle();
Expand Down Expand Up @@ -153,27 +161,68 @@ pub fn scramble_square1() -> Alg {

// <<< let scramble_pattern = scramble_pattern.apply_alg(&parse_alg!("U_SQ_2' _SLASH_ U_SQ_5 D_SQ_2 _SLASH_ U_SQ_4 D_SQ_2' _SLASH_")).unwrap();
// <<< let scramble_pattern = scramble_pattern.apply_alg(&parse_alg!("U_SQ_3 D_SQ_2 _SLASH_ D_SQ_")).unwrap();
let scramble_pattern = scramble_pattern.apply_alg(&parse_alg!("U_SQ_5' D_SQ_0 _SLASH_ U_SQ_4' D_SQ_2 _SLASH_ U_SQ_1 D_SQ_5' _SLASH_ U_SQ_3' D_SQ_0 _SLASH_ U_SQ_1' D_SQ_4' _SLASH_ U_SQ_2' D_SQ_0 _SLASH_ U_SQ_3' D_SQ_0 ")).unwrap();
let scramble_pattern = scramble_pattern.apply_alg(&parse_alg!("(U_SQ_5' D_SQ_0) / (U_SQ_0 D_SQ_3) / (U_SQ_3 D_SQ_0) / (U_SQ_' D_SQ_4') / (U_SQ_4 D_SQ_2') / (U_SQ_5 D_SQ_4') / (U_SQ_2' D_SQ_0) / (U_SQ_0 D_SQ_3') / (U_SQ_' D_SQ_0) / (U_SQ_3 D_SQ_4') / (U_SQ_4 D_SQ_2') /")).unwrap();

let phase1_start_pattern = mask(&scramble_pattern, square1_cube_shape_kpattern());
let phase1_start_pattern = mask(&scramble_pattern, square1_cube_shape_kpattern()).unwrap();

if !Square1SlicableChecker::is_valid(&phase1_start_pattern) {
println!("discaring invalid scramble"); //<<<
println!("discarding invalid scramble"); //<<<
continue;
}

dbg!(serde_json::to_string(&phase1_start_pattern));
println!(
"{}",
serde_json::to_string_pretty(&phase1_start_pattern.to_data()).unwrap()
);

println!(
"{}",
serde_json::to_string_pretty(&square1_cube_shape_kpattern().to_data()).unwrap()
);

let generators = generators_from_vec_str(vec!["U_SQ_", "D_SQ_", "_SLASH_"]); // TODO: cache
// <<< if let Some(solution) = simple_filtered_search(&phase1_start_pattern, generators, 11, None) {
if let Some(solution) = simple_filtered_search::<Square1SlicableChecker>(
&phase1_start_pattern,
generators,
0, /* TODO */

let mut phase1_filtered_search = FilteredSearch::<Square1SlicableChecker>::new(
kpuzzle,
generators.clone(),
None,
) {
//<<<
return solution.invert();
square1_cube_shape_kpattern().clone(),
);

let mut phase1_solution =
phase1_filtered_search.generate_scramble(&phase1_start_pattern, None);

while let Some(cubing::alg::AlgNode::MoveNode(r#move)) = phase1_solution.nodes.last() {
if r#move == &parse_move!("_SLASH_'")
// TODO: redundant parsing
{
break;
}
phase1_solution.nodes.pop();
}
dbg!(&parse_move!("/"));

let phase2_start_pattern = scramble_pattern.apply_alg(&phase1_solution).unwrap();

// dbg!(basic_parity(phase2_start_pattern.));

let mut phase2_filtered_search = FilteredSearch::<Square1CubeShapeChecker>::new(
kpuzzle,
generators,
None,
square1_cube_shape_kpattern().clone(),
);
let mut phase2_solution =
phase2_filtered_search.generate_scramble(&phase2_start_pattern, None);

let mut nodes = phase1_solution.nodes;
nodes.append(&mut phase2_solution.nodes);
Alg { nodes }.invert();

// if let Some(solution) = filtered_search.generate_scramble(&phase1_start_pattern, 0) {
// //<<<
// return solution.invert();
// }
}
}
2 changes: 1 addition & 1 deletion src/rs/scramble/randomize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn set_parity(permutation: &mut [u8], target_parity: BasicParity) {
};
}

#[derive(PartialEq)]
#[derive(PartialEq, Debug)]
pub(crate) enum BasicParity {
Even,
Odd,
Expand Down
20 changes: 10 additions & 10 deletions src/rs/scramble/scramble_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use cubing::{
};

use crate::_internal::{
options::{CustomGenerators, Generators, MetricEnum, VerbosityLevel}, CheckPattern, IDFSearch, IndividualSearchOptions, SearchLogger
options::{CustomGenerators, Generators, MetricEnum, VerbosityLevel},
CheckPattern, IDFSearch, IndividualSearchOptions, SearchLogger,
};

pub fn move_list_from_vec(move_str_list: Vec<&str>) -> Vec<Move> {
Expand All @@ -23,7 +24,7 @@ pub fn generators_from_vec_str(move_str_list: Vec<&str>) -> Generators {
})
}

pub(crate) fn idfs_with_target_pattern<T: CheckPattern> (
pub(crate) fn idfs_with_target_pattern<T: CheckPattern>(
kpuzzle: &KPuzzle,
generators: Generators,
target_pattern: KPattern,
Expand All @@ -48,13 +49,9 @@ pub(crate) fn basic_idfs<T: CheckPattern>(
kpuzzle: &KPuzzle,
generators: Generators,
min_prune_table_size: Option<usize>,
target_pattern: KPattern,
) -> IDFSearch<T> {
idfs_with_target_pattern(
kpuzzle,
generators,
kpuzzle.default_pattern(),
min_prune_table_size,
)
idfs_with_target_pattern(kpuzzle, generators, target_pattern, min_prune_table_size)
}

pub struct FilteredSearch<T: CheckPattern> {
Expand All @@ -66,8 +63,9 @@ impl<T: CheckPattern> FilteredSearch<T> {
kpuzzle: &KPuzzle,
generators: Generators,
min_prune_table_size: Option<usize>,
target_pattern: KPattern,
) -> FilteredSearch<T> {
let idfs = basic_idfs(kpuzzle, generators, min_prune_table_size);
let idfs = basic_idfs(kpuzzle, generators, min_prune_table_size, target_pattern);
Self { idfs }
}

Expand Down Expand Up @@ -118,7 +116,9 @@ pub(crate) fn simple_filtered_search<T: CheckPattern>(
min_optimal_moves: usize,
min_scramble_moves: Option<usize>,
) -> Option<Alg> {
let mut filtered_search = FilteredSearch::<T>::new(scramble_pattern.kpuzzle(), generators, None);
let kpuzzle = scramble_pattern.kpuzzle();
let mut filtered_search =
FilteredSearch::<T>::new(kpuzzle, generators, None, kpuzzle.default_pattern());
if filtered_search
.filter(scramble_pattern, min_optimal_moves)
.is_some()
Expand Down

0 comments on commit 1633f72

Please sign in to comment.