From 745d04169cc67a53dc251516634c78e504a74427 Mon Sep 17 00:00:00 2001 From: MrGeorgen Date: Tue, 8 Feb 2022 20:45:19 +0100 Subject: [PATCH] generics --- Aufgabe2-Rechenrätsel/src/main.rs | 175 +++++++++++++++++------------- 1 file changed, 99 insertions(+), 76 deletions(-) diff --git a/Aufgabe2-Rechenrätsel/src/main.rs b/Aufgabe2-Rechenrätsel/src/main.rs index 1c28895..5c23403 100644 --- a/Aufgabe2-Rechenrätsel/src/main.rs +++ b/Aufgabe2-Rechenrätsel/src/main.rs @@ -1,9 +1,16 @@ +#![feature(trait_alias)] + use clap::Parser; use std::collections::HashSet; use std::collections::HashMap; use rand::distributions::{Distribution, Uniform}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; +use num_traits::NumCast; +use num_integer::Integer; +use std::hash::Hash; + +trait BasicInteger = Integer + Hash + Copy; #[derive(FromPrimitive)] enum Operator { @@ -35,31 +42,33 @@ struct Args { solution_print: bool, } -type RiddleMap = HashMap; - -struct PartOperation { - results: RiddleMap, +struct PartOperation { + results: HashMap>, last_operator: Option, } -struct ResultStore { - riddles: RiddleMap, - results_already_taken: HashSet, +struct ResultStore { + riddles: HashMap, + results_already_taken: HashSet, } -impl ResultStore { +impl ResultStore { fn new() -> Self { Self{ riddles: HashMap::new(), results_already_taken: HashSet::new(), } } - fn store(&mut self, result: i64, operators: u64) { + fn store(&mut self, result: T, operators: Option) { if self.results_already_taken.contains(&result) {return;} - match self.riddles.remove(&result) { - None => {self.riddles.insert(result, operators);} - Some(_x) => {self.results_already_taken.insert(result);} + if match operators { + None => true, + Some(_x) => {self.riddles.contains_key(&result)} + } { + self.riddles.remove(&result); + self.results_already_taken.insert(result); } + else {self.riddles.insert(result, operators.unwrap());} } } @@ -92,76 +101,84 @@ fn main() { *digit = rand_number + 1; } } - { - let mut results = ResultStore::new(); - for dm_as_map in 0..2u64.pow(args.count as u32) { - let mut results_multiplicate: Vec = Vec::new(); + calc_results::(args, digits); +} + +fn calc_results(args: Args, digits: Vec) { + let mut results = ResultStore::new(); + for dm_as_map in 0..2u32.pow(args.count as u32) { + let mut results_multiplicate: Vec> = Vec::new(); + { + let mut last_i: usize = 0; + let mut i: usize; + let mut state: AddSubOrMultiplicateDivide = FromPrimitive::from_u32(dm_as_map & 1).unwrap(); + while last_i < args.count as usize { + i = last_i; + while i < args.count as usize && dm_as_map >> i & 1 == state as u32 { + if state == AddSubOrMultiplicateDivide::AddSub { + results_multiplicate.push(insert_digit(&digits, i)); + } + i += 1; + } + if state == AddSubOrMultiplicateDivide::MultiplicateDivide { + let mut part_results: HashMap> = HashMap::new(); + i += 1; + let mut digits_calc = digits[last_i .. i].iter(); + let first_digit = FromPrimitive::from_u8(*digits_calc.next().unwrap()).unwrap(); + multiplicate_divide(digits_calc, &mut part_results, last_i as u8 * 2, first_digit, 0); + results_multiplicate.push(PartOperation{ + results: part_results, + last_operator: last_operator_helper(last_i), + }); + } + state = match state { + AddSubOrMultiplicateDivide::MultiplicateDivide => AddSubOrMultiplicateDivide::AddSub, + AddSubOrMultiplicateDivide::AddSub => AddSubOrMultiplicateDivide::MultiplicateDivide, + }; + last_i = i; + } + if dm_as_map >> args.count - 1 & 1 == AddSubOrMultiplicateDivide::AddSub as u32 { + results_multiplicate.push(insert_digit(&digits, digits.len() - 1)); + } { - let mut last_i: usize = 0; - let mut i: usize; - let mut state: AddSubOrMultiplicateDivide = FromPrimitive::from_u64(dm_as_map & 1).unwrap(); - while last_i < args.count as usize { - i = last_i; - while i < args.count as usize && dm_as_map >> i & 1 == state as u64 { - if state == AddSubOrMultiplicateDivide::AddSub { - results_multiplicate.push(insert_digit(&digits, i)); - } - i += 1; - } - if state == AddSubOrMultiplicateDivide::MultiplicateDivide { - let mut part_results = ResultStore::new(); - i += 1; - let mut digits_calc = digits[last_i .. i].iter(); - let first_digit = *digits_calc.next().unwrap() as i64; - calc_part(digits_calc, &mut part_results, last_i as u8 * 2, first_digit, 0); - results_multiplicate.push(PartOperation{ - results: part_results.riddles, - last_operator: last_operator_helper(last_i), - }); - } - state = match state { - AddSubOrMultiplicateDivide::MultiplicateDivide => AddSubOrMultiplicateDivide::AddSub, - AddSubOrMultiplicateDivide::AddSub => AddSubOrMultiplicateDivide::MultiplicateDivide, - }; - last_i = i; - } - if dm_as_map >> args.count - 1 & 1 == AddSubOrMultiplicateDivide::AddSub as u64 { - results_multiplicate.push(insert_digit(&digits, digits.len() - 1)); - } - { - let mut iter = results_multiplicate.iter(); - for (part_result, operators) in &iter.next().unwrap().results { - add_sub(iter.clone(), &mut results, *part_result, *operators); - } + let mut iter = results_multiplicate.iter(); + for (part_result, operators) in &iter.next().unwrap().results { + add_sub(iter.clone(), &mut results, *part_result, *operators); } } } - let mut not_first = false; - for (result, operators) in results.riddles { - if not_first {println!();} - not_first = true; - print_riddle(&digits, false, result, operators); - if args.solution_print { - print_riddle(&digits, true, result, operators); - } + } + let mut not_first = false; + for (result, operators) in results.riddles { + if not_first {println!();} + not_first = true; + let result_u128 = num_traits::cast(result).unwrap(); + print_riddle(&digits, false, result_u128, operators); + if args.solution_print { + print_riddle(&digits, true, result_u128, operators); } } } -fn calc_part<'a>(mut iter: impl Clone + Iterator, results: &mut ResultStore, operator_index: u8, part_result: i64, operators: u64) { +fn multiplicate_divide<'a, T: BasicInteger + FromPrimitive> +(mut iter: impl Clone + Iterator, results: &mut HashMap>, +operator_index: u8, part_result: T, operators: u64) { match iter.next() { - None => results.store(part_result, operators), + None => { + results.insert(part_result, if results.contains_key(&part_result) + {None} else {Some(operators)}); + } Some(next) => { - let next_digit = *next as i64; + let next_digit = FromPrimitive::from_u8(*next).unwrap(); for operator in [Operator::Multiplicate, Operator::Divide] { - calc_part(iter.clone(), results, operator_index + 2, + multiplicate_divide(iter.clone(), results, operator_index + 2, match operator { Operator::Multiplicate => part_result * next_digit, Operator::Divide => { - if part_result % next_digit != 0 {continue;} + if part_result % next_digit != T::zero() {continue;} part_result / next_digit } - _ => 0, + _ => T::zero(), }, operators | (operator as u64) << operator_index); } @@ -169,21 +186,27 @@ fn calc_part<'a>(mut iter: impl Clone + Iterator, results: &mut R } } -fn add_sub<'a>(mut iter: impl Clone + Iterator, results: &mut ResultStore, part_result: i64, operators: u64) { +fn add_sub<'a, T: BasicInteger + 'static> +(mut iter: impl Clone + Iterator>, +results: &mut ResultStore, part_result: T, operators: Option) { match iter.next() { None => { - if part_result > 0 {results.store(part_result, operators);} + if part_result > T::zero() {results.store(part_result, operators);} } Some(next) => { for (next_result, part_operators) in &next.results { for operator in [Operator::Add, Operator::Subtract] { add_sub(iter.clone(), results, match operator { - Operator::Add => part_result + next_result, - Operator::Subtract => part_result - next_result, - _ => 0, + Operator::Add => part_result + *next_result, + Operator::Subtract => part_result - *next_result, + _ => T::zero(), }, - operators | part_operators | (operator as u64) << 2 * next.last_operator.unwrap() + if operators == None || *part_operators == None {None} + else { + Some(operators.unwrap() | part_operators.unwrap() | + (operator as u64) << 2 * next.last_operator.unwrap()) + } ); } } @@ -195,16 +218,16 @@ fn last_operator_helper(index: usize) -> Option { if index == 0 {None} else {Some(index as usize - 1)} } -fn insert_digit(digits: &Vec, i: usize) -> PartOperation { - let mut result_map = RiddleMap::new(); - result_map.insert(digits[i] as i64, 0); +fn insert_digit(digits: &Vec, i: usize) -> PartOperation { + let mut result_map: HashMap> = HashMap::new(); + result_map.insert(T::from_u8(digits[i]).unwrap(), Some(0)); return PartOperation{ results: result_map, last_operator: last_operator_helper(i), }; } -fn print_riddle(digits: &Vec, show_solution: bool, result: i64, operators: u64) { +fn print_riddle(digits: &Vec, show_solution: bool, result: u128, operators: u64) { print!("{}: ", if show_solution {"Lösung"} else {"Rätsel"}); let mut i = 0; for digit in digits[.. digits.len() - 1].iter() {