use set_theory::laws::SetLaws;
use set_theory::models::{CustomSet, MultiSet};
use set_theory::operations::{AdvancedSetOperations, SetOperations};
fn main() {
println!("=== Set Theory Demo in Rust ===\n");
println!("1. CREATING SETS");
let a = CustomSet::from(vec![1, 2, 3, 4]);
let b = CustomSet::from(vec![3, 4, 5, 6]);
println!("A = {}", a);
println!("B = {}\n", b);
println!("2. MEMBERSHIP");
println!("3 ∈ A: {}", a.contains(&3));
println!("5 ∈ A: {}\n", a.contains(&5));
println!("3. CARDINALITY");
println!("|A| = {}", a.cardinality());
println!("|B| = {}\n", b.cardinality());
println!("4. SUBSETS");
let c = CustomSet::from(vec![1, 2]);
println!("C = {}", c);
println!("C ⊆ A: {}", c.is_subset_of(&a));
println!("C ⊂ A: {}\n", c.is_proper_subset_of(&a));
println!("5. BASIC OPERATIONS");
println!("A ∩ B = {}", SetOperations::intersection(&a, &b));
println!("A ∪ B = {}", SetOperations::union(&a, &b));
println!("A - B = {}", SetOperations::difference(&a, &b));
println!("A ⊕ B = {}\n", SetOperations::symmetric_difference(&a, &b));
println!("6. COMPLEMENT");
let universal = CustomSet::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
println!("U = {}", universal);
println!("A' = {}\n", SetOperations::complement(&a, &universal));
println!("7. CARTESIAN PRODUCT");
let x = CustomSet::from(vec![1, 2]);
let y = CustomSet::from(vec!['a', 'b']);
let cartesian = AdvancedSetOperations::cartesian_product(&x, &y);
println!("X × Y = {:?}", cartesian);
println!("|X × Y| = {}\n", cartesian.cardinality());
println!("8. POWER SET");
let small = CustomSet::from(vec![1, 2]);
let power_set: Vec<_> = small.power_set().collect();
println!("P({{1, 2}}) = {:?}", power_set);
println!("|P({{1, 2}})| = {}\n", power_set.len());
println!("9. SET LAWS");
println!(
"Commutative Law (A ∪ B = B ∪ A): {}",
SetLaws::commutative_union(&a, &b)
);
println!(
"Distributive Law: {}",
SetLaws::distributive_union(&a, &b, &c)
);
println!(
"De Morgan's Law: {}\n",
SetLaws::de_morgan_union(&a, &b, &universal)
);
println!("10. MULTISET");
let ms1 = MultiSet::from(vec!['a', 'a', 'b', 'c']);
let ms2 = MultiSet::from(vec!['a', 'b', 'b', 'd']);
println!("P = {}", ms1);
println!("Q = {}", ms2);
println!("P ∪ Q = {}", ms1.union(&ms2));
println!("P ∩ Q = {}", ms1.intersection(&ms2));
println!("P - Q = {}", ms1.difference(&ms2));
println!("P + Q = {}\n", ms1.sum(&ms2));
println!("11. INCLUSION-EXCLUSION PRINCIPLE");
let numbers = CustomSet::from((1..=100).collect::<Vec<_>>());
let div3 = CustomSet::from_predicate(numbers.iter().cloned(), |x| x % 3 == 0);
let div5 = CustomSet::from_predicate(numbers.iter().cloned(), |x| x % 5 == 0);
let count = AdvancedSetOperations::inclusion_exclusion_2(&div3, &div5);
println!("Numbers 1-100 divisible by 3 or 5: {}", count);
println!("\n=== Demo Complete ===");
}