Created
October 23, 2022 16:18
-
-
Save zRains/5e3a3578390017103bf429e9b2e61ba8 to your computer and use it in GitHub Desktop.
leetcode 1024 Rust implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::cell::RefCell; | |
use std::cmp; | |
use std::collections::HashSet; | |
use std::fmt::Debug; | |
use std::hash::Hash; | |
use std::rc::Rc; | |
#[derive(Debug)] | |
#[allow(dead_code)] | |
struct CalcResult<'a> { | |
numbers: Vec<i32>, | |
symbols: Vec<&'a str>, | |
} | |
fn calc(num_1: i32, symbol: &str, num_2: i32) -> Result<i32, &str> { | |
match symbol { | |
"+" | "-" => match num_1.overflowing_add(num_2) { | |
(_, true) => Err("Add/Sub operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
"*" => match num_1.overflowing_mul(num_2) { | |
(_, true) => Err("Multiply operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
"//" => match num_1.overflowing_div(num_2) { | |
(_, true) => Err("Divide operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
"**" if num_2 >= 0 => match num_1.overflowing_pow(num_2 as u32) { | |
(_, true) => Err("Exponential operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
"%" => match num_1.overflowing_rem(num_2) { | |
(_, true) => Err("Remain operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
"<<" if num_2 >= 0 => match num_1.overflowing_shl(num_2 as u32) { | |
(_, true) => Err("Right shifted operation overflow occurs"), | |
(result, _) => Ok(result), | |
}, | |
">>" if num_2 >= 0 => Ok(num_1 >> (cmp::min(31, num_2))), | |
"|" => Ok(num_1 | num_2), | |
"&" => Ok(num_1 & num_2), | |
"^" => Ok(num_1 ^ num_2), | |
_ => Err("Invalid symbol or SHR"), | |
} | |
} | |
fn permutation<T: Clone + Debug>(arr: Vec<T>) -> Vec<Vec<T>> { | |
let arr_len = arr.len() as i32; | |
let result = Rc::new(RefCell::new(Vec::<Vec<T>>::new())); | |
fn recur<K: Clone>( | |
recur_arr: Rc<RefCell<Vec<K>>>, | |
recur_arr_len: i32, | |
recur_result: Rc<RefCell<Vec<Vec<K>>>>, | |
) { | |
if recur_arr_len == 1 { | |
recur_result | |
.borrow_mut() | |
.push(recur_arr.as_ref().borrow().clone()) | |
} | |
for idx in 0..recur_arr_len { | |
recur( | |
Rc::clone(&recur_arr), | |
recur_arr_len - 1, | |
Rc::clone(&recur_result), | |
); | |
if recur_arr_len % 2 == 1 { | |
recur_arr.borrow_mut().swap(0, (recur_arr_len - 1) as usize) | |
} else { | |
recur_arr | |
.borrow_mut() | |
.swap(idx as usize, (recur_arr_len - 1) as usize) | |
} | |
} | |
} | |
recur(Rc::new(RefCell::new(arr)), arr_len, Rc::clone(&result)); | |
result.take() | |
} | |
fn combination<T: Clone + Debug>(arr: Vec<T>, amount: u8) -> Vec<Vec<T>> { | |
let result = Rc::new(RefCell::new(Vec::<Vec<T>>::new())); | |
let path = Rc::new(RefCell::new(Vec::<T>::new())); | |
fn recur<K: Clone>( | |
idx: u8, | |
recur_amount: u8, | |
recur_arr: Rc<RefCell<Vec<K>>>, | |
recur_path: Rc<RefCell<Vec<K>>>, | |
recur_result: Rc<RefCell<Vec<Vec<K>>>>, | |
) { | |
if recur_path.as_ref().borrow().len() == recur_amount as usize { | |
recur_result | |
.borrow_mut() | |
.push(recur_path.as_ref().borrow().clone()); | |
return; | |
} | |
for i in idx..recur_arr.as_ref().borrow().len() as u8 { | |
recur_path | |
.borrow_mut() | |
.push(recur_arr.as_ref().borrow()[i as usize].clone()); | |
recur( | |
i + 1, | |
recur_amount, | |
Rc::clone(&recur_arr), | |
Rc::clone(&recur_path), | |
Rc::clone(&recur_result), | |
); | |
recur_path.borrow_mut().pop(); | |
} | |
} | |
recur( | |
0, | |
amount, | |
Rc::new(RefCell::new(arr)), | |
path, | |
Rc::clone(&result), | |
); | |
result.take() | |
} | |
fn group<T: Clone + Debug + Eq + Hash>(arr: Vec<T>, amount: u8) -> Vec<Vec<T>> { | |
let mut result = Vec::<Vec<T>>::new(); | |
let mut set = HashSet::<Vec<T>>::new(); | |
combination(arr, amount).into_iter().for_each(|c| { | |
permutation(c).into_iter().for_each(|p| { | |
if !set.contains(&p) { | |
set.insert(p.clone()); | |
result.push(p) | |
} | |
}) | |
}); | |
result | |
} | |
fn calc_all<'a>(numbers: &'a Vec<i32>, symbols: &'a Vec<&str>) -> Result<i32, &'a str> { | |
let mut num_1 = numbers[0]; | |
for idx in 0..3 { | |
num_1 = calc(num_1, symbols[idx], numbers[idx + 1])?; | |
} | |
Ok(num_1) | |
} | |
fn process(number_cards: Vec<i32>, symbol_cards: Vec<&str>) -> Vec<CalcResult> { | |
let mut result = Vec::<CalcResult>::new(); | |
let number_groups = group(number_cards, 4); | |
let symbol_groups = group(symbol_cards, 3); | |
for numbers in &number_groups { | |
for symbols in &symbol_groups { | |
if let Ok(calc_result) = calc_all(numbers, symbols) { | |
if calc_result == 1024 { | |
result.push(CalcResult { | |
numbers: numbers.clone(), | |
symbols: symbols.clone(), | |
}) | |
} | |
} | |
} | |
} | |
result | |
} | |
fn main() { | |
println!("{:#?}", process(vec![4, 4, 21, 1024], vec!["%", "^", "&"])); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment