chore: unwrap one layer

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-12-12 14:36:00 +01:00
parent 4fcc0c57fd
commit 2351dfd0ee
Signed by: mfocko
GPG key ID: 7C47D46246790496
180 changed files with 2 additions and 3 deletions

13
rs/add-digits.rs Normal file
View file

@ -0,0 +1,13 @@
impl Solution {
pub fn add_digits(num: i32) -> i32 {
if num == 0 {
return 0;
}
if num % 9 == 0 {
return 9;
}
num % 9
}
}

View file

@ -0,0 +1,102 @@
#[derive(Debug)]
struct State {
price: i32,
profit: i32,
}
impl State {
fn new() -> State {
State {
price: i32::MAX,
profit: 0,
}
}
fn update(&self, previous: &State, price: i32) -> State {
let new_price = std::cmp::min(self.price, price - previous.profit);
State {
price: new_price,
profit: std::cmp::max(self.profit, price - new_price),
}
}
}
impl Solution {
pub fn max_profit(k: i32, prices: Vec<i32>) -> i32 {
let mut states: Vec<State> = (0..=k).map(|_| State::new()).collect();
prices.iter().for_each(|p| {
let mut new_states = Vec::from([State::new()]);
new_states.extend(
states
.iter()
.zip(states.iter().skip(1))
.map(|(prev_state, state)| state.update(prev_state, *p)),
);
states = new_states;
});
states.last().expect("No state is present").profit
}
}
struct Solution {}
fn main() {
println!("Hello World!");
}
#[cfg(test)]
mod tests_max_profit {
use super::*;
#[test]
fn test_small_example() {
assert_eq!(Solution::max_profit(2, vec![2, 4, 1]), 2);
}
#[test]
fn test_bigger_example() {
assert_eq!(Solution::max_profit(2, vec![3, 2, 6, 5, 0, 3]), 7);
}
#[test]
fn test_small_no_transaction() {
assert_eq!(Solution::max_profit(0, vec![2, 4, 1]), 0);
}
#[test]
fn test_small_one_transaction() {
assert_eq!(Solution::max_profit(1, vec![2, 4, 1]), 2);
}
#[test]
fn test_bigger_one_transaction() {
assert_eq!(Solution::max_profit(1, vec![3, 2, 6, 5, 0, 3]), 4);
}
#[test]
fn test_big_all_transactions() {
assert_eq!(
Solution::max_profit(10, vec![3, 2, 6, 5, 0, 3, 1, 13, 5, 2, 1, 9, 4, 5, 69, 42]),
92
);
}
#[test]
fn test_buy_expensive() {
assert_eq!(Solution::max_profit(2, vec![2, 3, 14, 15]), 13);
}
#[test]
fn test_accumulates_profit() {
assert_eq!(Solution::max_profit(5, vec![1, 2, 1, 2, 1, 2, 1, 2, 5]), 7);
}
#[test]
fn test_no_profit_made() {
assert_eq!(Solution::max_profit(2, vec![5, 4]), 0);
}
}

View file

@ -0,0 +1,40 @@
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
fn inorder(values: &mut Vec<i32>, node: Option<&Rc<RefCell<TreeNode>>>) {
match node {
None => {},
Some(n) => {
Solution::inorder(values, (*n).borrow().left.as_ref());
values.push((*n).borrow().val);
Solution::inorder(values, (*n).borrow().right.as_ref());
}
}
}
pub fn inorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut values: Vec<i32> = Vec::new();
Solution::inorder(&mut values, root.as_ref());
values
}
}

View file

