Solved game jump from leet code

This commit is contained in:
BoolPurist 2024-08-06 10:01:55 +02:00
commit 39c3fae613
5 changed files with 140 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "jump_game"
version = "0.1.0"

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "jump_game"
version = "0.1.0"
edition = "2021"
[dependencies]

123
src/lib.rs Normal file
View file

@ -0,0 +1,123 @@
struct Solution;
// Copy from here for submitting this solution to leet code
impl Solution {
pub fn can_jump(nums: Vec<i32>) -> bool {
Solution::idiom_can_jump(&nums)
}
///
/// ## Mapping elements to nodes in a graph
/// Every index is viewed as a node in a graph.
/// The value of a node (value of the element in the array)
/// is the number of edges to subsequent successors.
///
/// ### Example
/// Given the first element in \[3,2,1,0,4\]
///
/// This element has two edges, with the second and the third elements as subsequent successors
///
/// ## Why the mapping to a graph
///
/// By doing so, one can skip redundant work.
/// Redundant work would be walking a path more than once.
/// Walking a path is simulating jumping from 1 to the max jump height.
/// Path walking checks if any jump height from a certain index will reach the last index.
/// Every simulated jump height serves as a next start point for new path walking if this starting
/// point was not tried before
pub fn idiom_can_jump(nums: &[i32]) -> bool {
if nums.is_empty() {
return false;
}
let target_val = (nums.len() - 1) as i32;
let mut next_nodes = Vec::from([(0, nums[0])]);
// index visited yet
let mut visted_indices = -1;
if Self::check_with_target_value(target_val, 0) {
return true;
}
while let Some(next_node) = next_nodes.pop() {
let (index, steps) = next_node;
let max_jump_height = index + steps;
if Self::check_with_target_value(target_val, max_jump_height) {
return true;
}
// It can start at 1 because the every index was checked in previous path walking
for next_to_check in 1..=steps {
let to_add = index + next_to_check;
if visted_indices >= to_add {
// already visited this index
continue;
}
visted_indices = to_add;
next_nodes.push((to_add, nums[to_add as usize]));
}
}
false
}
fn check_with_target_value(target: i32, value: i32) -> bool {
target <= value
}
}
// Stop copying from here for submitting this solution to leet code
#[cfg(test)]
mod testing {
use crate::Solution;
#[test]
fn empty_input() {
let given = vec![];
let expected = false;
assert_case(given, expected);
}
#[test]
fn jumping_no_matter_because_one_element() {
let given = vec![0];
let expected = true;
assert_case(given, expected);
}
#[test]
//Input: nums = [2,3,1,1,4]
//Output: true
//Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
fn jump_possible() {
// Example 1:
//
let given = vec![2, 3, 1, 1, 4];
let expected = true;
assert_case(given, expected);
}
//Example 2:
//
//Input: nums = [3,2,1,0,4]
//Output: false
#[test]
fn no_jump_possible() {
let given = vec![3, 2, 1, 0, 4];
let expected = false;
assert_case(given, expected);
}
#[test]
fn jump_two_elements() {
let given = vec![2, 0];
let expected = true;
assert_case(given, expected);
}
#[test]
fn can_jump_complex_array() {
let given = vec![3, 0, 8, 2, 0, 0, 1];
let expected = true;
assert_case(given, expected);
}
fn assert_case(given: Vec<i32>, expected: bool) {
let actual = Solution::idiom_can_jump(&given);
assert_eq!(expected, actual, "Given input: {:#?}", &given);
}
}

3
src/main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}