summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan.tuomi@eficode.com>2018-12-15 21:05:55 +0200
committerJan Tuomi <jan.tuomi@eficode.com>2018-12-15 21:05:55 +0200
commitddb1435a05484d6f7373e8e47170f95f75cff739 (patch)
tree32cf3ac7bfb7d8883437ec85088fee10f98d8f82
parent757ba3350662da82b4e824d4d0ee814f66b24f74 (diff)
Solve day13
-rw-r--r--day13/.vscode/launch.json43
-rw-r--r--day13/Cargo.lock4
-rw-r--r--day13/Cargo.toml6
-rw-r--r--day13/input_ex.txt6
-rw-r--r--day13/input_ex2.txt7
-rw-r--r--day13/src/main.rs218
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