diff --git a/combinatoric-solver/Cargo.lock b/combinatoric-solver/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..d5d26d1b0e334c49a64c5ea48b05e6f8fa414172 --- /dev/null +++ b/combinatoric-solver/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "combinatoric-solver" +version = "0.1.0" diff --git a/combinatoric-solver/Cargo.toml b/combinatoric-solver/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..cd0e8603bee10ba489005d64ce0a9c7fdf095a14 --- /dev/null +++ b/combinatoric-solver/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "combinatoric-solver" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/combinatoric-solver/src/collection.rs b/combinatoric-solver/src/collection.rs new file mode 100644 index 0000000000000000000000000000000000000000..f16919cc65443c9c68774e4d9a82a70ab019517e --- /dev/null +++ b/combinatoric-solver/src/collection.rs @@ -0,0 +1,67 @@ +use crate::score::Score; + +#[derive(Clone)] +pub struct Collection<const MAX_ITEMS: usize, S, ItemVariant> +where + S: Score, + ItemVariant: Eq, +{ + pub score: S, + pub item_quantity: usize, + pub item_variant: [ItemVariant; MAX_ITEMS], +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq + Default + Copy> + Collection<MAX_ITEMS, S, ItemVariant> +{ + pub fn push(&self, item_variant: ItemVariant) -> Self { + let mut new = self.clone(); + new.item_variant[self.item_quantity] = item_variant; + new.item_quantity += 1; + new + } +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq + Default + Copy> Default + for Collection<MAX_ITEMS, S, ItemVariant> +{ + fn default() -> Self { + let score = S::default(); + let item_quantity = 0; + let item_variant = [ItemVariant::default(); MAX_ITEMS]; + Self { + score, + item_quantity, + item_variant, + } + } +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq> PartialEq + for Collection<MAX_ITEMS, S, ItemVariant> +{ + fn eq(&self, other: &Self) -> bool { + self.item_variant == other.item_variant + } +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq> PartialOrd + for Collection<MAX_ITEMS, S, ItemVariant> +{ + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + self.score.partial_cmp(&other.score) + } +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq> Eq + for Collection<MAX_ITEMS, S, ItemVariant> +{ +} + +impl<const MAX_ITEMS: usize, S: Score, ItemVariant: Eq> Ord + for Collection<MAX_ITEMS, S, ItemVariant> +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.score.cmp(&other.score) + } +} diff --git a/combinatoric-solver/src/item.rs b/combinatoric-solver/src/item.rs new file mode 100644 index 0000000000000000000000000000000000000000..a37121c21ec510789e597288e4195971d908b067 --- /dev/null +++ b/combinatoric-solver/src/item.rs @@ -0,0 +1,6 @@ +pub trait ItemVariant: Eq + Copy + Default {} + +pub trait CombinatoricItem { + type ItemVariant; + fn variants(&self) -> impl IntoIterator<Item = Self::ItemVariant>; +} diff --git a/combinatoric-solver/src/lib.rs b/combinatoric-solver/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8d79d2533a131ace47671c564057a957139b9f02 --- /dev/null +++ b/combinatoric-solver/src/lib.rs @@ -0,0 +1,6 @@ +pub mod collection; +pub mod item; +pub mod score; +pub mod solver; + +pub use crate::solver::Solver; diff --git a/combinatoric-solver/src/score.rs b/combinatoric-solver/src/score.rs new file mode 100644 index 0000000000000000000000000000000000000000..426175d2839de0a0eba7cdd3b72fdc98a3cf8fa3 --- /dev/null +++ b/combinatoric-solver/src/score.rs @@ -0,0 +1 @@ +pub trait Score: Ord + Default + Clone {} diff --git a/combinatoric-solver/src/solver.rs b/combinatoric-solver/src/solver.rs new file mode 100644 index 0000000000000000000000000000000000000000..863a28795b985889b69b3673a064f841f4b723c6 --- /dev/null +++ b/combinatoric-solver/src/solver.rs @@ -0,0 +1,56 @@ +use std::{cmp::Reverse, collections::BinaryHeap}; + +use crate::{ + collection::Collection, + item::{CombinatoricItem, ItemVariant}, + score::Score, +}; + +pub struct Solver<const MAX_ITEMS: usize, S, V, I, Parameters> +where + S: Score, + V: ItemVariant, + I: CombinatoricItem, +{ + top_items: BinaryHeap<Reverse<Collection<MAX_ITEMS, S, V>>>, + max_capacity: usize, + parameters: Parameters, + items: Vec<I>, +} + +impl<'a, const MAX_ITEMS: usize, S, V, I, Parameters> Solver<MAX_ITEMS, S, V, I, Parameters> +where + S: Score, + V: ItemVariant, + I: CombinatoricItem<ItemVariant = V>, +{ + pub fn new(max_capacity: usize, items: Vec<I>, parameters: Parameters) -> Self { + let top_items = BinaryHeap::with_capacity(max_capacity); + Self { + top_items, + max_capacity, + parameters, + items, + } + } + pub fn solve(mut self) -> Vec<I> { + let item = &self.items; + Self::rec_iter(0, Collection::default(), item, &mut self.top_items); + vec![] + } + fn rec_iter( + i: usize, + collection: Collection<MAX_ITEMS, S, V>, + items: &'a [I], + top_items: &mut BinaryHeap<Reverse<Collection<MAX_ITEMS, S, V>>>, + ) { + if i >= items.len() { + return; + } + + for variant in items[i].variants() { + let collections = collection.push(variant); + Self::rec_iter(i + 1, collections, items, top_items); + } + } +}