diff options
| author | Jan Tuomi <jan.tuomi@eficode.com> | 2018-12-15 21:05:55 +0200 |
|---|---|---|
| committer | Jan Tuomi <jan.tuomi@eficode.com> | 2018-12-15 21:05:55 +0200 |
| commit | ddb1435a05484d6f7373e8e47170f95f75cff739 (patch) | |
| tree | 32cf3ac7bfb7d8883437ec85088fee10f98d8f82 /day13 | |
| parent | 757ba3350662da82b4e824d4d0ee814f66b24f74 (diff) | |
Solve day13
Diffstat (limited to 'day13')
| -rw-r--r-- | day13/.vscode/launch.json | 43 | ||||
| -rw-r--r-- | day13/Cargo.lock | 4 | ||||
| -rw-r--r-- | day13/Cargo.toml | 6 | ||||
| -rw-r--r-- | day13/input_ex.txt | 6 | ||||
| -rw-r--r-- | day13/input_ex2.txt | 7 | ||||
| -rw-r--r-- | day13/src/main.rs | 218 |
6 files changed, 284 insertions, 0 deletions
diff --git a/day13/.vscode/launch.json b/day13/.vscode/launch.json new file mode 100644 index 0000000..0c534fa --- /dev/null +++ b/day13/.vscode/launch.json @@ -0,0 +1,43 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'day13'", + "cargo": { + "args": [ + "build", + "--bin=day13", + "--package=day13" + ], + "filter": { + "kind": "bin" + } + }, + "args": ["input_ex2.txt"], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'day13'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=day13", + "--package=day13" + ], + "filter": { + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +}
\ No newline at end of file diff --git a/day13/Cargo.lock b/day13/Cargo.lock new file mode 100644 index 0000000..da4efb4 --- /dev/null +++ b/day13/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "day13" +version = "0.1.0" + diff --git a/day13/Cargo.toml b/day13/Cargo.toml new file mode 100644 index 0000000..4466c8c --- /dev/null +++ b/day13/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day13" +version = "0.1.0" +authors = ["Jan Tuomi <jan.tuomi@eficode.com>"] + +[dependencies] diff --git a/day13/input_ex.txt b/day13/input_ex.txt new file mode 100644 index 0000000..45af070 --- /dev/null +++ b/day13/input_ex.txt @@ -0,0 +1,6 @@ +/->-\ +| | /----\ +| /-+--+-\ | +| | | | v | +\-+-/ \-+--/ + \------/ diff --git a/day13/input_ex2.txt b/day13/input_ex2.txt new file mode 100644 index 0000000..e286657 --- /dev/null +++ b/day13/input_ex2.txt @@ -0,0 +1,7 @@ +/>-<\ +| | +| /<+-\ +| | | v +\>+</ | + | ^ + \<->/
\ No newline at end of file diff --git a/day13/src/main.rs b/day13/src/main.rs new file mode 100644 index 0000000..d53423b --- /dev/null +++ b/day13/src/main.rs @@ -0,0 +1,218 @@ +use std::env; +use std::io::BufReader; +use std::io::BufRead; +use std::fs::File; +use std::process; +use std::collections::{HashMap, HashSet}; +use std::io::{stdin, stdout, Write}; + +type Track = char; + +#[derive(Copy)] +struct Cart { + dir: (i32, i32), + next_rot: i32, + id: u32 +} + +impl Clone for Cart { + fn clone(&self) -> Cart { *self } +} + +type Tracks = HashMap<(usize, usize), Track>; +type Carts = HashMap<(usize, usize), Cart>; + +impl Cart { + fn char(&self) -> char { + match self.dir { + (1, 0) => '>', + (-1, 0) => '<', + (0, 1) => 'v', + (0, -1) => '^', + _ => panic!("Invalid dir") + } + } +} + +fn is_track(ch: char) -> bool { + ch == '/' || ch == '\\' || ch == '+' +} + +fn track_at(tracks: &Tracks, x: usize, y: usize) -> bool { + tracks.contains_key(&(x, y)) +} + +fn is_cart(ch: char) -> bool { + ch == '<' || ch == '>' || ch == '^' || ch == 'v' +} + +fn cart_at(carts: &Carts, x: usize, y: usize) -> bool { + carts.contains_key(&(x, y)) +} + +fn cart_dir(ch: char) -> (i32, i32) { + match ch { + '>' => (1, 0), + '<' => (-1, 0), + '^' => (0, -1), + 'v' => (0, 1), + _ => panic!("Not a cart") + } +} + +fn rot_cart(cart: &Cart, curve: char) -> (i32, i32) { + let dir = cart.dir; + if curve == '/' { + match dir { + (1, 0) => (0, -1), + (-1, 0) => (0, 1), + (0, -1) => (1, 0), + (0, 1) => (-1, 0), + _ => panic!("Not a correct direction") + } + } + else if curve == '\\' { + match dir { + (1, 0) => (0, 1), + (-1, 0) => (0, -1), + (0, -1) => (-1, 0), + (0, 1) => (1, 0), + _ => panic!("Not a correct direction") + } + } + else if curve == '+' { + match cart.next_rot { + -1 => match dir { + (1, 0) => (0, -1), + (0, 1) => (1, 0), + (-1, 0) => (0, 1), + (0, -1) => (-1, 0), + _ => panic!("Not a correct direction") + }, + 0 => dir, + 1 => match dir { + (1, 0) => (0, 1), + (0, 1) => (-1, 0), + (-1, 0) => (0, -1), + (0, -1) => (1, 0), + _ => panic!("Not a correct direction") + }, + _ => panic!("Not a correct next_rot") + } + } else { + panic!("Not a valid curve"); + } +} + +fn visualize(tracks: &Tracks, carts: &Carts, my: usize, mx: usize) { + for y in 0..my { + for x in 0..mx { + if cart_at(carts, x, y) { + print!("{}", carts[&(x, y)].char()); + } + else if track_at(&tracks, x, y) { + print!("{}", tracks[&(x, y)]); + } + else { + print!(" "); + } + } + print!("\n"); + } + + let mut s = String::new(); + let _ = stdout().flush(); + stdin().read_line(&mut s).expect("Did not enter a correct string"); + +} + +fn main() { + let args: Vec<String> = env::args().collect(); + if args.len() != 2 { + println!("Wrong number of arguments. Provide a file name and worker count."); + process::exit(1); + } + let filename = &args[1]; + + println!("Using file {} as input.", filename); + let f = match File::open(filename) { + Ok(file) => file, + Err(e) => { + println!("Failed to open file {}. {:?}", filename, e); + process::exit(1); + } + }; + let file = BufReader::new(&f); + let lines: Vec<String> = file.lines() + .map(|line| line.expect("Could not parse line.")) + .collect(); + + let mut tracks = Tracks::new(); + let mut carts = Carts::new(); + let my = lines.len(); + let mx = lines[0].len(); + let mut id = 0; + for (y, line) in lines.iter().enumerate() { + let chars: Vec<char> = line.chars().collect(); + for (x, &ch) in chars.iter().enumerate() { + if is_track(ch) { + tracks.insert((x, y), ch); + } else if is_cart(ch) { + let dir = cart_dir(ch); + let cart = Cart { dir, next_rot: -1, id }; + carts.insert((x, y), cart); + id += 1; + } + } + } + + // visualize(&tracks, &carts, my, mx); + + let MAX_ITERS = 100000; + for iter in 0..MAX_ITERS { + let mut moved: HashSet<u32> = HashSet::new(); + for y in 0..my { + for x in 0..mx { + if !cart_at(&carts, x, y) { continue; } + let mut cart = carts[&(x, y)].clone(); + if moved.contains(&cart.id) { continue; } + let next_x = (x as i32 + cart.dir.0) as usize; + let next_y = (y as i32 + cart.dir.1) as usize; + + if track_at(&tracks, next_x, next_y) { + let track = tracks[&(next_x, next_y)]; + let new_dir = rot_cart(&cart, track); + if track == '+' { + cart.next_rot = (cart.next_rot + 2) % 3 - 1; + } + cart.dir = new_dir; + } + + // Move cart + carts.remove(&(x, y)); + moved.insert(cart.id); + if cart_at(&carts, next_x, next_y) { + println!("#{}: Collision at ({}, {})", iter, next_x, next_y); + carts.remove(&(next_x, next_y)); + } else { + carts.insert((next_x, next_y), cart); + } + } + } + + // visualize(&tracks, &carts, my, mx); + + if carts.len() == 1 { + let keys = carts.keys(); + for (last_x, last_y) in keys { + println!("#{}: Last position: ({}, {})", iter, last_x, last_y); + return; + } + } + else if carts.len() == 0 { + panic!("Even number of carts, no result!"); + } + } + + println!("Reached end of iterations"); +}
\ No newline at end of file |
