use nalgebra::base::{Dynamic, MatrixMN};
use num::rational::Ratio;
use std::vec::Vec;
use super::maths::g_elim::GaussianElimination;
use crate::public::{failures::ErrorCases, traits::CheckedType, types::DataSetIn};
pub fn balancer<T: CheckedType>(ds: DataSetIn<T>) -> Result<Vec<Vec<T>>, ErrorCases> {
let (cd, data) = ds;
let v = data
.iter()
.flat_map(|x| x)
.map(|x| Ratio::<T>::from_integer(*x))
.collect::<Vec<_>>();
let equation_matrix =
MatrixMN::<Ratio<T>, Dynamic, Dynamic>::from_row_slice(data.len(), cd.sum, &v[..]);
let ans = GaussianElimination::<T>::new(equation_matrix).solve()?;
let result = ans
.into_iter()
.map(|v| {
let lcm: T = v.iter().fold(T::one(), |lcm, ratio| lcm.lcm(ratio.denom()));
v.into_iter()
.map(|ratio| lcm / *ratio.denom() * *ratio.numer())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
Ok(result)
}