@ -0,0 +1,190 @@
use std::collections::HashMap;
impl Solution {
const MODULO: i64 = 1000000007;
fn process_factor(factors: &[i32], j: usize, counts: &mut HashMap<i32, i64>, factor: i32) {
counts.insert(factor, 1);
for i in 0..j {
if factor % factors[i] == 0 && counts.contains_key(&(factor / factors[i])) {
let previous = *counts.get(&factor).unwrap();
let left = counts[&factors[i]];
let right = counts[&(factor / factors[i])];
counts.insert(factor, (previous + left * right) % Solution::MODULO);
}
}
}
pub fn num_factored_binary_trees(arr: Vec<i32>) -> i32 {
let mut factors = arr;
factors.sort_unstable();
let mut counts = HashMap::<i32, i64>::new();
for (i, factor) in factors.iter().enumerate() {
Solution::process_factor(&factors, i, &mut counts, *factor);
}
counts
.values()
.fold(0, |acc: i64, &x| (acc + x) % Solution::MODULO) as i32
}
}
struct Solution {}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example_1() {
assert_eq!(Solution::num_factored_binary_trees(vec![2, 4]), 3);
}
#[test]
fn test_example_2() {
assert_eq!(Solution::num_factored_binary_trees(vec![2, 4, 5, 10]), 7);
}
#[test]
fn test_example_3() {
assert_eq!(Solution::num_factored_binary_trees(vec![2, 8]), 2);
// assert_eq!(Solution::num_factored_binary_trees(vec![2, 8]), 3);
}
#[test]
fn test_forgor_modulo() {
assert_eq!(
Solution::num_factored_binary_trees(vec![
46, 144, 5040, 4488, 544, 380, 4410, 34, 11, 5, 3063808, 5550, 34496, 12, 540, 28,
18, 13, 2, 1056, 32710656, 31, 91872, 23, 26, 240, 18720, 33, 49, 4, 38, 37, 1457,
3, 799, 557568, 32, 1400, 47, 10, 20774, 1296, 9, 21, 92928, 8704, 29, 2162, 22,
1883700, 49588, 1078, 36, 44, 352, 546, 19, 523370496, 476, 24, 6000, 42, 30, 8,
16262400, 61600, 41, 24150, 1968, 7056, 7, 35, 16, 87, 20, 2730, 11616, 10912, 690,
150, 25, 6, 14, 1689120, 43, 3128, 27, 197472, 45, 15, 585, 21645, 39, 40, 2205,
17, 48, 136
]),
509730797
);
}
#[test]
fn test_wtf() {
assert_eq!(
Solution::num_factored_binary_trees(vec![
60588000, 36158400, 950040, 162450288, 446000100, 1807920, 31590000, 360,
166153680, 6, 91213584, 34186320, 915124000, 68600, 6497400, 10, 194304, 951035904,
393822000, 23522400, 14400, 821376000, 80, 881118000, 576000, 3660480, 106801200,
180690300, 5100, 1573200, 36288000, 38, 197643600, 221852925, 8820, 36000,
822294528, 13935240, 236307456, 17409600, 443741760, 62868, 548800000, 25271064,
34848, 344137500, 8383500, 186, 45, 100980, 722358000, 63000000, 16442400, 1579500,
684, 12970692, 243540, 232560, 149153400, 437400, 16215, 713460, 75524400, 118800,
1575, 106920, 10150, 13770000, 33999966, 177811200, 64680, 2880768, 632459520,
8675100, 498700800, 213572700, 18657600, 22, 6993, 49, 177147000, 6480, 20,
3910368, 85201200, 1764, 120093120, 16022160, 290822400, 6219200, 29376000, 235290,
20979000, 5, 384, 959140, 443944800, 11303040, 952560, 47736000, 33404280, 39936,
11864320, 144270720, 12868224, 18289152, 87230682, 145860, 262548, 10276500, 12,
612, 179010000, 622987200, 108475200, 1012, 60, 14880, 10924200, 2285568,
149178000, 1573936, 195695500, 213269760, 24975, 12000, 3706560, 168382080, 114724,
87650640, 8019000, 8035200, 8621844, 514500, 155, 132612480, 1676700, 627318720,
39330, 17, 926100000, 283360, 69949440, 856575, 4092, 130, 720, 958035000, 5396820,
2668, 6606336, 169708000, 2352240, 26, 40608000, 324576, 3220, 4945920, 187697664,
350, 3965520, 40500, 9000, 142560, 39580800, 447051000, 19077120, 36605250, 775,
19404, 87514000, 2673, 9720, 4942080, 56752500, 118216665, 858, 18225, 3124800,
1530, 380160, 24554880, 2762100, 646945200, 173210400, 22376250, 731076192, 161,
44705100, 145981440, 18223660, 215424, 878526000, 22883952, 92092, 7306200, 32,
2708160, 566957475, 17305344, 119556000, 411402240, 1292544, 454480, 2208,
27498240, 249230520, 88058880, 2108, 527800, 455, 49846104, 801900, 252450, 7644,
129540320, 2241675, 1330, 71089200, 2709630, 43545600, 497250, 4972968, 826277760,
249091200, 68827500, 60900, 271282240, 13910400, 88609950, 46189440, 3088800,
582912000, 4284000, 304980000, 32736, 992, 52992, 454545000, 14064960, 72967500,
892584000, 61678260, 3410, 49104000, 840931520, 107805600, 200475, 35384580,
4289408, 599079390, 777, 465696, 7956000, 540960, 3385200, 8741250, 17748, 2528240,
2248480, 83076840, 366282000, 15120000, 6871956, 15586560, 992673792, 367200,
65577600, 635796000, 150, 62524000, 7551600, 1716660, 85932, 209986560, 6167826,
1557192, 20702500, 157320, 14427072, 553402080, 203290560, 3830112, 1500,
120992256, 89280, 66943800, 8937984, 30, 32457600, 75140, 874, 34398000, 390600,
955500, 32542560, 51068160, 6624, 545368824, 316461600, 236670, 598067712,
97538400, 3240000, 664801200, 6120, 477487296, 445419000, 38318280, 148800, 7,
1055600, 9128700, 6472800, 13176240, 535680, 7998, 345960, 1262250, 78693120, 1364,
15, 13800, 406000, 42, 23, 703872, 787939152, 24288, 37795758, 6300000, 145704960,
124, 46920, 3142656, 31725, 92, 186300, 1470, 73500, 3495250, 196416, 639878400,
65800, 1015680, 131176500, 37264500, 243984000, 19227000, 917280, 9384000, 81840,
454406400, 795217500, 147420000, 6976800, 14651280, 116, 11960, 153740160,
799948800, 5184000, 501686640, 1020, 773500, 145763550, 26417664, 11446380, 13,
14817600, 406125720, 7068600, 730667520, 3371004, 2677752, 2692305, 70615314, 1771,
388411200, 20175075, 14742000, 139991040, 302400, 40131360, 21740796, 5996025,
205615179, 469193472, 23220, 8286300, 19706400, 2812992, 72886425, 3072, 6557760,
551779200, 960, 74592, 185427840, 40068864, 883872000, 85250, 3499200, 2210,
402772500, 1274, 106260, 4392080, 953146480, 90744192, 132699840, 4270560,
361746000, 342720, 673536600, 2418, 234600, 967255800, 34500, 8910, 196040,
374190336, 9790200, 694747200, 5385600, 907200, 493426080, 804683880, 13820544,
7999488, 4879680, 88400, 13765500, 28, 377, 172339200, 97152, 427680, 41731200,
92610, 13950000, 564200, 2520, 74970, 11603592, 16, 18200, 201386250, 474525,
531468, 1860, 51840, 677376, 59520, 4457400, 8912376, 6742008, 11013975, 566280,
330832, 110707200, 172727100, 382200, 942480, 10200, 3210480, 2033600, 11289564,
6667920, 675347400, 79994880, 27676800, 158100, 133722000, 66769920, 332041248, 25,
1545600, 21450, 655966080, 11814660, 223200, 4151040, 1016064, 35, 1607040, 924,
586333020, 174787200, 63756, 18957120, 788900000, 351900000, 1380, 5441800, 374,
44200, 38640, 8307684, 109707264, 2178, 7440, 6577200, 29435, 264600000, 12960000,
2646, 891691416, 475656192, 214033920, 431708160, 70340256, 404736, 39104,
787059000, 3208500, 220103100, 191268, 66960000, 18500832, 856016640, 173901000,
1238688, 157489920, 54782, 550946880, 242573760, 257040, 282720, 117645000,
165369600, 13110, 434079360, 9133344, 621000, 174037500, 126960, 6147900,
137491200, 29559600, 700, 185220000, 317520000, 200344320, 14036, 26601120,
3535488, 3649940, 16240, 61659000, 430848, 779483250, 363528000, 419764800,
729933750, 386661600, 111481920, 35700, 6561000, 68695200, 70, 297, 83700, 990,
113076810, 461538, 787529952, 4324, 20727, 40350150, 218700, 846720, 540, 29889000,
1016600, 277704000, 62734080, 14856192, 210924000, 589248000, 5760, 222393600,
30180600, 166059400, 31021056, 98208, 21, 21168, 98208000, 13464, 1555200,
16077600, 288, 4332042, 320550912, 204989400, 785664, 67897440, 65472, 16228800,
70560, 80352, 8, 9520896, 71280, 4862, 44, 12545280, 657395200, 39, 64152000,
283719996, 247443840, 924159600, 20286000, 268065, 138983850, 9300, 5286120,
61534200, 496601280, 875033280, 6370, 5940, 364, 29412, 261360, 1248, 477290880,
5880, 669600, 82174400, 53568, 483000, 36, 18, 29728512, 12057760, 3046680, 44660,
368874000, 167040, 4276800, 83462400, 11050, 638, 34300000, 27, 509110272,
437132430, 81200, 33, 6277500, 113601600, 14850, 10789200, 157216500, 20348928,
10701900, 365904000, 1728, 1782960, 1255800, 38321400, 3542, 6229872, 40864824,
514483200, 43, 1159200, 413100, 1127100, 8019, 198251550, 47, 30950400, 2115, 46,
45900, 233280000, 125736, 200508, 5742, 222456, 442520, 245188944, 162288000,
5589000, 76923, 2461536, 415457280, 715936320, 179289600, 14826240, 17150000,
13759200, 63240, 7001280, 663000, 22776600, 221925825, 920700, 1421000, 1715616,
30198960, 1766100, 2480, 290, 460, 1556640, 1015, 145411200, 11350500, 824199480,
539028000, 11865150, 882000, 19, 830297000, 159840, 7632800, 81053840, 68250,
77873400, 123965952, 164826900, 23040, 347200, 51323580, 30294000, 140777000, 1023,
147556500, 273420, 13665960, 2760, 21780, 77552640, 3245760, 341433225, 930, 12740,
441, 960498, 184988160, 219240000, 125854344, 13986, 174960, 53978400, 2163168,
456840000, 1513400, 179676000, 90810720, 28569600, 4923072, 807003000, 49758720,
47404500, 480, 42340320, 837000000, 3, 3720, 15847920, 1400, 1715000, 251160, 198,
504708750, 8932000, 6311250, 1458240, 96, 37235712, 911400, 255816, 142084800,
39346560, 2384640, 38491200, 1872000, 899640, 14586, 294624, 37, 239760, 469476000,
1015200, 531454000, 411840, 36352800, 15367680, 273454272, 63987840, 22416750,
24500, 171535, 683384832, 47586240, 82800, 112266, 12746370, 429545025, 875769840,
125468160, 74, 39412800, 45904320, 9313920, 1589760, 24, 570240, 72912000, 107880,
1758120, 7980, 2614640, 34, 12987000, 3124044, 728640, 21420, 4, 22855680, 21600,
99, 11, 203076720, 90132, 687447000, 5049000, 747225, 37620, 13363200, 209265525,
171169600, 461039040, 36946, 79197560, 35280, 108100, 22032000, 343062720,
29141775, 906782240, 297600, 298378080, 486129600, 979104000, 22151360, 74576700,
1647030, 58870, 828100, 1064, 58605120, 12182400, 860288, 41, 62107500, 9,
310495680, 71951360, 29, 105995232, 13838, 1617000, 832431600, 328671, 510,
3826550, 689018400, 10959300, 48, 3294060, 22720320, 132022800, 24663600, 40, 520,
6756750, 429624000, 79497600, 11427840, 489167910, 54734592, 10847520, 887284800,
223948800, 735139125, 3478200, 470235, 649152000, 86619456, 932536800, 2976, 675,
491756100, 73780, 1142784, 5488560, 1473780, 301693392, 8819902, 88357500, 40392,
579600, 457113600, 2, 692841600, 77189112, 49538412, 18086640, 104976000, 35162400,
4320, 435, 107892000, 14, 832, 257094000, 345, 323389440, 813440, 13392000, 29760,
8391600, 599400, 1713600, 154560, 7380480, 127429200, 198360, 8625, 459345600,
13117650, 1309440, 85680, 41972175, 75710880, 87339648, 55296000, 1054, 10098,
269414640, 787644000, 34560, 253, 721353600, 28072, 5984, 148764, 84630, 25966080,
141120, 46368, 101680, 31, 82197720, 3312400, 2980800, 18247680, 12453120, 9108,
3050400
]),
874417692
);
}
}

View file

@ -0,0 +1,31 @@
struct Solution {}
impl Solution {
pub fn can_make_arithmetic_progression(mut arr: Vec<i32>) -> bool {
arr.sort();
let diffs: Vec<i32> = arr.windows(2).map(|pair| pair[1] - pair[0]).collect();
diffs.windows(2).all(|pair| pair[0] == pair[1])
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
// Input: arr = [3,5,1]
// Output: true
// Explanation: We can reorder the elements as [1,3,5] or [5,3,1] with differences 2 and -2 respectively, between each consecutive elements.
#[test]
fn example_1() {
assert!(Solution::can_make_arithmetic_progression(vec![3, 5, 1]));
}
// Input: arr = [1,2,4]
// Output: false
// Explanation: There is no way to reorder the elements to obtain an arithmetic progression.
#[test]
fn example_2() {
assert!(!Solution::can_make_arithmetic_progression(vec![2, 4, 1]));
}
}

View file

@ -0,0 +1,58 @@
struct Solution {}
impl Solution {
fn x_diff(a: &[i32], b: &[i32]) -> i32 {
a[0] - b[0]
}
fn y_diff(a: &[i32], b: &[i32]) -> i32 {
a[1] - b[1]
}
pub fn check_straight_line(coordinates: Vec<Vec<i32>>) -> bool {
assert!(coordinates.len() > 1);
let (dx, dy) = (
Solution::x_diff(&coordinates[0], &coordinates[1]),
Solution::y_diff(&coordinates[0], &coordinates[1]),
);
coordinates.iter().all(|pt| {
dx * Solution::y_diff(pt, &coordinates[0]) == dy * Solution::x_diff(pt, &coordinates[0])
})
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
// Input: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]
// Output: true
#[test]
fn example_1() {
assert!(Solution::check_straight_line(vec![
vec![1, 2],
vec![2, 3],
vec![3, 4],
vec![4, 5],
vec![5, 6],
vec![6, 7]
]));
}
// Input: coordinates = [[1,1],[2,2],[3,4],[4,5],[5,6],[7,7]]
// Output: false
#[test]
fn example_2() {
assert!(!Solution::check_straight_line(vec![
vec![1, 1],
vec![2, 2],
vec![3, 4],
vec![4, 5],
vec![5, 6],
vec![7, 7]
]));
}
}

View file

@ -0,0 +1,42 @@
use std::fmt;
use std::str::FromStr;
#[derive(Debug, PartialEq)]
struct Complex {
real: i32,
imag: i32,
}
#[derive(Debug)]
struct InvalidComplex;
impl FromStr for Complex {
type Err = InvalidComplex;
fn from_str(input: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = input.split('+').collect();
let real = parts[0].parse::<i32>().unwrap();
let imag = parts[1].trim_end_matches('i').parse::<i32>().unwrap();
Ok(Complex { real, imag })
}
}
impl fmt::Display for Complex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}+{}i", self.real, self.imag)
}
}
impl Solution {
pub fn complex_number_multiply(num1: String, num2: String) -> String {
let left: Complex = num1.parse().unwrap();
let right: Complex = num2.parse().unwrap();
(Complex {
real: left.real * right.real - left.imag * right.imag,
imag: left.real * right.imag + left.imag * right.real,
})
.to_string()
}
}

View file

