Skip to content

Commit

Permalink
Rust (#190)
Browse files Browse the repository at this point in the history
Add Rust implementation of some algorithms
  • Loading branch information
indy256 authored Jan 27, 2024
1 parent 478e019 commit 4b2d565
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 1 deletion.
20 changes: 20 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Rust CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build-ubuntu-rustc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: install rustc
run: |
sudo apt install rustc
- name: compile
run: |
cd rust
cargo
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![C++ CI](https://github.com/indy256/codelibrary/actions/workflows/cpp.yml/badge.svg)](https://github.com/indy256/codelibrary/actions/workflows/cpp.yml)
[![License](https://img.shields.io/badge/license-UNLICENSE-green.svg)](https://github.com/indy256/codelibrary/blob/master/UNLICENSE)

### Collection of algorithms and data structures in C++, Java, Kotlin and Python
### Collection of algorithms and data structures in C++, Java, Kotlin, Python and Rust

#### Data structures
+ [x] Segment tree [**c++**](cpp/structures/segment_tree.h) [**java**](java/structures/SegmentTree.java) [**kotlin**](kotlin/SegmentTree.kt)
Expand Down
4 changes: 4 additions & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea
*.iml
Cargo.lock
target
29 changes: 29 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "codelibrary"
version = "0.1.0"

edition = "2018"

[[bin]]
name = "topological_sort"
path = "graphs/dfs/topological_sort.rs"

[[bin]]
name = "dijkstra"
path = "graphs/shortestpaths/dijkstra.rs"

[[bin]]
name = "max_bipartite_matching_EV"
path = "graphs/matchings/max_bipartite_matching_EV.rs"

[[bin]]
name = "euclid"
path = "numbertheory/euclid.rs"

[[bin]]
name = "disjoint_sets"
path = "structures/disjoint_sets.rs"

[[bin]]
name = "fenwick_tree"
path = "structures/fenwick_tree.rs"
28 changes: 28 additions & 0 deletions rust/graphs/dfs/topological_sort.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
fn dfs(graph: &Vec<Vec<usize>>, used: &mut Vec<bool>, order: &mut Vec<usize>, u: usize) {
used[u] = true;
for v in &graph[u] {
if !used[*v] {
dfs(graph, used, order, *v);
}
}
order.push(u);
}

pub fn topological_sort(graph: &Vec<Vec<usize>>) -> Vec<usize> {
let n = graph.len();
let mut used = vec![false; n];
let mut order = Vec::<usize>::new();
for i in 0..n {
if !used[i] {
dfs(graph, &mut used, &mut order, i);
}
}
order.reverse();
return order;
}

fn main() {
let g = vec![vec![0], vec![], vec![0, 1]];
let order = topological_sort(&g);
assert_eq!(order, vec![2, 1, 0]);
}
31 changes: 31 additions & 0 deletions rust/graphs/matchings/max_bipartite_matching_EV.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
fn find_path(graph: &Vec<Vec<usize>>, u1: usize, matching: &mut Vec<usize>, vis: &mut Vec<bool>) -> bool {
vis[u1] = true;
for v in &graph[u1] {
let u2 = matching[*v];
if u2 == usize::MAX || (!vis[u2] && find_path(graph, u2, matching, vis)) {
matching[*v] = u1;
return true;
}
}
return false;
}

pub fn max_matching(graph: &Vec<Vec<usize>>, n2: usize) -> (usize, Vec<usize>) {
let n1 = graph.len();
let mut matching = vec![usize::MAX; n2];
let mut matches = 0;
for u in 0..n1 {
let mut vis = vec![false; n1];
if find_path(graph, u, &mut matching, &mut vis) {
matches += 1;
}
}
return (matches, matching);
}

fn main() {
let g = vec![vec![0, 1], vec![0]];
let (cardinality, matching) = max_matching(&g, 2);
assert_eq!(cardinality, 2);
assert_eq!(matching, vec![1, 0]);
}
31 changes: 31 additions & 0 deletions rust/graphs/shortestpaths/dijkstra.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::collections::BinaryHeap;

// https://cp-algorithms.com/graph/dijkstra_sparse.html
// O(E*log(V)) time and O(E) memory
pub fn dijkstra_heap(graph: &Vec<Vec<(usize, i32)>>, s: usize) -> (Vec<i32>, Vec<usize>) {
let n = graph.len();
let mut prio = vec![i32::MAX; n];
let mut pred = vec![usize::MAX; n];
let mut q = BinaryHeap::<(i32, usize)>::new();
prio[s] = 0;
q.push((0, s));
while let Some((d, u)) = q.pop() {
if -d != prio[u] { continue; }
for (v, len) in &graph[u] {
let nprio = prio[u] + len;
if prio[*v] > nprio {
prio[*v] = nprio;
pred[*v] = u;
q.push((-nprio, *v));
}
}
}
return (prio, pred);
}

fn main() {
let g = vec![vec![(1, 10), (2, 8)], vec![(2, -5)], vec![]];
let (prio, pred) = dijkstra_heap(&g, 0);
assert_eq!(prio, vec![0, 10, 5]);
assert_eq!(pred, vec![usize::MAX, 0, 1]);
}
30 changes: 30 additions & 0 deletions rust/numbertheory/euclid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fn gcd(a: i32, b: i32) -> i32 {
return if b == 0 { a.abs() } else { gcd(b, a % b) };
}

// returns { gcd(a,b), x, y } such that gcd(a,b) = a*x + b*y
fn euclid(mut a: i64, mut b: i64) -> [i64; 3] {
let mut x: i64 = 1;
let mut y: i64 = 0;
let mut x1: i64 = 0;
let mut y1: i64 = 1;
// invariant: a=a_orig*x+b_orig*y, b=a_orig*x1+b_orig*y1
while b != 0 {
let q = a / b;
let _x1 = x1;
let _y1 = y1;
let _b = b;
x1 = x - q * x1;
y1 = y - q * y1;
b = a - q * b;
x = _x1;
y = _y1;
a = _b;
}
return if a > 0 { [a, x, y] } else { [-a, -x, -y] };
}

fn main() {
assert_eq!(gcd(15, 20), 5);
assert_eq!(euclid(6, 9), [3, -1, 1]);
}
30 changes: 30 additions & 0 deletions rust/structures/disjoint_sets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
struct DisjointSets {
p: Vec<usize>
}

impl DisjointSets {
pub fn new(n: usize) -> Self {
DisjointSets { p: (0..n).collect() }
}

pub fn root(&mut self, x: usize) -> usize {
if x != self.p[x] {
self.p[x] = self.root(self.p[x]);
}
self.p[x]
}

pub fn unite(&mut self, a: usize, b: usize) {
let a = self.root(a);
let b = self.root(b);
self.p[b] = a;
}
}

fn main() {
let mut ds = DisjointSets::new(3);
ds.unite(0, 2);
assert_eq!(ds.root(0), 0);
assert_eq!(ds.root(1), 1);
assert_eq!(ds.root(2), 0);
}
38 changes: 38 additions & 0 deletions rust/structures/fenwick_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::ops::AddAssign;

struct Fenwick<T> {
t: Vec<T>
}

impl<T: AddAssign + Copy + From<i32>> Fenwick<T> {
fn new(n: usize) -> Self {
Fenwick { t: vec![0.into(); n] }
}

pub fn add(&mut self, mut i: usize, value: T) {
while i < self.t.len() {
self.t[i] += value;
i |= i + 1;
}
}

// sum[0..i]
pub fn sum(&self, mut i: i32) -> T {
let mut res: T = 0.into();
while i >= 0 {
res += self.t[i as usize];
i = (i & (i + 1)) - 1;
}
return res;
}
}

fn main() {
let mut t = Fenwick::<i32>::new(3);
t.add(0, 4);
t.add(1, 5);
t.add(2, 5);
t.add(2, 5);
assert_eq!(t.sum(0), 4);
assert_eq!(t.sum(2), 19);
}

0 comments on commit 4b2d565

Please sign in to comment.