Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ csa_hs
csa_cpp
csa_go
*.class
target/
Cargo.lock
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "csa_rs"
version = "0.1.0"
authors = ["Stanislas Signoud <[email protected]>"]

[[bin]]
name = "csa_rs"
path = "csa.rs"

125 changes: 125 additions & 0 deletions csa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use std::io;
use std::iter::repeat;

const MAX_STATIONS: usize = 100000;

#[derive(Debug)]
struct Connection {
departure_station: usize,
arrival_station: usize,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using u32 seems much better as it is read as u32 and u32 is more effective. That'll also avoid the ugly std::u32::MAX as usize

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it's something I don't understand; it seems that I can only index an array using usize. When I tried to use u32 everywhere, I had an error about arrays not being indexable using u32.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, sure, you'll have to as usize when using it as a slice index as the implementation is impl<T> Index<usize> for [T] and there is no implicit conversion from u32 to usize

departure_timestamp: u32,
arrival_timestamp: u32
}

impl Connection {
fn parse(line: &str) -> Connection {
let mut splitted = line.split(" ").map(|bite| { bite.parse::<u32>().unwrap() });

Connection {
departure_station: splitted.next().unwrap() as usize,
arrival_station: splitted.next().unwrap() as usize,
departure_timestamp: splitted.next().unwrap(),
arrival_timestamp: splitted.next().unwrap(),
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can avoid the collect here:

let mut splitted = line.split(" ").map(|bite| { bite.parse::<u32>().unwrap() });
Connection {
    departure_station: splitted.next().unwrap() as usize,
    arrival_station: splitted.next().unwrap() as usize,
    departure_timestamp: splitted.next().unwrap(),
    arrival_timestamp: splitted.next().unwrap(),
}

}
}

fn csa_main_loop(timetable: &[Connection], arrival_station: usize, earliest_arrival: &mut [u32], in_connection: &mut [usize]) {
let mut earliest = std::u32::MAX;

for (i, connection) in timetable.iter().enumerate() {
if connection.departure_timestamp >= earliest_arrival[connection.departure_station] &&
connection.arrival_timestamp < earliest_arrival[connection.arrival_station] {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each time you do a v[i], you do a bound check, so better to do that once (even if the compiler may be clever).

earliest_arrival[connection.arrival_station] = connection.arrival_timestamp;
in_connection[connection.arrival_station] = i;

if connection.arrival_station == arrival_station && connection.arrival_timestamp < earliest {
earliest = connection.arrival_timestamp;
}
} else if connection.arrival_timestamp > earliest {
break;
}
}
}

fn csa_print_result(timetable: &Vec<Connection>, in_connection: &[usize], arrival_station: usize) {
if in_connection[arrival_station] == std::u32::MAX as usize {
println!("NO_SOLUTION");
} else {
let mut route = Vec::new();
let mut last_connection_index = in_connection[arrival_station];

while last_connection_index != std::u32::MAX as usize {
let ref connection = timetable[last_connection_index];
route.push(connection);
last_connection_index = in_connection[connection.departure_station];
}

for connection in route.iter().rev() {
println!("{} {} {} {}", connection.departure_station, connection.arrival_station, connection.departure_timestamp, connection.arrival_timestamp);
}
}
println!("");
}

fn csa_compute(timetable: &Vec<Connection>, departure_station: usize, arrival_station: usize, departure_time: u32)
{
let mut in_connection = Vec::new();
in_connection.extend(repeat(std::u32::MAX as usize).take(MAX_STATIONS));
let mut earliest_arrival = Vec::new();
earliest_arrival.extend(repeat(std::u32::MAX).take(MAX_STATIONS));

earliest_arrival[departure_station as usize] = departure_time;

if departure_station < MAX_STATIONS && arrival_station < MAX_STATIONS {
csa_main_loop(&timetable, arrival_station, &mut earliest_arrival, &mut in_connection);
}

csa_print_result(&timetable, &in_connection, arrival_station);
}

fn main() {
let mut timetable = Vec::<Connection>::new();

// Importing connections

loop {
let raw_line = {
let mut line = String::new();
io::stdin().read_line(&mut line).ok().expect("failed to read connection line");
line
};
let input_line = raw_line.trim_right();

if input_line.is_empty() {
break;
} else {
timetable.push(Connection::parse(input_line));
};
}

// Responding to requests from stdin

loop {
let raw_line = {
let mut line = String::new();
io::stdin().read_line(&mut line).ok().expect("failed to read connection line");
line
};
let input_line = raw_line.trim_right();

if input_line.is_empty() {
break;
} else {
let params = input_line.split(" ")
.map(|bite| { bite.parse().ok().expect(&format!("failed to read {} as integer", bite)) })
.collect::<Vec<u32>>();

let departure_station = params[0] as usize;
let arrival_station = params[1] as usize;
let departure_time = params[2];

csa_compute(&timetable, departure_station, arrival_station, departure_time);
}
}
}
6 changes: 6 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ Run the test with ```ruby test.rb "java CSA"```

Run the test with ```ruby test.rb "luajit csa.lua"```

## Rust implementation

Build: ```cargo build --release```

Run the test with ```ruby test.rb ./target/release/csa_rs```

## Challenge

Try to write:
Expand Down