@ -0,0 +1,104 @@
use std::collections::HashMap;
type CacheKey = (i32, char);
struct Cache {
cache: HashMap<CacheKey, i32>,
}
impl Cache {
const MODULO: i32 = 1000000007;
fn new() -> Cache {
let mut cache = HashMap::<CacheKey, i32>::new();
for c in "aeiou".chars() {
cache.insert((1, c), 1);
}
Cache { cache: cache }
}
fn is_precomputed(&self, n: i32) -> bool {
self.cache.keys().any(|key| key.0 == n)
}
fn get(&self, n: i32) -> i32 {
self.cache
.keys()
.filter(|key| key.0 == n)
.fold(0, |acc, key| {
// Since the answer may be too large, return it modulo 10^9 + 7.
(acc + self.cache.get(key).unwrap_or(&0)) % Self::MODULO
})
}
fn precompute(&mut self, n: i32) {
if self.is_precomputed(n) {
return;
}
if !self.is_precomputed(n - 1) {
self.precompute(n - 1);
}
for (current, continuation) in vec![
('a', "e"),
('e', "ai"),
('i', "aeou"),
('o', "iu"),
('u', "a"),
] {
self.cache.insert(
(n, current),
continuation.chars().fold(0, |acc, vowel| {
(acc + self.cache.get(&(n - 1, vowel)).unwrap()) % Self::MODULO
}),
);
}
}
}
struct Solution {}
impl Solution {
pub fn count_vowel_permutation(n: i32) -> i32 {
let mut cache = Cache::new();
cache.precompute(n);
cache.get(n)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example_1() {
// Input: n = 1
// Output: 5
// Explanation: All possible strings are: "a", "e", "i" , "o" and "u".
assert_eq!(count_vowel_permutation(1), 5);
}
#[test]
fn test_example_2() {
// Input: n = 2
// Output: 10
// Explanation: All possible strings are: All possible strings are: "ae", "ea", "ei", "ia", "ie", "io", "iu", "oi", "ou" and "ua".
assert_eq!(count_vowel_permutation(2), 10);
}
#[test]
fn test_example_3() {
// Input: n = 5
// Output: 68
assert_eq!(count_vowel_permutation(5), 68);
}
#[test]
fn test_example_4() {
// Input: n = 3
// Output: 19
assert_eq!(count_vowel_permutation(3), 19);
}
}

View file

@ -0,0 +1,118 @@
use std::collections::{HashMap, HashSet, VecDeque};
fn distance(a: (i64, i64), b: (i64, i64)) -> i64 {
let (x1, y1) = a;
let (x2, y2) = b;
(x1 - x2).pow(2) + (y1 - y2).pow(2)
}
struct Graph {
edges: HashMap<usize, HashSet<usize>>,
}
impl Graph {
fn new(bombs: &[Vec<i32>]) -> Self {
let mut edges = HashMap::new();
for (i, bomb) in bombs.iter().enumerate() {
edges.insert(i, HashSet::new());
let neighbours = edges.get_mut(&i).unwrap();
let (x, y, r) = (bomb[0], bomb[1], bomb[2]);
let rr = (r as i64).pow(2);
for j in 0..bombs.len() {
if i == j {
continue;
}
let (x1, y1) = (bombs[j][0], bombs[j][1]);
if distance((x as i64, y as i64), (x1 as i64, y1 as i64)) <= rr {
neighbours.insert(j);
}
}
}
Self { edges }
}
fn bfs(&self, mut visited: Vec<bool>, u0: usize) -> i32 {
let mut found = 0;
let mut q = VecDeque::new();
q.push_back(u0);
visited[u0] = true;
while let Some(u) = q.pop_front() {
found += 1;
for &v in self.edges.get(&u).unwrap_or(&HashSet::new()) {
if !visited[v] {
q.push_back(v);
visited[v] = true;
}
}
}
found
}
}
struct Solution {}
impl Solution {
pub fn maximum_detonation(bombs: Vec<Vec<i32>>) -> i32 {
let graph = Graph::new(&bombs);
let visited = vec![false; bombs.len()];
(0..bombs.len())
.map(|u| graph.bfs(visited.clone(), u))
.max()
.unwrap_or(0)
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
assert_eq!(
Solution::maximum_detonation(vec![vec![2, 1, 3], vec![6, 1, 4]]),
2
);
}
#[test]
fn example_2() {
assert_eq!(
Solution::maximum_detonation(vec![vec![1, 1, 5], vec![10, 10, 5]]),
1
);
}
#[test]
fn example_3() {
assert_eq!(
Solution::maximum_detonation(vec![
vec![1, 2, 3],
vec![2, 3, 1],
vec![3, 4, 2],
vec![4, 5, 3],
vec![5, 6, 4]
]),
5
);
}
#[test]
fn regression_1() {
assert_eq!(
Solution::maximum_detonation(vec![vec![1, 1, 100000], vec![100000, 100000, 1]]),
1
);
}
}

View file

@ -0,0 +1,54 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::rc::Rc;
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None,
// }
// }
// }
// struct Solution {}
impl Solution {
pub fn find_mode(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut counters: BTreeMap<i32, usize> = BTreeMap::new();
let mut stack: Vec<Option<Rc<RefCell<TreeNode>>>> = Vec::new();
stack.push(root.clone());
while let Some(node) = stack.pop() {
if node.is_none() {
continue;
}
let node = node.unwrap();
let n = node.borrow();
counters
.entry(n.val)
.and_modify(|curr| *curr += 1)
.or_insert(1);
stack.push(n.left.clone());
stack.push(n.right.clone());
}
let maximum = *counters.values().max().unwrap();
counters
.iter()
.filter_map(|(&k, &c)| if c == maximum { Some(k) } else { None })
.collect()
}
}

20
rs/find-pivot-index.rs Normal file
View file

@ -0,0 +1,20 @@
use std::convert::TryInto;
impl Solution {
pub fn pivot_index(nums: Vec<i32>) -> i32 {
let mut from_left: i32 = 0;
let mut from_right: i32 = nums.iter().sum();
for (i, e) in nums.iter().enumerate() {
from_right -= e;
if from_left == from_right {
return i.try_into().unwrap();
}
from_left += e;
}
-1
}
}

View file

@ -0,0 +1,54 @@
struct Solution {}
impl Solution {
pub fn longest_obstacle_course_at_each_position(obstacles: Vec<i32>) -> Vec<i32> {
let size = obstacles.len();
let mut lengths: Vec<i32> = vec![1; size];
let mut longest_increasing: Vec<i32> = vec![];
for (i, &height) in obstacles.iter().enumerate() {
let idx = longest_increasing.partition_point(|&x| x <= height);
if idx == longest_increasing.len() {
longest_increasing.push(height);
} else {
longest_increasing[idx] = height;
}
lengths[i] = (idx + 1) as i32;
}
lengths
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
assert_eq!(
Solution::longest_obstacle_course_at_each_position(vec![1, 2, 3, 2]),
vec![1, 2, 3, 3]
);
}
#[test]
fn example_2() {
assert_eq!(
Solution::longest_obstacle_course_at_each_position(vec![2, 2, 1]),
vec![1, 2, 1]
);
}
#[test]
fn example_3() {
assert_eq!(
Solution::longest_obstacle_course_at_each_position(vec![3, 1, 5, 6, 4, 2]),
vec![1, 1, 2, 3, 2, 2]
);
}
}

75
rs/is-graph-bipartite.rs Normal file
View file

@ -0,0 +1,75 @@
use std::collections::VecDeque;
struct Solution {}
impl Solution {
fn color(graph: &Vec<Vec<i32>>, start: usize, colors: &mut Vec<i32>) -> bool {
let mut q: VecDeque<usize> = VecDeque::new();
q.push_back(start);
while let Some(u) = q.pop_front() {
let u_color = colors[u];
let next_color = (colors[u] + 1) % 2;
for v in &graph[u] {
let v = *v as usize;
match colors[v] {
-1 => {
colors[v] = next_color;
q.push_back(v);
}
_ => {
if colors[v] != next_color {
return false;
}
}
}
}
}
true
}
pub fn is_bipartite(graph: Vec<Vec<i32>>) -> bool {
let mut colors = vec![-1; graph.len()];
for u in 0..graph.len() {
if colors[u] != -1 {
continue;
}
colors[u] = 0;
if !Solution::color(&graph, u, &mut colors) {
return false;
}
}
true
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
assert!(!Solution::is_bipartite(vec![
vec![1, 2, 3],
vec![0, 2],
vec![0, 1, 3],
vec![0, 2]
]));
}
#[test]
fn example_2() {
assert!(Solution::is_bipartite(vec![
vec![1, 3],
vec![0, 2],
vec![1, 3],
vec![0, 2]
]));
}
}

View file

@ -0,0 +1,41 @@
struct Solution {}
impl Solution {
pub fn kids_with_candies(candies: Vec<i32>, extra_candies: i32) -> Vec<bool> {
let max = *candies.iter().max().unwrap();
candies
.iter()
.map(|candies| candies + extra_candies >= max)
.collect()
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
assert_eq!(
Solution::kids_with_candies(vec![2, 3, 5, 1, 3], 3),
vec![true, true, true, false, true]
);
}
#[test]
fn example_2() {
assert_eq!(
Solution::kids_with_candies(vec![4, 2, 1, 1, 2], 1),
vec![true, false, false, false, false]
);
}
#[test]
fn example_3() {
assert_eq!(
Solution::kids_with_candies(vec![12, 1, 12], 10),
vec![true, false, true]
);
}
}

View file

@ -0,0 +1,18 @@
use std::cmp::max;
impl Solution {
pub fn length_of_lis(nums: Vec<i32>) -> i32 {
let mut dp = Vec::<i32>::new();
dp.resize(nums.len(), 1);
for i in 1..nums.len() {
for j in 0..i {
if nums[i] > nums[j] {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
*dp.iter().max().unwrap()
}
}

View file

@ -0,0 +1,45 @@
use std::cmp;
struct Solution {}
impl Solution {
pub fn longest_palindrome_subseq(s: String) -> i32 {
let mut longest: Vec<Vec<i32>> = vec![];
longest.resize_with(s.len(), || {
let mut nested: Vec<i32> = vec![];
nested.resize(s.len(), 0);
nested
});
for i in (0..s.len()).rev() {
longest[i][i] = 1;
for j in i + 1..s.len() {
if s.as_bytes()[i] == s.as_bytes()[j] {
longest[i][j] = 2 + longest[i + 1][j - 1];
} else {
longest[i][j] = cmp::max(longest[i + 1][j], longest[i][j - 1]);
}
}
}
longest[0][s.len() - 1]
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn with_skip() {
assert_eq!(Solution::longest_palindrome_subseq("bbbab".to_owned()), 4);
}
#[test]
fn without_skip() {
assert_eq!(Solution::longest_palindrome_subseq("cbbd".to_owned()), 2);
}
}

View file

@ -0,0 +1,60 @@
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::cell::RefCell;
use std::convert::TryInto;
use std::rc::Rc;
impl Solution {
fn max_sum(levels: &mut Vec<i32>, level: usize, root: Option<Rc<RefCell<TreeNode>>>) {
if root == None {
return;
}
let r = root.unwrap();
if level >= levels.len() {
levels.resize(level + 1, 0);
}
levels[level] += r.borrow().val;
Solution::max_sum(levels, level + 1, r.borrow().left.clone());
Solution::max_sum(levels, level + 1, r.borrow().right.clone());
}
pub fn max_level_sum(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
let mut levels = vec![];
Solution::max_sum(&mut levels, 0, root);
levels
.iter()
.enumerate()
.fold((0, i32::MIN), |(max_l, max_s), (l, s)| {
if *s > max_s {
(l + 1, *s)
} else {
(max_l, max_s)
}
})
.0
.try_into()
.unwrap()
}
}

View file

@ -0,0 +1,14 @@
impl Solution {
pub fn max_coins(piles: Vec<i32>) -> i32 {
let mut sorted_piles = piles.clone();
sorted_piles.sort();
sorted_piles
.iter()
.rev()
.skip(1)
.step_by(2)
.take(piles.len() / 3)
.sum()
}
}

View file

@ -0,0 +1,17 @@
impl Solution {
pub fn max_run_time(n: i32, mut batteries: Vec<i32>) -> i64 {
batteries.sort();
let mut total = batteries.iter().map(|x| *x as u64).sum::<u64>();
let mut k: u64 = 0;
while *batteries.last().unwrap() as u64 > total / (n as u64 - k) {
total -= *batteries.last().unwrap() as u64;
batteries.pop();
k += 1;
}
(total / (n as u64 - k)) as i64
}
}

View file

@ -0,0 +1,73 @@
use std::cmp;
struct Solution {}
impl Solution {
pub fn max_value_of_coins(piles: Vec<Vec<i32>>, k: i32) -> i32 {
let k = k as usize;
let mut mem: Vec<Vec<i32>> = vec![];
mem.resize_with(piles.len() + 1, || {
let mut v = vec![];
v.resize(k as usize + 1, 0);
v
});
for i in 1..=piles.len() {
for max_j in 0..=k {
let mut running_sum = 0;
for j in 0..=cmp::min(piles[i - 1].len(), max_j as usize) {
if j > 0 {
running_sum += piles[i - 1][j - 1];
}
mem[i][max_j] = cmp::max(mem[i][max_j], running_sum + mem[i - 1][max_j - j]);
}
}
}
mem[piles.len()][k]
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
let piles = vec![vec![1, 100, 3], vec![7, 8, 9]];
let expected = vec![0, 7, 101, 108, 116, 125, 128, 128];
for (k, right) in expected.iter().enumerate() {
assert_eq!(
Solution::max_value_of_coins(piles.clone(), k as i32),
*right
);
}
}
#[test]
fn example_2() {
let piles = vec![
vec![100],
vec![100],
vec![100],
vec![100],
vec![100],
vec![100],
vec![1, 1, 1, 1, 1, 1, 700],
];
let expected = vec![
0, 100, 200, 300, 400, 500, 600, 706, 806, 906, 1006, 1106, 1206, 1306, 1306,
];
for (k, right) in expected.iter().enumerate() {
assert_eq!(
Solution::max_value_of_coins(piles.clone(), k as i32),
*right
);
}
}
}

View file

@ -0,0 +1,64 @@
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::cell::RefCell;
use std::cmp;
use std::rc::Rc;
struct Result {
min: i32,
d: i32,
max: i32,
}
impl Solution {
fn find_min_diff(root: Option<Rc<RefCell<TreeNode>>>) -> Result {
match root {
None => Result {
min: i32::MAX,
d: i32::MAX,
max: i32::MIN,
},
Some(r) => {
let l_min = Solution::find_min_diff(r.borrow().left.clone());
let r_min = Solution::find_min_diff(r.borrow().right.clone());
let mut current_d = i32::MAX;
if l_min.max != i32::MIN {
current_d = (r.borrow().val - l_min.max).abs();
}
if r_min.min != i32::MAX {
current_d = cmp::min(current_d, (r_min.min - r.borrow().val).abs());
}
Result {
min: cmp::min(l_min.min, r.borrow().val),
d: cmp::min(cmp::min(l_min.d, r_min.d), current_d),
max: cmp::max(r.borrow().val, r_min.max),
}
}
}
}
pub fn get_minimum_difference(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
let r = Solution::find_min_diff(root);
r.d
}
}

View file

@ -0,0 +1,19 @@
impl Solution {
pub fn find_smallest_set_of_vertices(n: i32, edges: Vec<Vec<i32>>) -> Vec<i32> {
// It should be possible to use topological ordering + BFS, but…
let mut is_reachable: Vec<bool> = vec![false; n as usize];
for dst in edges.iter().map(|edge| edge[1] as usize) {
is_reachable[dst] = true;
}
let mut result: Vec<i32> = vec![];
for (i, &reachable) in is_reachable.iter().enumerate() {
if !reachable {
result.push(i as i32);
}
}
result
}
}

92
rs/number-of-islands.rs Normal file
View file

@ -0,0 +1,92 @@
use std::collections::{HashSet, VecDeque};
type Position = (i32, i32);
type Grid = Vec<Vec<char>>;
impl Solution {
fn indices(grid: &Grid) -> impl Iterator<Item = Position> + '_ {
(0..grid.len() as i32)
.flat_map(move |y| (0..grid[y as usize].len() as i32).map(move |x| (y, x)))
}
fn interesting(grid: &Grid, visited: &HashSet<Position>, p: &Position) -> bool {
let (max_y, max_x) = (grid.len() as i32, grid[0].len() as i32);
let &(y, x) = p;
y >= 0
&& y < max_y
&& x >= 0
&& x < max_x
&& grid[p.0 as usize][p.1 as usize] != '0'
&& !visited.contains(p)
}
fn bfs(grid: &Grid, visited: &mut HashSet<Position>, pos: Position) {
let mut queue: VecDeque<Position> = VecDeque::new();
queue.push_back(pos);
visited.insert(pos);
while let Some(p) = queue.pop_front() {
for d in [-1, 1] {
for adjacent in [(p.0 + d, p.1), (p.0, p.1 + d)] {
if Solution::interesting(grid, visited, &adjacent) {
queue.push_back(adjacent);
visited.insert(adjacent);
}
}
}
}
}
pub fn num_islands(grid: Grid) -> i32 {
let mut visited: HashSet<Position> = HashSet::new();
let mut islands = 0;
for (y, x) in Solution::indices(&grid) {
if !Solution::interesting(&grid, &visited, &(y, x)) {
continue;
}
Solution::bfs(&grid, &mut visited, (y, x));
islands += 1;
}
islands
}
}
struct Solution {}
fn main() {
println!("Hello World!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example_1() {
assert_eq!(
Solution::num_islands(vec![
vec!['1', '1', '1', '1', '0'],
vec!['1', '1', '0', '1', '0'],
vec!['1', '1', '0', '0', '0'],
vec!['0', '0', '0', '0', '0']
]),
1
);
}
#[test]
fn test_example_2() {
assert_eq!(
Solution::num_islands(vec![
vec!['1', '1', '0', '0', '0'],
vec!['1', '1', '0', '0', '0'],
vec!['0', '0', '1', '0', '0'],
vec!['0', '0', '0', '1', '1']
]),
3
);
}
}

64
rs/number-of-provinces.rs Normal file
View file

@ -0,0 +1,64 @@
use std::collections::VecDeque;
struct Solution {}
impl Solution {
fn bfs(graph: &[Vec<i32>], visited: &mut [bool], u0: usize) {
let mut q = VecDeque::new();
q.push_back(u0);
visited[u0] = true;
while let Some(u) = q.pop_front() {
for v in (0..graph.len()).filter(|&v| graph[u][v] != 0) {
if visited[v] {
continue;
}
q.push_back(v);
visited[v] = true;
}
}
}
pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
let mut visited = vec![false; is_connected.len()];
let mut count = 0;
for i in 0..is_connected.len() {
if visited[i] {
continue;
}
Solution::bfs(&is_connected, &mut visited, i);
count += 1;
}
count
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
// Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
// Output: 2
#[test]
fn example_1() {
assert_eq!(
Solution::find_circle_num(vec![vec![1, 1, 0], vec![1, 1, 0], vec![0, 0, 1]]),
2
);
}
// Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
// Output: 3
#[test]
fn example_2() {
assert_eq!(
Solution::find_circle_num(vec![vec![1, 0, 0], vec![0, 1, 0], vec![0, 0, 1]]),
3
);
}
}

View file

@ -0,0 +1,246 @@
use std::{collections::VecDeque, ops::BitOr};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
enum Reachable {
None = 0x0,
Pacific = 0x1,
Atlantic = 0x2,
Both = 0x3,
}
impl Reachable {
fn new(y: usize, x: usize, max_y: usize, max_x: usize) -> Reachable {
let reaches_pacific = y == 0 || x == 0;
let reaches_atlantic = y == max_y - 1 || x == max_x - 1;
match (reaches_pacific, reaches_atlantic) {
(true, true) => Reachable::Both,
(true, _) => Reachable::Pacific,
(_, true) => Reachable::Atlantic,
(_, _) => Reachable::None,
}
}
}
impl From<u8> for Reachable {
fn from(u: u8) -> Self {
match u {
0 => Reachable::None,
1 => Reachable::Pacific,
2 => Reachable::Atlantic,
3 => Reachable::Both,
_ => panic!("Invalid conversion"),
}
}
}
impl From<Reachable> for u8 {
fn from(r: Reachable) -> Self {
match r {
Reachable::None => 0,
Reachable::Pacific => 1,
Reachable::Atlantic => 2,
Reachable::Both => 3,
}
}
}
impl BitOr for Reachable {
type Output = Reachable;
fn bitor(self, rhs: Self) -> Self::Output {
let (lhs, rhs): (u8, u8) = (self.into(), rhs.into());
(lhs | rhs).into()
}
}
#[derive(PartialEq, Eq)]
enum State {
Unvisited,
Queued,
Visited,
}
struct Vertex {
height: i32,
reaches: Reachable,
state: State,
}
struct Graph {
vertices: Vec<Vec<Vertex>>,
max_y: usize,
max_x: usize,
}
impl Graph {
pub fn new(heights: &Vec<Vec<i32>>) -> Graph {
let max_y = heights.len();
let max_x = heights[0].len();
Graph {
vertices: heights
.iter()
.enumerate()
.map(|(y, row)| {
row.iter()
.enumerate()
.map(|(x, h)| Vertex {
height: *h,
reaches: Reachable::new(y, x, max_y, max_x),
state: State::Unvisited,
})
.collect()
})
.collect(),
max_y,
max_x,
}
}
pub fn vertices(&self) -> &Vec<Vec<Vertex>> {
&self.vertices
}
fn _vertex(&mut self, y: i32, x: i32) -> Option<&mut Vertex> {
if y >= 0 && y < self.max_y as i32 && x >= 0 && x < self.max_x as i32 {
Some(&mut self.vertices[y as usize][x as usize])
} else {
None
}
}
fn _run_bfs(&mut self, q: &mut VecDeque<(i32, i32)>) {
q.iter().for_each(|&(y, x)| {
self._vertex(y, x).unwrap().state = State::Queued;
});
while let Some((y, x)) = q.pop_front() {
self._vertex(y, x).unwrap().state = State::Visited;
let h = self._vertex(y, x).unwrap().height;
let r = self._vertex(y, x).unwrap().reaches;
for d in [-1, 1] {
for (next_y, next_x) in [(y + d, x), (y, x + d)] {
if let Some(v) = self._vertex(next_y, next_x) {
if matches!(v.state, State::Unvisited) && h <= v.height {
q.push_back((next_y, next_x));
v.state = State::Queued;
v.reaches = r | v.reaches;
}
}
}
}
}
}
fn _reset(&mut self) {
for y in 0..self.max_y {
for x in 0..self.max_x {
self.vertices[y][x].state = State::Unvisited;
}
}
}
pub fn bfs(&mut self) {
// Run BFS from Pacific Ocean
self._run_bfs(&mut VecDeque::from(
(0..self.max_x)
.map(|x| (0_i32, x as i32))
.chain((0..self.max_y).map(|y| (y as i32, 0_i32)))
.collect::<Vec<(i32, i32)>>(),
));
// Reset the visited
self._reset();
// Run BFS from Atlantic Ocean
self._run_bfs(&mut VecDeque::from(
(0..self.max_x)
.map(|x| (self.max_y as i32 - 1, x as i32))
.chain((0..self.max_y).map(|y| (y as i32, self.max_x as i32 - 1)))
.collect::<Vec<(i32, i32)>>(),
));
}
}
impl Solution {
pub fn pacific_atlantic(heights: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let mut g = Graph::new(&heights);
g.bfs();
g.vertices().iter().for_each(|row| {
row.iter().for_each(|v| {
print!("{:?} ", v.reaches);
});
println!();
});
g.vertices()
.iter()
.enumerate()
.flat_map(|(y, row)| {
row.iter()
.enumerate()
.filter(|&(_, v)| matches!(v.reaches, Reachable::Both))
.map(move |(x, _)| vec![y as i32, x as i32])
})
.collect()
}
}
struct Solution {}
fn main() {
println!("Hello World!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example_1() {
assert_eq!(
Solution::pacific_atlantic(vec![
vec![1, 2, 2, 3, 5],
vec![3, 2, 3, 4, 4],
vec![2, 4, 5, 3, 1],
vec![6, 7, 1, 4, 5],
vec![5, 1, 1, 2, 4]
]),
vec![
vec![0, 4],
vec![1, 3],
vec![1, 4],
vec![2, 2],
vec![3, 0],
vec![3, 1],
vec![4, 0]
]
);
}
#[test]
fn test_example_2() {
assert_eq!(Solution::pacific_atlantic(vec![vec![1]]), vec![vec![0, 0]]);
}
#[test]
fn test_wrong() {
assert_eq!(
Solution::pacific_atlantic(vec![vec![3, 3, 3], vec![3, 1, 3], vec![0, 2, 4]]),
vec![
vec![0, 0],
vec![0, 1],
vec![0, 2],
vec![1, 0],
vec![1, 2],
vec![2, 0],
vec![2, 1],
vec![2, 2]
]
);
}
}

15
rs/power-of-four.rs Normal file
View file

@ -0,0 +1,15 @@
impl Solution {
pub fn is_power_of_four(n: i32) -> bool {
if n == 0 {
return false;
}
let mut x = n;
while x % 4 == 0 {
x >>= 2;
}
x == 1
}
}

22
rs/predict-the-winner.rs Normal file
View file

@ -0,0 +1,22 @@
use std::cmp::max;
impl Solution {
pub fn predict_the_winner(nums: Vec<i32>) -> bool {
let mut dp = vec![vec![0; nums.len()]; nums.len()];
// initialize
for (i, &num) in nums.iter().enumerate() {
dp[i][i] = num;
}
// carry on the DP
for d in 1..nums.len() {
for l in 0..nums.len() - d {
let r = l + d;
dp[l][r] = max(nums[l] - dp[l + 1][r], nums[r] - dp[l][r - 1]);
}
}
dp[0][nums.len() - 1] >= 0
}
}

View file

@ -0,0 +1,45 @@
#[derive(Debug)]
struct NumArray {
prefix_sums: Vec<i32>,
}
impl NumArray {
fn new(nums: Vec<i32>) -> Self {
let mut total = nums.iter().sum::<i32>();
let mut prefix_sums: Vec<i32> = nums
.iter()
.scan(total, |total, &x| {
let prev = *total;
*total -= x;
Some(prev)
})
.collect();
prefix_sums.push(0);
Self { prefix_sums }
}
fn sum_range(&self, left: i32, right: i32) -> i32 {
self.prefix_sums[left as usize] - self.prefix_sums[right as usize + 1]
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
let num_arr = NumArray::new(vec![-2, 0, 3, -5, 2, -1]);
dbg!("{:?}", &num_arr);
assert_eq!(num_arr.sum_range(0, 2), 1);
assert_eq!(num_arr.sum_range(2, 5), -1);
assert_eq!(num_arr.sum_range(0, 5), -3);
}
}

View file

@ -0,0 +1,89 @@
use std::collections::BTreeMap;
struct Accumulator {
removed: usize,
removed_distinct: i32,
}
impl Accumulator {
fn new() -> Accumulator {
Accumulator { removed: 0, removed_distinct: 0 }
}
fn update(self, length: usize, count: i32) -> Accumulator {
if 2 * self.removed < length {
Accumulator {
removed: self.removed + count as usize,
removed_distinct: self.removed_distinct + 1,
}
} else {
self
}
}
}
impl Solution {
pub fn min_set_size(arr: Vec<i32>) -> i32 {
let mut counts = arr
.iter()
.fold(BTreeMap::<i32, i32>::new(), |mut acc: BTreeMap<i32, i32>, x: &i32| {
let current = *acc.get(x).unwrap_or(&0);
acc.insert(*x, current + 1);
acc
})
.iter()
.map(|(&x, &y)| { (x, y) })
.collect::<Vec<(i32, i32)>>();
counts
.sort_by(|&(_, y0), &(_, y1)| y1.cmp(&y0));
counts
.iter()
.fold(Accumulator::new(), |acc, &(_, count)| {
acc.update(arr.len(), count)
}).removed_distinct
}
}
struct Solution {}
fn main() {
println!("Hello, world!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example() {
assert_eq!(Solution::min_set_size(vec![3, 3, 3, 3, 5, 5, 5, 2, 2, 7]), 2);
}
#[test]
fn test_all_same() {
assert_eq!(Solution::min_set_size(vec![7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]), 1);
}
#[test]
fn test_remove_exact_half() {
assert_eq!(Solution::min_set_size(vec![1, 1, 2, 2]), 1);
}
#[test]
fn test_remove_more_than_half() {
assert_eq!(Solution::min_set_size(vec![1, 1, 2, 2, 2]), 1);
}
#[test]
fn test_all_distinct() {
assert_eq!(Solution::min_set_size(vec![1, 2, 3, 4, 5, 6, 7]), 4);
}
#[test]
fn test_big_distinct() {
assert_eq!(Solution::min_set_size((1..=100).rev().collect()), 50);
}
}

View file

@ -0,0 +1,8 @@
impl Solution {
pub fn running_sum(nums: Vec<i32>) -> Vec<i32> {
nums.iter().scan(0, |s, &x| {
*s = *s + x;
Some(*s)
}).collect()
}
}

View file

@ -0,0 +1,106 @@
use std::collections::VecDeque;
use std::convert::TryInto;
struct Solution {}
impl Solution {
pub fn shortest_path_binary_matrix(grid: Vec<Vec<i32>>) -> i32 {
let n = grid.len();
// create an array of distances
let mut distances = grid.clone();
for y in 0..n {
for x in 0..n {
distances[y][x] = -1;
}
}
// initialize the start with an initial distance
let mut q: VecDeque<(usize, usize)> = VecDeque::new();
if grid[0][0] == 0 {
distances[0][0] = 1;
q.push_back((0, 0));
}
while let Some((y, x)) = q.pop_front() {
if (y, x) == (n - 1, n - 1) {
break;
}
for (next_y, next_x) in (-1_isize..=1)
.flat_map(|dy| (-1_isize..=1).map(move |dx| (dy, dx)))
.map(|(dy, dx)| (y as isize + dy, x as isize + dx))
.filter(|&(next_y, next_x)| {
(next_y, next_x) != (y as isize, x as isize)
&& next_y >= 0
&& next_y < n.try_into().unwrap()
&& next_x >= 0
&& next_x < n.try_into().unwrap()
})
{
let (next_y, next_x) = (next_y as usize, next_x as usize);
if distances[next_y][next_x] == -1 && grid[next_y][next_x] == 0 {
distances[next_y][next_x] = distances[y][x] + 1;
q.push_back((
(next_y as isize).try_into().unwrap(),
(next_x as isize).try_into().unwrap(),
));
}
}
}
distances[n - 1][n - 1]
}
}
fn main() {
assert_eq!(
Solution::shortest_path_binary_matrix(vec![vec![0, 1], vec![1, 0]]),
2
);
assert_eq!(
Solution::shortest_path_binary_matrix(vec![vec![0, 0, 0], vec![1, 1, 0], vec![1, 1, 0]]),
4
);
assert_eq!(
Solution::shortest_path_binary_matrix(vec![vec![1, 0, 0], vec![1, 1, 0], vec![1, 1, 0]]),
-1
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
assert_eq!(
Solution::shortest_path_binary_matrix(vec![vec![0, 1], vec![1, 0]]),
2
);
}
#[test]
fn example_2() {
assert_eq!(
Solution::shortest_path_binary_matrix(vec![
vec![0, 0, 0],
vec![1, 1, 0],
vec![1, 1, 0]
]),
4
);
}
#[test]
fn example_3() {
assert_eq!(
Solution::shortest_path_binary_matrix(vec![
vec![1, 0, 0],
vec![1, 1, 0],
vec![1, 1, 0]
]),
-1
);
}
}

49
rs/simplify-path.rs Normal file
View file

@ -0,0 +1,49 @@
struct Solution {}
impl Solution {
pub fn simplify_path(path: String) -> String {
let mut simplified_path = Vec::<&str>::new();
path.split('/').for_each(|seg| {
if seg.is_empty() || seg == "." {
return;
}
if seg == ".." {
simplified_path.pop();
return;
}
simplified_path.push(seg);
});
"/".to_owned() + &simplified_path.join("/")
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn one_directory() {
assert_eq!(
Solution::simplify_path("/home/".to_owned()),
"/home".to_owned()
);
}
#[test]
fn just_root() {
assert_eq!(Solution::simplify_path("/../".to_owned()), "/".to_owned());
}
#[test]
fn consecutive_slashes() {
assert_eq!(
Solution::simplify_path("/home//foo/".to_owned()),
"/home/foo".to_owned()
);
}
}

View file

@ -0,0 +1,69 @@
use std::collections::BTreeSet;
struct SmallestInfiniteSet {
smaller: BTreeSet<i32>,
next_infinite: i32,
}
/**
* `&self` means the method takes an immutable reference.
* If you need a mutable reference, change it to `&mut self` instead.
*/
impl SmallestInfiniteSet {
fn new() -> Self {
Self {
smaller: BTreeSet::new(),
next_infinite: 1,
}
}
fn pop_smallest(&mut self) -> i32 {
if let Some(&m) = self.smaller.iter().min() {
self.smaller.remove(&m);
return m;
}
self.next_infinite += 1;
self.next_infinite - 1
}
fn add_back(&mut self, num: i32) {
if num >= self.next_infinite {
return;
}
self.smaller.insert(num);
}
}
/*
* Your SmallestInfiniteSet object will be instantiated and called as such:
* let obj = SmallestInfiniteSet::new();
* let ret_1: i32 = obj.pop_smallest();
* obj.add_back(num);
*/
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_1() {
let mut s = SmallestInfiniteSet::new();
s.add_back(2);
assert_eq!(s.pop_smallest(), 1);
assert_eq!(s.pop_smallest(), 2);
assert_eq!(s.pop_smallest(), 3);
s.add_back(1);
assert_eq!(s.pop_smallest(), 1);
assert_eq!(s.pop_smallest(), 4);
assert_eq!(s.pop_smallest(), 5);
}
}

View file

@ -0,0 +1,71 @@
use std::cmp;
#[derive(Debug)]
struct Question {
answered: i64,
skipped: i64,
}
impl Question {
fn get_with_offset(stack: &Vec<Self>, offset: i64) -> i64 {
let i = stack.len() as i64 - offset - 1;
if i < 0 || i >= stack.len() as i64 {
return 0;
}
stack[i as usize].get()
}
pub fn new(q: &[i32], stack: &Vec<Self>) -> Self {
Self {
answered: q[0] as i64 + Self::get_with_offset(stack, q[1].into()),
skipped: Self::get_with_offset(stack, 0),
}
}
pub fn get(&self) -> i64 {
cmp::max(self.answered, self.skipped)
}
}
struct Solution {}
impl Solution {
pub fn most_points(questions: Vec<Vec<i32>>) -> i64 {
let mut stack: Vec<Question> = vec![];
for input_q in questions.iter().rev() {
stack.push(Question::new(&input_q, &stack));
}
stack.last().unwrap().get()
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example_1() {
assert_eq!(
Solution::most_points(vec![vec![3, 2], vec![4, 3], vec![4, 4], vec![2, 5]]),
5
);
}
#[test]
fn test_example_2() {
assert_eq!(
Solution::most_points(vec![
vec![1, 1],
vec![2, 2],
vec![3, 3],
vec![4, 4],
vec![5, 5]
]),
7
);
}
}

View file

@ -0,0 +1,18 @@
use std::cmp::Reverse;
use std::collections::BTreeMap;
impl Solution {
pub fn frequency_sort(s: String) -> String {
let mut freqs: BTreeMap<_, usize> = BTreeMap::new();
s.as_str().chars().for_each(|c| {
let current = freqs.get(&c).unwrap_or(&0);
freqs.insert(c, 1 + current);
});
let mut frequencies: Vec<_> = freqs.iter().collect();
frequencies.sort_by_key(|&(_, count)| Reverse(count));
frequencies.iter().fold(String::new(), |s, (c, count)| s + &c.to_string().repeat(**count))
}
}

View file

@ -0,0 +1,86 @@
impl Solution {
fn can_stamp(stamp: &Vec<char>, tape: &Vec<char>, i: usize) -> bool {
!Solution::is_fully_stamped_section(stamp.len(), &tape, i)
&& (0..stamp.len())
.map(|j| (stamp[j], tape[i + j]))
.all(|(s, t)| s == t || t == '?')
}
fn is_fully_stamped_section(length: usize, tape: &Vec<char>, i: usize) -> bool {
(i..i + length).all(|j| tape[j] == '?')
}
fn stamp_tape(length: usize, tape: &mut Vec<char>, i: usize) {
(i..i + length).for_each(|j| {
tape[j] = '?';
})
}
pub fn moves_to_stamp(stamp: String, target: String) -> Vec<i32> {
// convert stamp to usable interpretation
let stamp: Vec<char> = stamp.chars().collect();
// convert target to a mutable array of characters
let mut tape: Vec<char> = target.chars().collect();
// keep track of stamped indices
let mut stamped: Vec<i32> = Vec::new();
// go over and try to stamp while possible
let mut has_changed = true;
while has_changed && stamped.len() <= 10 * tape.len() {
has_changed = false;
(0..tape.len() + 1 - stamp.len()).for_each(|i| {
if Solution::can_stamp(&stamp, &tape, i) {
Solution::stamp_tape(stamp.len(), &mut tape, i);
stamped.push(i as i32);
has_changed = true;
}
});
}
if stamped.len() > 10 * tape.len()
|| !Solution::is_fully_stamped_section(tape.len(), &tape, 0)
{
stamped.clear();
}
stamped.reverse();
stamped
}
}
struct Solution {}
fn main() {
println!("Hello World!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example() {
assert_eq!(
Solution::moves_to_stamp("abc".to_string(), "ababc".to_string()),
vec![0, 2]
);
}
#[test]
fn test_another_example() {
assert_eq!(
Solution::moves_to_stamp("abca".to_string(), "aabcaca".to_string()),
vec![0, 3, 1]
);
}
#[test]
fn test_unusable_stamp() {
assert_eq!(
Solution::moves_to_stamp("stamp".to_string(), "tamps".to_string()),
vec![]
);
}
}

View file

@ -0,0 +1,125 @@
#[derive(Debug, PartialEq, Eq)]
struct Property {
attack: i32,
defense: i32,
}
impl Property {
fn is_weak(&self, rhs: &Property) -> bool {
self.attack < rhs.attack && self.defense < rhs.defense
}
}
impl From<&Vec<i32>> for Property {
fn from(v: &Vec<i32>) -> Self {
Self {
attack: v[0],
defense: v[1],
}
}
}
impl PartialOrd for Property {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.attack.partial_cmp(&other.attack) {
Some(core::cmp::Ordering::Equal) => other.defense.partial_cmp(&self.defense),
ord => ord,
}
}
}
impl Ord for Property {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.attack != other.attack {
self.attack.cmp(&other.attack)
} else {
other.defense.cmp(&self.defense)
}
}
}
struct Acc {
max: i32,
count: i32,
}
impl Acc {
fn new(m: i32) -> Acc {
Acc { max: m, count: 0 }
}
fn update(self, p: &Property) -> Acc {
if p.defense < self.max {
Acc {
max: self.max,
count: self.count + 1,
}
} else {
Acc {
max: p.defense,
count: self.count,
}
}
}
}
impl Solution {
pub fn number_of_weak_characters(properties: Vec<Vec<i32>>) -> i32 {
let mut properties: Vec<Property> = properties.iter().map(From::from).collect();
properties.sort();
properties
.iter()
.rfold(Acc::new(properties.last().unwrap().defense), Acc::update)
.count
}
}
struct Solution {}
fn main() {
println!("Hello World!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_example() {
assert_eq!(
Solution::number_of_weak_characters(vec![vec![5, 5], vec![6, 3], vec![3, 6]]),
0
);
}
#[test]
fn test_another_example() {
assert_eq!(
Solution::number_of_weak_characters(vec![vec![2, 2], vec![3, 3]]),
1
);
}
#[test]
fn test_another_another_example() {
assert_eq!(
Solution::number_of_weak_characters(vec![vec![1, 5], vec![10, 4], vec![4, 3]]),
1
);
}
#[test]
fn test_bigger_example() {
assert_eq!(
Solution::number_of_weak_characters(vec![
vec![1, 5],
vec![10, 4],
vec![4, 3],
vec![2, 6],
vec![1, 1],
vec![10, 6]
]),
3
);
}
}

View file

@ -0,0 +1,78 @@
use std::collections::{HashMap, HashSet, VecDeque};
struct Solution {}
impl Solution {
fn from_managers(managers: &[i32]) -> HashMap<usize, HashSet<usize>> {
let mut mapping = HashMap::new();
for (i, manager) in managers
.iter()
.enumerate()
.filter(|&(_, &manager)| manager != -1)
{
mapping
.entry(*manager as usize)
.or_insert_with(HashSet::new)
.insert(i);
}
mapping
}
pub fn num_of_minutes(_n: i32, head_id: i32, manager: Vec<i32>, inform_time: Vec<i32>) -> i32 {
let manager_mapping = Solution::from_managers(&manager);
let mut q = VecDeque::new();
q.push_back((head_id as usize, 0));
let mut minutes = -1;
while let Some((manager, t)) = q.pop_front() {
minutes = std::cmp::max(minutes, t);
for employee in manager_mapping.get(&manager).unwrap_or(&HashSet::new()) {
q.push_back((*employee, t + inform_time[manager]));
}
}
minutes
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
// Input: n = 1, headID = 0, manager = [-1], informTime = [0]
// Output: 0
// Explanation: The head of the company is the only employee in the company.
#[test]
fn example_1() {
assert_eq!(Solution::num_of_minutes(1, 0, vec![-1], vec![0]), 0);
}
// Input: n = 6, headID = 2, manager = [2,2,-1,2,2,2], informTime = [0,0,1,0,0,0]
// Output: 1
// Explanation: The head of the company with id = 2 is the direct manager of all the employees in the company and needs 1 minute to inform them all.
// The tree structure of the employees in the company is shown.
#[test]
fn example_2() {
assert_eq!(
Solution::num_of_minutes(6, 2, vec![2, 2, -1, 2, 2, 2], vec![0, 0, 1, 0, 0, 0]),
1
);
}
#[test]
fn regression_1() {
assert_eq!(
Solution::num_of_minutes(
15,
0,
vec![-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6],
vec![1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
),
3
);
}
}

View file

@ -0,0 +1,56 @@
struct Solution {}
impl Solution {
pub fn validate_stack_sequences(pushed: Vec<i32>, popped: Vec<i32>) -> bool {
let mut stack: Vec<i32> = vec![];
let mut i = 0;
let mut j = 0;
loop {
// If the top is to be popped, pop it
if let Some(&top) = stack.last() {
if j < popped.len() && top == popped[j] {
stack.pop();
j += 1;
continue;
}
}
// If I have an element that can be pushed, push it
if i < pushed.len() {
stack.push(pushed[i]);
i += 1;
continue;
}
// If I can't pop nor push, it's done or screwed up
break;
}
// If it's correct simulation, stack must be empty
stack.is_empty()
}
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn success() {
assert!(Solution::validate_stack_sequences(
vec![1, 2, 3, 4, 5],
vec![4, 5, 3, 2, 1]
));
}
#[test]
fn fail() {
assert!(!Solution::validate_stack_sequences(
vec![1, 2, 3, 4, 5],
vec![4, 3, 5, 1, 2]
));
}
}