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
|
- **[`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
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;
|
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
|
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
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
|
// 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."),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,8 @@ pub enum Prealgebra {
|
||||||
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.
|
||||||
|
|
@ -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
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