Commit 00549e11 authored by tleydxdy's avatar tleydxdy

more refactors using BTreeMap's features

parent 8bdae45e
......@@ -39,10 +39,10 @@ impl<T: Cost> Cost for &T {
pub mod cga {
use super::Cost;
use std::collections::btree_map::Keys;
use std::collections::btree_map::Values;
use std::collections::btree_map::ValuesMut;
use std::collections::BTreeMap;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Key(usize, usize);
impl Cost for Key {
......@@ -51,7 +51,6 @@ pub mod cga {
}
}
#[derive(Debug)]
struct Solution<T: Cost + Copy>(BTreeMap<Key, Vec<T>>);
impl<T> Solution<T>
......@@ -91,8 +90,8 @@ pub mod cga {
self.0.len()
}
fn values(&self) -> Values<Key, Vec<T>> {
self.0.values()
fn values_mut(&mut self) -> ValuesMut<Key, Vec<T>> {
self.0.values_mut()
}
fn keys(&self) -> Keys<Key, Vec<T>> {
......@@ -124,147 +123,134 @@ pub mod cga {
}
}
fn is_perfect<T>(best: &Option<Solution<T>>, k: usize, total: usize) -> bool
where
T: Cost + Copy,
{
best.as_ref().map_or(false, |s| s.is_perfect(k, total))
}
fn best_cost<T>(best: &Option<Solution<T>>, bound: usize) -> usize
where
T: Cost + Copy,
{
best.as_ref().map_or(bound, |s| s.cost())
}
fn _solve<T>(
k: usize,
input: &Vec<T>,
cur: usize,
mut input: impl Iterator<Item = T> + Clone + std::iter::ExactSizeIterator,
total: usize,
best_cost: &mut usize,
part: &mut Solution<T>,
best: &mut Option<Solution<T>>,
) -> usize
) -> Option<Solution<T>>
where
T: Cost + Copy,
{
if cur < input.len() {
let item = input[cur];
let mut cur_best = best_cost(best, total);
// If there's still empty bins, try the empty bin first.
if part.len() < k {
let key = part.add_bin(part.len(), item);
let ret = _solve(k, input, cur + 1, cur_best, part, best);
part.remove_bin(key);
if ret < cur_best {
if is_perfect(best, k, total) {
return ret;
match input.next() {
Some(item) => {
let mut cur_best = None;
// If there's still empty bins, try the empty bin first.
if part.len() < k {
let key = part.add_bin(part.len(), item);
match _solve(k, input.clone(), total, best_cost, part) {
Some(s) => {
if s.is_perfect(k, total) {
return Some(s);
}
*best_cost = s.cost();
cur_best = Some(s);
}
None => (),
}
cur_best = best_cost(best, cur_best);
}
}
let cur_max = part.cost();
// Proceed if lowering the best is possible.
// Use ((a - 1) / b) + 1 for always round up division.
if ((total - cur_max - 1) / k) + 1 < cur_best {
// If all the bins are the same, just use the first one.
let &key = part.keys().next().unwrap();
let cur_min = key.cost();
if cur_min == cur_max && cur_min + item.cost() < cur_best {
let key = part.push(key, item);
let ret = _solve(k, input, cur + 1, cur_best, part, best);
part.pop(key);
return ret;
part.remove_bin(key);
}
// Try all the bins one by one,
for (i, &key) in part.clone().keys().enumerate() {
// for the last i item they only need to be put in the
// i smallest bins.
if input.len() - cur < i {
break;
// Proceed if lowering the best is possible.
// Use ((a - 1) / b) + 1 for always round up division.
let cur_max = part.cost();
if ((total - cur_max - 1) / k) + 1 < *best_cost {
let keys: Vec<Key> = part.keys().map(|&k| k).collect();
// Try all the bins one by one, for the last i item they
// only need to be put in the i smallest bins. If all
// the bins are the same, just use the first one.
let cur_min = keys[0].cost();
let until;
if cur_min == cur_max {
until = 1;
} else {
until = input.len() + 1;
}
if key.cost() + item.cost() < cur_best {
let key = part.push(key, item);
let ret = _solve(k, input, cur + 1, cur_best, part, best);
part.pop(key);
if ret < cur_best {
if is_perfect(best, k, total) {
return ret;
for (_, &key) in (0..until).zip(keys.iter()) {
if key.cost() + item.cost() < *best_cost {
let key = part.push(key, item);
match _solve(k, input.clone(), total, best_cost, part) {
Some(s) => {
if s.is_perfect(k, total) {
return Some(s);
}
*best_cost = s.cost();
cur_best = Some(s);
}
None => (),
}
cur_best = best_cost(best, cur_best);
part.pop(key);
}
}
}
// return best found in all leaf
cur_best
}
None => {
// Leaf node, update best.
return Some(part.clone());
}
cur_best
} else {
// Leaf node, update best.
*best = Some(part.clone());
part.cost()
}
}
pub fn solve<T>(k: usize, mut input: Vec<&T>) -> Vec<Vec<&T>>
pub fn solve<T>(k: usize, mut input: Vec<T>) -> Vec<Vec<T>>
where
T: Cost,
T: Cost + Copy,
{
// Deal with dumb inputs.
let total = input.iter().map(|x| x.cost()).sum();
if k == 1 || total == 0 {
if k == 1 || input.len() == 0 {
return vec![input];
} else if input.len() <= k {
return input.iter().map(|x| vec![*x]).collect();
}
// Sort by decreasing order.
input.sort_unstable_by(|a, b| b.cost().cmp(&a.cost()));
let mut total = input.iter().map(|x| x.cost()).sum();
input.sort_unstable_by_key(|x| x.cost());
// First number always goes in the "first" bin, so don't need to search a tree.
let mut part = Solution::new();
part.add_bin(0, input[0]);
let mut result = None;
_solve(k, &input, 1, total, &mut part, &mut result);
result.unwrap().values().map(|v| v.clone()).collect()
let first = &input.pop().unwrap();
part.add_bin(0, first);
_solve(k, input.iter().rev(), total, &mut total, &mut part)
.unwrap()
.values_mut()
.map(|v| v.drain(..).map(|&x| x).collect())
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[test]
fn test_cga() {
assert_eq!(cga::solve(1, vec![&1, &3, &2]), vec![vec![&1, &3, &2]]);
assert_eq!(cga::solve(1, vec![1, 3, 2]), vec![vec![1, 3, 2]]);
assert_eq!(cga::solve(2, vec![1, 3, 2]), vec![vec![3], vec![2, 1]]);
assert_eq!(
cga::solve(2, vec![&1, &3, &2]),
vec![vec![&3], vec![&2, &1]]
cga::solve(3, vec![1, 3, 2]),
vec![vec![1], vec![3], vec![2]]
);
assert_eq!(
cga::solve(3, vec![&1, &3, &2]),
vec![vec![&1], vec![&3], vec![&2]]
cga::solve(4, vec![1, 3, 2]),
vec![vec![1], vec![3], vec![2]]
);
assert_eq!(
cga::solve(4, vec![&1, &3, &2]),
vec![vec![&1], vec![&3], vec![&2]]
cga::solve(3, vec![8, 4, 7, 5, 6]),
vec![vec![8], vec![7, 4], vec![6, 5]]
);
assert_eq!(
cga::solve(3, vec![&8, &4, &7, &5, &6]),
vec![vec![&8], vec![&7, &4], vec![&6, &5]]
);
assert_eq!(
cga::solve(4, vec![&8, &4, &7, &5, &6]),
vec![vec![&6], vec![&7], vec![&8], vec![&5, &4]]
cga::solve(4, vec![8, 4, 7, 5, 6]),
vec![vec![6], vec![7], vec![8], vec![5, 4]]
);
}
use test::Bencher;
#[bench]
fn test_cga_big(b: &mut Bencher) {
// random big numbers, to avoid perfect partition
......@@ -273,20 +259,20 @@ mod tests {
cga::solve(
8,
vec![
&32525, &17303, &7084, &24185, &2233, &23788, &20717, &25841, &14545,
&14807, &30030, &23001, &310, &10096, &27283, &8125, &28625, &21273,
&19109, &25831, &3628, &25627, &15169, &26692,
32525, 17303, 7084, 24185, 2233, 23788, 20717, 25841, 14545, 14807, 30030,
23001, 310, 10096, 27283, 8125, 28625, 21273, 19109, 25831, 3628, 25627,
15169, 26692,
]
),
vec![
vec![&25841, &15169, &14807],
vec![&26692, &19109, &10096],
vec![&25831, &23001, &7084],
vec![&30030, &25627, &310],
vec![&32525, &21273, &2233],
vec![&24185, &17303, &14545],
vec![&28625, &23788, &3628],
vec![&27283, &20717, &8125]
vec![25841, 15169, 14807],
vec![26692, 19109, 10096],
vec![25831, 23001, 7084],
vec![30030, 25627, 310],
vec![32525, 21273, 2233],
vec![24185, 17303, 14545],
vec![28625, 23788, 3628],
vec![27283, 20717, 8125]
]
)
});
......@@ -300,27 +286,28 @@ mod tests {
cga::solve(
8,
vec![
&13, &151, &172, &121, &185, &236, &237, &241, &209, &215, &78, &217, &54,
&112, &147, &189, &209, &25, &165, &231, &44, &27, &65, &68, &150, &127,
&241, &129, &235, &85, &49, &248, &236, &220, &112, &164, &199, &92, &148,
&152, &50, &225, &112, &103, &80, &2, &36, &32, &26, &200, &6, &70, &227,
&71, &137, &120, &197, &122, &248, &175, &206, &40, &166, &185, &3, &22,
&92, &201, &113, &239, &96, &163, &208, &207, &9, &31, &208, &44, &63,
&234, &244, &68, &47, &214, &138, &183, &77, &78, &48, &68, &253, &254,
&107, &162, &182, &109, &183, &18, &53, &40,
13, 151, 172, 121, 185, 236, 237, 241, 209, 215, 78, 217, 54, 112, 147,
189, 209, 25, 165, 231, 44, 27, 65, 68, 150, 127, 241, 129, 235, 85, 49,
248, 236, 220, 112, 164, 199, 92, 148, 152, 50, 225, 112, 103, 80, 2, 36,
32, 26, 200, 6, 70, 227, 71, 137, 120, 197, 122, 248, 175, 206, 40, 166,
185, 3, 22, 92, 201, 113, 239, 96, 163, 208, 207, 9, 31, 208, 44, 63, 234,
244, 68, 47, 214, 138, 183, 77, 78, 48, 68, 253, 254, 107, 162, 182, 109,
183, 18, 53, 40,
]
),
vec![
vec![&248, &231, &209, &206, &166, &163, &121, &109, &78, &54, &49, &27],
vec![&241, &236, &217, &189, &183, &151, &129, &103, &85, &53, &48, &26],
vec![&241, &236, &215, &199, &172, &162, &113, &112, &78, &68, &40, &25],
vec![&254, &225, &214, &197, &182, &148, &122, &112, &71, &68, &47, &13, &9],
vec![&253, &227, &208, &207, &165, &164, &120, &112, &70, &68, &44, &18, &6],
vec![&248, &234, &208, &200, &175, &152, &137, &96, &80, &65, &36, &31],
vec![&244, &235, &209, &201, &183, &147, &127, &107, &77, &63, &44, &22, &3],
vec![&239, &237, &220, &185, &185, &150, &138, &92, &92, &50, &40, &32, &2]
vec![248, 231, 209, 206, 166, 163, 121, 109, 78, 54, 49, 27],
vec![241, 236, 217, 189, 183, 151, 129, 103, 85, 53, 48, 26],
vec![241, 236, 215, 199, 172, 162, 113, 112, 78, 68, 40, 25],
vec![254, 225, 214, 197, 182, 148, 122, 112, 71, 68, 47, 13, 9],
vec![253, 227, 208, 207, 165, 164, 120, 112, 70, 68, 44, 18, 6],
vec![248, 234, 208, 200, 175, 152, 137, 96, 80, 65, 36, 31],
vec![244, 235, 209, 201, 183, 147, 127, 107, 77, 63, 44, 22, 3],
vec![239, 237, 220, 185, 185, 150, 138, 92, 92, 50, 40, 32, 2]
]
)
});
}
/*
*/
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment