Skip to content

Instantly share code, notes, and snippets.

@zRains
Created October 23, 2022 16:18
Show Gist options
  • Save zRains/5e3a3578390017103bf429e9b2e61ba8 to your computer and use it in GitHub Desktop.
Save zRains/5e3a3578390017103bf429e9b2e61ba8 to your computer and use it in GitHub Desktop.
leetcode 1024 Rust implementation
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