feat: add dsa, update get_multiples_in_range, add rust notebook

This commit is contained in:
rzmk 2024-03-04 17:44:04 -05:00
parent f135bad4ad
commit 6a3f4cc7e4
No known key found for this signature in database
10 changed files with 287 additions and 98 deletions

View file

@ -4,7 +4,7 @@ The `ladderz` project is a collection of math and tech concepts implemented in c
- **[`ladderz` library](https://rzmk.github.io/ladderz/)** - A Rust library for running concept implementations - **[`ladderz` library](https://rzmk.github.io/ladderz/)** - A Rust library for running concept implementations
- **[`lz` CLI](lz)** - A command line tool for running ladderz functions - **[`lz` CLI](lz)** - A command line tool for running ladderz functions
- **[notebooks](notebooks)** - Jupyter notebooks with concept exercises and solutions in Python - **[notebooks](notebooks)** - Rust & Python Jupyter notebooks with concept exercises and solutions
> If you're looking for a more efficient implementation of a concept (e.g., for use in your programs), other resources may be more useful. > If you're looking for a more efficient implementation of a concept (e.g., for use in your programs), other resources may be more useful.
@ -41,7 +41,7 @@ Now let's run the `lz` CLI tool with the `prealgebra` subject and `get-factors`
lz prealgebra get-factors 12 lz prealgebra get-factors 12
``` ```
The printed output should be: The printed output may be:
```console ```console
The factors of 12 are {2, 3, 6, 1, 4, 12}. The factors of 12 are {2, 3, 6, 1, 4, 12}.
@ -53,7 +53,7 @@ We can use the `--raw` flag to get the raw output of the function:
lz prealgebra get-factors 12 --raw lz prealgebra get-factors 12 --raw
``` ```
The printed output may be: The printed raw output may be:
```console ```console
{1, 2, 3, 4, 6, 12} {1, 2, 3, 4, 6, 12}
@ -154,7 +154,6 @@ Not currently implemented, but ideas that may be useful:
- Linear Algebra - Linear Algebra
- Statistics - Statistics
- Discrete Math - Discrete Math
- Algorithms
- Bioinformatics - Bioinformatics
- **ladderz-py** - A package for running implementations of mathematical concepts in Python - **ladderz-py** - A package for running implementations of mathematical concepts in Python
- **ladderz-app** - An interactive cross-platform (web, desktop, mobile) app potentially including visualizations, practice problems, & a course-like structure (potentially in Flutter or Tauri with Next.js & Rust) - **ladderz-app** - An interactive cross-platform (web, desktop, mobile) app potentially including visualizations, practice problems, & a course-like structure (potentially in Flutter or Tauri with Next.js & Rust)

24
ladderz/src/dsa.rs Normal file
View file

@ -0,0 +1,24 @@
use std::collections::HashSet;
pub fn contains_duplicate(nums: Vec<i32>) -> bool {
let mut seen = HashSet::<i32>::new();
for &num in nums.iter() {
if seen.contains(&num) {
return true;
}
seen.insert(num);
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_contains_duplicate() {
let result = contains_duplicate(vec![1, 2, 3, 2]);
let expected = true;
assert_eq!(result, expected);
}
}

View file

@ -9,7 +9,7 @@
//! ```toml //! ```toml
//! ladderz = { git = "https://github.com/rzmk/ladderz", branch = "main" } //! ladderz = { git = "https://github.com/rzmk/ladderz", branch = "main" }
//! ``` //! ```
//! //!
//! # Example //! # Example
//! //!
//! ```rust //! ```rust
@ -43,3 +43,21 @@
/// ``` /// ```
/// ///
pub mod prealgebra; pub mod prealgebra;
/// Various data structures and algorithms implementations.
///
/// # Example
///
/// ```rust
/// use ladderz::dsa::contains_duplicate;
///
/// let nums: Vec<i32> = vec![2, 3, 4, 2];
/// let result = contains_duplicate(nums.clone());
/// println!("The vector {:?} {} contain a duplicate.", &nums, if result { "does" } else { "does not" });
/// ```
///
/// ```console
/// The vector [2, 3, 4, 2] does contain a duplicate.
/// ```
///
pub mod dsa;

View file

@ -113,7 +113,7 @@ pub fn is_multiple(x: u32, y: u32) -> bool {
x % y == 0 x % y == 0
} }
/// Finds all the multiples of a positive integer `n` up to and including `end` (in the range [n, end]). /// Finds all the multiples of a positive integer `n` starting from `start` and ending at `end` (inclusive).
/// ///
/// A multiple of `n` is a positive integer `num` where `num` is evenly divisible by `n` (i.e., `num % n == 0`). /// A multiple of `n` is a positive integer `num` where `num` is evenly divisible by `n` (i.e., `num % n == 0`).
/// ///
@ -123,14 +123,18 @@ pub fn is_multiple(x: u32, y: u32) -> bool {
/// use ladderz::prealgebra::get_multiples_in_range; /// use ladderz::prealgebra::get_multiples_in_range;
/// use std::collections::HashSet; /// use std::collections::HashSet;
/// ///
/// let result: HashSet<u32> = get_multiples_in_range(2, 10); /// let result: HashSet<u32> = get_multiples_in_range(2, 5, 10);
/// let expected: HashSet<u32> = [2, 4, 6, 8, 10].into(); /// let expected: HashSet<u32> = [6, 8, 10].into();
/// assert_eq!(result, expected); /// assert_eq!(result, expected);
/// ``` /// ```
pub fn get_multiples_in_range(n: u32, end: u32) -> HashSet<u32> { pub fn get_multiples_in_range(n: u32, start: u32, end: u32) -> HashSet<u32> {
let mut multiples: HashSet<u32> = HashSet::new(); let mut multiples: HashSet<u32> = HashSet::new();
let initial = if start % n == 0 {
for num in (n..end + 1).step_by(n as usize) { start
} else {
start + n - (start % n)
};
for num in (initial..end + 1).step_by(n as usize) {
multiples.insert(num); multiples.insert(num);
} }
multiples multiples
@ -304,16 +308,16 @@ mod tests {
#[test] #[test]
fn test_get_multiples_in_range() { fn test_get_multiples_in_range() {
let result: HashSet<u32> = get_multiples_in_range(2, 20); let result: HashSet<u32> = get_multiples_in_range(2, 10, 20);
let expected: HashSet<u32> = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20].into(); let expected: HashSet<u32> = [10, 12, 14, 16, 18, 20].into();
assert_eq!(result, expected); assert_eq!(result, expected);
let result_2: HashSet<u32> = get_multiples_in_range(5, 34); let result_2: HashSet<u32> = get_multiples_in_range(5, 23, 34);
let expected_2: HashSet<u32> = [5, 10, 15, 20, 25, 30].into(); let expected_2: HashSet<u32> = [25, 30].into();
assert_eq!(result_2, expected_2); assert_eq!(result_2, expected_2);
let result_3: HashSet<u32> = get_multiples_in_range(7, 11); let result_3: HashSet<u32> = get_multiples_in_range(7, 10, 11);
let expected_3: HashSet<u32> = [7].into(); let expected_3: HashSet<u32> = [].into();
assert_eq!(expected_3, result_3); assert_eq!(expected_3, result_3);
} }

57
lz/src/dsa.rs Normal file
View file

@ -0,0 +1,57 @@
use clap::Subcommand;
#[derive(Subcommand)]
#[command(arg_required_else_help(true))]
pub enum Dsa {
/// Returns true or false based on whether the vector has a duplicate.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz dsa contains-duplicate 1,2,3,2
/// # Alternatively you may delimit the numbers with spaces:
/// lz dsa contains-duplicate 1 2 3 2
/// ```
///
/// ### Output
///
/// ```bash
/// The vector [1, 2, 3, 2] does contain a duplicate.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// true
/// ```
ContainsDuplicate {
/// The vector of numbers to detect whether it has a duplicate.
#[arg(value_delimiter = ',', num_args = 1)]
n: Vec<i32>,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
}
pub fn match_dsa(function: Option<Dsa>) {
use ladderz::dsa::*;
match function {
Some(Dsa::ContainsDuplicate { n, raw }) => match raw {
true => println!("{:?}", contains_duplicate(n)),
false => {
let result = contains_duplicate(n.clone());
println!(
"The vector {:?} {} contain a duplicate.",
&n,
if result { "does" } else { "does not" }
)
}
},
None => {
println!("Please provide a function to use.");
}
}
}

View file

@ -1,31 +1,31 @@
//! # lz //! # lz
//! //!
//! A command-line interface for various math/tech subjects. Based on the [ladderz](https://github.com/rzmk/ladderz) library. //! A command-line interface for various math/tech subjects. Based on the [ladderz](https://github.com/rzmk/ladderz) library.
//! //!
//! # Installation //! # Installation
//! //!
//! To install the command-line interface, run the following command in your terminal: //! To install the command-line interface, run the following command in your terminal:
//! //!
//! ```bash //! ```bash
//! cargo install --git https://github.com/rzmk/ladderz --branch main //! cargo install --git https://github.com/rzmk/ladderz --branch main
//! ``` //! ```
//! //!
//! # Example //! # Example
//! //!
//! ```bash //! ```bash
//! lz prealgebra is-factor 3 12 //! lz prealgebra is-factor 3 12
//! ``` //! ```
//! //!
//! ```console //! ```console
//! 3 is a factor of 12. //! 3 is a factor of 12.
//! ``` //! ```
//! //!
//! You may view the help menu for a subject and a function by running the command with the `-h` or `--help` flag: //! You may view the help menu for a subject and a function by running the command with the `-h` or `--help` flag:
//! //!
//! ```bash //! ```bash
//! lz prealgebra is-factor -h //! lz prealgebra is-factor -h
//! ``` //! ```
//! //!
//! Learn more on [GitHub](https://github.com/rzmk/ladderz). //! Learn more on [GitHub](https://github.com/rzmk/ladderz).
// External modules // External modules
@ -34,6 +34,8 @@ use clap::{Parser, Subcommand};
// Local modules // Local modules
pub mod prealgebra; pub mod prealgebra;
use prealgebra::{match_prealgebra, Prealgebra}; use prealgebra::{match_prealgebra, Prealgebra};
pub mod dsa;
use dsa::{match_dsa, Dsa};
#[derive(Parser)] #[derive(Parser)]
#[command( #[command(
@ -56,6 +58,10 @@ enum Subjects {
#[command(subcommand)] #[command(subcommand)]
function: Option<Prealgebra>, function: Option<Prealgebra>,
}, },
Dsa {
#[command(subcommand)]
function: Option<Dsa>,
},
} }
fn main() { fn main() {
@ -64,8 +70,7 @@ fn main() {
// Match the subject to run the correct function. // Match the subject to run the correct function.
match cli.subject { match cli.subject {
Some(Subjects::Prealgebra { function }) => match_prealgebra(function), Some(Subjects::Prealgebra { function }) => match_prealgebra(function),
None => { Some(Subjects::Dsa { function }) => match_dsa(function),
println!("Please provide a subject to use."); None => println!("Please provide a subject to use."),
}
} }
} }

View file

@ -4,23 +4,23 @@ use clap::Subcommand;
#[command(arg_required_else_help(true))] #[command(arg_required_else_help(true))]
pub enum Prealgebra { pub enum Prealgebra {
/// Finds all factor pairs for a positive integer. /// Finds all factor pairs for a positive integer.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra factor-pairs 12 /// lz prealgebra factor-pairs 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// The factor pairs of 12 are {(1, 12), (2, 6), (3, 4)}. /// The factor pairs of 12 are {(1, 12), (2, 6), (3, 4)}.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// {(1, 12), (2, 6), (3, 4)} /// {(1, 12), (2, 6), (3, 4)}
/// ``` /// ```
@ -34,21 +34,21 @@ pub enum Prealgebra {
/// Finds all factors for a positive integer. /// Finds all factors for a positive integer.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra factors 12 /// lz prealgebra factors 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// The factors of 12 are {1, 2, 3, 4, 6, 12}. /// The factors of 12 are {1, 2, 3, 4, 6, 12}.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// {1, 2, 3, 4, 6, 12} /// {1, 2, 3, 4, 6, 12}
/// ``` /// ```
@ -60,29 +60,31 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Finds all multiples of a positive integer in a given range. /// Finds all multiples of a positive integer in a given range.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra multiples-in-range 3 10 /// lz prealgebra multiples-in-range 3 10
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// The multiples of 3 in the range [1, 10] are {3, 6, 9}. /// The multiples of 3 in the range [1, 10] are {3, 6, 9}.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// {3, 6, 9} /// {3, 6, 9}
/// ``` /// ```
MultiplesInRange { MultiplesInRange {
/// The positive integer to find multiples for. /// The positive integer to find multiples for.
n: u32, n: u32,
/// The lower bound of the range to find multiples in.
lower_bound: u32,
/// The upper bound of the range to find multiples in. /// The upper bound of the range to find multiples in.
upper_bound: u32, upper_bound: u32,
/// Whether or not to return the raw output. /// Whether or not to return the raw output.
@ -90,23 +92,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Finds all primes in a given range. /// Finds all primes in a given range.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra primes-in-range 1 10 /// lz prealgebra primes-in-range 1 10
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// The primes in the range [1, 10] are {2, 3, 7, 5}. /// The primes in the range [1, 10] are {2, 3, 7, 5}.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// {2, 3, 7, 5} /// {2, 3, 7, 5}
/// ``` /// ```
@ -120,23 +122,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Finds the prime factorization of a positive integer. /// Finds the prime factorization of a positive integer.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra prime-factorization 12 /// lz prealgebra prime-factorization 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// The prime factorization of 12 is {3: 1, 2: 2}. /// The prime factorization of 12 is {3: 1, 2: 2}.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// {3: 1, 2: 2} /// {3: 1, 2: 2}
/// ``` /// ```
@ -148,23 +150,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Determines if a positive integer is composite. /// Determines if a positive integer is composite.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra is-composite 12 /// lz prealgebra is-composite 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// 12 is composite. /// 12 is composite.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// true /// true
/// ``` /// ```
@ -176,23 +178,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Determines if a positive integer is prime. /// Determines if a positive integer is prime.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra is-prime 12 /// lz prealgebra is-prime 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// 12 is not prime. /// 12 is not prime.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// false /// false
/// ``` /// ```
@ -204,23 +206,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Determines if a positive integer is a factor of another positive integer. /// Determines if a positive integer is a factor of another positive integer.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra is-factor 3 12 /// lz prealgebra is-factor 3 12
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// 3 is a factor of 12. /// 3 is a factor of 12.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// true /// true
/// ``` /// ```
@ -234,23 +236,23 @@ pub enum Prealgebra {
raw: bool, raw: bool,
}, },
/// Determines if a positive integer is a multiple of another positive integer. /// Determines if a positive integer is a multiple of another positive integer.
/// ///
/// ## Example /// ## Example
/// ///
/// ### Input /// ### Input
/// ///
/// ```bash /// ```bash
/// lz prealgebra is-multiple 12 3 /// lz prealgebra is-multiple 12 3
/// ``` /// ```
/// ///
/// ### Output /// ### Output
/// ///
/// ```bash /// ```bash
/// 12 is a multiple of 3. /// 12 is a multiple of 3.
/// ``` /// ```
/// ///
/// ## Raw Output (use `-r` or `--raw`) /// ## Raw Output (use `-r` or `--raw`)
/// ///
/// ```bash /// ```bash
/// true /// true
/// ``` /// ```
@ -278,15 +280,17 @@ pub fn match_prealgebra(function: Option<Prealgebra>) {
}, },
Some(Prealgebra::MultiplesInRange { Some(Prealgebra::MultiplesInRange {
n, n,
lower_bound,
upper_bound, upper_bound,
raw, raw,
}) => match raw { }) => match raw {
true => println!("{:?}", get_multiples_in_range(n, upper_bound)), true => println!("{:?}", get_multiples_in_range(n, lower_bound, upper_bound)),
false => println!( false => println!(
"The multiples of {} in the range [1, {}] are {:?}.", "The multiples of {} in the range [{}, {}] are {:?}.",
n, n,
lower_bound,
upper_bound, upper_bound,
get_multiples_in_range(n, upper_bound) get_multiples_in_range(n, lower_bound, upper_bound)
), ),
}, },
Some(Prealgebra::PrimesInRange { Some(Prealgebra::PrimesInRange {
@ -340,8 +344,6 @@ pub fn match_prealgebra(function: Option<Prealgebra>) {
m m
), ),
}, },
None => { None => println!("Please provide a function to use."),
println!("Please provide a function to use.");
}
} }
} }

80
notebooks/rust/dsa.ipynb Normal file
View file

@ -0,0 +1,80 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ladderz dsa usage\n",
"\n",
"Here are some examples of using the `dsa` (data structures and algorithms) module from `ladderz`.\n",
"\n",
"> This notebook uses [evcxr](https://github.com/evcxr/evcxr) for a Rust Jupyter Kernel. See [the evcxr_jupyter README.md](https://github.com/evcxr/evcxr/blob/main/evcxr_jupyter/README.md) for more info on how to run this notebook on your machine."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"// Uncomment the next line and comment the subsequent line if not running notebook from source\n",
"// :dep ladderz = { git = \"https://github.com/rzmk/ladderz\", branch = \"main\" }\n",
":dep ladderz = { path = \"../../ladderz\" }\n",
"\n",
"use ladderz::dsa;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 217. Contains Duplicate"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dsa::contains_duplicate(vec![1, 3, 4, 2, 4])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Rust",
"language": "rust",
"name": "rust"
},
"language_info": {
"codemirror_mode": "rust",
"file_extension": ".rs",
"mimetype": "text/rust",
"name": "Rust",
"pygment_lexer": "rust",
"version": ""
}
},
"nbformat": 4,
"nbformat_minor": 2
}