feat: add lz CLI and use cargo workspace

This commit is contained in:
rzmk 2024-01-01 23:14:03 -05:00
parent 3feb126908
commit 47ee3c8e23
No known key found for this signature in database
14 changed files with 525 additions and 55 deletions

View file

@ -1,6 +1,6 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/ladderz" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "cargo"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

View file

@ -18,8 +18,7 @@ jobs:
- name: Build Documentation
run: |
cd ladderz
cargo doc
cargo doc --no-deps
echo '<meta http-equiv="refresh" content="0; url=https://rzmk.github.io/ladderz/ladderz/index.html" />' > ./target/doc/index.html
cd ..
@ -27,4 +26,4 @@ jobs:
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./ladderz/target/doc
publish_dir: ./target/doc

18
.gitignore vendored
View file

@ -1 +1,17 @@
venv
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# Python virtual environment
venv

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[workspace]
resolver = "2"
members = [
"ladderz",
"lz",
]

View file

@ -2,19 +2,61 @@
The `ladderz` project is a collection of math and tech concepts implemented in code.
- **[`ladderz` crate](https://rzmk.github.io/ladderz/)** - A Rust library crate 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
- **[notebooks](notebooks)** - Jupyter notebooks with concept exercises and solutions in Python
> 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.
### `ladderz` crate
## Demos
#### Demo
### `lz` CLI Demo
![ladderz-crate-demo](ladderz-crate-demo.png)
![ladderz-crate-demo-output](ladderz-crate-demo-output.png)
### ladderz Library Demo
#### Example
## CLI Example
The `lz` CLI tool can be used to run ladderz functions from the command line. Built with the [clap](https://clap.rs) crate, users may select a subject and concept to run on their given input.
First let's install the `lz` CLI tool using [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html):
```bash
cargo install --git https://github.com/rzmk/ladderz --branch main
```
You may read the help text for the `lz` CLI tool and its subcommands with a `-h` or `--help` flag. For example, to read the help text for the `prealgebra` subject run:
```bash
lz prealgebra -h
```
Now let's run the `lz` CLI tool with the `prealgebra` subject and `get-factors` concept as an example. We want to get the factors of the positive integer `12`:
```bash
lz prealgebra get-factors 12
```
The printed output should be:
```console
The factors of 12 are {2, 3, 6, 1, 4, 12}.
```
We can use the `--raw` flag to get the raw output of the function:
```bash
lz prealgebra get-factors 12 --raw
```
The printed output should be:
```console
{1, 2, 3, 4, 6, 12}
```
Note that the numbers may not be sorted.
## Library Example
Here's an example of using the `ladderz` crate to get the factors and factor pairs of a positive integer in sorted order.
@ -34,7 +76,7 @@ ladderz = { git = "https://github.com/rzmk/ladderz", branch = "main" }
Now in `src/main.rs` let's replace the contents with the following code:
```rust
use ladderz::pre_algebra::{get_factors, get_factor_pairs};
use ladderz::prealgebra::{get_factors, get_factor_pairs};
use std::env;
fn main() {
@ -67,7 +109,6 @@ fn main() {
None => println!("No input provided."),
}
}
```
Now let's build the project's binary file so we can run it from the command line:
@ -109,6 +150,6 @@ Not currently implemented, but ideas that may be useful:
- Statistics
- Discrete Math
- Algorithms
- **py-ladderz** - A package for running implementations of mathematical concepts in Python
- **ladderz CLI** - A CLI tool for ladderz in Rust
- **ladderz App** - An interactive multi-platform (web, desktop, mobile) app potentially including visualizations, practice problems, & a course-like structure (potentially in Flutter or Tauri with Next.js & Rust)
- 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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

14
ladderz/.gitignore vendored
View file

@ -1,14 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

View file

@ -3,10 +3,4 @@ name = "ladderz"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "ladderz"
path = "src/lib.rs"
[dependencies]

View file

@ -2,18 +2,18 @@
//!
//! Implementations of mathematical and technical concepts in Rust.
//!
//! # Installing the crate
//! # Installation
//!
//! To add the crate to your project, add the following dependency under your `[dependencies]` section in your `Cargo.toml`:
//! To add the library crate to your project, add the following dependency under your `[dependencies]` section in your `Cargo.toml`:
//!
//! ```toml
//! ladderz = { git = "https://github.com/rzmk/ladderz", branch = "main" }
//! ```
//!
//!
//! # Example
//!
//! ```rust
//!use ladderz::pre_algebra::get_factors;
//!use ladderz::prealgebra::get_factors;
//!
//!let x: u32 = 10;
//!println!("The factors of {x} are {:?}.", get_factors(x));
@ -23,7 +23,7 @@
//! The factors of 10 are {1, 5, 2, 10}.
//! ```
//!
//! For a more detailed example of how to use the `ladderz` crate, please see the [example on GitHub](https://github.com/rzmk/ladderz#example).
//! For a more detailed example of how to use the `ladderz` crate, please see the [library example on GitHub](https://github.com/rzmk/ladderz#library-example).
//!
//! Choose a module to view its available functions.
@ -32,7 +32,7 @@
/// # Example
///
/// ```rust
/// use ladderz::pre_algebra::get_factors;
/// use ladderz::prealgebra::get_factors;
///
/// let x: u32 = 10;
/// println!("The factors of {x} are {:?}.", get_factors(x));
@ -42,4 +42,4 @@
/// The factors of 10 are {1, 5, 2, 10}.
/// ```
///
pub mod pre_algebra;
pub mod prealgebra;

View file

@ -12,7 +12,7 @@ use std::collections::{HashMap, HashSet};
///
/// ```rust
/// use std::collections::HashSet;
/// use ladderz::pre_algebra::get_factor_pairs;
/// use ladderz::prealgebra::get_factor_pairs;
///
/// let result_pairs = get_factor_pairs(12);
/// let expected_pairs: HashSet<(u32, u32)> = [(1, 12), (2, 6), (3, 4)].into();
@ -53,7 +53,7 @@ pub fn get_factor_pairs(n: u32) -> HashSet<(u32, u32)> {
///
/// ```rust
/// use std::collections::HashSet;
/// use ladderz::pre_algebra::get_factors;
/// use ladderz::prealgebra::get_factors;
///
/// let result_factors = get_factors(16);
/// let expected_factors: HashSet<u32> = [1, 2, 4, 8, 16].into();
@ -83,7 +83,7 @@ pub fn get_factors(n: u32) -> HashSet<u32> {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::is_factor;
/// use ladderz::prealgebra::is_factor;
///
/// assert!(is_factor(2, 16)); // 2 is a factor of 16
/// assert!(!is_factor(3, 16)); // 3 is not a factor of 16
@ -104,7 +104,7 @@ pub fn is_factor(x: u32, y: u32) -> bool {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::is_multiple;
/// use ladderz::prealgebra::is_multiple;
///
/// assert!(is_multiple(16, 2)); // 16 is a multiple of 2
/// assert!(!is_multiple(16, 3)); // 16 is not a multiple of 3
@ -120,7 +120,7 @@ pub fn is_multiple(x: u32, y: u32) -> bool {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::get_multiples_in_range;
/// use ladderz::prealgebra::get_multiples_in_range;
/// use std::collections::HashSet;
///
/// let result: HashSet<u32> = get_multiples_in_range(2, 10);
@ -144,7 +144,7 @@ pub fn get_multiples_in_range(n: u32, end: u32) -> HashSet<u32> {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::is_prime;
/// use ladderz::prealgebra::is_prime;
///
/// assert!(!is_prime(1)); // 1 is not a prime number
/// assert!(is_prime(2)); // 2 is a prime number
@ -176,7 +176,7 @@ pub fn is_prime(n: u32) -> bool {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::is_composite;
/// use ladderz::prealgebra::is_composite;
///
/// assert!(!is_composite(1)); // 1 is not a composite number
/// assert!(!is_composite(2)); // 2 is not a composite number
@ -200,7 +200,7 @@ pub fn is_composite(n: u32) -> bool {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::get_primes_in_range;
/// use ladderz::prealgebra::get_primes_in_range;
/// use std::collections::HashSet;
///
/// let result: HashSet<u32> = get_primes_in_range(2, 10);
@ -226,7 +226,7 @@ pub fn get_primes_in_range(start: u32, end: u32) -> HashSet<u32> {
/// # Examples
///
/// ```rust
/// use ladderz::pre_algebra::get_prime_factorization;
/// use ladderz::prealgebra::get_prime_factorization;
/// use std::collections::HashMap;
///
/// let result: HashMap<u32, u32> = get_prime_factorization(12);

10
lz/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "lz"
version = "0.1.0"
edition = "2021"
[dependencies]
ladderz = { git = "https://github.com/rzmk/ladderz", branch = "main" }
# For local development, use:
# ladderz = { path = "../ladderz" }
clap = { version = "4.4.12", features = ["derive"] }

71
lz/src/main.rs Normal file
View file

@ -0,0 +1,71 @@
//! # lz
//!
//! A command-line interface for various math/tech subjects. Based on the [ladderz](https://github.com/rzmk/ladderz) library.
//!
//! # Installation
//!
//! To install the command-line interface, run the following command in your terminal:
//!
//! ```bash
//! cargo install --git https://github.com/rzmk/ladderz --branch main
//! ```
//!
//! # Example
//!
//! ```bash
//! lz prealgebra is-factor 3 12
//! ```
//!
//! ```console
//! 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:
//!
//! ```bash
//! lz prealgebra is-factor -h
//! ```
//!
//! Learn more on [GitHub](https://github.com/rzmk/ladderz).
// External modules
use clap::{Parser, Subcommand};
// Local modules
pub mod prealgebra;
use prealgebra::{match_prealgebra, Prealgebra};
#[derive(Parser)]
#[command(
author = "Mueez Khan",
about = "Run various functions from a range of math/tech subjects on the command line.",
subcommand_value_name = "SUBJECT",
arg_required_else_help(true)
)]
struct Cli {
#[command(subcommand)]
subject: Option<Subjects>,
}
/// The subjects that can be used.
#[derive(Subcommand)]
#[command(arg_required_else_help(true))]
enum Subjects {
Prealgebra {
/// The function (command) to run.
#[command(subcommand)]
function: Option<Prealgebra>,
},
}
fn main() {
let cli: Cli = Cli::parse();
// 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.");
}
}
}

347
lz/src/prealgebra.rs Normal file
View file

@ -0,0 +1,347 @@
use clap::Subcommand;
#[derive(Subcommand)]
#[command(arg_required_else_help(true))]
pub enum Prealgebra {
/// Finds all factor pairs for a positive integer.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra factor-pairs 12
/// ```
///
/// ### Output
///
/// ```bash
/// The factor pairs of 12 are [(1, 12), (2, 6), (3, 4)].
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// [(1, 12), (2, 6), (3, 4)]
/// ```
FactorPairs {
/// The positive integer to find factor pairs for.
n: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Finds all factors for a positive integer.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra factors 12
/// ```
///
/// ### Output
///
/// ```bash
/// The factors of 12 are [1, 2, 3, 4, 6, 12].
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// [1, 2, 3, 4, 6, 12]
/// ```
Factors {
/// The positive integer to find factors for.
n: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Finds all multiples of a positive integer in a given range.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra multiples-in-range 3 10
/// ```
///
/// ### Output
///
/// ```bash
/// The multiples of 3 in the range [1, 10] are [3, 6, 9].
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// [3, 6, 9]
/// ```
MultiplesInRange {
/// The positive integer to find multiples for.
n: u32,
/// The upper bound of the range to find multiples in.
upper_bound: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Finds all primes in a given range.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra primes-in-range 1 10
/// ```
///
/// ### Output
///
/// ```bash
/// The primes in the range [1, 10] are [2, 3, 5, 7].
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// [2, 3, 5, 7]
/// ```
PrimesInRange {
/// The lower bound of the range to find primes in.
lower_bound: u32,
/// The upper bound of the range to find primes in.
upper_bound: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Finds the prime factorization of a positive integer.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra prime-factorization 12
/// ```
///
/// ### Output
///
/// ```bash
/// The prime factorization of 12 is {2: 2, 3: 1}.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// {2: 2, 3: 1}
/// ```
PrimeFactorization {
/// The positive integer to find the prime factorization of.
n: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Determines if a positive integer is composite.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra is-composite 12
/// ```
///
/// ### Output
///
/// ```bash
/// 12 is composite.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// true
/// ```
IsComposite {
/// The positive integer to determine if it is composite.
n: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Determines if a positive integer is prime.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra is-prime 12
/// ```
///
/// ### Output
///
/// ```bash
/// 12 is not prime.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// false
/// ```
IsPrime {
/// The positive integer to determine if it is prime.
n: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Determines if a positive integer is a factor of another positive integer.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra is-factor 3 12
/// ```
///
/// ### Output
///
/// ```bash
/// 3 is a factor of 12.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// true
/// ```
IsFactor {
/// The positive integer to determine if it is a factor.
n: u32,
/// The positive integer to determine if it is a multiple.
m: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
/// Determines if a positive integer is a multiple of another positive integer.
///
/// ## Example
///
/// ### Input
///
/// ```bash
/// lz prealgebra is-multiple 12 3
/// ```
///
/// ### Output
///
/// ```bash
/// 12 is a multiple of 3.
/// ```
///
/// ## Raw Output (use `-r` or `--raw`)
///
/// ```bash
/// true
/// ```
IsMultiple {
/// The positive integer to determine if it is a multiple.
n: u32,
/// The positive integer to determine if it is a factor.
m: u32,
/// Whether or not to return the raw output.
#[arg(short = 'r', long)]
raw: bool,
},
}
pub fn match_prealgebra(function: Option<Prealgebra>) {
use ladderz::prealgebra::*;
match function {
Some(Prealgebra::FactorPairs { n, raw }) => match raw {
true => println!("{:?}", get_factor_pairs(n)),
false => println!("The factor pairs of {} are {:?}.", n, get_factor_pairs(n)),
},
Some(Prealgebra::Factors { n, raw }) => match raw {
true => println!("{:?}", get_factors(n)),
false => println!("The factors of {} are {:?}.", n, get_factors(n)),
},
Some(Prealgebra::MultiplesInRange {
n,
upper_bound,
raw,
}) => match raw {
true => println!("{:?}", get_multiples_in_range(n, upper_bound)),
false => println!(
"The multiples of {} in the range [1, {}] are {:?}.",
n,
upper_bound,
get_multiples_in_range(n, upper_bound)
),
},
Some(Prealgebra::PrimesInRange {
lower_bound,
upper_bound,
raw,
}) => match raw {
true => println!("{:?}", get_primes_in_range(lower_bound, upper_bound)),
false => println!(
"The primes in the range [{}, {}] are {:?}.",
lower_bound,
upper_bound,
get_primes_in_range(lower_bound, upper_bound)
),
},
Some(Prealgebra::PrimeFactorization { n, raw }) => match raw {
true => println!("{:?}", get_prime_factorization(n)),
false => println!(
"The prime factorization of {} is {:?}.",
n,
get_prime_factorization(n)
),
},
Some(Prealgebra::IsComposite { n, raw }) => match raw {
true => println!("{:?}", is_composite(n)),
false => println!(
"{} is {}composite.",
n,
if is_composite(n) { "" } else { "not " }
),
},
Some(Prealgebra::IsPrime { n, raw }) => match raw {
true => println!("{:?}", is_prime(n)),
false => println!("{} is {}prime.", n, if is_prime(n) { "" } else { "not " }),
},
Some(Prealgebra::IsFactor { n, m, raw }) => match raw {
true => println!("{:?}", is_factor(n, m)),
false => println!(
"{} is {}a factor of {}.",
n,
if is_factor(n, m) { "" } else { "not " },
m
),
},
Some(Prealgebra::IsMultiple { n, m, raw }) => match raw {
true => println!("{:?}", is_multiple(n, m)),
false => println!(
"{} is {}a multiple of {}.",
n,
if is_multiple(n, m) { "" } else { "not " },
m
),
},
None => {
println!("Please provide a function to use.");
}
}
}