-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Rust: Apply `cargo fmt` * Rust: Fix Cippy warnings To run Clippy lint, run `cargo clean && cargo clippy`. * Rust: Update the Makefile to invoke `cargo` rather than `rustc` * Rust: Use Rust 2018 Edition https://doc.rust-lang.org/stable/edition-guide/ * Rust: Replace the HashMap with FxHashMap from rustc-hash https://crates.io/crates/rustc-hash * Rust: Try not to create a temporary Vec * Rust: Error handling - use `?` operator when possible
- Loading branch information
1 parent
89cac73
commit 8763034
Showing
4 changed files
with
165 additions
and
142 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
all: main | ||
|
||
clean: | ||
rm main | ||
rm -rf target | ||
cargo clean | ||
rm -f main | ||
|
||
main: src/main.rs | ||
rustc -C opt-level=3 src/main.rs | ||
cargo build --release | ||
cp -p ./target/release/langs-bench-rust ./main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,167 +1,178 @@ | ||
use std::cmp::Reverse; | ||
use std::collections::BinaryHeap; | ||
use std::env; | ||
use std::error::Error; | ||
use std::io; | ||
use std::io::prelude::*; | ||
use std::collections::HashMap; | ||
use std::collections::BinaryHeap; | ||
use std::cmp::Reverse; | ||
|
||
use rustc_hash::FxHashMap; | ||
|
||
type NodeId = u32; | ||
type NodeIndex = u32; | ||
type Distance = u32; | ||
|
||
const DISTANCE_MULTIPLE:u32 = 100; | ||
const DISTANCE_MULTIPLE: u32 = 100; | ||
|
||
struct Edge { | ||
first: NodeIndex, | ||
second: Distance, | ||
first: NodeIndex, | ||
second: Distance, | ||
} | ||
|
||
struct G { | ||
id2idx: HashMap<NodeId,NodeIndex>, | ||
idx2id: Vec<NodeId>, | ||
idx: NodeIndex, | ||
edge: Vec<Vec<Edge>>, | ||
id2idx: FxHashMap<NodeId, NodeIndex>, | ||
idx2id: Vec<NodeId>, | ||
idx: NodeIndex, | ||
edge: Vec<Vec<Edge>>, | ||
} | ||
|
||
fn get_idx(g:&mut G, id:NodeId) -> NodeIndex { | ||
if let Some(i) = g.id2idx.get(&id) { | ||
return *i; | ||
} | ||
let i = g.idx; | ||
g.id2idx.insert(id, i); | ||
g.idx2id.push(id); | ||
g.edge.push(vec![]); | ||
g.idx += 1; | ||
return i; | ||
fn get_idx(g: &mut G, id: NodeId) -> NodeIndex { | ||
if let Some(i) = g.id2idx.get(&id) { | ||
return *i; | ||
} | ||
let i = g.idx; | ||
g.id2idx.insert(id, i); | ||
g.idx2id.push(id); | ||
g.edge.push(vec![]); | ||
g.idx += 1; | ||
i | ||
} | ||
|
||
fn add_edge(g:&mut G, start:NodeId, end:NodeId, distance:Distance) { | ||
let s = get_idx(g, start); | ||
let e = get_idx(g, end); | ||
g.edge[(s as usize)].push(Edge{first:e, second:distance}); | ||
|
||
fn add_edge(g: &mut G, start: NodeId, end: NodeId, distance: Distance) { | ||
let s = get_idx(g, start); | ||
let e = get_idx(g, end); | ||
g.edge[(s as usize)].push(Edge { | ||
first: e, | ||
second: distance, | ||
}); | ||
} | ||
|
||
fn stof100(s:&str) -> u32 { | ||
let mut result:u32 = 0; | ||
let mut place:u32 = 0; | ||
for ch in s.chars() { | ||
if ch == '.' { | ||
place = 1; | ||
continue; | ||
} | ||
result *= 10; | ||
result += (ch as u32) - ('0' as u32); | ||
if place > 0 { | ||
place = place + 1; | ||
if place >= 3 { | ||
break; | ||
} | ||
} | ||
} | ||
while place < 3 { | ||
result *= 10; | ||
place += 1; | ||
} | ||
return result; | ||
fn stof100(s: &str) -> u32 { | ||
let mut result = 0; | ||
let mut place = 0u32; | ||
for ch in s.chars() { | ||
if ch == '.' { | ||
place = 1; | ||
continue; | ||
} | ||
result *= 10; | ||
result += (ch as u32) - ('0' as u32); | ||
if place > 0 { | ||
place += 1; | ||
if place >= 3 { | ||
break; | ||
} | ||
} | ||
} | ||
while place < 3 { | ||
result *= 10; | ||
place += 1; | ||
} | ||
result | ||
} | ||
|
||
fn load(g:&mut G) { | ||
for (index, line) in io::stdin().lock().lines().enumerate() { | ||
if index == 0 { | ||
continue; | ||
} | ||
if let Ok(l) = line { | ||
let fields: Vec<&str> = l.split(',').collect(); | ||
let s: u32 = fields[2].parse().unwrap(); | ||
let e: u32 = fields[3].parse().unwrap(); | ||
let d: u32 = stof100(fields[5]); | ||
unsafe { | ||
if IS_DEBUG { | ||
println!("line: {} s: {} e: {} D: {}", l, s, e, d); | ||
} | ||
} | ||
add_edge(g, s, e, d as Distance); | ||
} | ||
} | ||
fn load(g: &mut G) -> Result<(), Box<dyn Error>> { | ||
for line in io::stdin().lock().lines().skip(1) { | ||
let line = line?; | ||
let mut fields = line.split(',').skip(2); | ||
let s: u32 = fields.next().unwrap().parse()?; | ||
let e: u32 = fields.next().unwrap().parse()?; | ||
fields.next().unwrap(); | ||
let d = stof100(fields.next().unwrap()); | ||
unsafe { | ||
if IS_DEBUG { | ||
println!("line: {} s: {} e: {} D: {}", line, s, e, d); | ||
} | ||
} | ||
add_edge(g, s, e, d as Distance); | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn dijkstra(g:&G, start:NodeId, end:NodeId) -> (Distance, Vec<NodeId>) { | ||
let s = *g.id2idx.get(&start).unwrap(); | ||
let e = *g.id2idx.get(&end).unwrap(); | ||
|
||
let size = g.idx as usize; | ||
let mut d = vec![0 as Distance; size]; | ||
let mut prev = vec![0 as NodeIndex; size]; | ||
|
||
//let mut vv = vec![0; size]; | ||
|
||
let mut queue = BinaryHeap::new(); | ||
queue.push((Reverse(0), Reverse(s))); | ||
|
||
let mut visited = 0; | ||
while let Some(v) = queue.pop() { | ||
let (Reverse(distance), Reverse(here)) = (v.0, v.1); | ||
unsafe { | ||
if IS_DEBUG { | ||
println!("visiting: {} distance: {}", here, distance); | ||
} | ||
} | ||
visited = visited + 1; | ||
//println!("visiting: {} distance: {} qlen:{} visited:{} avg:{}, max:{}", here, distance, queue.len(), visited, sum/n, max); | ||
// std::thread::sleep(std::time::Duration::from_millis(1000)); | ||
for edge in &g.edge[here as usize] { | ||
let (to, weight) = (edge.first as usize, edge.second); | ||
let w = distance + weight; | ||
// println!("visiting:{} distance:{} to:{}, d[to]:{}, w:{}, qlen:{} visited:{}", here, distance, to, d[to], w, queue.len(), visited); | ||
if d[to] == 0 || w < d[to] { | ||
prev[to] = here; | ||
d[to] = w; | ||
// vv[to] = vv[to] + 1; | ||
queue.push((Reverse(w), Reverse(to as NodeIndex))); | ||
} | ||
} | ||
} | ||
println!("visited: {}", visited); | ||
|
||
let mut n = e; | ||
let mut result = vec![g.idx2id[n as usize]]; | ||
|
||
while d[n as usize] != 0 && n != s && n != 0 { | ||
n = prev[n as usize]; | ||
result.push(g.idx2id[n as usize]); | ||
} | ||
|
||
return ((d[e as usize] / DISTANCE_MULTIPLE) as Distance, result); | ||
// Disable Clippy warning for a lint: more than 4 bindings with single-character names in a scope. | ||
// https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names | ||
#[allow(clippy::many_single_char_names)] | ||
fn dijkstra(g: &G, start: NodeId, end: NodeId) -> (Distance, Vec<NodeId>) { | ||
let s = *g.id2idx.get(&start).unwrap(); | ||
let e = *g.id2idx.get(&end).unwrap(); | ||
|
||
let size = g.idx as usize; | ||
let mut d = vec![0 as Distance; size]; | ||
let mut prev = vec![0 as NodeIndex; size]; | ||
|
||
//let mut vv = vec![0; size]; | ||
|
||
let mut queue = BinaryHeap::new(); | ||
queue.push((Reverse(0), Reverse(s))); | ||
|
||
let mut visited = 0; | ||
while let Some(v) = queue.pop() { | ||
let (Reverse(distance), Reverse(here)) = (v.0, v.1); | ||
unsafe { | ||
if IS_DEBUG { | ||
println!("visiting: {} distance: {}", here, distance); | ||
} | ||
} | ||
visited += 1; | ||
//println!("visiting: {} distance: {} qlen:{} visited:{} avg:{}, max:{}", here, distance, queue.len(), visited, sum/n, max); | ||
// std::thread::sleep(std::time::Duration::from_millis(1000)); | ||
for edge in &g.edge[here as usize] { | ||
let (to, weight) = (edge.first as usize, edge.second); | ||
let w = distance + weight; | ||
// println!("visiting:{} distance:{} to:{}, d[to]:{}, w:{}, qlen:{} visited:{}", here, distance, to, d[to], w, queue.len(), visited); | ||
if d[to] == 0 || w < d[to] { | ||
prev[to] = here; | ||
d[to] = w; | ||
// vv[to] = vv[to] + 1; | ||
queue.push((Reverse(w), Reverse(to as NodeIndex))); | ||
} | ||
} | ||
} | ||
println!("visited: {}", visited); | ||
|
||
let mut n = e; | ||
let mut result = vec![g.idx2id[n as usize]]; | ||
|
||
while d[n as usize] != 0 && n != s && n != 0 { | ||
n = prev[n as usize]; | ||
result.push(g.idx2id[n as usize]); | ||
} | ||
|
||
((d[e as usize] / DISTANCE_MULTIPLE) as Distance, result) | ||
} | ||
|
||
static mut IS_DEBUG: bool = false; | ||
|
||
fn main() { | ||
let args: Vec<String> = env::args().collect(); | ||
let count: i32 = args[1].parse().unwrap(); | ||
unsafe { | ||
IS_DEBUG = args.len() > 2 && args[2] == "debug"; | ||
} | ||
|
||
let mut g = G{id2idx:HashMap::new(), idx2id:vec![0], idx:1, edge:vec![vec![]]}; | ||
|
||
load(&mut g); | ||
println!("loaded nodes: {}", g.idx); | ||
|
||
let mut distance: Distance; | ||
let mut route = vec![0 as NodeId; 0]; | ||
for i in 0..count { | ||
let s = g.idx2id[((i+1)*1000) as usize]; | ||
let result = dijkstra(&g, s, g.idx2id[1]); | ||
distance = result.0; | ||
route = result.1; | ||
println!("distance: {}", distance); | ||
} | ||
|
||
let mut result = String::from("route: "); | ||
for id in route { | ||
result = result + &id.to_string() + " "; | ||
} | ||
println!("{}", result); | ||
fn main() -> Result<(), Box<dyn Error>> { | ||
let args: Vec<String> = env::args().collect(); | ||
let count: i32 = args[1].parse()?; | ||
unsafe { | ||
IS_DEBUG = args.len() > 2 && args[2] == "debug"; | ||
} | ||
|
||
let mut g = G { | ||
id2idx: FxHashMap::default(), | ||
idx2id: vec![0], | ||
idx: 1, | ||
edge: vec![vec![]], | ||
}; | ||
|
||
load(&mut g)?; | ||
println!("loaded nodes: {}", g.idx); | ||
|
||
let mut distance: Distance; | ||
let mut route = vec![0 as NodeId; 0]; | ||
for i in 0..count { | ||
let s = g.idx2id[((i + 1) * 1000) as usize]; | ||
let result = dijkstra(&g, s, g.idx2id[1]); | ||
distance = result.0; | ||
route = result.1; | ||
println!("distance: {}", distance); | ||
} | ||
|
||
let mut result = String::from("route: "); | ||
for id in route { | ||
result = result + &id.to_string() + " "; | ||
} | ||
println!("{}", result); | ||
Ok(()) | ||
} |