mirror of
https://github.com/rzmk/ladderz.git
synced 2025-12-19 06:59:25 +00:00
feat: add dsa, update get_multiples_in_range, add rust notebook
This commit is contained in:
parent
f135bad4ad
commit
6a3f4cc7e4
10 changed files with 287 additions and 98 deletions
|
|
@ -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
|
||||
- **[`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.
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ Now let's run the `lz` CLI tool with the `prealgebra` subject and `get-factors`
|
|||
lz prealgebra get-factors 12
|
||||
```
|
||||
|
||||
The printed output should be:
|
||||
The printed output may be:
|
||||
|
||||
```console
|
||||
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
|
||||
```
|
||||
|
||||
The printed output may be:
|
||||
The printed raw output may be:
|
||||
|
||||
```console
|
||||
{1, 2, 3, 4, 6, 12}
|
||||
|
|
@ -154,7 +154,6 @@ Not currently implemented, but ideas that may be useful:
|
|||
- Linear Algebra
|
||||
- Statistics
|
||||
- Discrete Math
|
||||
- Algorithms
|
||||
- Bioinformatics
|
||||
- **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)
|
||||
|
|
|
|||
24
ladderz/src/dsa.rs
Normal file
24
ladderz/src/dsa.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -43,3 +43,21 @@
|
|||
/// ```
|
||||
///
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ pub fn is_multiple(x: u32, y: u32) -> bool {
|
|||
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`).
|
||||
///
|
||||
|
|
@ -123,14 +123,18 @@ pub fn is_multiple(x: u32, y: u32) -> bool {
|
|||
/// use ladderz::prealgebra::get_multiples_in_range;
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let result: HashSet<u32> = get_multiples_in_range(2, 10);
|
||||
/// let expected: HashSet<u32> = [2, 4, 6, 8, 10].into();
|
||||
/// let result: HashSet<u32> = get_multiples_in_range(2, 5, 10);
|
||||
/// let expected: HashSet<u32> = [6, 8, 10].into();
|
||||
/// 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();
|
||||
|
||||
for num in (n..end + 1).step_by(n as usize) {
|
||||
let initial = if start % n == 0 {
|
||||
start
|
||||
} else {
|
||||
start + n - (start % n)
|
||||
};
|
||||
for num in (initial..end + 1).step_by(n as usize) {
|
||||
multiples.insert(num);
|
||||
}
|
||||
multiples
|
||||
|
|
@ -304,16 +308,16 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_get_multiples_in_range() {
|
||||
let result: HashSet<u32> = get_multiples_in_range(2, 20);
|
||||
let expected: HashSet<u32> = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20].into();
|
||||
let result: HashSet<u32> = get_multiples_in_range(2, 10, 20);
|
||||
let expected: HashSet<u32> = [10, 12, 14, 16, 18, 20].into();
|
||||
assert_eq!(result, expected);
|
||||
|
||||
let result_2: HashSet<u32> = get_multiples_in_range(5, 34);
|
||||
let expected_2: HashSet<u32> = [5, 10, 15, 20, 25, 30].into();
|
||||
let result_2: HashSet<u32> = get_multiples_in_range(5, 23, 34);
|
||||
let expected_2: HashSet<u32> = [25, 30].into();
|
||||
assert_eq!(result_2, expected_2);
|
||||
|
||||
let result_3: HashSet<u32> = get_multiples_in_range(7, 11);
|
||||
let expected_3: HashSet<u32> = [7].into();
|
||||
let result_3: HashSet<u32> = get_multiples_in_range(7, 10, 11);
|
||||
let expected_3: HashSet<u32> = [].into();
|
||||
assert_eq!(expected_3, result_3);
|
||||
}
|
||||
|
||||
|
|
|
|||
57
lz/src/dsa.rs
Normal file
57
lz/src/dsa.rs
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,8 @@ use clap::{Parser, Subcommand};
|
|||
// Local modules
|
||||
pub mod prealgebra;
|
||||
use prealgebra::{match_prealgebra, Prealgebra};
|
||||
pub mod dsa;
|
||||
use dsa::{match_dsa, Dsa};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
|
|
@ -56,6 +58,10 @@ enum Subjects {
|
|||
#[command(subcommand)]
|
||||
function: Option<Prealgebra>,
|
||||
},
|
||||
Dsa {
|
||||
#[command(subcommand)]
|
||||
function: Option<Dsa>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -64,8 +70,7 @@ fn main() {
|
|||
// Match the subject to run the correct function.
|
||||
match cli.subject {
|
||||
Some(Subjects::Prealgebra { function }) => match_prealgebra(function),
|
||||
None => {
|
||||
println!("Please provide a subject to use.");
|
||||
}
|
||||
Some(Subjects::Dsa { function }) => match_dsa(function),
|
||||
None => println!("Please provide a subject to use."),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ pub enum Prealgebra {
|
|||
MultiplesInRange {
|
||||
/// The positive integer to find multiples for.
|
||||
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.
|
||||
upper_bound: u32,
|
||||
/// Whether or not to return the raw output.
|
||||
|
|
@ -278,15 +280,17 @@ pub fn match_prealgebra(function: Option<Prealgebra>) {
|
|||
},
|
||||
Some(Prealgebra::MultiplesInRange {
|
||||
n,
|
||||
lower_bound,
|
||||
upper_bound,
|
||||
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!(
|
||||
"The multiples of {} in the range [1, {}] are {:?}.",
|
||||
"The multiples of {} in the range [{}, {}] are {:?}.",
|
||||
n,
|
||||
lower_bound,
|
||||
upper_bound,
|
||||
get_multiples_in_range(n, upper_bound)
|
||||
get_multiples_in_range(n, lower_bound, upper_bound)
|
||||
),
|
||||
},
|
||||
Some(Prealgebra::PrimesInRange {
|
||||
|
|
@ -340,8 +344,6 @@ pub fn match_prealgebra(function: Option<Prealgebra>) {
|
|||
m
|
||||
),
|
||||
},
|
||||
None => {
|
||||
println!("Please provide a function to use.");
|
||||
}
|
||||
None => println!("Please provide a function to use."),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
80
notebooks/rust/dsa.ipynb
Normal file
80
notebooks/rust/dsa.ipynb
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue