diff --git a/examples/Dijkstra Algorithm/.gitignore b/examples/Dijkstra Algorithm/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/examples/Dijkstra Algorithm/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/Dijkstra Algorithm/Cargo.toml b/examples/Dijkstra Algorithm/Cargo.toml new file mode 100644 index 0000000000..a96ed078b3 --- /dev/null +++ b/examples/Dijkstra Algorithm/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "graph-in-rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/examples/Dijkstra Algorithm/readme.md b/examples/Dijkstra Algorithm/readme.md new file mode 100644 index 0000000000..9a0c18abfd --- /dev/null +++ b/examples/Dijkstra Algorithm/readme.md @@ -0,0 +1,5 @@ +## Dijsktra Algorithm in Rust + +The `src` directory consist of 2 files: `main.rs` and `graph.in`. The `graph.in` file consist of a `vec![]` which is a `vector` of data as: `(source, destination, cost)`. This graph is comprised of `6` nodes and their `cost`. + +The algorithm returns the shortest path between 2 nodes. The function `shortest_path(g: &Graph, start: Node, goal: Node)` takes start and end nodes and returns the total cost to reach the goal. diff --git a/examples/Dijkstra Algorithm/src/graph.in b/examples/Dijkstra Algorithm/src/graph.in new file mode 100644 index 0000000000..0ba7f53437 --- /dev/null +++ b/examples/Dijkstra Algorithm/src/graph.in @@ -0,0 +1,9 @@ +vec![ + (0, 1, 5), + (0, 2, 10), + (1, 2, 7), + (1, 4, 3), + (2, 4, 5), + (4, 5, 10), + (5, 6, 7) +] \ No newline at end of file diff --git a/examples/Dijkstra Algorithm/src/main.rs b/examples/Dijkstra Algorithm/src/main.rs new file mode 100644 index 0000000000..5daee46da3 --- /dev/null +++ b/examples/Dijkstra Algorithm/src/main.rs @@ -0,0 +1,132 @@ +use std::cmp::Ordering; +use std::collections::{BinaryHeap, HashMap, HashSet}; +type Node = usize; +type Cost = usize; + +struct Graph { + edges: HashMap>, + nodes: HashSet, +} +#[warn(clippy::redundant_closure)] +// The graph is created from the list provided by file graph.in +impl Graph { + fn from_edge_list(edge_list: &[(Node, Node, Cost)]) -> Self { + let mut adjacency_list: HashMap> = HashMap::new(); + let mut nodes = HashSet::new(); + + for &(source, destination, cost) in edge_list.iter() { + let destinations = adjacency_list.entry(source).or_insert_with(|| Vec::new()); + + destinations.push((destination, cost)); + nodes.insert(source); + nodes.insert(destination); + } + + Graph { + edges: adjacency_list, + nodes, + } + } +} + +// #[derive(Clone, PartialEq, Eq)] +#[derive(Eq, PartialEq)] +struct Curr { + cost: Cost, + position: Node, + path: Vec, +} +impl Curr { + fn new(position: Node, cost: Cost, path: Vec) -> Self { + Curr { + cost, + position, + path, + } + } + fn new_start(start: Node) -> Self { + Curr { + cost: 0, + position: start, + path: vec![], + } + } +} + + +impl Ord for Curr { + fn cmp(&self, other: &Self) -> Ordering { + other + .cost + .cmp(&self.cost) + .then_with(|| self.position.cmp(&other.position)) + } +} + +impl PartialOrd for Curr { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +fn shortest_path(g: &Graph, start: Node, goal: Node) -> Option<(Vec, Cost)> { + let mut priority_queue = BinaryHeap::new(); + priority_queue.push(Curr::new_start(start)); + + let mut dist: HashMap = g + .nodes + .iter() + .map(|&x| if x == start { (x, 0) } else { (x, usize::MAX) }) + .collect(); + + while let Some(Curr { + cost, + position, + mut path, + }) = priority_queue.pop() + { + if position == goal { + path.push(position); + return Some((path, cost)); + } + + // pq. push (cost+ currcost, start->next, path.add(start) ) + // So iterate, through all the nodes of start node which are in g + // g[start]= Vec[node, cost] + + if let Some(connected_nodes) = &g.edges.get(&position) { + for &(next_node, next_cost) in connected_nodes.iter() { + if next_cost < dist[&next_node] { + let mut next = Curr::new(next_node, cost + next_cost, path.clone()); + next.path.push(position); + priority_queue.push(next); + + if let Some(past_cost) = dist.get_mut(&next_node) { + *past_cost = next_cost; + } + } + } + } + } + + None +} + +fn main() { + let edge_list = include!("graph.in"); + let g = Graph::from_edge_list(&edge_list); + + if let Some((path, cost)) = shortest_path(&g, 1, 6) { + println!("Shortest distance from 1 to 6 is: , {path:?} {cost}"); + }; +} + +#[test] +fn large_graph() { + let edge_list = include!("graph.in"); + let g = Graph::from_edge_list(&edge_list); + + let path = shortest_path(&g, 1, 6); + assert!(path.is_some()); + assert_eq!(path.unwrap().1, 20); +} diff --git a/examples/dns/README.md b/examples/dns/README.md new file mode 100644 index 0000000000..1f7ddafe15 --- /dev/null +++ b/examples/dns/README.md @@ -0,0 +1,28 @@ +# DNS Smart contract + +The DNS smart contract is our showcase for decentralizing the Domain naming system. + + + +> This contract compiles with ink! 4.0-beta version + +Domain name service contract inspired by + [this blog post on medium](https://medium.com/@chainx_org/secure-and-decentralized-polkadot-domain-name-system-e06c35c2a48d). + +### Description +The registration of a new Domain works by the function `register` defined in the contract which takes 2 parameters: name and hash. Client sends a request to the DNS system such as "polka.dot" which returns the resolver address as shown below. The "polka.dot" is resolved by mapping the it to a `hash value` from the function named `Get_address` in the `lib.rs` file. + +
+
+ +![Image](images/dns_diagram.png) + +## Functionalities provided: + +- Registration of a new Domain Name +- Transfer the (already exsiting) owner to new Address +- Change the Domain Name + + + + \ No newline at end of file diff --git a/examples/dns/images/dns_diagram.png b/examples/dns/images/dns_diagram.png new file mode 100644 index 0000000000..a9f569a8a3 Binary files /dev/null and b/examples/dns/images/dns_diagram.png differ