Skip to content

Commit

Permalink
Add problem 2400: Number of Ways to Reach a Position After Exactly k …
Browse files Browse the repository at this point in the history
…Steps
  • Loading branch information
EFanZh committed Jan 17, 2025
1 parent 62d06ec commit c790d74
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,7 @@ pub mod problem_2395_find_subarrays_with_equal_sum;
pub mod problem_2396_strictly_palindromic_number;
pub mod problem_2397_maximum_rows_covered_by_columns;
pub mod problem_2399_check_distances_between_same_letters;
pub mod problem_2400_number_of_ways_to_reach_a_position_after_exactly_k_steps;

#[cfg(test)]
mod test_utilities;
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::cmp::Ordering;

impl Solution {
const MODULUS: u64 = 1_000_000_007;

fn exp_mod(mut base: u64, mut exponent: u32) -> u64 {
let mut result = 1;

loop {
if exponent & 1 != 0 {
result = (result * base) % Self::MODULUS;
}

exponent >>= 1;

if exponent == 0 {
break;
}

base = (base * base) % Self::MODULUS;
}

result
}

fn mod_inverse(x: u64) -> u64 {
Self::exp_mod(x, Self::MODULUS as u32 - 2)
}

pub fn number_of_ways(start_pos: i32, end_pos: i32, k: i32) -> i32 {
let k = k as u32;
let distance = start_pos.abs_diff(end_pos);

match k.cmp(&distance) {
Ordering::Less => 0,
Ordering::Equal => 1,
Ordering::Greater => {
let k_plus_distance = k + distance;

if k_plus_distance % 2 == 0 {
let t = k_plus_distance / 2;
let mut factorial = 1;

let factorials = (1..=u64::from(k))
.map(|i| {
let result = factorial as u32;

factorial = (factorial * i) % Self::MODULUS;

result
})
.collect::<Box<_>>();

(factorial
* Self::mod_inverse(
u64::from(factorials[t as usize]) * u64::from(factorials[(k - t) as usize]) % Self::MODULUS,
)
% Self::MODULUS) as _
} else {
0
}
}
}
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn number_of_ways(start_pos: i32, end_pos: i32, k: i32) -> i32 {
Self::number_of_ways(start_pos, end_pos, k)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub mod mathematical;

pub trait Solution {
fn number_of_ways(start_pos: i32, end_pos: i32, k: i32) -> i32;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [((1, 2, 3), 3), ((2, 5, 10), 0), ((1, 10, 3), 0), ((1, 1000, 999), 1)];

for ((start_pos, end_pos, k), expected) in test_cases {
assert_eq!(S::number_of_ways(start_pos, end_pos, k), expected);
}
}
}

0 comments on commit c790d74

Please sign in to comment.