#![allow(unused)]
use std::{cell::RefCell, ops::DerefMut};
use itertools::Itertools;
use rand::seq::SliceRandom;
use rand_pcg::Pcg64Mcg;
use settheory::{CardSelection, Deck, Set};
const DIM: usize = 4;
const RUNS: usize = 10000;
thread_local! {
static RNG: RefCell<Pcg64Mcg> = RefCell::new(Pcg64Mcg::new(0xcafef00dd15ea5e5));
}
fn main() {
let mut avg = 0;
let mut min = usize::MAX;
let mut max = usize::MIN;
let mut dist = [0; 7];
let mut avg_sets_in_sel = 0;
let mut selection_count = 0;
let mut max_sets_in_sel = usize::MIN;
let mut max_sets_sel = CardSelection::new();
let mut sets_in_sel_dist = [0; 16];
let mut avg_same_count = 0;
let mut no_same_count = 0;
let mut games_no_same_set = 0;
'runs: for _ in 0..RUNS {
let mut deck = Deck::new();
let mut selection: CardSelection<DIM> = deck.draw(12).collect();
let mut no_same_set = false;
loop {
let mut sets = selection.sets().collect_vec();
if sets.is_empty() {
deck.reshuffle(&selection);
if !deck.has_sets() {
avg += deck.len();
min = usize::min(min, deck.len());
max = usize::max(max, deck.len());
dist[deck.len() / 3] += 1;
games_no_same_set += if no_same_set { 1 } else { 0 };
continue 'runs;
}
selection = deck.draw(12).collect();
continue;
}
avg_sets_in_sel += sets.len();
selection_count += 1;
if max_sets_in_sel < sets.len() {
max_sets_in_sel = sets.len();
max_sets_sel = selection.clone();
}
sets_in_sel_dist[sets.len()] += 1;
sets.sort_unstable_by_key(Set::same_count);
let set_found = sets.pop().unwrap();
avg_same_count += set_found.same_count() as u64;
if set_found.same_count() == 0 {
no_same_count += 1;
no_same_set = true;
}
selection -= set_found;
}
}
println!(
"The average number of cards left at the end was {:.3}",
avg as f32 / RUNS as f32
);
println!("The minimum number was {min}");
println!("The maximum number was {max}");
println!(
"Distribution:\n{}\n{}\n{}",
(0..7)
.map(|i| format!("{:6}", i))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
dist.into_iter()
.map(|i| format!("{:6}", i))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
dist.into_iter()
.map(|i| format!("{:6.1}%", i as f32 * 100.0 / RUNS as f32))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
);
println!(
"The average number of sets in a selection with sets was {:.3}",
avg_sets_in_sel as f32 / selection_count as f32
);
println!("The maximum number of sets in one selection was {max_sets_in_sel}");
println!("Selection: {max_sets_sel}");
println!(
"Distribution:\n{}\n{}\n{}",
(0..16)
.map(|i| format!("{:6}", i))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
sets_in_sel_dist
.into_iter()
.map(|i| format!("{:6}", i))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
sets_in_sel_dist
.into_iter()
.map(|i| format!(
"{:6.1}%",
i as f32 * 100.0 / sets_in_sel_dist.iter().sum::<usize>() as f32
))
.reduce(|a, b| a + " |" + &b)
.unwrap(),
);
println!(
"The average same count was {:.2}",
avg_same_count as f32 / selection_count as f32
);
println!(
"The average amount of times per game with only sets without same attributes was {}",
no_same_count as f32 / RUNS as f32
);
println!(
"The percentage of games with sets with no shared attributes was {:.2}%",
games_no_same_set as f32 * 100.0 / RUNS as f32
);
}