├── .gitignore ├── aoc-13-02-wasm ├── www │ ├── .gitignore │ ├── bootstrap.js │ ├── webpack.config.js │ ├── .bin │ │ └── create-wasm-app.js │ ├── package.json │ ├── index.html │ └── index.js ├── src │ ├── main.rs │ └── lib.rs ├── Cargo.toml ├── Cargo.lock └── input ├── aoc-12-01 ├── input ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-12-02 ├── input ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-10-01 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-10-02 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-01-01 ├── Cargo.lock ├── Cargo.toml ├── src │ └── main.rs └── input ├── aoc-01-02 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-02-01 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-02-02 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-03-01 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-03-02 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-04-01 ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-04-02 ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-05-01 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-05-02 ├── Cargo.lock ├── Cargo.toml ├── input └── src │ └── main.rs ├── aoc-06-01 ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-06-02 ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-08-01 ├── Cargo.lock ├── Cargo.toml ├── src │ └── main.rs └── input ├── aoc-08-02 ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── aoc-09-01 ├── Cargo.lock ├── Cargo.toml └── input ├── aoc-09-02 ├── Cargo.lock ├── Cargo.toml └── input ├── aoc-11-01 ├── Cargo.lock ├── Cargo.toml └── input ├── aoc-11-02 ├── Cargo.lock ├── Cargo.toml └── input ├── aoc-13-01 ├── Cargo.lock ├── Cargo.toml └── input ├── aoc-07-01 ├── Cargo.toml ├── Cargo.lock ├── input └── src │ └── main.rs ├── aoc-07-02 ├── Cargo.toml ├── Cargo.lock ├── input └── src │ └── main.rs ├── aoc-13-02 ├── Cargo.toml ├── Cargo.lock └── input ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /aoc-12-01/input: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /aoc-12-02/input: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /aoc-10-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-10-01" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /aoc-10-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-10-01" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /aoc-12-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-12-01" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /aoc-12-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-12-01" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /aoc-01-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-01-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-01-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-01-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-02-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-02-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-03-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-03-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-03-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-03-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-04-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-04-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-04-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-04-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-05-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-05-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-06-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-06-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-06-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-06-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-08-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-08-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-08-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-08-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-09-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-09-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-11-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-11-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-13-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /aoc-01-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-01-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-01-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-01-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-02-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-02-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-03-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-03-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-03-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-03-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-04-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-04-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-04-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-04-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-05-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-05-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-06-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-06-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-06-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-06-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-08-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-08-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-08-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-08-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-09-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-09-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-10-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-10-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-10-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-10-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-11-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-11-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-12-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-12-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-12-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-12-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-13-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut screen = aoc_13_02::Screen::new(); 3 | let mut game_over = screen.run(); 4 | 5 | while !game_over { 6 | println!("{}", screen); 7 | game_over = screen.run(); 8 | } 9 | 10 | println!("score: {}", screen.score()); 11 | } 12 | -------------------------------------------------------------------------------- /aoc-07-01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | permute = "*" 11 | -------------------------------------------------------------------------------- /aoc-07-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | permute = "*" 11 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/bootstrap.js: -------------------------------------------------------------------------------- 1 | // A dependency graph that contains any wasm must all be imported 2 | // asynchronously. This `bootstrap.js` file does the single async import, so 3 | // that no one else needs to worry about it again. 4 | import("./index.js") 5 | .catch(e => console.error("Error importing `index.js`:", e)); 6 | -------------------------------------------------------------------------------- /aoc-13-02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-02-01" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | ncurses = "*" 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code 2019 2 | 3 | My solutions, in Rust of course. I'm doing these for fun, not for leaderboard points, so my 4 | solutions might be posted late or not at all. 5 | 6 | Starting on day 2, I tried to commit before doing `cargo test` or `cargo run`, and then not 7 | squashing any commits, so that you can see all my mistakes! 8 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-13-02" 3 | version = "0.1.0" 4 | authors = ["Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | wasm-bindgen = "0.2" 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [profile.release] 14 | # Tell `rustc` to optimize for small code size. 15 | opt-level = "s" 16 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/webpack.config.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require("copy-webpack-plugin"); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | entry: "./bootstrap.js", 6 | output: { 7 | path: path.resolve(__dirname, "dist"), 8 | filename: "bootstrap.js", 9 | }, 10 | mode: "development", 11 | plugins: [ 12 | new CopyWebpackPlugin(['index.html']) 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /aoc-02-01/input: -------------------------------------------------------------------------------- 1 | 1,12,2,3,1,1,2,3,1,3,4,3,1,5,0,3,2,6,1,19,1,19,9,23,1,23,9,27,1,10,27,31,1,13,31,35,1,35,10,39,2,39,9,43,1,43,13,47,1,5,47,51,1,6,51,55,1,13,55,59,1,59,6,63,1,63,10,67,2,67,6,71,1,71,5,75,2,75,10,79,1,79,6,83,1,83,5,87,1,87,6,91,1,91,13,95,1,95,6,99,2,99,10,103,1,103,6,107,2,6,107,111,1,13,111,115,2,115,10,119,1,119,5,123,2,10,123,127,2,127,9,131,1,5,131,135,2,10,135,139,2,139,9,143,1,143,2,147,1,5,147,0,99,2,0,14,0 2 | -------------------------------------------------------------------------------- /aoc-02-02/input: -------------------------------------------------------------------------------- 1 | 1,12,2,3,1,1,2,3,1,3,4,3,1,5,0,3,2,6,1,19,1,19,9,23,1,23,9,27,1,10,27,31,1,13,31,35,1,35,10,39,2,39,9,43,1,43,13,47,1,5,47,51,1,6,51,55,1,13,55,59,1,59,6,63,1,63,10,67,2,67,6,71,1,71,5,75,2,75,10,79,1,79,6,83,1,83,5,87,1,87,6,91,1,91,13,95,1,95,6,99,2,99,10,103,1,103,6,107,2,6,107,111,1,13,111,115,2,115,10,119,1,119,5,123,2,10,123,127,2,127,9,131,1,5,131,135,2,10,135,139,2,139,9,143,1,143,2,147,1,5,147,0,99,2,0,14,0 2 | -------------------------------------------------------------------------------- /aoc-07-01/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "permute 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 8 | ] 9 | 10 | [[package]] 11 | name = "permute" 12 | version = "0.1.0" 13 | source = "registry+https://github.com/rust-lang/crates.io-index" 14 | 15 | [metadata] 16 | "checksum permute 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "add5cf6a6a9e572d398fc2e73500305c18b6eb66c46cc730ee3737025a4e9209" 17 | -------------------------------------------------------------------------------- /aoc-07-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "permute 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 8 | ] 9 | 10 | [[package]] 11 | name = "permute" 12 | version = "0.1.0" 13 | source = "registry+https://github.com/rust-lang/crates.io-index" 14 | 15 | [metadata] 16 | "checksum permute 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "add5cf6a6a9e572d398fc2e73500305c18b6eb66c46cc730ee3737025a4e9209" 17 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/.bin/create-wasm-app.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { spawn } = require("child_process"); 4 | const fs = require("fs"); 5 | 6 | let folderName = '.'; 7 | 8 | if (process.argv.length >= 3) { 9 | folderName = process.argv[2]; 10 | if (!fs.existsSync(folderName)) { 11 | fs.mkdirSync(folderName); 12 | } 13 | } 14 | 15 | const clone = spawn("git", ["clone", "https://github.com/rustwasm/create-wasm-app.git", folderName]); 16 | 17 | clone.on("close", code => { 18 | if (code !== 0) { 19 | console.error("cloning the template failed!") 20 | process.exit(code); 21 | } else { 22 | console.log("🦀 Rust + 🕸 Wasm = ❤"); 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aoc-13-02-wasm", 3 | "version": "0.1.0", 4 | "description": "AOC Day 13 Part 2, Breakout Game", 5 | "main": "index.js", 6 | "bin": { 7 | "create-wasm-app": ".bin/create-wasm-app.js" 8 | }, 9 | "scripts": { 10 | "build": "webpack --config webpack.config.js", 11 | "start": "webpack-dev-server" 12 | }, 13 | "author": "Carol (Nichols || Goulding)", 14 | "license": "MIT", 15 | "dependencies": { 16 | "aoc-13-02": "file:../pkg" 17 | }, 18 | "devDependencies": { 19 | "hello-wasm-pack": "^0.1.0", 20 | "webpack": "^4.29.3", 21 | "webpack-cli": "^3.1.0", 22 | "webpack-dev-server": "^3.1.5", 23 | "copy-webpack-plugin": "^5.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Advent of Code Day 13 Part 2 in wasm 6 | 20 | 21 | 22 | 23 | 24 | 25 |
Loading, please wait...
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /aoc-01-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fs; 3 | 4 | fn main() -> Result<(), Box> { 5 | let input = fs::read_to_string("input")?; 6 | let answer: i32 = input 7 | .lines() 8 | .map(|line| { 9 | fuel( 10 | line.parse() 11 | .expect("input should have been parsed as a number"), 12 | ) 13 | }) 14 | .sum(); 15 | println!("the answer is {}", answer); 16 | Ok(()) 17 | } 18 | 19 | fn fuel(mass: i32) -> i32 { 20 | mass / 3 - 2 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::fuel; 26 | 27 | #[test] 28 | fn example_test_cases() { 29 | assert_eq!(fuel(12), 2); 30 | assert_eq!(fuel(14), 2); 31 | assert_eq!(fuel(1969), 654); 32 | assert_eq!(fuel(100756), 33583); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Carol (Nichols || Goulding) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /aoc-07-01/input: -------------------------------------------------------------------------------- 1 | 3,8,1001,8,10,8,105,1,0,0,21,38,63,72,85,110,191,272,353,434,99999,3,9,102,4,9,9,101,2,9,9,102,3,9,9,4,9,99,3,9,1001,9,4,9,102,2,9,9,1001,9,5,9,1002,9,5,9,101,3,9,9,4,9,99,3,9,1001,9,2,9,4,9,99,3,9,1001,9,3,9,102,2,9,9,4,9,99,3,9,101,2,9,9,102,2,9,9,1001,9,2,9,1002,9,4,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99 2 | -------------------------------------------------------------------------------- /aoc-07-02/input: -------------------------------------------------------------------------------- 1 | 3,8,1001,8,10,8,105,1,0,0,21,38,63,72,85,110,191,272,353,434,99999,3,9,102,4,9,9,101,2,9,9,102,3,9,9,4,9,99,3,9,1001,9,4,9,102,2,9,9,1001,9,5,9,1002,9,5,9,101,3,9,9,4,9,99,3,9,1001,9,2,9,4,9,99,3,9,1001,9,3,9,102,2,9,9,4,9,99,3,9,101,2,9,9,102,2,9,9,1001,9,2,9,1002,9,4,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99 2 | -------------------------------------------------------------------------------- /aoc-01-01/input: -------------------------------------------------------------------------------- 1 | 77680 2 | 106826 3 | 120225 4 | 122031 5 | 100287 6 | 70402 7 | 145496 8 | 73956 9 | 148205 10 | 52065 11 | 149237 12 | 116195 13 | 84309 14 | 105327 15 | 134606 16 | 109489 17 | 104474 18 | 69536 19 | 141469 20 | 72321 21 | 75154 22 | 142565 23 | 57104 24 | 111925 25 | 100109 26 | 75178 27 | 115130 28 | 75586 29 | 148587 30 | 116029 31 | 113969 32 | 66072 33 | 90521 34 | 116324 35 | 137009 36 | 92880 37 | 110895 38 | 131046 39 | 83273 40 | 99576 41 | 70466 42 | 93602 43 | 63435 44 | 103569 45 | 56610 46 | 58392 47 | 95060 48 | 59101 49 | 121838 50 | 93494 51 | 52243 52 | 146982 53 | 142260 54 | 107232 55 | 117600 56 | 59715 57 | 80284 58 | 128223 59 | 123676 60 | 81060 61 | 99425 62 | 50621 63 | 101184 64 | 112136 65 | 131262 66 | 53150 67 | 113522 68 | 117802 69 | 120251 70 | 102322 71 | 111247 72 | 117719 73 | 88873 74 | 133541 75 | 92695 76 | 125445 77 | 149048 78 | 146928 79 | 83909 80 | 109466 81 | 94063 82 | 62338 83 | 124098 84 | 64769 85 | 104722 86 | 106612 87 | 53882 88 | 108847 89 | 92739 90 | 88496 91 | 89773 92 | 57471 93 | 140532 94 | 87308 95 | 137247 96 | 62816 97 | 118893 98 | 101446 99 | 149208 100 | 68267 101 | -------------------------------------------------------------------------------- /aoc-01-02/input: -------------------------------------------------------------------------------- 1 | 77680 2 | 106826 3 | 120225 4 | 122031 5 | 100287 6 | 70402 7 | 145496 8 | 73956 9 | 148205 10 | 52065 11 | 149237 12 | 116195 13 | 84309 14 | 105327 15 | 134606 16 | 109489 17 | 104474 18 | 69536 19 | 141469 20 | 72321 21 | 75154 22 | 142565 23 | 57104 24 | 111925 25 | 100109 26 | 75178 27 | 115130 28 | 75586 29 | 148587 30 | 116029 31 | 113969 32 | 66072 33 | 90521 34 | 116324 35 | 137009 36 | 92880 37 | 110895 38 | 131046 39 | 83273 40 | 99576 41 | 70466 42 | 93602 43 | 63435 44 | 103569 45 | 56610 46 | 58392 47 | 95060 48 | 59101 49 | 121838 50 | 93494 51 | 52243 52 | 146982 53 | 142260 54 | 107232 55 | 117600 56 | 59715 57 | 80284 58 | 128223 59 | 123676 60 | 81060 61 | 99425 62 | 50621 63 | 101184 64 | 112136 65 | 131262 66 | 53150 67 | 113522 68 | 117802 69 | 120251 70 | 102322 71 | 111247 72 | 117719 73 | 88873 74 | 133541 75 | 92695 76 | 125445 77 | 149048 78 | 146928 79 | 83909 80 | 109466 81 | 94063 82 | 62338 83 | 124098 84 | 64769 85 | 104722 86 | 106612 87 | 53882 88 | 108847 89 | 92739 90 | 88496 91 | 89773 92 | 57471 93 | 140532 94 | 87308 95 | 137247 96 | 62816 97 | 118893 98 | 101446 99 | 149208 100 | 68267 101 | -------------------------------------------------------------------------------- /aoc-06-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let input = include_str!("../input"); 5 | println!("{}", orbit_count(input)); 6 | } 7 | 8 | fn orbit_count(input: &str) -> usize { 9 | let mut orbits = HashMap::new(); 10 | 11 | for line in input.lines() { 12 | let mut bodies = line.split(")"); 13 | 14 | let orbited = bodies.next().expect("Must have a body being orbited"); 15 | let orbiting = bodies.next().expect("Must have a body doing the orbiting"); 16 | 17 | orbits.insert(orbiting, orbited); 18 | } 19 | 20 | let mut total = 0; 21 | for body in orbits.keys() { 22 | let mut current = body; 23 | while *current != "COM" { 24 | total += 1; 25 | current = orbits.get(current).expect("Must be orbiting something"); 26 | } 27 | } 28 | total 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | 35 | #[test] 36 | fn one_direct_orbit_only() { 37 | let input = "COM)A"; 38 | let total = orbit_count(input); 39 | assert_eq!(total, 1); 40 | } 41 | 42 | #[test] 43 | fn one_direct_and_one_indirect() { 44 | let input = "COM)A\nA)B"; 45 | let total = orbit_count(input); 46 | assert_eq!(total, 3); 47 | } 48 | 49 | #[test] 50 | fn orbits_specified_in_example() { 51 | let input = "COM)B 52 | B)C 53 | C)D 54 | D)E 55 | E)F 56 | B)G 57 | G)H 58 | D)I 59 | E)J 60 | J)K 61 | K)L"; 62 | let total = orbit_count(input); 63 | assert_eq!(total, 42); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /aoc-01-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fs; 3 | 4 | fn main() -> Result<(), Box> { 5 | let input = fs::read_to_string("input")?; 6 | let answer: i32 = input 7 | .lines() 8 | .map(|line| { 9 | fuel_for_mass_and_fuel( 10 | line.parse() 11 | .expect("input should have been parsed as a number"), 12 | ) 13 | }) 14 | .sum(); 15 | println!("the answer is {}", answer); 16 | Ok(()) 17 | } 18 | 19 | fn fuel(mass: i32) -> i32 { 20 | mass / 3 - 2 21 | } 22 | 23 | fn fuel_for_mass_and_fuel(mass: i32) -> i32 { 24 | FuelAccumulator { current_mass: mass }.sum() 25 | } 26 | 27 | struct FuelAccumulator { 28 | current_mass: i32, 29 | } 30 | 31 | impl Iterator for FuelAccumulator { 32 | type Item = i32; 33 | 34 | fn next(&mut self) -> Option { 35 | self.current_mass = fuel(self.current_mass); 36 | if self.current_mass > 0 { 37 | Some(self.current_mass) 38 | } else { 39 | None 40 | } 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use super::*; 47 | 48 | #[test] 49 | fn example_test_cases() { 50 | assert_eq!(fuel(12), 2); 51 | assert_eq!(fuel(14), 2); 52 | assert_eq!(fuel(1969), 654); 53 | assert_eq!(fuel(100756), 33583); 54 | } 55 | 56 | #[test] 57 | fn example_fuel_for_mass_and_fuel_test_cases() { 58 | assert_eq!(fuel_for_mass_and_fuel(14), 2); 59 | assert_eq!(fuel_for_mass_and_fuel(1969), 966); 60 | assert_eq!(fuel_for_mass_and_fuel(100756), 50346); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /aoc-13-02/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-02-01" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "ncurses 5.99.0 (registry+https://github.com/rust-lang/crates.io-index)", 8 | ] 9 | 10 | [[package]] 11 | name = "cc" 12 | version = "1.0.48" 13 | source = "registry+https://github.com/rust-lang/crates.io-index" 14 | 15 | [[package]] 16 | name = "libc" 17 | version = "0.2.66" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | 20 | [[package]] 21 | name = "ncurses" 22 | version = "5.99.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | dependencies = [ 25 | "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", 26 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 27 | "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 28 | ] 29 | 30 | [[package]] 31 | name = "pkg-config" 32 | version = "0.3.17" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | 35 | [metadata] 36 | "checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" 37 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 38 | "checksum ncurses 5.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15699bee2f37e9f8828c7b35b2bc70d13846db453f2d507713b758fabe536b82" 39 | "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" 40 | -------------------------------------------------------------------------------- /aoc-04-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | fn main() { 4 | let possible_passwords: Vec<_> = (145852..=616942) 5 | .into_iter() 6 | .filter(|&num| possible_password(num)) 7 | .collect(); 8 | println!("There are {} passwords", possible_passwords.len()); 9 | } 10 | 11 | fn number_to_digits(mut num: i32) -> Vec { 12 | let mut v = vec![]; 13 | while num > 0 { 14 | v.push(num % 10); 15 | num /= 10; 16 | } 17 | v.into_iter().rev().collect() 18 | } 19 | 20 | fn never_decrease(list: &[i32]) -> bool { 21 | let mut sorted = list.to_owned(); 22 | sorted.sort(); 23 | sorted == list 24 | } 25 | 26 | fn duplicate_digits(list: &[i32]) -> bool { 27 | let digits: HashSet<_> = list.into_iter().collect(); 28 | digits.len() < list.len() 29 | } 30 | 31 | fn possible_password(num: i32) -> bool { 32 | let digits = number_to_digits(num); 33 | never_decrease(&digits) && duplicate_digits(&digits) 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn convert_number_to_digits() { 42 | let number = 145852; 43 | let digits = number_to_digits(number); 44 | assert_eq!(digits, vec![1, 4, 5, 8, 5, 2]); 45 | } 46 | 47 | #[test] 48 | fn can_tell_when_digits_never_decrease() { 49 | assert!(never_decrease(&[1, 2])); 50 | assert!(never_decrease(&[1, 1])); 51 | assert!(!never_decrease(&[2, 1])); 52 | } 53 | 54 | #[test] 55 | fn can_tell_if_theres_duplicate_digits() { 56 | assert!(duplicate_digits(&[1, 1])); 57 | assert!(!duplicate_digits(&[1, 2])); 58 | } 59 | 60 | #[test] 61 | fn can_tell_if_a_number_is_possibly_a_password() { 62 | assert!(possible_password(111111)); 63 | assert!(!possible_password(223450)); 64 | assert!(!possible_password(123789)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /aoc-11-01/input: -------------------------------------------------------------------------------- 1 | 3,8,1005,8,284,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,28,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,50,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,72,1006,0,24,1,1106,12,10,1006,0,96,1,1008,15,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,108,1006,0,54,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,101,0,8,134,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,155,1006,0,60,1006,0,64,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,183,1006,0,6,1006,0,62,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1002,8,1,211,1,108,0,10,2,1002,15,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,242,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,1002,8,1,263,101,1,9,9,1007,9,1010,10,1005,10,15,99,109,606,104,0,104,1,21101,0,666526126996,1,21101,301,0,0,1105,1,405,21101,846138811028,0,1,21101,312,0,0,1106,0,405,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,248129978391,1,21101,359,0,0,1105,1,405,21101,97751403560,0,1,21102,1,370,0,1106,0,405,3,10,104,0,104,0,3,10,104,0,104,0,21101,988753585000,0,1,21101,393,0,0,1105,1,405,21102,867961709324,1,1,21102,404,1,0,1106,0,405,99,109,2,22102,1,-1,1,21102,40,1,2,21101,436,0,3,21102,1,426,0,1105,1,469,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,431,432,447,4,0,1001,431,1,431,108,4,431,10,1006,10,463,1102,0,1,431,109,-2,2106,0,0,0,109,4,1202,-1,1,468,1207,-3,0,10,1006,10,486,21102,1,0,-3,22101,0,-3,1,21202,-2,1,2,21102,1,1,3,21101,505,0,0,1106,0,510,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,533,2207,-4,-2,10,1006,10,533,22101,0,-4,-4,1105,1,601,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,552,0,1105,1,510,21202,1,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,571,21102,1,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,593,21202,-1,1,1,21102,1,593,0,106,0,468,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0 2 | -------------------------------------------------------------------------------- /aoc-11-02/input: -------------------------------------------------------------------------------- 1 | 3,8,1005,8,284,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,28,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,50,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,72,1006,0,24,1,1106,12,10,1006,0,96,1,1008,15,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,108,1006,0,54,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,101,0,8,134,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,155,1006,0,60,1006,0,64,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,183,1006,0,6,1006,0,62,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1002,8,1,211,1,108,0,10,2,1002,15,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,242,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,1002,8,1,263,101,1,9,9,1007,9,1010,10,1005,10,15,99,109,606,104,0,104,1,21101,0,666526126996,1,21101,301,0,0,1105,1,405,21101,846138811028,0,1,21101,312,0,0,1106,0,405,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,248129978391,1,21101,359,0,0,1105,1,405,21101,97751403560,0,1,21102,1,370,0,1106,0,405,3,10,104,0,104,0,3,10,104,0,104,0,21101,988753585000,0,1,21101,393,0,0,1105,1,405,21102,867961709324,1,1,21102,404,1,0,1106,0,405,99,109,2,22102,1,-1,1,21102,40,1,2,21101,436,0,3,21102,1,426,0,1105,1,469,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,431,432,447,4,0,1001,431,1,431,108,4,431,10,1006,10,463,1102,0,1,431,109,-2,2106,0,0,0,109,4,1202,-1,1,468,1207,-3,0,10,1006,10,486,21102,1,0,-3,22101,0,-3,1,21202,-2,1,2,21102,1,1,3,21101,505,0,0,1106,0,510,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,533,2207,-4,-2,10,1006,10,533,22101,0,-4,-4,1105,1,601,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,552,0,1105,1,510,21202,1,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,571,21102,1,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,593,21202,-1,1,1,21102,1,593,0,106,0,468,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0 2 | -------------------------------------------------------------------------------- /aoc-04-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let possible_passwords: Vec<_> = (145852..=616942) 5 | .into_iter() 6 | .filter(|&num| possible_password(num)) 7 | .collect(); 8 | println!("There are {} passwords", possible_passwords.len()); 9 | } 10 | 11 | fn number_to_digits(mut num: i32) -> Vec { 12 | let mut v = vec![]; 13 | while num > 0 { 14 | v.push(num % 10); 15 | num /= 10; 16 | } 17 | v.into_iter().rev().collect() 18 | } 19 | 20 | fn never_decrease(list: &[i32]) -> bool { 21 | let mut sorted = list.to_owned(); 22 | sorted.sort(); 23 | sorted == list 24 | } 25 | 26 | fn exactly_two(list: &[i32]) -> bool { 27 | let mut digit_counts = HashMap::new(); 28 | for digit in list { 29 | let count = digit_counts.entry(digit).or_insert(0); 30 | *count += 1; 31 | } 32 | digit_counts.values().any(|&value| value == 2) 33 | } 34 | 35 | fn possible_password(num: i32) -> bool { 36 | let digits = number_to_digits(num); 37 | never_decrease(&digits) && exactly_two(&digits) 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn convert_number_to_digits() { 46 | let number = 145852; 47 | let digits = number_to_digits(number); 48 | assert_eq!(digits, vec![1, 4, 5, 8, 5, 2]); 49 | } 50 | 51 | #[test] 52 | fn can_tell_when_digits_never_decrease() { 53 | assert!(never_decrease(&[1, 2])); 54 | assert!(never_decrease(&[1, 1])); 55 | assert!(!never_decrease(&[2, 1])); 56 | } 57 | 58 | #[test] 59 | fn can_tell_if_theres_some_group_of_exactly_two_digits() { 60 | assert!(exactly_two(&[1, 1])); 61 | assert!(!exactly_two(&[1, 2])); 62 | assert!(!exactly_two(&[1, 1, 1])); 63 | } 64 | 65 | #[test] 66 | fn can_tell_if_a_number_is_possibly_a_password() { 67 | assert!(!possible_password(111111)); 68 | assert!(!possible_password(223450)); 69 | assert!(!possible_password(123789)); 70 | assert!(!possible_password(123444)); 71 | 72 | assert!(possible_password(112233)); 73 | assert!(possible_password(111122)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /aoc-08-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let input = include_str!("../input"); 5 | let image = SpaceImage::new(25, 6, input); 6 | 7 | let digits_per_layer = image.digits_per_layer(); 8 | 9 | let layer_with_fewest_0s = digits_per_layer 10 | .iter() 11 | .min_by_key(|counts| counts.get(&0).copied().unwrap_or(0)) 12 | .expect("Image should not be empty"); 13 | 14 | println!( 15 | "{}", 16 | layer_with_fewest_0s.get(&1).copied().unwrap_or(0) 17 | * layer_with_fewest_0s.get(&2).copied().unwrap_or(0) 18 | ); 19 | } 20 | 21 | struct SpaceImage { 22 | layers: Vec>, 23 | } 24 | 25 | impl SpaceImage { 26 | fn new(width: usize, height: usize, data: &str) -> SpaceImage { 27 | let digits: Vec<_> = data.trim().chars().map(|c| c.to_digit(10).unwrap()).collect(); 28 | let layers: Vec<_> = digits.chunks(width * height).map(|s| s.to_vec()).collect(); 29 | 30 | SpaceImage { layers } 31 | } 32 | 33 | fn digits_per_layer(&self) -> Vec> { 34 | self.layers 35 | .iter() 36 | .map(|layer| { 37 | let mut counts = HashMap::new(); 38 | 39 | for &digit in layer { 40 | *counts.entry(digit).or_insert(0) += 1; 41 | } 42 | 43 | counts 44 | }) 45 | .collect() 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod tests { 51 | use super::*; 52 | 53 | #[test] 54 | fn parsing_data_into_images() { 55 | let data = "123456789012"; 56 | let sample = SpaceImage::new(3, 2, data); 57 | 58 | assert_eq!(sample.layers.len(), 2); 59 | assert_eq!(sample.layers[0], vec![1, 2, 3, 4, 5, 6]); 60 | assert_eq!(sample.layers[1], vec![7, 8, 9, 0, 1, 2]); 61 | } 62 | 63 | #[test] 64 | fn counting_digits_per_layer() { 65 | let data = "113456789012"; 66 | let sample = SpaceImage::new(3, 2, data); 67 | 68 | let digits_per_layer = sample.digits_per_layer(); 69 | assert_eq!(digits_per_layer[0].get(&1), Some(&2)); 70 | assert_eq!(digits_per_layer[1].get(&1), Some(&1)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /aoc-05-01/input: -------------------------------------------------------------------------------- 1 | 3,225,1,225,6,6,1100,1,238,225,104,0,1102,46,47,225,2,122,130,224,101,-1998,224,224,4,224,1002,223,8,223,1001,224,6,224,1,224,223,223,1102,61,51,225,102,32,92,224,101,-800,224,224,4,224,1002,223,8,223,1001,224,1,224,1,223,224,223,1101,61,64,225,1001,118,25,224,101,-106,224,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,1102,33,25,225,1102,73,67,224,101,-4891,224,224,4,224,1002,223,8,223,1001,224,4,224,1,224,223,223,1101,14,81,225,1102,17,74,225,1102,52,67,225,1101,94,27,225,101,71,39,224,101,-132,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1002,14,38,224,101,-1786,224,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1,65,126,224,1001,224,-128,224,4,224,1002,223,8,223,101,6,224,224,1,224,223,223,1101,81,40,224,1001,224,-121,224,4,224,102,8,223,223,101,4,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1008,677,226,224,1002,223,2,223,1005,224,329,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,344,101,1,223,223,1107,677,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1108,226,226,224,1002,223,2,223,1006,224,374,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,389,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,404,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,419,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,434,1001,223,1,223,108,226,677,224,102,2,223,223,1006,224,449,1001,223,1,223,8,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,1007,677,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,494,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1108,226,677,224,102,2,223,223,1005,224,524,1001,223,1,223,7,226,226,224,102,2,223,223,1005,224,539,1001,223,1,223,8,677,677,224,1002,223,2,223,1005,224,554,101,1,223,223,107,677,226,224,102,2,223,223,1006,224,569,1001,223,1,223,7,226,677,224,1002,223,2,223,1005,224,584,1001,223,1,223,1008,226,226,224,1002,223,2,223,1006,224,599,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,614,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,629,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,226,226,224,102,2,223,223,1005,224,659,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226 2 | -------------------------------------------------------------------------------- /aoc-05-02/input: -------------------------------------------------------------------------------- 1 | 3,225,1,225,6,6,1100,1,238,225,104,0,1102,46,47,225,2,122,130,224,101,-1998,224,224,4,224,1002,223,8,223,1001,224,6,224,1,224,223,223,1102,61,51,225,102,32,92,224,101,-800,224,224,4,224,1002,223,8,223,1001,224,1,224,1,223,224,223,1101,61,64,225,1001,118,25,224,101,-106,224,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,1102,33,25,225,1102,73,67,224,101,-4891,224,224,4,224,1002,223,8,223,1001,224,4,224,1,224,223,223,1101,14,81,225,1102,17,74,225,1102,52,67,225,1101,94,27,225,101,71,39,224,101,-132,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1002,14,38,224,101,-1786,224,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1,65,126,224,1001,224,-128,224,4,224,1002,223,8,223,101,6,224,224,1,224,223,223,1101,81,40,224,1001,224,-121,224,4,224,102,8,223,223,101,4,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1008,677,226,224,1002,223,2,223,1005,224,329,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,344,101,1,223,223,1107,677,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1108,226,226,224,1002,223,2,223,1006,224,374,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,389,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,404,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,419,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,434,1001,223,1,223,108,226,677,224,102,2,223,223,1006,224,449,1001,223,1,223,8,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,1007,677,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,494,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1108,226,677,224,102,2,223,223,1005,224,524,1001,223,1,223,7,226,226,224,102,2,223,223,1005,224,539,1001,223,1,223,8,677,677,224,1002,223,2,223,1005,224,554,101,1,223,223,107,677,226,224,102,2,223,223,1006,224,569,1001,223,1,223,7,226,677,224,1002,223,2,223,1005,224,584,1001,223,1,223,1008,226,226,224,1002,223,2,223,1006,224,599,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,614,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,629,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,226,226,224,102,2,223,223,1005,224,659,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226 2 | -------------------------------------------------------------------------------- /aoc-10-01/input: -------------------------------------------------------------------------------- 1 | #.#................#..............#......#...... 2 | .......##..#..#....#.#.....##...#.........#.#... 3 | .#...............#....#.##...................... 4 | ......#..####.........#....#.......#..#.....#... 5 | .....#............#......#................#.#... 6 | ....##...#.#.#.#.............#..#.#.......#..... 7 | ..#.#.........#....#..#.#.........####.......... 8 | ....#...#.#...####..#..#..#.....#............... 9 | .............#......#..........#...........#.... 10 | ......#.#.........#...............#............. 11 | ..#......#..#.....##...##.....#....#.#......#... 12 | ...#.......##.........#.#..#......#........#.#.. 13 | #.............#..........#....#.#.....#......... 14 | #......#.#................#.......#..#.#........ 15 | #..#.#.....#.....###..#.................#..#.... 16 | ...............................#..........#..... 17 | ###.#.....#.....#.............#.......#....#.... 18 | .#.....#.........#.....#....#................... 19 | ........#....................#..#............... 20 | .....#...#.##......#............#......#.....#.. 21 | ..#..#..............#..#..#.##........#......... 22 | ..#.#...#.......#....##...#........#...#.#....#. 23 | .....#.#..####...........#.##....#....#......#.. 24 | .....#..#..##...............................#... 25 | .#....#..#......#.#............#........##...#.. 26 | .......#.....................#..#....#.....#.... 27 | #......#..###...........#.#....#......#......... 28 | ..............#..#.#...#.......#..#.#...#......# 29 | .......#...........#.....#...#.............#.#.. 30 | ..##..##.............#........#........#........ 31 | ......#.............##..#.........#...#.#.#..... 32 | #........#.........#...#.....#................#. 33 | ...#.#...........#.....#.........#......##...... 34 | ..#..#...........#..........#................... 35 | .........#..#.......................#.#......... 36 | ......#.#.#.....#...........#...............#... 37 | ......#.##...........#....#............#........ 38 | #...........##.#.#........##...........##....... 39 | ......#....#..#.......#.....#.#.......#.##...... 40 | .#....#......#..............#.......#........... 41 | ......##.#..........#..................#........ 42 | ......##.##...#..#........#............#........ 43 | ..#.....#.................###...#.....###.#..#.. 44 | ....##...............#....#..................#.. 45 | .....#................#.#.#.......#..........#.. 46 | #........................#.##..........#....##.. 47 | .#.........#.#.#...#...#....#........#..#....... 48 | ...#..#.#......................#...............# 49 | -------------------------------------------------------------------------------- /aoc-10-02/input: -------------------------------------------------------------------------------- 1 | #.#................#..............#......#...... 2 | .......##..#..#....#.#.....##...#.........#.#... 3 | .#...............#....#.##...................... 4 | ......#..####.........#....#.......#..#.....#... 5 | .....#............#......#................#.#... 6 | ....##...#.#.#.#.............#..#.#.......#..... 7 | ..#.#.........#....#..#.#.........####.......... 8 | ....#...#.#...####..#..#..#.....#............... 9 | .............#......#..........#...........#.... 10 | ......#.#.........#...............#............. 11 | ..#......#..#.....##...##.....#....#.#......#... 12 | ...#.......##.........#.#..#......#........#.#.. 13 | #.............#..........#....#.#.....#......... 14 | #......#.#................#.......#..#.#........ 15 | #..#.#.....#.....###..#.................#..#.... 16 | ...............................#..........#..... 17 | ###.#.....#.....#.............#.......#....#.... 18 | .#.....#.........#.....#....#................... 19 | ........#....................#..#............... 20 | .....#...#.##......#............#......#.....#.. 21 | ..#..#..............#..#..#.##........#......... 22 | ..#.#...#.......#....##...#........#...#.#....#. 23 | .....#.#..####...........#.##....#....#......#.. 24 | .....#..#..##...............................#... 25 | .#....#..#......#.#............#........##...#.. 26 | .......#.....................#..#....#.....#.... 27 | #......#..###...........#.#....#......#......... 28 | ..............#..#.#...#.......#..#.#...#......# 29 | .......#...........#.....#...#.............#.#.. 30 | ..##..##.............#........#........#........ 31 | ......#.............##..#.........#...#.#.#..... 32 | #........#.........#...#.....#................#. 33 | ...#.#...........#.....#.........#......##...... 34 | ..#..#...........#..........#................... 35 | .........#..#.......................#.#......... 36 | ......#.#.#.....#...........#...............#... 37 | ......#.##...........#....#............#........ 38 | #...........##.#.#........##...........##....... 39 | ......#....#..#.......#.....#.#.......#.##...... 40 | .#....#......#..............#.......#........... 41 | ......##.#..........#..................#........ 42 | ......##.##...#..#........#............#........ 43 | ..#.....#.................###...#.....###.#..#.. 44 | ....##...............#....#..................#.. 45 | .....#................#.#.#.......#..........#.. 46 | #........................#.##..........#....##.. 47 | .#.........#.#.#...#...#....#........#..#....... 48 | ...#..#.#......................#...............# 49 | -------------------------------------------------------------------------------- /aoc-06-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | fn main() { 4 | let input = include_str!("../input"); 5 | println!("{}", num_transfers_to_santa(input)); 6 | } 7 | 8 | fn orbit_graph(input: &str) -> HashMap<&str, &str> { 9 | let mut orbits = HashMap::new(); 10 | 11 | for line in input.lines() { 12 | let mut bodies = line.split(")"); 13 | 14 | let orbited = bodies.next().expect("Must have a body being orbited"); 15 | let orbiting = bodies.next().expect("Must have a body doing the orbiting"); 16 | 17 | orbits.insert(orbiting, orbited); 18 | } 19 | 20 | orbits 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn you_orbiting_same_as_santa_is_0() { 29 | let input = "COM)SAN\nCOM)YOU"; 30 | let total = num_transfers_to_santa(input); 31 | assert_eq!(total, 0); 32 | } 33 | 34 | #[test] 35 | fn one_further_out_than_santa_is_1() { 36 | let input = "COM)SAN\nCOM)A\nA)YOU"; 37 | let total = num_transfers_to_santa(input); 38 | assert_eq!(total, 1); 39 | } 40 | 41 | #[test] 42 | fn one_further_in_than_santa_is_1() { 43 | let input = "COM)YOU\nCOM)A\nA)SAN"; 44 | let total = num_transfers_to_santa(input); 45 | assert_eq!(total, 1); 46 | } 47 | } 48 | 49 | fn num_transfers_to_santa(input: &str) -> usize { 50 | let orbits = orbit_graph(input); 51 | let santa_orbiting = *orbits.get("SAN").expect("SAN must be orbiting something"); 52 | 53 | let mut candidates = HashSet::new(); 54 | candidates.insert(*orbits.get("YOU").expect("YOU must be orbiting something")); 55 | let mut num_transfers = 0; 56 | let mut visited = HashSet::new(); 57 | visited.insert("YOU"); 58 | 59 | while !candidates.contains(&santa_orbiting) { 60 | num_transfers += 1; 61 | 62 | let mut new_candidates = HashSet::new(); 63 | for c in &candidates { 64 | visited.insert(c); 65 | } 66 | 67 | for c in candidates { 68 | if let Some(&inner) = orbits.get(c) { 69 | if !visited.contains(inner) { 70 | new_candidates.insert(inner); 71 | } 72 | } 73 | 74 | for (outer, _) in orbits 75 | .iter() 76 | .filter(|(&k, &v)| v == c && !visited.contains(k)) { 77 | new_candidates.insert(outer); 78 | } 79 | } 80 | 81 | candidates = new_candidates; 82 | } 83 | num_transfers 84 | } 85 | -------------------------------------------------------------------------------- /aoc-03-01/input: -------------------------------------------------------------------------------- 1 | R992,U284,L447,D597,R888,D327,R949,U520,R27,U555,L144,D284,R538,U249,R323,U297,R136,U838,L704,D621,R488,U856,R301,U539,L701,U363,R611,D94,L734,D560,L414,U890,R236,D699,L384,D452,R702,D637,L164,U410,R649,U901,L910,D595,R339,D346,R959,U777,R218,D667,R534,D762,R484,D914,L25,U959,R984,D922,R612,U999,L169,D599,L604,D357,L217,D327,L730,D949,L565,D332,L114,D512,R460,D495,L187,D697,R313,U319,L8,D915,L518,D513,R738,U9,R137,U542,L188,U440,R576,D307,R734,U58,R285,D401,R166,U156,L859,U132,L10,U753,L933,U915,R459,D50,R231,D166,L253,U844,R585,D871,L799,U53,R785,U336,R622,D108,R555,D918,L217,D668,L220,U738,L997,D998,R964,D456,L54,U930,R985,D244,L613,D116,L994,D20,R949,D245,L704,D564,L210,D13,R998,U951,L482,U579,L793,U680,L285,U770,L975,D54,R79,U613,L907,U467,L256,D783,R883,U810,R409,D508,L898,D286,L40,U741,L759,D549,R210,U411,R638,D643,L784,U538,L739,U771,L773,U491,L303,D425,L891,U182,R412,U951,L381,U501,R482,D625,R870,D320,L464,U555,R566,D781,L540,D754,L211,U73,L321,D869,R994,D177,R496,U383,R911,U819,L651,D774,L591,U666,L883,U767,R232,U822,L499,U44,L45,U873,L98,D487,L47,U803,R855,U256,R567,D88,R138,D678,L37,U38,R783,U569,L646,D261,L597,U275,L527,U48,R433,D324,L631,D160,L145,D128,R894,U223,R664,U510,R756,D700,R297,D361,R837,U996,L769,U813,L477,U420,L172,U482,R891,D379,L329,U55,R284,U155,L816,U659,L671,U996,R997,U252,R514,D718,L661,D625,R910,D960,L39,U610,R853,U859,R174,U215,L603,U745,L587,D736,R365,U78,R306,U158,L813,U885,R558,U631,L110,D232,L519,D366,R909,D10,R294 2 | L1001,D833,L855,D123,R36,U295,L319,D700,L164,U576,L68,D757,R192,D738,L640,D660,R940,D778,R888,U772,R771,U900,L188,D464,L572,U184,R889,D991,L961,U751,R560,D490,L887,D748,R37,U910,L424,D401,L385,U415,L929,U193,R710,D855,L596,D323,L966,D505,L422,D139,L108,D135,R737,U176,R538,D173,R21,D951,R949,D61,L343,U704,R127,U468,L240,D834,L858,D127,R328,D863,R329,U477,R131,U864,R997,D38,R418,U611,R28,U705,R148,D414,R786,U264,L785,D650,R201,D250,R528,D910,R670,U309,L658,U190,R704,U21,R288,D7,R930,U62,R782,U621,R328,D725,R305,U700,R494,D137,R969,U142,L867,U577,R300,U162,L13,D698,R333,U865,R941,U796,L60,U902,L784,U832,R78,D578,R196,D390,R728,D922,R858,D994,L457,U547,R238,D345,R329,D498,R873,D212,R501,U474,L657,U910,L335,U133,R213,U417,R698,U829,L2,U704,L273,D83,R231,D247,R675,D23,L692,D472,L325,D659,L408,U746,L715,U395,L596,U296,R52,D849,L713,U815,R684,D551,L319,U768,R176,D182,R557,U731,R314,D543,L9,D256,R38,D809,L567,D332,R375,D572,R81,D479,L71,U968,L831,D247,R989,U390,R463,D576,R740,D539,R488,U367,L596,U375,L763,D824,R70,U448,R979,D977,L744,D379,R488,D671,L516,D334,L542,U517,L488,D390,L713,D932,L28,U924,L448,D229,L488,D501,R19,D910,L979,D411,R711,D824,L973,U291,R794,D485,R208,U370,R655,U450,L40,D804,L374,D671,R962,D829,L209,U111,L84,D876,L832,D747,L733,D560,L702,D972,R188,U817,L111,U26,L492,U485,L71,D59,L269,D870,L152,U539,R65,D918,L932,D260,L485,U77,L699,U254,R924,U643,L264,U96,R395,D917,R360,U354,R101,D682,R854,U450,L376,D378,R872,D311,L881,U630,R77,D766,R672 3 | -------------------------------------------------------------------------------- /aoc-03-02/input: -------------------------------------------------------------------------------- 1 | R992,U284,L447,D597,R888,D327,R949,U520,R27,U555,L144,D284,R538,U249,R323,U297,R136,U838,L704,D621,R488,U856,R301,U539,L701,U363,R611,D94,L734,D560,L414,U890,R236,D699,L384,D452,R702,D637,L164,U410,R649,U901,L910,D595,R339,D346,R959,U777,R218,D667,R534,D762,R484,D914,L25,U959,R984,D922,R612,U999,L169,D599,L604,D357,L217,D327,L730,D949,L565,D332,L114,D512,R460,D495,L187,D697,R313,U319,L8,D915,L518,D513,R738,U9,R137,U542,L188,U440,R576,D307,R734,U58,R285,D401,R166,U156,L859,U132,L10,U753,L933,U915,R459,D50,R231,D166,L253,U844,R585,D871,L799,U53,R785,U336,R622,D108,R555,D918,L217,D668,L220,U738,L997,D998,R964,D456,L54,U930,R985,D244,L613,D116,L994,D20,R949,D245,L704,D564,L210,D13,R998,U951,L482,U579,L793,U680,L285,U770,L975,D54,R79,U613,L907,U467,L256,D783,R883,U810,R409,D508,L898,D286,L40,U741,L759,D549,R210,U411,R638,D643,L784,U538,L739,U771,L773,U491,L303,D425,L891,U182,R412,U951,L381,U501,R482,D625,R870,D320,L464,U555,R566,D781,L540,D754,L211,U73,L321,D869,R994,D177,R496,U383,R911,U819,L651,D774,L591,U666,L883,U767,R232,U822,L499,U44,L45,U873,L98,D487,L47,U803,R855,U256,R567,D88,R138,D678,L37,U38,R783,U569,L646,D261,L597,U275,L527,U48,R433,D324,L631,D160,L145,D128,R894,U223,R664,U510,R756,D700,R297,D361,R837,U996,L769,U813,L477,U420,L172,U482,R891,D379,L329,U55,R284,U155,L816,U659,L671,U996,R997,U252,R514,D718,L661,D625,R910,D960,L39,U610,R853,U859,R174,U215,L603,U745,L587,D736,R365,U78,R306,U158,L813,U885,R558,U631,L110,D232,L519,D366,R909,D10,R294 2 | L1001,D833,L855,D123,R36,U295,L319,D700,L164,U576,L68,D757,R192,D738,L640,D660,R940,D778,R888,U772,R771,U900,L188,D464,L572,U184,R889,D991,L961,U751,R560,D490,L887,D748,R37,U910,L424,D401,L385,U415,L929,U193,R710,D855,L596,D323,L966,D505,L422,D139,L108,D135,R737,U176,R538,D173,R21,D951,R949,D61,L343,U704,R127,U468,L240,D834,L858,D127,R328,D863,R329,U477,R131,U864,R997,D38,R418,U611,R28,U705,R148,D414,R786,U264,L785,D650,R201,D250,R528,D910,R670,U309,L658,U190,R704,U21,R288,D7,R930,U62,R782,U621,R328,D725,R305,U700,R494,D137,R969,U142,L867,U577,R300,U162,L13,D698,R333,U865,R941,U796,L60,U902,L784,U832,R78,D578,R196,D390,R728,D922,R858,D994,L457,U547,R238,D345,R329,D498,R873,D212,R501,U474,L657,U910,L335,U133,R213,U417,R698,U829,L2,U704,L273,D83,R231,D247,R675,D23,L692,D472,L325,D659,L408,U746,L715,U395,L596,U296,R52,D849,L713,U815,R684,D551,L319,U768,R176,D182,R557,U731,R314,D543,L9,D256,R38,D809,L567,D332,R375,D572,R81,D479,L71,U968,L831,D247,R989,U390,R463,D576,R740,D539,R488,U367,L596,U375,L763,D824,R70,U448,R979,D977,L744,D379,R488,D671,L516,D334,L542,U517,L488,D390,L713,D932,L28,U924,L448,D229,L488,D501,R19,D910,L979,D411,R711,D824,L973,U291,R794,D485,R208,U370,R655,U450,L40,D804,L374,D671,R962,D829,L209,U111,L84,D876,L832,D747,L733,D560,L702,D972,R188,U817,L111,U26,L492,U485,L71,D59,L269,D870,L152,U539,R65,D918,L932,D260,L485,U77,L699,U254,R924,U643,L264,U96,R395,D917,R360,U354,R101,D682,R854,U450,L376,D378,R872,D311,L881,U630,R77,D766,R672 3 | -------------------------------------------------------------------------------- /aoc-02-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::error::Error; 3 | 4 | fn main() -> Result<(), Box>{ 5 | let input = fs::read_to_string("input")?; 6 | let program: Vec<_> = input 7 | .trim() 8 | .split(",") 9 | .map(|n| n.parse().expect("input should have been a number")) 10 | .collect(); 11 | let answer = run_intcode(program); 12 | println!("{:?}", answer); 13 | Ok(()) 14 | } 15 | 16 | fn run_intcode(mut program: Vec) -> Vec { 17 | let mut current_position = 0; 18 | let mut current_opcode = program[current_position]; 19 | 20 | while current_opcode != 99 { 21 | match current_opcode { 22 | 1 => { 23 | let output_position = program[current_position + 3] as usize; 24 | let input_position_1 = program[current_position + 1] as usize; 25 | let input_position_2 = program[current_position + 2] as usize; 26 | let answer = program[input_position_1] + program[input_position_2]; 27 | program[output_position] = answer; 28 | } 29 | 2 => { 30 | let output_position = program[current_position + 3] as usize; 31 | let input_position_1 = program[current_position + 1] as usize; 32 | let input_position_2 = program[current_position + 2] as usize; 33 | let answer = program[input_position_1] * program[input_position_2]; 34 | program[output_position] = answer; 35 | } 36 | other => panic!("Unknown opcode: {}", other), 37 | } 38 | current_position += 4; 39 | current_opcode = program[current_position]; 40 | } 41 | 42 | program 43 | } 44 | 45 | #[cfg(test)] 46 | mod tests { 47 | use super::*; 48 | 49 | #[test] 50 | fn opcode_99_ends() { 51 | let program = vec![99]; 52 | let answer = run_intcode(program); 53 | assert_eq!(answer, vec![99]); 54 | } 55 | 56 | #[test] 57 | fn opcode_1_adds() { 58 | let program = vec![1, 0, 0, 0, 99]; 59 | let answer = run_intcode(program); 60 | assert_eq!(answer, vec![2, 0, 0, 0, 99]); 61 | } 62 | 63 | #[test] 64 | fn opcode_2_multiplies() { 65 | let program = vec![2, 3, 0, 3, 99]; 66 | let answer = run_intcode(program); 67 | assert_eq!(answer, vec![2, 3, 0, 6, 99]); 68 | } 69 | 70 | #[test] 71 | fn multiply_and_store_after_program() { 72 | let program = vec![2, 4, 4, 5, 99, 0]; 73 | let answer = run_intcode(program); 74 | assert_eq!(answer, vec![2, 4, 4, 5, 99, 9801]); 75 | } 76 | 77 | #[test] 78 | fn program_keeps_going_if_an_instruction_changes() { 79 | let program = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; 80 | let answer = run_intcode(program); 81 | assert_eq!(answer, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); 82 | } 83 | 84 | #[test] 85 | #[should_panic(expected = "Unknown opcode: 42")] 86 | fn unknown_opcode_panics() { 87 | let program = vec![42]; 88 | run_intcode(program); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /aoc-09-01/input: -------------------------------------------------------------------------------- 1 | 1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,550,1027,1101,0,0,1020,1101,30,0,1004,1101,0,22,1014,1102,1,36,1009,1101,37,0,1007,1102,25,1,1010,1102,1,33,1012,1102,282,1,1029,1102,1,488,1025,1101,0,31,1019,1101,0,21,1008,1101,0,35,1015,1101,664,0,1023,1102,26,1,1001,1101,28,0,1016,1102,29,1,1005,1102,1,24,1002,1101,20,0,1018,1101,27,0,1013,1101,38,0,1017,1102,1,1,1021,1102,1,557,1026,1102,1,39,1000,1101,23,0,1006,1101,493,0,1024,1102,1,291,1028,1101,671,0,1022,1101,0,34,1003,1101,0,32,1011,109,10,21108,40,40,8,1005,1018,199,4,187,1105,1,203,1001,64,1,64,1002,64,2,64,109,-14,2108,30,8,63,1005,63,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,3,2102,1,4,63,1008,63,34,63,1005,63,251,4,231,1001,64,1,64,1106,0,251,1002,64,2,64,109,12,2107,22,-5,63,1005,63,269,4,257,1105,1,273,1001,64,1,64,1002,64,2,64,109,20,2106,0,-3,4,279,1001,64,1,64,1106,0,291,1002,64,2,64,109,-16,21108,41,40,-3,1005,1012,311,1001,64,1,64,1105,1,313,4,297,1002,64,2,64,109,-13,2101,0,2,63,1008,63,30,63,1005,63,335,4,319,1105,1,339,1001,64,1,64,1002,64,2,64,109,-3,2102,1,4,63,1008,63,35,63,1005,63,359,1106,0,365,4,345,1001,64,1,64,1002,64,2,64,109,15,1205,6,377,1105,1,383,4,371,1001,64,1,64,1002,64,2,64,109,5,21102,42,1,-2,1008,1017,39,63,1005,63,403,1106,0,409,4,389,1001,64,1,64,1002,64,2,64,109,-17,21107,43,44,10,1005,1012,431,4,415,1001,64,1,64,1106,0,431,1002,64,2,64,109,14,21107,44,43,-4,1005,1012,451,1001,64,1,64,1106,0,453,4,437,1002,64,2,64,109,1,21102,45,1,-3,1008,1014,45,63,1005,63,479,4,459,1001,64,1,64,1105,1,479,1002,64,2,64,109,7,2105,1,0,4,485,1106,0,497,1001,64,1,64,1002,64,2,64,109,5,1206,-8,513,1001,64,1,64,1106,0,515,4,503,1002,64,2,64,109,-33,2101,0,7,63,1008,63,32,63,1005,63,535,1106,0,541,4,521,1001,64,1,64,1002,64,2,64,109,23,2106,0,8,1001,64,1,64,1106,0,559,4,547,1002,64,2,64,109,-1,21101,46,0,-5,1008,1013,46,63,1005,63,585,4,565,1001,64,1,64,1105,1,585,1002,64,2,64,109,-4,21101,47,0,2,1008,1016,44,63,1005,63,605,1105,1,611,4,591,1001,64,1,64,1002,64,2,64,109,-18,1207,4,38,63,1005,63,627,1106,0,633,4,617,1001,64,1,64,1002,64,2,64,109,5,2107,22,7,63,1005,63,649,1106,0,655,4,639,1001,64,1,64,1002,64,2,64,109,12,2105,1,10,1001,64,1,64,1106,0,673,4,661,1002,64,2,64,109,-10,1208,6,33,63,1005,63,693,1001,64,1,64,1106,0,695,4,679,1002,64,2,64,109,-7,2108,35,7,63,1005,63,715,1001,64,1,64,1106,0,717,4,701,1002,64,2,64,109,6,1208,5,37,63,1005,63,735,4,723,1106,0,739,1001,64,1,64,1002,64,2,64,109,-4,1202,5,1,63,1008,63,34,63,1005,63,765,4,745,1001,64,1,64,1105,1,765,1002,64,2,64,109,29,1206,-7,783,4,771,1001,64,1,64,1105,1,783,1002,64,2,64,109,-28,1201,6,0,63,1008,63,29,63,1005,63,809,4,789,1001,64,1,64,1106,0,809,1002,64,2,64,109,5,1202,2,1,63,1008,63,20,63,1005,63,829,1106,0,835,4,815,1001,64,1,64,1002,64,2,64,109,-1,1201,6,0,63,1008,63,35,63,1005,63,859,1001,64,1,64,1105,1,861,4,841,1002,64,2,64,109,2,1207,-3,25,63,1005,63,879,4,867,1105,1,883,1001,64,1,64,1002,64,2,64,109,13,1205,3,901,4,889,1001,64,1,64,1106,0,901,4,64,99,21101,0,27,1,21101,915,0,0,1106,0,922,21201,1,22987,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1106,0,922,22101,0,1,-1,21201,-2,-3,1,21101,0,957,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2105,1,0 2 | -------------------------------------------------------------------------------- /aoc-09-02/input: -------------------------------------------------------------------------------- 1 | 1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,550,1027,1101,0,0,1020,1101,30,0,1004,1101,0,22,1014,1102,1,36,1009,1101,37,0,1007,1102,25,1,1010,1102,1,33,1012,1102,282,1,1029,1102,1,488,1025,1101,0,31,1019,1101,0,21,1008,1101,0,35,1015,1101,664,0,1023,1102,26,1,1001,1101,28,0,1016,1102,29,1,1005,1102,1,24,1002,1101,20,0,1018,1101,27,0,1013,1101,38,0,1017,1102,1,1,1021,1102,1,557,1026,1102,1,39,1000,1101,23,0,1006,1101,493,0,1024,1102,1,291,1028,1101,671,0,1022,1101,0,34,1003,1101,0,32,1011,109,10,21108,40,40,8,1005,1018,199,4,187,1105,1,203,1001,64,1,64,1002,64,2,64,109,-14,2108,30,8,63,1005,63,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,3,2102,1,4,63,1008,63,34,63,1005,63,251,4,231,1001,64,1,64,1106,0,251,1002,64,2,64,109,12,2107,22,-5,63,1005,63,269,4,257,1105,1,273,1001,64,1,64,1002,64,2,64,109,20,2106,0,-3,4,279,1001,64,1,64,1106,0,291,1002,64,2,64,109,-16,21108,41,40,-3,1005,1012,311,1001,64,1,64,1105,1,313,4,297,1002,64,2,64,109,-13,2101,0,2,63,1008,63,30,63,1005,63,335,4,319,1105,1,339,1001,64,1,64,1002,64,2,64,109,-3,2102,1,4,63,1008,63,35,63,1005,63,359,1106,0,365,4,345,1001,64,1,64,1002,64,2,64,109,15,1205,6,377,1105,1,383,4,371,1001,64,1,64,1002,64,2,64,109,5,21102,42,1,-2,1008,1017,39,63,1005,63,403,1106,0,409,4,389,1001,64,1,64,1002,64,2,64,109,-17,21107,43,44,10,1005,1012,431,4,415,1001,64,1,64,1106,0,431,1002,64,2,64,109,14,21107,44,43,-4,1005,1012,451,1001,64,1,64,1106,0,453,4,437,1002,64,2,64,109,1,21102,45,1,-3,1008,1014,45,63,1005,63,479,4,459,1001,64,1,64,1105,1,479,1002,64,2,64,109,7,2105,1,0,4,485,1106,0,497,1001,64,1,64,1002,64,2,64,109,5,1206,-8,513,1001,64,1,64,1106,0,515,4,503,1002,64,2,64,109,-33,2101,0,7,63,1008,63,32,63,1005,63,535,1106,0,541,4,521,1001,64,1,64,1002,64,2,64,109,23,2106,0,8,1001,64,1,64,1106,0,559,4,547,1002,64,2,64,109,-1,21101,46,0,-5,1008,1013,46,63,1005,63,585,4,565,1001,64,1,64,1105,1,585,1002,64,2,64,109,-4,21101,47,0,2,1008,1016,44,63,1005,63,605,1105,1,611,4,591,1001,64,1,64,1002,64,2,64,109,-18,1207,4,38,63,1005,63,627,1106,0,633,4,617,1001,64,1,64,1002,64,2,64,109,5,2107,22,7,63,1005,63,649,1106,0,655,4,639,1001,64,1,64,1002,64,2,64,109,12,2105,1,10,1001,64,1,64,1106,0,673,4,661,1002,64,2,64,109,-10,1208,6,33,63,1005,63,693,1001,64,1,64,1106,0,695,4,679,1002,64,2,64,109,-7,2108,35,7,63,1005,63,715,1001,64,1,64,1106,0,717,4,701,1002,64,2,64,109,6,1208,5,37,63,1005,63,735,4,723,1106,0,739,1001,64,1,64,1002,64,2,64,109,-4,1202,5,1,63,1008,63,34,63,1005,63,765,4,745,1001,64,1,64,1105,1,765,1002,64,2,64,109,29,1206,-7,783,4,771,1001,64,1,64,1105,1,783,1002,64,2,64,109,-28,1201,6,0,63,1008,63,29,63,1005,63,809,4,789,1001,64,1,64,1106,0,809,1002,64,2,64,109,5,1202,2,1,63,1008,63,20,63,1005,63,829,1106,0,835,4,815,1001,64,1,64,1002,64,2,64,109,-1,1201,6,0,63,1008,63,35,63,1005,63,859,1001,64,1,64,1105,1,861,4,841,1002,64,2,64,109,2,1207,-3,25,63,1005,63,879,4,867,1105,1,883,1001,64,1,64,1002,64,2,64,109,13,1205,3,901,4,889,1001,64,1,64,1106,0,901,4,64,99,21101,0,27,1,21101,915,0,0,1106,0,922,21201,1,22987,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1106,0,922,22101,0,1,-1,21201,-2,-3,1,21101,0,957,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2105,1,0 2 | -------------------------------------------------------------------------------- /aoc-02-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::error::Error; 3 | 4 | fn main() -> Result<(), Box>{ 5 | let input = fs::read_to_string("input")?; 6 | let program: Vec<_> = input 7 | .trim() 8 | .split(",") 9 | .map(|n| n.parse().expect("input should have been a number")) 10 | .collect(); 11 | 12 | for noun in 0..=99 { 13 | for verb in 0..=99 { 14 | let mut modified_program = program.clone(); 15 | modified_program[1] = noun; 16 | modified_program[2] = verb; 17 | let answer = run_intcode(modified_program); 18 | 19 | if answer[0] == 19690720 { 20 | println!("noun = {}, verb = {}, answer = {}", noun, verb, 100 * noun + verb); 21 | break; 22 | } 23 | } 24 | } 25 | 26 | Ok(()) 27 | } 28 | 29 | fn run_intcode(mut program: Vec) -> Vec { 30 | let mut current_position = 0; 31 | let mut current_opcode = program[current_position]; 32 | 33 | while current_opcode != 99 { 34 | match current_opcode { 35 | 1 => { 36 | let output_position = program[current_position + 3] as usize; 37 | let input_position_1 = program[current_position + 1] as usize; 38 | let input_position_2 = program[current_position + 2] as usize; 39 | let answer = program[input_position_1] + program[input_position_2]; 40 | program[output_position] = answer; 41 | } 42 | 2 => { 43 | let output_position = program[current_position + 3] as usize; 44 | let input_position_1 = program[current_position + 1] as usize; 45 | let input_position_2 = program[current_position + 2] as usize; 46 | let answer = program[input_position_1] * program[input_position_2]; 47 | program[output_position] = answer; 48 | } 49 | other => panic!("Unknown opcode: {}", other), 50 | } 51 | current_position += 4; 52 | current_opcode = program[current_position]; 53 | } 54 | 55 | program 56 | } 57 | 58 | #[cfg(test)] 59 | mod tests { 60 | use super::*; 61 | 62 | #[test] 63 | fn opcode_99_ends() { 64 | let program = vec![99]; 65 | let answer = run_intcode(program); 66 | assert_eq!(answer, vec![99]); 67 | } 68 | 69 | #[test] 70 | fn opcode_1_adds() { 71 | let program = vec![1, 0, 0, 0, 99]; 72 | let answer = run_intcode(program); 73 | assert_eq!(answer, vec![2, 0, 0, 0, 99]); 74 | } 75 | 76 | #[test] 77 | fn opcode_2_multiplies() { 78 | let program = vec![2, 3, 0, 3, 99]; 79 | let answer = run_intcode(program); 80 | assert_eq!(answer, vec![2, 3, 0, 6, 99]); 81 | } 82 | 83 | #[test] 84 | fn multiply_and_store_after_program() { 85 | let program = vec![2, 4, 4, 5, 99, 0]; 86 | let answer = run_intcode(program); 87 | assert_eq!(answer, vec![2, 4, 4, 5, 99, 9801]); 88 | } 89 | 90 | #[test] 91 | fn program_keeps_going_if_an_instruction_changes() { 92 | let program = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; 93 | let answer = run_intcode(program); 94 | assert_eq!(answer, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); 95 | } 96 | 97 | #[test] 98 | #[should_panic(expected = "Unknown opcode: 42")] 99 | fn unknown_opcode_panics() { 100 | let program = vec![42]; 101 | run_intcode(program); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /aoc-08-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::fmt; 3 | 4 | fn main() { 5 | let input = include_str!("../input"); 6 | let image = SpaceImage::new(25, 6, input); 7 | 8 | println!("{}", image); 9 | } 10 | 11 | struct SpaceImage { 12 | width: usize, 13 | layers: Vec>, 14 | } 15 | 16 | impl fmt::Display for SpaceImage { 17 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18 | write!( 19 | f, 20 | "{}", 21 | self.flatten() 22 | .chunks(self.width) 23 | .map(|row| row.iter().map(|&pixel| { 24 | match pixel { 25 | 0 => " ", 26 | 1 => "X", 27 | _ => panic!("unknown pixel"), 28 | } 29 | }).collect::>().join("")) 30 | .collect::>() 31 | .join("\n") 32 | ) 33 | } 34 | } 35 | 36 | impl SpaceImage { 37 | fn new(width: usize, height: usize, data: &str) -> SpaceImage { 38 | let digits: Vec<_> = data 39 | .trim() 40 | .chars() 41 | .map(|c| c.to_digit(10).unwrap()) 42 | .collect(); 43 | let layers: Vec<_> = digits.chunks(width * height).map(|s| s.to_vec()).collect(); 44 | 45 | SpaceImage { width, layers } 46 | } 47 | 48 | fn digits_per_layer(&self) -> Vec> { 49 | self.layers 50 | .iter() 51 | .map(|layer| { 52 | let mut counts = HashMap::new(); 53 | 54 | for &digit in layer { 55 | *counts.entry(digit).or_insert(0) += 1; 56 | } 57 | 58 | counts 59 | }) 60 | .collect() 61 | } 62 | 63 | fn flatten(&self) -> Vec { 64 | (0..self.layers[0].len()) 65 | .into_iter() 66 | .map(|i| { 67 | self.layers 68 | .iter() 69 | .map(|layer| layer[i]) 70 | .skip_while(|&pixel| pixel == 2) 71 | .next() 72 | .expect("All locations should have a color pixel in some layer") 73 | }) 74 | .collect() 75 | } 76 | } 77 | 78 | #[cfg(test)] 79 | mod tests { 80 | use super::*; 81 | 82 | #[test] 83 | fn parsing_data_into_images() { 84 | let data = "123456789012"; 85 | let sample = SpaceImage::new(3, 2, data); 86 | 87 | assert_eq!(sample.layers.len(), 2); 88 | assert_eq!(sample.layers[0], vec![1, 2, 3, 4, 5, 6]); 89 | assert_eq!(sample.layers[1], vec![7, 8, 9, 0, 1, 2]); 90 | } 91 | 92 | #[test] 93 | fn counting_digits_per_layer() { 94 | let data = "113456789012"; 95 | let sample = SpaceImage::new(3, 2, data); 96 | 97 | let digits_per_layer = sample.digits_per_layer(); 98 | assert_eq!(digits_per_layer[0].get(&1), Some(&2)); 99 | assert_eq!(digits_per_layer[1].get(&1), Some(&1)); 100 | } 101 | 102 | #[test] 103 | fn flatten_layers() { 104 | let data = "0222112222120000"; 105 | let sample = SpaceImage::new(2, 2, data); 106 | 107 | let flat = sample.flatten(); 108 | assert_eq!(flat, vec![0, 1, 1, 0]); 109 | } 110 | 111 | #[test] 112 | fn display_flattened_image_according_to_width_and_height() { 113 | let data = "0222112222120000"; 114 | let sample = SpaceImage::new(2, 2, data); 115 | 116 | assert_eq!(sample.to_string(), " X\nX "); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/www/index.js: -------------------------------------------------------------------------------- 1 | import { Screen, Tile, Joystick } from "aoc-13-02"; 2 | import { memory } from "aoc-13-02/aoc_13_02_bg"; 3 | 4 | const CELL_SIZE = 10; // px 5 | const GRID_COLOR = "#CCCCCC"; 6 | const EMPTY_COLOR = "#FFFFFF"; 7 | const WALL_COLOR = "#000000"; 8 | const BLOCK_COLOR = "#CC00CC"; 9 | const PADDLE_COLOR = "#00CCCC"; 10 | const BALL_COLOR = "#CCCC00"; 11 | 12 | // Construct the game screen, and get its width and height. 13 | let game_screen = Screen.new(); 14 | const width = game_screen.width(); 15 | const height = game_screen.height(); 16 | 17 | // Give the canvas room for all of our tiles and a 1px border 18 | // around each of them. 19 | const canvas = document.getElementById("breakout-canvas"); 20 | canvas.height = (CELL_SIZE + 1) * height + 1; 21 | canvas.width = (CELL_SIZE + 1) * width + 1; 22 | const ctx = canvas.getContext('2d'); 23 | 24 | const game_status = document.getElementById("breakout-status"); 25 | let game_started = false; 26 | let game_over = false; 27 | let speed = 10; 28 | 29 | const renderLoop = () => { 30 | setTimeout(function () { 31 | game_over = game_screen.run(); 32 | game_status.textContent = "Score: " + game_screen.score(); 33 | 34 | if (game_over) { 35 | game_status.textContent += ". Press space to play again"; 36 | } else { 37 | drawGrid(); 38 | drawCells(); 39 | requestAnimationFrame(renderLoop); 40 | } 41 | }, 1000/speed); 42 | }; 43 | 44 | const drawGrid = () => { 45 | ctx.beginPath(); 46 | ctx.strokeStyle = GRID_COLOR; 47 | 48 | // Vertical lines. 49 | for (let i = 0; i <= width; i++) { 50 | ctx.moveTo(i * (CELL_SIZE + 1) + 1, 0); 51 | ctx.lineTo(i * (CELL_SIZE + 1) + 1, (CELL_SIZE + 1) * height + 1); 52 | } 53 | 54 | // Horizontal lines. 55 | for (let j = 0; j <= height; j++) { 56 | ctx.moveTo(0, j * (CELL_SIZE + 1) + 1); 57 | ctx.lineTo((CELL_SIZE + 1) * width + 1, j * (CELL_SIZE + 1) + 1); 58 | } 59 | 60 | ctx.stroke(); 61 | }; 62 | 63 | const getIndex = (row, column) => { 64 | return row * width + column; 65 | }; 66 | 67 | const drawCells = () => { 68 | const tilesPtr = game_screen.tiles(); 69 | const tiles = new Uint8Array(memory.buffer, tilesPtr, width * height); 70 | 71 | ctx.beginPath(); 72 | 73 | for (let row = 0; row < height; row++) { 74 | for (let col = 0; col < width; col++) { 75 | const idx = getIndex(row, col); 76 | const tile = tiles[idx]; 77 | 78 | if (tile === Tile.Wall) { 79 | ctx.fillStyle = WALL_COLOR; 80 | } else if (tile === Tile.Block) { 81 | ctx.fillStyle = BLOCK_COLOR; 82 | } else if (tile === Tile.Paddle) { 83 | ctx.fillStyle = PADDLE_COLOR; 84 | } else if (tile === Tile.Ball) { 85 | ctx.fillStyle = BALL_COLOR; 86 | } else { 87 | ctx.fillStyle = EMPTY_COLOR; 88 | } 89 | 90 | ctx.fillRect( 91 | col * (CELL_SIZE + 1) + 1, 92 | row * (CELL_SIZE + 1) + 1, 93 | CELL_SIZE, 94 | CELL_SIZE 95 | ); 96 | } 97 | } 98 | 99 | ctx.stroke(); 100 | }; 101 | 102 | let joystick = Joystick.Neutral; 103 | 104 | const setJoystick = (value) => { 105 | if (joystick !== value) { 106 | joystick = value; 107 | game_screen.set_joystick(value); 108 | } 109 | } 110 | 111 | const keyDownHandler = (event) => { 112 | if (event.keyCode === 39) { // right 113 | setJoystick(Joystick.Right); 114 | } else if (event.keyCode === 37) { // left 115 | setJoystick(Joystick.Left); 116 | } else if (event.keyCode === 32 && !game_started) { // space 117 | game_started = true; 118 | setJoystick(Joystick.Neutral); 119 | requestAnimationFrame(renderLoop); 120 | } else if (event.keyCode === 32 && game_over) { 121 | game_screen = Screen.new(); 122 | game_started = false; 123 | game_over = false; 124 | 125 | game_over = game_screen.run(); 126 | 127 | drawGrid(); 128 | drawCells(); 129 | game_status.textContent = "Press space to start"; 130 | 131 | } else { 132 | setJoystick(Joystick.Neutral); 133 | } 134 | }; 135 | 136 | const keyUpHandler = (event) => { 137 | setJoystick(Joystick.Neutral); 138 | }; 139 | 140 | document.addEventListener('keydown', keyDownHandler, false); 141 | document.addEventListener('keyup', keyUpHandler, false); 142 | 143 | drawGrid(); 144 | drawCells(); 145 | 146 | game_over = game_screen.run(); 147 | 148 | drawGrid(); 149 | drawCells(); 150 | game_status.textContent = "Press space to start"; 151 | -------------------------------------------------------------------------------- /aoc-10-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let input = include_str!("../input"); 5 | let mut grid = Grid::new(input.trim(), (37, 25)); 6 | } 7 | 8 | #[derive(Debug)] 9 | struct Grid { 10 | width: usize, 11 | height: usize, 12 | asteroid_locations: HashMap<(usize, usize), f64>, 13 | laser_location: (usize, usize), 14 | } 15 | 16 | impl Grid { 17 | fn new(text: &str, laser_location: (usize, usize)) -> Grid { 18 | let mut width = 0; 19 | let mut height = 0; 20 | let mut asteroid_locations = HashMap::new(); 21 | 22 | for line in text.lines() { 23 | width = 0; 24 | 25 | for c in line.chars() { 26 | if c == '#' { 27 | asteroid_locations.insert((width, height), 0.0); 28 | } 29 | width += 1; 30 | } 31 | 32 | height += 1; 33 | } 34 | 35 | asteroid_locations.remove(&laser_location); 36 | 37 | Grid { 38 | width, 39 | height, 40 | asteroid_locations, 41 | laser_location, 42 | } 43 | } 44 | 45 | fn compute_angles(&mut self) { 46 | let locations: Vec<(usize, usize)> = self.asteroid_locations.keys().cloned().collect(); 47 | for to in locations { 48 | 49 | let x_diff = (to.0 as isize - self.laser_location.0 as isize) as f64; 50 | let y_diff = (to.1 as isize - self.laser_location.1 as isize) as f64; 51 | 52 | let angle = (y_diff / x_diff).atan(); 53 | self.asteroid_locations.insert(to, angle); 54 | } 55 | } 56 | 57 | fn asteroids_sorted_by_angle(&self) -> Vec<(usize, usize)> { 58 | let mut vec: Vec<_> = self.asteroid_locations.iter().collect(); 59 | vec.sort_by(|a, b| a.1.partial_cmp(b.1).unwrap()); 60 | vec.iter().map(|&(location, _)| location).copied().collect() 61 | } 62 | 63 | fn destroy_order(&mut self) -> Vec<(usize, usize)> { 64 | let mut destroy_order = vec![]; 65 | 66 | while !self.asteroid_locations.is_empty() { 67 | let candidates = self.asteroids_sorted_by_angle(); 68 | for asteroid in candidates { 69 | if self.can_see(self.laser_location, asteroid) { 70 | destroy_order.push(asteroid); 71 | } 72 | } 73 | 74 | for destroyed in &destroy_order { 75 | self.asteroid_locations.remove(&destroyed); 76 | } 77 | } 78 | 79 | destroy_order 80 | } 81 | 82 | fn can_see(&self, from: (usize, usize), to: (usize, usize)) -> bool { 83 | if from == to { 84 | false 85 | } else { 86 | let angle = reduced_angle(from, to); 87 | 88 | let mut check_x = from.0 as isize + angle.0; 89 | let mut check_y = from.1 as isize + angle.1; 90 | 91 | while !(check_x == to.0 as isize && check_y == to.1 as isize) { 92 | if check_x < 0 || check_y < 0 { 93 | panic!( 94 | "something when terribly wrong, tried to check ({}, {})", 95 | check_x, check_y 96 | ); 97 | } 98 | if self 99 | .asteroid_locations 100 | .contains_key(&(check_x as usize, check_y as usize)) 101 | { 102 | return false; 103 | } 104 | check_x += angle.0; 105 | check_y += angle.1; 106 | } 107 | 108 | true 109 | } 110 | } 111 | } 112 | 113 | #[cfg(test)] 114 | mod tests { 115 | use super::*; 116 | 117 | #[test] 118 | fn example() { 119 | let input = "\ 120 | .#....#####...#.. 121 | ##...##.#####..## 122 | ##...#...#.#####. 123 | ..#.....#...###.. 124 | ..#.#.....#....##"; 125 | let mut grid = Grid::new(input, (8, 3)); 126 | grid.compute_angles(); 127 | 128 | // dbg!(grid.asteroids_sorted_by_angle()); 129 | // assert!(false); 130 | 131 | assert_eq!(grid.destroy_order(), vec![ 132 | (8, 1), (9, 0), (9, 1), (10, 0), (9, 2), (11, 1), (12, 1), (11, 2), (15, 1), 133 | (12, 2), (13, 2), (14, 2), (15, 2), (12, 3), (16, 4), (15, 4), (10, 4), (4, 4), 134 | (2, 4), (2, 3), (0, 2), (1, 2), (0, 1), (1, 1), (5, 2), (1, 0), (5, 1), 135 | (6, 1), (6, 0), (7, 0), (8, 0), (10, 1), (14, 0), (16, 1), (13, 3), (14, 3) 136 | ]); 137 | } 138 | 139 | #[test] 140 | fn greatest_common_factor() { 141 | assert_eq!(gcf(48, 18), 6); 142 | assert_eq!(gcf(18, 48), 6); 143 | assert_eq!(gcf(2, 0), 2); 144 | assert_eq!(gcf(0, 2), 2); 145 | assert_eq!(gcf(2, 3), 1); 146 | assert_eq!(gcf(3, 2), 1); 147 | assert_eq!(gcf(-10, 5), 5); 148 | assert_eq!(gcf(10, -5), 5); 149 | } 150 | 151 | #[test] 152 | fn reduced_angle_works() { 153 | assert_eq!(reduced_angle((0, 0), (1, 0)), (1, 0)); 154 | assert_eq!(reduced_angle((0, 0), (2, 0)), (1, 0)); 155 | 156 | assert_eq!(reduced_angle((1, 0), (0, 0)), (-1, 0)); 157 | assert_eq!(reduced_angle((2, 0), (0, 0)), (-1, 0)); 158 | 159 | assert_eq!(reduced_angle((1, 1), (3, 3)), (1, 1)); 160 | assert_eq!(reduced_angle((3, 3), (1, 1)), (-1, -1)); 161 | 162 | assert_eq!(reduced_angle((0, 0), (48, 18)), (8, 3)); 163 | 164 | assert_eq!(reduced_angle((0, 0), (2, 3)), (2, 3)); 165 | } 166 | } 167 | 168 | fn reduced_angle(from: (usize, usize), to: (usize, usize)) -> (isize, isize) { 169 | let from = (from.0 as isize, from.1 as isize); 170 | let to = (to.0 as isize, to.1 as isize); 171 | 172 | let x_diff = to.0 - from.0; 173 | let y_diff = to.1 - from.1; 174 | 175 | let gcf = gcf(x_diff, y_diff); 176 | 177 | (x_diff / gcf, y_diff / gcf) 178 | } 179 | 180 | fn gcf(a: isize, b: isize) -> isize { 181 | if b == 0 { 182 | a.abs() 183 | } else { 184 | gcf(b, a % b) 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aoc-13-02" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "wasm-bindgen 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 8 | ] 9 | 10 | [[package]] 11 | name = "bumpalo" 12 | version = "2.6.0" 13 | source = "registry+https://github.com/rust-lang/crates.io-index" 14 | 15 | [[package]] 16 | name = "cfg-if" 17 | version = "0.1.10" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | 20 | [[package]] 21 | name = "lazy_static" 22 | version = "1.4.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | 25 | [[package]] 26 | name = "log" 27 | version = "0.4.8" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | dependencies = [ 30 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 31 | ] 32 | 33 | [[package]] 34 | name = "proc-macro2" 35 | version = "1.0.6" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | dependencies = [ 38 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "quote" 43 | version = "1.0.2" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | dependencies = [ 46 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 47 | ] 48 | 49 | [[package]] 50 | name = "syn" 51 | version = "1.0.11" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | dependencies = [ 54 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 57 | ] 58 | 59 | [[package]] 60 | name = "unicode-xid" 61 | version = "0.2.0" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | 64 | [[package]] 65 | name = "wasm-bindgen" 66 | version = "0.2.56" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | dependencies = [ 69 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "wasm-bindgen-macro 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 71 | ] 72 | 73 | [[package]] 74 | name = "wasm-bindgen-backend" 75 | version = "0.2.56" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | dependencies = [ 78 | "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 79 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 80 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 81 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 82 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 83 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "wasm-bindgen-shared 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 85 | ] 86 | 87 | [[package]] 88 | name = "wasm-bindgen-macro" 89 | version = "0.2.56" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | dependencies = [ 92 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "wasm-bindgen-macro-support 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 94 | ] 95 | 96 | [[package]] 97 | name = "wasm-bindgen-macro-support" 98 | version = "0.2.56" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | dependencies = [ 101 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "wasm-bindgen-backend 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "wasm-bindgen-shared 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", 106 | ] 107 | 108 | [[package]] 109 | name = "wasm-bindgen-shared" 110 | version = "0.2.56" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | 113 | [metadata] 114 | "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" 115 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 116 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 117 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 118 | "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 119 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 120 | "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" 121 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 122 | "checksum wasm-bindgen 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)" = "99de4b68939a880d530aed51289a7c7baee154e3ea8ac234b542c49da7134aaf" 123 | "checksum wasm-bindgen-backend 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)" = "b58e66a093a7b7571cb76409763c495b8741ac4319ac20acc2b798f6766d92ee" 124 | "checksum wasm-bindgen-macro 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)" = "a80f89daea7b0a67b11f6e9f911422ed039de9963dce00048a653b63d51194bf" 125 | "checksum wasm-bindgen-macro-support 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)" = "4f9dbc3734ad6cff6b76b75b7df98c06982becd0055f651465a08f769bca5c61" 126 | "checksum wasm-bindgen-shared 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)" = "d907984f8506b3554eab48b8efff723e764ddbf76d4cd4a3fe4196bc00c49a70" 127 | -------------------------------------------------------------------------------- /aoc-13-01/input: -------------------------------------------------------------------------------- 1 | 1,380,379,385,1008,2367,810138,381,1005,381,12,99,109,2368,1101,0,0,383,1102,0,1,382,21001,382,0,1,20101,0,383,2,21102,37,1,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,36,381,1005,381,22,1001,383,1,383,1007,383,24,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1102,1,-1,384,1106,0,119,1007,392,34,381,1006,381,161,1101,0,1,384,20101,0,392,1,21101,22,0,2,21101,0,0,3,21101,0,138,0,1105,1,549,1,392,384,392,21001,392,0,1,21102,22,1,2,21101,3,0,3,21101,161,0,0,1106,0,549,1101,0,0,384,20001,388,390,1,21001,389,0,2,21102,1,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,0,205,0,1106,0,393,1002,390,-1,390,1101,0,1,384,21002,388,1,1,20001,389,391,2,21102,228,1,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,21002,388,1,1,20001,389,391,2,21101,0,253,0,1105,1,393,1002,391,-1,391,1102,1,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21102,279,1,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,1,0,384,1005,384,161,21002,388,1,1,20102,1,389,2,21102,1,0,3,21102,1,338,0,1105,1,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21101,4,0,3,21101,365,0,0,1105,1,549,1007,389,23,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,213,16,19,1,1,18,109,3,21202,-2,1,1,22102,1,-1,2,21101,0,0,3,21102,1,414,0,1105,1,549,21201,-2,0,1,21201,-1,0,2,21101,429,0,0,1106,0,601,2101,0,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,21201,-3,0,-7,109,-8,2106,0,0,109,4,1202,-2,36,566,201,-3,566,566,101,639,566,566,1202,-1,1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,36,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2105,1,0,109,3,22102,24,-2,1,22201,1,-1,1,21102,1,439,2,21102,1,233,3,21102,1,864,4,21101,0,630,0,1106,0,456,21201,1,1503,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,0,0,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2,2,0,2,0,2,0,0,0,0,0,0,0,1,1,0,0,2,2,0,0,0,2,2,2,0,0,0,2,0,2,2,0,0,0,0,2,2,2,0,0,0,2,2,0,0,0,2,0,1,1,0,0,0,2,2,2,2,2,0,0,2,0,2,0,2,0,2,0,2,0,0,0,0,2,2,0,0,2,0,2,2,2,2,0,1,1,0,0,2,0,2,0,0,2,0,2,0,0,0,2,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,2,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,0,2,0,0,0,2,2,2,0,0,0,0,0,2,0,2,0,0,0,2,0,2,2,2,0,0,2,0,2,0,0,0,0,1,1,0,2,0,0,0,2,0,2,2,0,0,0,0,2,2,0,2,0,0,2,2,0,0,0,0,0,2,0,2,2,0,0,0,0,1,1,0,2,2,2,0,2,0,0,2,0,2,0,0,0,2,2,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,0,2,0,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0,2,2,0,2,0,0,0,2,2,0,0,0,0,0,2,0,0,2,2,2,0,1,1,0,2,2,0,2,0,2,2,0,2,2,2,0,2,0,0,2,2,0,0,2,2,0,2,0,0,0,0,0,2,0,0,0,0,1,1,0,0,2,0,0,2,2,0,2,2,0,2,2,0,2,2,0,0,2,0,0,0,0,0,2,2,0,0,0,2,2,0,0,0,1,1,0,0,2,2,0,2,0,2,2,0,2,2,0,0,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,0,0,2,0,0,1,1,0,2,2,2,0,0,2,0,0,0,2,0,0,2,0,2,0,0,2,2,0,0,0,2,0,2,2,2,0,0,0,0,2,0,1,1,0,0,0,2,2,0,2,0,0,2,0,0,0,2,2,2,0,0,0,2,2,0,0,2,0,0,0,0,2,0,0,0,0,0,1,1,0,0,2,2,2,0,0,2,0,0,0,0,0,2,0,2,2,2,2,0,0,0,2,0,0,2,0,2,0,2,0,2,2,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,2,0,2,2,0,0,2,0,2,2,0,2,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,6,16,92,72,80,96,26,54,61,9,5,36,81,14,76,83,59,88,74,16,69,57,76,35,51,42,88,8,89,80,10,96,1,1,18,93,46,94,5,40,63,18,90,31,7,8,46,96,13,53,21,13,66,64,67,26,11,77,23,46,8,20,97,24,26,9,11,65,36,71,13,35,18,81,66,40,88,89,56,9,24,8,78,16,44,20,57,1,69,13,71,77,37,68,31,18,32,60,37,70,8,3,46,41,18,50,78,87,4,94,91,82,96,76,15,73,47,85,6,8,92,7,46,72,68,90,22,78,6,66,1,26,98,85,80,66,95,39,62,81,52,35,98,71,58,8,55,16,93,75,77,47,36,41,91,39,20,97,13,5,31,67,91,96,10,75,7,95,59,43,90,94,25,89,21,66,98,11,2,49,67,25,96,91,72,51,41,47,1,76,30,55,20,5,97,61,73,43,79,13,16,81,1,27,11,96,47,89,48,26,25,34,37,64,13,53,69,41,30,39,93,80,34,75,41,30,42,42,49,68,49,37,40,62,93,77,86,49,72,52,5,78,31,86,86,62,60,56,17,19,80,2,39,49,50,85,63,48,61,95,82,21,18,85,16,86,45,75,28,97,33,21,56,96,40,33,95,69,53,75,47,70,51,80,92,4,54,79,59,42,15,30,86,27,86,63,64,36,27,98,49,58,78,5,16,57,61,32,14,25,51,75,96,93,25,87,20,76,32,96,96,39,84,48,62,82,11,36,1,11,44,71,86,58,4,74,35,3,31,3,27,52,78,96,10,43,16,93,93,61,23,54,90,47,81,70,81,26,89,17,63,60,48,29,77,53,80,80,12,79,80,76,37,80,79,54,17,73,68,15,40,64,81,5,62,74,27,42,72,93,2,21,46,29,76,51,61,13,19,21,96,45,38,47,87,47,67,95,82,56,51,32,1,73,59,83,65,33,92,8,94,14,45,60,20,87,82,1,29,9,15,10,76,90,27,80,30,65,9,79,2,97,41,75,8,68,23,37,19,80,22,15,52,93,79,79,23,61,37,5,88,28,5,44,31,36,20,37,71,45,21,25,16,2,79,28,67,19,47,9,19,64,46,8,88,29,75,65,22,64,32,78,20,88,48,72,90,84,50,59,63,20,86,58,50,97,14,61,10,68,45,81,43,27,95,95,80,91,68,17,83,55,49,41,9,33,51,19,60,54,24,43,68,36,60,5,20,97,14,55,70,35,27,96,80,32,3,63,52,70,31,2,58,3,70,54,35,83,87,83,50,14,97,47,38,44,71,52,3,97,83,24,36,11,45,5,87,21,80,88,98,45,42,37,96,28,42,72,47,39,58,78,23,24,50,78,1,87,81,32,49,21,60,28,33,29,5,38,36,8,59,52,66,67,15,95,87,61,67,80,54,58,36,89,72,96,78,32,58,37,39,76,43,69,20,96,26,71,98,50,36,46,18,68,24,50,43,32,95,70,18,18,66,84,18,13,44,44,6,4,42,37,31,88,18,82,29,41,88,12,96,58,61,72,72,79,80,60,48,15,26,24,29,45,7,36,2,16,31,13,60,13,84,53,4,5,94,52,39,8,14,6,30,70,75,46,13,38,57,24,24,69,51,87,96,65,57,57,14,10,27,97,98,18,4,92,47,6,17,66,93,3,82,83,56,75,82,75,92,35,68,1,43,51,24,13,57,33,87,62,92,38,61,90,1,95,45,4,70,63,34,43,67,5,91,75,23,55,27,70,52,16,78,87,46,2,56,89,88,58,23,95,31,98,96,22,11,61,29,55,77,50,55,96,64,33,14,51,25,47,48,3,15,2,18,63,12,56,47,88,74,32,87,21,74,53,37,93,21,37,9,42,16,39,57,57,59,57,96,88,17,14,5,85,18,40,54,47,80,22,35,84,10,43,91,10,82,85,52,70,69,64,44,93,77,72,80,39,86,20,44,48,24,72,810138 2 | -------------------------------------------------------------------------------- /aoc-13-02/input: -------------------------------------------------------------------------------- 1 | 2,380,379,385,1008,2367,810138,381,1005,381,12,99,109,2368,1101,0,0,383,1102,0,1,382,21001,382,0,1,20101,0,383,2,21102,37,1,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,36,381,1005,381,22,1001,383,1,383,1007,383,24,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1102,1,-1,384,1106,0,119,1007,392,34,381,1006,381,161,1101,0,1,384,20101,0,392,1,21101,22,0,2,21101,0,0,3,21101,0,138,0,1105,1,549,1,392,384,392,21001,392,0,1,21102,22,1,2,21101,3,0,3,21101,161,0,0,1106,0,549,1101,0,0,384,20001,388,390,1,21001,389,0,2,21102,1,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,0,205,0,1106,0,393,1002,390,-1,390,1101,0,1,384,21002,388,1,1,20001,389,391,2,21102,228,1,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,21002,388,1,1,20001,389,391,2,21101,0,253,0,1105,1,393,1002,391,-1,391,1102,1,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21102,279,1,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,1,0,384,1005,384,161,21002,388,1,1,20102,1,389,2,21102,1,0,3,21102,1,338,0,1105,1,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21101,4,0,3,21101,365,0,0,1105,1,549,1007,389,23,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,213,16,19,1,1,18,109,3,21202,-2,1,1,22102,1,-1,2,21101,0,0,3,21102,1,414,0,1105,1,549,21201,-2,0,1,21201,-1,0,2,21101,429,0,0,1106,0,601,2101,0,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,21201,-3,0,-7,109,-8,2106,0,0,109,4,1202,-2,36,566,201,-3,566,566,101,639,566,566,1202,-1,1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,36,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2105,1,0,109,3,22102,24,-2,1,22201,1,-1,1,21102,1,439,2,21102,1,233,3,21102,1,864,4,21101,0,630,0,1106,0,456,21201,1,1503,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,0,0,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2,2,0,2,0,2,0,0,0,0,0,0,0,1,1,0,0,2,2,0,0,0,2,2,2,0,0,0,2,0,2,2,0,0,0,0,2,2,2,0,0,0,2,2,0,0,0,2,0,1,1,0,0,0,2,2,2,2,2,0,0,2,0,2,0,2,0,2,0,2,0,0,0,0,2,2,0,0,2,0,2,2,2,2,0,1,1,0,0,2,0,2,0,0,2,0,2,0,0,0,2,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,2,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,0,2,0,0,0,2,2,2,0,0,0,0,0,2,0,2,0,0,0,2,0,2,2,2,0,0,2,0,2,0,0,0,0,1,1,0,2,0,0,0,2,0,2,2,0,0,0,0,2,2,0,2,0,0,2,2,0,0,0,0,0,2,0,2,2,0,0,0,0,1,1,0,2,2,2,0,2,0,0,2,0,2,0,0,0,2,2,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,0,2,0,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0,2,2,0,2,0,0,0,2,2,0,0,0,0,0,2,0,0,2,2,2,0,1,1,0,2,2,0,2,0,2,2,0,2,2,2,0,2,0,0,2,2,0,0,2,2,0,2,0,0,0,0,0,2,0,0,0,0,1,1,0,0,2,0,0,2,2,0,2,2,0,2,2,0,2,2,0,0,2,0,0,0,0,0,2,2,0,0,0,2,2,0,0,0,1,1,0,0,2,2,0,2,0,2,2,0,2,2,0,0,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,0,0,2,0,0,1,1,0,2,2,2,0,0,2,0,0,0,2,0,0,2,0,2,0,0,2,2,0,0,0,2,0,2,2,2,0,0,0,0,2,0,1,1,0,0,0,2,2,0,2,0,0,2,0,0,0,2,2,2,0,0,0,2,2,0,0,2,0,0,0,0,2,0,0,0,0,0,1,1,0,0,2,2,2,0,0,2,0,0,0,0,0,2,0,2,2,2,2,0,0,0,2,0,0,2,0,2,0,2,0,2,2,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,2,0,2,2,0,0,2,0,2,2,0,2,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,6,16,92,72,80,96,26,54,61,9,5,36,81,14,76,83,59,88,74,16,69,57,76,35,51,42,88,8,89,80,10,96,1,1,18,93,46,94,5,40,63,18,90,31,7,8,46,96,13,53,21,13,66,64,67,26,11,77,23,46,8,20,97,24,26,9,11,65,36,71,13,35,18,81,66,40,88,89,56,9,24,8,78,16,44,20,57,1,69,13,71,77,37,68,31,18,32,60,37,70,8,3,46,41,18,50,78,87,4,94,91,82,96,76,15,73,47,85,6,8,92,7,46,72,68,90,22,78,6,66,1,26,98,85,80,66,95,39,62,81,52,35,98,71,58,8,55,16,93,75,77,47,36,41,91,39,20,97,13,5,31,67,91,96,10,75,7,95,59,43,90,94,25,89,21,66,98,11,2,49,67,25,96,91,72,51,41,47,1,76,30,55,20,5,97,61,73,43,79,13,16,81,1,27,11,96,47,89,48,26,25,34,37,64,13,53,69,41,30,39,93,80,34,75,41,30,42,42,49,68,49,37,40,62,93,77,86,49,72,52,5,78,31,86,86,62,60,56,17,19,80,2,39,49,50,85,63,48,61,95,82,21,18,85,16,86,45,75,28,97,33,21,56,96,40,33,95,69,53,75,47,70,51,80,92,4,54,79,59,42,15,30,86,27,86,63,64,36,27,98,49,58,78,5,16,57,61,32,14,25,51,75,96,93,25,87,20,76,32,96,96,39,84,48,62,82,11,36,1,11,44,71,86,58,4,74,35,3,31,3,27,52,78,96,10,43,16,93,93,61,23,54,90,47,81,70,81,26,89,17,63,60,48,29,77,53,80,80,12,79,80,76,37,80,79,54,17,73,68,15,40,64,81,5,62,74,27,42,72,93,2,21,46,29,76,51,61,13,19,21,96,45,38,47,87,47,67,95,82,56,51,32,1,73,59,83,65,33,92,8,94,14,45,60,20,87,82,1,29,9,15,10,76,90,27,80,30,65,9,79,2,97,41,75,8,68,23,37,19,80,22,15,52,93,79,79,23,61,37,5,88,28,5,44,31,36,20,37,71,45,21,25,16,2,79,28,67,19,47,9,19,64,46,8,88,29,75,65,22,64,32,78,20,88,48,72,90,84,50,59,63,20,86,58,50,97,14,61,10,68,45,81,43,27,95,95,80,91,68,17,83,55,49,41,9,33,51,19,60,54,24,43,68,36,60,5,20,97,14,55,70,35,27,96,80,32,3,63,52,70,31,2,58,3,70,54,35,83,87,83,50,14,97,47,38,44,71,52,3,97,83,24,36,11,45,5,87,21,80,88,98,45,42,37,96,28,42,72,47,39,58,78,23,24,50,78,1,87,81,32,49,21,60,28,33,29,5,38,36,8,59,52,66,67,15,95,87,61,67,80,54,58,36,89,72,96,78,32,58,37,39,76,43,69,20,96,26,71,98,50,36,46,18,68,24,50,43,32,95,70,18,18,66,84,18,13,44,44,6,4,42,37,31,88,18,82,29,41,88,12,96,58,61,72,72,79,80,60,48,15,26,24,29,45,7,36,2,16,31,13,60,13,84,53,4,5,94,52,39,8,14,6,30,70,75,46,13,38,57,24,24,69,51,87,96,65,57,57,14,10,27,97,98,18,4,92,47,6,17,66,93,3,82,83,56,75,82,75,92,35,68,1,43,51,24,13,57,33,87,62,92,38,61,90,1,95,45,4,70,63,34,43,67,5,91,75,23,55,27,70,52,16,78,87,46,2,56,89,88,58,23,95,31,98,96,22,11,61,29,55,77,50,55,96,64,33,14,51,25,47,48,3,15,2,18,63,12,56,47,88,74,32,87,21,74,53,37,93,21,37,9,42,16,39,57,57,59,57,96,88,17,14,5,85,18,40,54,47,80,22,35,84,10,43,91,10,82,85,52,70,69,64,44,93,77,72,80,39,86,20,44,48,24,72,810138 2 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/input: -------------------------------------------------------------------------------- 1 | 2,380,379,385,1008,2367,810138,381,1005,381,12,99,109,2368,1101,0,0,383,1102,0,1,382,21001,382,0,1,20101,0,383,2,21102,37,1,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,36,381,1005,381,22,1001,383,1,383,1007,383,24,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1102,1,-1,384,1106,0,119,1007,392,34,381,1006,381,161,1101,0,1,384,20101,0,392,1,21101,22,0,2,21101,0,0,3,21101,0,138,0,1105,1,549,1,392,384,392,21001,392,0,1,21102,22,1,2,21101,3,0,3,21101,161,0,0,1106,0,549,1101,0,0,384,20001,388,390,1,21001,389,0,2,21102,1,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,0,205,0,1106,0,393,1002,390,-1,390,1101,0,1,384,21002,388,1,1,20001,389,391,2,21102,228,1,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,21002,388,1,1,20001,389,391,2,21101,0,253,0,1105,1,393,1002,391,-1,391,1102,1,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21102,279,1,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,1,0,384,1005,384,161,21002,388,1,1,20102,1,389,2,21102,1,0,3,21102,1,338,0,1105,1,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21101,4,0,3,21101,365,0,0,1105,1,549,1007,389,23,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,213,16,19,1,1,18,109,3,21202,-2,1,1,22102,1,-1,2,21101,0,0,3,21102,1,414,0,1105,1,549,21201,-2,0,1,21201,-1,0,2,21101,429,0,0,1106,0,601,2101,0,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,21201,-3,0,-7,109,-8,2106,0,0,109,4,1202,-2,36,566,201,-3,566,566,101,639,566,566,1202,-1,1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,36,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2105,1,0,109,3,22102,24,-2,1,22201,1,-1,1,21102,1,439,2,21102,1,233,3,21102,1,864,4,21101,0,630,0,1106,0,456,21201,1,1503,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,0,0,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2,2,0,2,0,2,0,0,0,0,0,0,0,1,1,0,0,2,2,0,0,0,2,2,2,0,0,0,2,0,2,2,0,0,0,0,2,2,2,0,0,0,2,2,0,0,0,2,0,1,1,0,0,0,2,2,2,2,2,0,0,2,0,2,0,2,0,2,0,2,0,0,0,0,2,2,0,0,2,0,2,2,2,2,0,1,1,0,0,2,0,2,0,0,2,0,2,0,0,0,2,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,2,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,2,2,0,0,2,0,2,2,0,2,2,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,0,2,0,0,0,2,2,2,0,0,0,0,0,2,0,2,0,0,0,2,0,2,2,2,0,0,2,0,2,0,0,0,0,1,1,0,2,0,0,0,2,0,2,2,0,0,0,0,2,2,0,2,0,0,2,2,0,0,0,0,0,2,0,2,2,0,0,0,0,1,1,0,2,2,2,0,2,0,0,2,0,2,0,0,0,2,2,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,0,2,0,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0,2,2,0,2,0,0,0,2,2,0,0,0,0,0,2,0,0,2,2,2,0,1,1,0,2,2,0,2,0,2,2,0,2,2,2,0,2,0,0,2,2,0,0,2,2,0,2,0,0,0,0,0,2,0,0,0,0,1,1,0,0,2,0,0,2,2,0,2,2,0,2,2,0,2,2,0,0,2,0,0,0,0,0,2,2,0,0,0,2,2,0,0,0,1,1,0,0,2,2,0,2,0,2,2,0,2,2,0,0,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,0,0,2,0,0,1,1,0,2,2,2,0,0,2,0,0,0,2,0,0,2,0,2,0,0,2,2,0,0,0,2,0,2,2,2,0,0,0,0,2,0,1,1,0,0,0,2,2,0,2,0,0,2,0,0,0,2,2,2,0,0,0,2,2,0,0,2,0,0,0,0,2,0,0,0,0,0,1,1,0,0,2,2,2,0,0,2,0,0,0,0,0,2,0,2,2,2,2,0,0,0,2,0,0,2,0,2,0,2,0,2,2,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,2,0,2,2,0,0,2,0,2,2,0,2,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,6,16,92,72,80,96,26,54,61,9,5,36,81,14,76,83,59,88,74,16,69,57,76,35,51,42,88,8,89,80,10,96,1,1,18,93,46,94,5,40,63,18,90,31,7,8,46,96,13,53,21,13,66,64,67,26,11,77,23,46,8,20,97,24,26,9,11,65,36,71,13,35,18,81,66,40,88,89,56,9,24,8,78,16,44,20,57,1,69,13,71,77,37,68,31,18,32,60,37,70,8,3,46,41,18,50,78,87,4,94,91,82,96,76,15,73,47,85,6,8,92,7,46,72,68,90,22,78,6,66,1,26,98,85,80,66,95,39,62,81,52,35,98,71,58,8,55,16,93,75,77,47,36,41,91,39,20,97,13,5,31,67,91,96,10,75,7,95,59,43,90,94,25,89,21,66,98,11,2,49,67,25,96,91,72,51,41,47,1,76,30,55,20,5,97,61,73,43,79,13,16,81,1,27,11,96,47,89,48,26,25,34,37,64,13,53,69,41,30,39,93,80,34,75,41,30,42,42,49,68,49,37,40,62,93,77,86,49,72,52,5,78,31,86,86,62,60,56,17,19,80,2,39,49,50,85,63,48,61,95,82,21,18,85,16,86,45,75,28,97,33,21,56,96,40,33,95,69,53,75,47,70,51,80,92,4,54,79,59,42,15,30,86,27,86,63,64,36,27,98,49,58,78,5,16,57,61,32,14,25,51,75,96,93,25,87,20,76,32,96,96,39,84,48,62,82,11,36,1,11,44,71,86,58,4,74,35,3,31,3,27,52,78,96,10,43,16,93,93,61,23,54,90,47,81,70,81,26,89,17,63,60,48,29,77,53,80,80,12,79,80,76,37,80,79,54,17,73,68,15,40,64,81,5,62,74,27,42,72,93,2,21,46,29,76,51,61,13,19,21,96,45,38,47,87,47,67,95,82,56,51,32,1,73,59,83,65,33,92,8,94,14,45,60,20,87,82,1,29,9,15,10,76,90,27,80,30,65,9,79,2,97,41,75,8,68,23,37,19,80,22,15,52,93,79,79,23,61,37,5,88,28,5,44,31,36,20,37,71,45,21,25,16,2,79,28,67,19,47,9,19,64,46,8,88,29,75,65,22,64,32,78,20,88,48,72,90,84,50,59,63,20,86,58,50,97,14,61,10,68,45,81,43,27,95,95,80,91,68,17,83,55,49,41,9,33,51,19,60,54,24,43,68,36,60,5,20,97,14,55,70,35,27,96,80,32,3,63,52,70,31,2,58,3,70,54,35,83,87,83,50,14,97,47,38,44,71,52,3,97,83,24,36,11,45,5,87,21,80,88,98,45,42,37,96,28,42,72,47,39,58,78,23,24,50,78,1,87,81,32,49,21,60,28,33,29,5,38,36,8,59,52,66,67,15,95,87,61,67,80,54,58,36,89,72,96,78,32,58,37,39,76,43,69,20,96,26,71,98,50,36,46,18,68,24,50,43,32,95,70,18,18,66,84,18,13,44,44,6,4,42,37,31,88,18,82,29,41,88,12,96,58,61,72,72,79,80,60,48,15,26,24,29,45,7,36,2,16,31,13,60,13,84,53,4,5,94,52,39,8,14,6,30,70,75,46,13,38,57,24,24,69,51,87,96,65,57,57,14,10,27,97,98,18,4,92,47,6,17,66,93,3,82,83,56,75,82,75,92,35,68,1,43,51,24,13,57,33,87,62,92,38,61,90,1,95,45,4,70,63,34,43,67,5,91,75,23,55,27,70,52,16,78,87,46,2,56,89,88,58,23,95,31,98,96,22,11,61,29,55,77,50,55,96,64,33,14,51,25,47,48,3,15,2,18,63,12,56,47,88,74,32,87,21,74,53,37,93,21,37,9,42,16,39,57,57,59,57,96,88,17,14,5,85,18,40,54,47,80,22,35,84,10,43,91,10,82,85,52,70,69,64,44,93,77,72,80,39,86,20,44,48,24,72,810138 2 | -------------------------------------------------------------------------------- /aoc-10-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let input = include_str!("../input"); 5 | let mut grid = Grid::new(input.trim()); 6 | grid.get_seeing_counts(); 7 | println!("Best location is: {:?}", grid.best_location()); 8 | } 9 | 10 | struct Grid { 11 | width: usize, 12 | height: usize, 13 | asteroid_locations: HashMap<(usize, usize), usize>, 14 | } 15 | 16 | impl Grid { 17 | fn new(text: &str) -> Grid { 18 | let mut width = 0; 19 | let mut height = 0; 20 | let mut asteroid_locations = HashMap::new(); 21 | 22 | for line in text.lines() { 23 | width = 0; 24 | 25 | for c in line.chars() { 26 | if c == '#' { 27 | asteroid_locations.insert((width, height), 0); 28 | } 29 | width += 1; 30 | } 31 | 32 | height += 1; 33 | } 34 | 35 | Grid { 36 | width, 37 | height, 38 | asteroid_locations, 39 | } 40 | } 41 | 42 | fn get_seeing_counts(&mut self) { 43 | let locations: Vec<(usize, usize)> = self.asteroid_locations.keys().cloned().collect(); 44 | for from_location in locations { 45 | let mut count = 0; 46 | for &to_location in self.asteroid_locations.keys() { 47 | if self.can_see(from_location, to_location) { 48 | count += 1; 49 | } 50 | } 51 | self.asteroid_locations.insert(from_location, count); 52 | } 53 | } 54 | 55 | fn best_location(&self) -> (&(usize, usize), &usize) { 56 | self.asteroid_locations 57 | .iter() 58 | .max_by_key(|&(_k, v)| v) 59 | .expect("Must have some locations and one of them must be best") 60 | } 61 | 62 | fn can_see(&self, from: (usize, usize), to: (usize, usize)) -> bool { 63 | if from == to { 64 | false 65 | } else { 66 | let angle = reduced_angle(from, to); 67 | 68 | let mut check_x = from.0 as isize + angle.0; 69 | let mut check_y = from.1 as isize + angle.1; 70 | 71 | while !(check_x == to.0 as isize && check_y == to.1 as isize) { 72 | if check_x < 0 || check_y < 0 { 73 | panic!( 74 | "something when terribly wrong, tried to check ({}, {})", 75 | check_x, check_y 76 | ); 77 | } 78 | if self 79 | .asteroid_locations 80 | .contains_key(&(check_x as usize, check_y as usize)) 81 | { 82 | return false; 83 | } 84 | check_x += angle.0; 85 | check_y += angle.1; 86 | } 87 | 88 | true 89 | } 90 | } 91 | } 92 | 93 | #[cfg(test)] 94 | mod tests { 95 | use super::*; 96 | 97 | #[test] 98 | fn can_read_text_into_a_list_of_asteroids() { 99 | let text = "...\n..."; 100 | let grid = Grid::new(text); 101 | assert_eq!(grid.width, 3); 102 | assert_eq!(grid.height, 2); 103 | assert!(grid.asteroid_locations.is_empty()); 104 | 105 | let text = "#.\n..\n.#"; 106 | let grid = Grid::new(text); 107 | assert_eq!(grid.width, 2); 108 | assert_eq!(grid.height, 3); 109 | assert_eq!(grid.asteroid_locations.len(), 2); 110 | assert!(grid.asteroid_locations.contains_key(&(0, 0))); 111 | assert!(grid.asteroid_locations.contains_key(&(1, 2))); 112 | } 113 | 114 | #[test] 115 | fn cant_see_yourself() { 116 | let grid = Grid::new("#"); 117 | assert!(!grid.can_see((0, 0), (0, 0))); 118 | } 119 | 120 | #[test] 121 | fn can_see_horizontally() { 122 | let grid = Grid::new("##"); 123 | assert!(grid.can_see((0, 0), (1, 0))); 124 | } 125 | 126 | #[test] 127 | fn cant_see_with_asteroid_in_the_way() { 128 | let grid = Grid::new("###"); 129 | assert!(!grid.can_see((0, 0), (2, 0))); 130 | } 131 | 132 | #[test] 133 | fn example() { 134 | let map = ".#..#\n.....\n#####\n....#\n...##"; 135 | let mut grid = Grid::new(map); 136 | grid.get_seeing_counts(); 137 | assert_eq!(grid.asteroid_locations[&(3, 4)], 8); 138 | assert_eq!(grid.asteroid_locations[&(1, 0)], 7); 139 | assert_eq!(grid.asteroid_locations[&(4, 0)], 7); 140 | assert_eq!(grid.asteroid_locations[&(0, 2)], 6); 141 | assert_eq!(grid.asteroid_locations[&(1, 2)], 7); 142 | assert_eq!(grid.asteroid_locations[&(2, 2)], 7); 143 | assert_eq!(grid.asteroid_locations[&(3, 2)], 7); 144 | assert_eq!(grid.asteroid_locations[&(4, 2)], 5); 145 | assert_eq!(grid.asteroid_locations[&(4, 3)], 7); 146 | assert_eq!(grid.asteroid_locations[&(4, 4)], 7); 147 | assert_eq!(grid.best_location(), (&(3, 4), &8)); 148 | } 149 | 150 | #[test] 151 | fn greatest_common_factor() { 152 | assert_eq!(gcf(48, 18), 6); 153 | assert_eq!(gcf(18, 48), 6); 154 | assert_eq!(gcf(2, 0), 2); 155 | assert_eq!(gcf(0, 2), 2); 156 | assert_eq!(gcf(2, 3), 1); 157 | assert_eq!(gcf(3, 2), 1); 158 | assert_eq!(gcf(-10, 5), 5); 159 | assert_eq!(gcf(10, -5), 5); 160 | } 161 | 162 | #[test] 163 | fn reduced_angle_works() { 164 | assert_eq!(reduced_angle((0, 0), (1, 0)), (1, 0)); 165 | assert_eq!(reduced_angle((0, 0), (2, 0)), (1, 0)); 166 | 167 | assert_eq!(reduced_angle((1, 0), (0, 0)), (-1, 0)); 168 | assert_eq!(reduced_angle((2, 0), (0, 0)), (-1, 0)); 169 | 170 | assert_eq!(reduced_angle((1, 1), (3, 3)), (1, 1)); 171 | assert_eq!(reduced_angle((3, 3), (1, 1)), (-1, -1)); 172 | 173 | assert_eq!(reduced_angle((0, 0), (48, 18)), (8, 3)); 174 | 175 | assert_eq!(reduced_angle((0, 0), (2, 3)), (2, 3)); 176 | } 177 | } 178 | 179 | fn reduced_angle(from: (usize, usize), to: (usize, usize)) -> (isize, isize) { 180 | let from = (from.0 as isize, from.1 as isize); 181 | let to = (to.0 as isize, to.1 as isize); 182 | 183 | let x_diff = to.0 - from.0; 184 | let y_diff = to.1 - from.1; 185 | 186 | let gcf = gcf(x_diff, y_diff); 187 | 188 | (x_diff / gcf, y_diff / gcf) 189 | } 190 | 191 | fn gcf(a: isize, b: isize) -> isize { 192 | if b == 0 { 193 | a.abs() 194 | } else { 195 | gcf(b, a % b) 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /aoc-12-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | fn main() { 4 | let mut moons = parse_moons(include_str!("../input")); 5 | 6 | let mut time = 0; 7 | while time < 1000 { 8 | time = time_step(&mut moons, time); 9 | } 10 | 11 | let total = total_energy(&moons); 12 | 13 | println!("Total energy = {}", total); 14 | } 15 | 16 | #[derive(Clone, Debug, PartialEq)] 17 | struct Moon { 18 | x: i32, 19 | y: i32, 20 | z: i32, 21 | dx: i32, 22 | dy: i32, 23 | dz: i32, 24 | } 25 | 26 | impl Moon { 27 | fn new(x: i32, y: i32, z: i32) -> Moon { 28 | Moon { 29 | x, 30 | y, 31 | z, 32 | dx: 0, 33 | dy: 0, 34 | dz: 0, 35 | } 36 | } 37 | 38 | fn parse(text: &str) -> Moon { 39 | // 40 | 41 | let mut chars = text.chars().skip_while(|&c| c != '='); 42 | chars.next(); // discard the = 43 | 44 | let mut x_digits = vec![]; 45 | let mut current_digit = chars.next().expect("Should have been some x digits"); 46 | while current_digit != ',' { 47 | x_digits.push(current_digit); 48 | current_digit = chars 49 | .next() 50 | .expect("Should have been either more x digits or a comma"); 51 | } 52 | let x_string: String = x_digits.iter().collect(); 53 | let x: i32 = x_string 54 | .parse() 55 | .expect("Should have been able to parse x_string"); 56 | 57 | let mut chars = chars.skip_while(|&c| c != '='); 58 | chars.next(); // discard the = 59 | 60 | let mut y_digits = vec![]; 61 | let mut current_digit = chars.next().expect("Should have been some y digits"); 62 | while current_digit != ',' { 63 | y_digits.push(current_digit); 64 | current_digit = chars 65 | .next() 66 | .expect("Should have been either more y digits or a comma"); 67 | } 68 | let y_string: String = y_digits.iter().collect(); 69 | let y: i32 = y_string 70 | .parse() 71 | .expect("Should have been able to parse y_string"); 72 | 73 | let mut chars = chars.skip_while(|&c| c != '='); 74 | chars.next(); // discard the = 75 | 76 | let mut z_digits = vec![]; 77 | let mut current_digit = chars.next().expect("Should have been some z digits"); 78 | while current_digit != '>' { 79 | z_digits.push(current_digit); 80 | current_digit = chars 81 | .next() 82 | .expect("Should have been either more z digits or a >"); 83 | } 84 | let z_string: String = z_digits.iter().collect(); 85 | let z: i32 = z_string 86 | .parse() 87 | .expect("Should have been able to parse x_string"); 88 | 89 | Moon::new(x, y, z) 90 | } 91 | 92 | fn apply_gravity(&mut self, moons: &[Moon]) { 93 | for moon in moons { 94 | self.dx += gravity_adjustment(self.x, moon.x); 95 | self.dy += gravity_adjustment(self.y, moon.y); 96 | self.dz += gravity_adjustment(self.z, moon.z); 97 | } 98 | } 99 | 100 | fn apply_velocity(&mut self) { 101 | self.x += self.dx; 102 | self.y += self.dy; 103 | self.z += self.dz; 104 | } 105 | 106 | fn total_energy(&self) -> i32 { 107 | self.potential_energy() * self.kinetic_energy() 108 | } 109 | 110 | fn potential_energy(&self) -> i32 { 111 | self.x.abs() + self.y.abs() + self.z.abs() 112 | } 113 | 114 | fn kinetic_energy(&self) -> i32 { 115 | self.dx.abs() + self.dy.abs() + self.dz.abs() 116 | } 117 | } 118 | 119 | fn gravity_adjustment(current_coordinate: i32, other_coordinate: i32) -> i32 { 120 | match current_coordinate.cmp(&other_coordinate) { 121 | Ordering::Less => 1, 122 | Ordering::Greater => -1, 123 | Ordering::Equal => 0, 124 | } 125 | } 126 | 127 | fn time_step(moons: &mut [Moon], time: i32) -> i32 { 128 | let immutable_moons: Vec<_> = moons.iter().cloned().collect(); 129 | 130 | for moon in moons.iter_mut() { 131 | moon.apply_gravity(&immutable_moons); 132 | } 133 | 134 | for moon in moons.iter_mut() { 135 | moon.apply_velocity(); 136 | } 137 | 138 | time + 1 139 | } 140 | 141 | fn parse_moons(text: &str) -> Vec { 142 | text.trim() 143 | .lines() 144 | .map(|moon_text| Moon::parse(moon_text)) 145 | .collect() 146 | } 147 | 148 | fn total_energy(moons: &[Moon]) -> i32 { 149 | moons.iter().map(|moon| moon.total_energy()).sum() 150 | } 151 | 152 | #[cfg(test)] 153 | mod tests { 154 | use super::*; 155 | 156 | #[test] 157 | fn create_moons_from_text() { 158 | let moons = parse_moons( 159 | "\n\n\n\n", 160 | ); 161 | let expected_moons = vec![ 162 | Moon::new(-1, 0, 2), 163 | Moon::new(2, -10, -7), 164 | Moon::new(4, -8, 8), 165 | Moon::new(3, 5, -1), 166 | ]; 167 | 168 | assert_eq!(moons, expected_moons); 169 | } 170 | 171 | #[test] 172 | fn one_step() { 173 | let mut moons = parse_moons( 174 | "\n\n\n\n", 175 | ); 176 | let expected_moons = vec![ 177 | Moon { x: 2, y: -1, z: 1, dx: 3, dy: -1, dz: -1 }, 178 | Moon { x: 3, y: -7, z: -4, dx: 1, dy: 3, dz: 3 }, 179 | Moon { x: 1, y: -7, z: 5, dx: -3, dy: 1, dz: -3 }, 180 | Moon { x: 2, y: 2, z: 0, dx: -1, dy: -3, dz: 1 }, 181 | ]; 182 | 183 | time_step(&mut moons, 0); 184 | 185 | assert_eq!(moons, expected_moons); 186 | } 187 | 188 | #[test] 189 | fn ten_steps() { 190 | let mut moons = parse_moons( 191 | "\n\n\n\n", 192 | ); 193 | let expected_moons = vec![ 194 | Moon { x: 2, y: 1, z: -3, dx: -3, dy: -2, dz: 1 }, 195 | Moon { x: 1, y: -8, z: 0, dx: -1, dy: 1, dz: 3 }, 196 | Moon { x: 3, y: -6, z: 1, dx: 3, dy: 2, dz: -3 }, 197 | Moon { x: 2, y: 0, z: 4, dx: 1, dy: -1, dz: -1 }, 198 | ]; 199 | 200 | let mut time = 0; 201 | while time < 10 { 202 | time = time_step(&mut moons, time); 203 | } 204 | 205 | assert_eq!(moons, expected_moons); 206 | 207 | assert_eq!(moons[0].potential_energy(), 6); 208 | assert_eq!(moons[0].kinetic_energy(), 6); 209 | assert_eq!(moons[0].total_energy(), 36); 210 | 211 | assert_eq!(total_energy(&moons), 179); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /aoc-12-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | fn main() { 4 | let mut moons = parse_moons(include_str!("../input")); 5 | 6 | let mut time = 0; 7 | while time < 1000 { 8 | time = time_step(&mut moons, time); 9 | } 10 | 11 | let total = total_energy(&moons); 12 | 13 | println!("Total energy = {}", total); 14 | } 15 | 16 | #[derive(Clone, Debug, PartialEq)] 17 | struct Moon { 18 | x: i32, 19 | y: i32, 20 | z: i32, 21 | dx: i32, 22 | dy: i32, 23 | dz: i32, 24 | } 25 | 26 | impl Moon { 27 | fn new(x: i32, y: i32, z: i32) -> Moon { 28 | Moon { 29 | x, 30 | y, 31 | z, 32 | dx: 0, 33 | dy: 0, 34 | dz: 0, 35 | } 36 | } 37 | 38 | fn parse(text: &str) -> Moon { 39 | // 40 | 41 | let mut chars = text.chars().skip_while(|&c| c != '='); 42 | chars.next(); // discard the = 43 | 44 | let mut x_digits = vec![]; 45 | let mut current_digit = chars.next().expect("Should have been some x digits"); 46 | while current_digit != ',' { 47 | x_digits.push(current_digit); 48 | current_digit = chars 49 | .next() 50 | .expect("Should have been either more x digits or a comma"); 51 | } 52 | let x_string: String = x_digits.iter().collect(); 53 | let x: i32 = x_string 54 | .parse() 55 | .expect("Should have been able to parse x_string"); 56 | 57 | let mut chars = chars.skip_while(|&c| c != '='); 58 | chars.next(); // discard the = 59 | 60 | let mut y_digits = vec![]; 61 | let mut current_digit = chars.next().expect("Should have been some y digits"); 62 | while current_digit != ',' { 63 | y_digits.push(current_digit); 64 | current_digit = chars 65 | .next() 66 | .expect("Should have been either more y digits or a comma"); 67 | } 68 | let y_string: String = y_digits.iter().collect(); 69 | let y: i32 = y_string 70 | .parse() 71 | .expect("Should have been able to parse y_string"); 72 | 73 | let mut chars = chars.skip_while(|&c| c != '='); 74 | chars.next(); // discard the = 75 | 76 | let mut z_digits = vec![]; 77 | let mut current_digit = chars.next().expect("Should have been some z digits"); 78 | while current_digit != '>' { 79 | z_digits.push(current_digit); 80 | current_digit = chars 81 | .next() 82 | .expect("Should have been either more z digits or a >"); 83 | } 84 | let z_string: String = z_digits.iter().collect(); 85 | let z: i32 = z_string 86 | .parse() 87 | .expect("Should have been able to parse x_string"); 88 | 89 | Moon::new(x, y, z) 90 | } 91 | 92 | fn apply_gravity(&mut self, moons: &[Moon]) { 93 | for moon in moons { 94 | self.dx += gravity_adjustment(self.x, moon.x); 95 | self.dy += gravity_adjustment(self.y, moon.y); 96 | self.dz += gravity_adjustment(self.z, moon.z); 97 | } 98 | } 99 | 100 | fn apply_velocity(&mut self) { 101 | self.x += self.dx; 102 | self.y += self.dy; 103 | self.z += self.dz; 104 | } 105 | 106 | fn total_energy(&self) -> i32 { 107 | self.potential_energy() * self.kinetic_energy() 108 | } 109 | 110 | fn potential_energy(&self) -> i32 { 111 | self.x.abs() + self.y.abs() + self.z.abs() 112 | } 113 | 114 | fn kinetic_energy(&self) -> i32 { 115 | self.dx.abs() + self.dy.abs() + self.dz.abs() 116 | } 117 | } 118 | 119 | fn gravity_adjustment(current_coordinate: i32, other_coordinate: i32) -> i32 { 120 | match current_coordinate.cmp(&other_coordinate) { 121 | Ordering::Less => 1, 122 | Ordering::Greater => -1, 123 | Ordering::Equal => 0, 124 | } 125 | } 126 | 127 | fn time_step(moons: &mut [Moon], time: i32) -> i32 { 128 | let immutable_moons: Vec<_> = moons.iter().cloned().collect(); 129 | 130 | for moon in moons.iter_mut() { 131 | moon.apply_gravity(&immutable_moons); 132 | } 133 | 134 | for moon in moons.iter_mut() { 135 | moon.apply_velocity(); 136 | } 137 | 138 | time + 1 139 | } 140 | 141 | fn parse_moons(text: &str) -> Vec { 142 | text.trim() 143 | .lines() 144 | .map(|moon_text| Moon::parse(moon_text)) 145 | .collect() 146 | } 147 | 148 | fn total_energy(moons: &[Moon]) -> i32 { 149 | moons.iter().map(|moon| moon.total_energy()).sum() 150 | } 151 | 152 | #[cfg(test)] 153 | mod tests { 154 | use super::*; 155 | 156 | #[test] 157 | fn create_moons_from_text() { 158 | let moons = parse_moons( 159 | "\n\n\n\n", 160 | ); 161 | let expected_moons = vec![ 162 | Moon::new(-1, 0, 2), 163 | Moon::new(2, -10, -7), 164 | Moon::new(4, -8, 8), 165 | Moon::new(3, 5, -1), 166 | ]; 167 | 168 | assert_eq!(moons, expected_moons); 169 | } 170 | 171 | #[test] 172 | fn one_step() { 173 | let mut moons = parse_moons( 174 | "\n\n\n\n", 175 | ); 176 | let expected_moons = vec![ 177 | Moon { x: 2, y: -1, z: 1, dx: 3, dy: -1, dz: -1 }, 178 | Moon { x: 3, y: -7, z: -4, dx: 1, dy: 3, dz: 3 }, 179 | Moon { x: 1, y: -7, z: 5, dx: -3, dy: 1, dz: -3 }, 180 | Moon { x: 2, y: 2, z: 0, dx: -1, dy: -3, dz: 1 }, 181 | ]; 182 | 183 | time_step(&mut moons, 0); 184 | 185 | assert_eq!(moons, expected_moons); 186 | } 187 | 188 | #[test] 189 | fn ten_steps() { 190 | let mut moons = parse_moons( 191 | "\n\n\n\n", 192 | ); 193 | let expected_moons = vec![ 194 | Moon { x: 2, y: 1, z: -3, dx: -3, dy: -2, dz: 1 }, 195 | Moon { x: 1, y: -8, z: 0, dx: -1, dy: 1, dz: 3 }, 196 | Moon { x: 3, y: -6, z: 1, dx: 3, dy: 2, dz: -3 }, 197 | Moon { x: 2, y: 0, z: 4, dx: 1, dy: -1, dz: -1 }, 198 | ]; 199 | 200 | let mut time = 0; 201 | while time < 10 { 202 | time = time_step(&mut moons, time); 203 | } 204 | 205 | assert_eq!(moons, expected_moons); 206 | 207 | assert_eq!(moons[0].potential_energy(), 6); 208 | assert_eq!(moons[0].kinetic_energy(), 6); 209 | assert_eq!(moons[0].total_energy(), 36); 210 | 211 | assert_eq!(total_energy(&moons), 179); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /aoc-03-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::error::Error; 3 | use std::fs; 4 | 5 | fn main() -> Result<(), Box> { 6 | let input = fs::read_to_string("input")?; 7 | let mut lines = input.lines(); 8 | 9 | let w1 = lines 10 | .next() 11 | .expect("Should have been at least 1 line in the input"); 12 | let w2 = lines 13 | .next() 14 | .expect("Should have been at least 2 lines in the input"); 15 | 16 | let closest_crossed_wires = closest_crossed_wires(&w1, &w2); 17 | 18 | println!( 19 | "Distance to the closest crossed wires is {}", 20 | closest_crossed_wires 21 | ); 22 | 23 | Ok(()) 24 | } 25 | 26 | // ## Assumptions/thoughts 27 | // 28 | // - The central port is at (0, 0) 29 | // - Right and Up amounts can be represented by positive numbers 30 | // - Left and Down amounts can be represented by negative numbers 31 | // - Right and Left are in the X direction 32 | // - Up and Down are in the Y direction 33 | // 34 | // ## Plan 35 | // 36 | // - Write code to parse "R2,D5" strings into a more convenient data structure 37 | // - Write code that can turn paths into a list of points that each wire touches 38 | // - Find the points that both wires have in their list of points 39 | // - The Manhattan distance of any point to (0, 0) is x + y 40 | // - Sort the intersection points by Manhattan distance and take the min 41 | 42 | #[derive(Debug, PartialEq)] 43 | enum PathPart { 44 | X(i32), 45 | Y(i32), 46 | } 47 | use PathPart::{X, Y}; 48 | 49 | fn locations_from_path(path: Vec) -> HashSet<(i32, i32)> { 50 | let mut current_location = (0, 0); 51 | let mut locations = HashSet::new(); 52 | 53 | for part in path { 54 | match part { 55 | X(x) => { 56 | let (range, amount) = if x > 0 { (0..x, 1) } else { (x..0, -1) }; 57 | 58 | for _ in range { 59 | current_location = (current_location.0 + amount, current_location.1); 60 | locations.insert(current_location); 61 | } 62 | } 63 | Y(y) => { 64 | let (range, amount) = if y > 0 { (0..y, 1) } else { (y..0, -1) }; 65 | 66 | for _ in range { 67 | current_location = (current_location.0, current_location.1 + amount); 68 | locations.insert(current_location); 69 | } 70 | } 71 | } 72 | } 73 | 74 | locations 75 | } 76 | 77 | fn min_manhattan_distance(points: &HashSet<(i32, i32)>) -> i32 { 78 | points 79 | .iter() 80 | .map(|point| point.0.abs() + point.1.abs()) 81 | .min() 82 | .expect("List should have had items in it") 83 | } 84 | 85 | fn parse_path(path_str: &str) -> Vec { 86 | path_str 87 | .split(",") 88 | .map(|segment| { 89 | let mut chars = segment.chars(); 90 | let direction = chars.next().expect(&format!( 91 | "Segment should have had a direction char: [{}]", 92 | segment 93 | )); 94 | let magnitude: i32 = chars.collect::().parse().expect(&format!( 95 | "Segment after direction char should have parsed as an i32: [{}]", 96 | segment 97 | )); 98 | 99 | match direction { 100 | 'R' => X(magnitude), 101 | 'L' => X(-magnitude), 102 | 'U' => Y(magnitude), 103 | 'D' => Y(-magnitude), 104 | _ => panic!("Unknown direction: [{}]", direction), 105 | } 106 | }) 107 | .collect() 108 | } 109 | 110 | fn closest_crossed_wires(path_str1: &str, path_str2: &str) -> i32 { 111 | let path1 = parse_path(path_str1); 112 | let path2 = parse_path(path_str2); 113 | 114 | let locations1 = locations_from_path(path1); 115 | let locations2 = locations_from_path(path2); 116 | 117 | let intersections: HashSet<_> = locations1.intersection(&locations2).cloned().collect(); 118 | 119 | min_manhattan_distance(&intersections) 120 | } 121 | 122 | #[cfg(test)] 123 | mod tests { 124 | use super::*; 125 | 126 | #[test] 127 | fn right() { 128 | let path = vec![X(1)]; 129 | let locations = locations_from_path(path); 130 | let expected: HashSet<_> = [(1, 0)].iter().cloned().collect(); 131 | assert_eq!(locations, expected); 132 | } 133 | 134 | #[test] 135 | fn left() { 136 | let path = vec![X(-1)]; 137 | let locations = locations_from_path(path); 138 | let expected: HashSet<_> = [(-1, 0)].iter().cloned().collect(); 139 | assert_eq!(locations, expected); 140 | } 141 | 142 | #[test] 143 | fn up() { 144 | let path = vec![Y(1)]; 145 | let locations = locations_from_path(path); 146 | let expected: HashSet<_> = [(0, 1)].iter().cloned().collect(); 147 | assert_eq!(locations, expected); 148 | } 149 | 150 | #[test] 151 | fn down() { 152 | let path = vec![Y(-1)]; 153 | let locations = locations_from_path(path); 154 | let expected: HashSet<_> = [(0, -1)].iter().cloned().collect(); 155 | assert_eq!(locations, expected); 156 | } 157 | 158 | #[test] 159 | fn example_from_problem_description() { 160 | let wire1_path_string = "R8,U5,L5,D3"; 161 | let wire2_path_string = "U7,R6,D4,L4"; 162 | 163 | let wire1_path = parse_path(wire1_path_string); 164 | assert_eq!(wire1_path, vec![X(8), Y(5), X(-5), Y(-3)]); 165 | 166 | let wire2_path = parse_path(wire2_path_string); 167 | assert_eq!(wire2_path, vec![Y(7), X(6), Y(-4), X(-4)]); 168 | 169 | let wire1_locations = locations_from_path(wire1_path); 170 | let wire2_locations = locations_from_path(wire2_path); 171 | 172 | let intersections: HashSet<_> = wire1_locations 173 | .intersection(&wire2_locations) 174 | .cloned() 175 | .collect(); 176 | let expected: HashSet<_> = [(3, 3), (6, 5)].iter().cloned().collect(); 177 | assert_eq!(intersections, expected); 178 | 179 | assert_eq!(min_manhattan_distance(&intersections), 6); 180 | } 181 | 182 | #[test] 183 | fn example_from_problem_description_all_at_once() { 184 | let wire1_path_string = "R8,U5,L5,D3"; 185 | let wire2_path_string = "U7,R6,D4,L4"; 186 | 187 | let closest_crossed_wires = closest_crossed_wires(wire1_path_string, wire2_path_string); 188 | assert_eq!(closest_crossed_wires, 6); 189 | } 190 | 191 | #[test] 192 | fn other_examples_from_problem_description() { 193 | let w1 = "R75,D30,R83,U83,L12,D49,R71,U7,L72"; 194 | let w2 = "U62,R66,U55,R34,D71,R55,D58,R83"; 195 | 196 | let closest = closest_crossed_wires(w1, w2); 197 | assert_eq!(closest, 159); 198 | 199 | let w1 = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51"; 200 | let w2 = "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7"; 201 | 202 | let closest = closest_crossed_wires(w1, w2); 203 | assert_eq!(closest, 135); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /aoc-05-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fs; 3 | 4 | fn main() -> Result<(), Box> { 5 | let program_input = fs::read_to_string("input")?; 6 | let program: Vec<_> = program_input 7 | .trim() 8 | .split(",") 9 | .map(|n| n.parse().expect("input should have been a number")) 10 | .collect(); 11 | 12 | let simulated_stdin = Some(1); 13 | let (_answer, output) = run_intcode(program, simulated_stdin); 14 | println!("{:?}", output); 15 | 16 | Ok(()) 17 | } 18 | 19 | fn run_intcode(mut program: Vec, input: Option) -> (Vec, Vec) { 20 | let mut current_position = 0; 21 | let mut current_inst = instruction(program[current_position]); 22 | let mut output = vec![]; 23 | 24 | while current_inst.opcode != 99 { 25 | match current_inst.opcode { 26 | 1 => { 27 | let output_position = program[current_position + 3] as usize; 28 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 29 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 30 | let answer = input1 + input2; 31 | program[output_position] = answer; 32 | current_position += 4; 33 | } 34 | 2 => { 35 | let output_position = program[current_position + 3] as usize; 36 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 37 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 38 | let answer = input1 * input2; 39 | program[output_position] = answer; 40 | current_position += 4; 41 | } 42 | 3 => { 43 | let output_position = program[current_position + 1] as usize; 44 | program[output_position] = input.expect("Should have had input for opcode 3"); 45 | current_position += 2; 46 | } 47 | 4 => { 48 | let printing_value = get_value(&program, current_position, ¤t_inst, 0); 49 | output.push(printing_value); 50 | current_position += 2; 51 | } 52 | other => panic!("Unknown opcode: {}", other), 53 | } 54 | current_inst = instruction(program[current_position]); 55 | } 56 | 57 | (program, output) 58 | } 59 | 60 | #[derive(Debug, PartialEq, Clone, Copy)] 61 | enum Mode { 62 | Position, 63 | Immediate, 64 | } 65 | 66 | #[derive(Debug, PartialEq)] 67 | struct Instruction { 68 | opcode: i32, 69 | modes: Vec, 70 | } 71 | 72 | impl Instruction { 73 | fn mode(&self, parameter: usize) -> Mode { 74 | self.modes.get(parameter).copied().unwrap_or(Mode::Position) 75 | } 76 | } 77 | 78 | fn instruction(mut full_opcode: i32) -> Instruction { 79 | let opcode = full_opcode % 100; 80 | full_opcode /= 100; 81 | 82 | let mut modes = vec![]; 83 | 84 | while full_opcode > 0 { 85 | let mode = match full_opcode % 10 { 86 | 0 => Mode::Position, 87 | 1 => Mode::Immediate, 88 | other => panic!("Unexpected parameter mode: {}", other), 89 | }; 90 | modes.push(mode); 91 | full_opcode /= 10; 92 | } 93 | 94 | Instruction { opcode, modes } 95 | } 96 | 97 | #[cfg(test)] 98 | mod tests { 99 | use super::*; 100 | 101 | #[test] 102 | fn opcode_99_ends() { 103 | let program = vec![99]; 104 | let (answer, _output) = run_intcode(program, None); 105 | assert_eq!(answer, vec![99]); 106 | } 107 | 108 | #[test] 109 | fn opcode_1_adds() { 110 | let program = vec![1, 0, 0, 0, 99]; 111 | let (answer, _output) = run_intcode(program, None); 112 | assert_eq!(answer, vec![2, 0, 0, 0, 99]); 113 | } 114 | 115 | #[test] 116 | fn opcode_2_multiplies() { 117 | let program = vec![2, 3, 0, 3, 99]; 118 | let (answer, _output) = run_intcode(program, None); 119 | assert_eq!(answer, vec![2, 3, 0, 6, 99]); 120 | } 121 | 122 | #[test] 123 | fn multiply_and_store_after_program() { 124 | let program = vec![2, 4, 4, 5, 99, 0]; 125 | let (answer, _output) = run_intcode(program, None); 126 | assert_eq!(answer, vec![2, 4, 4, 5, 99, 9801]); 127 | } 128 | 129 | #[test] 130 | fn program_keeps_going_if_an_instruction_changes() { 131 | let program = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; 132 | let (answer, _output) = run_intcode(program, None); 133 | assert_eq!(answer, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); 134 | } 135 | 136 | #[test] 137 | fn opcode_3_takes_input() { 138 | let program = vec![3, 0, 99]; 139 | let (answer, _output) = run_intcode(program, Some(7)); 140 | assert_eq!(answer, vec![7, 0, 99]); 141 | } 142 | 143 | #[test] 144 | fn opcode_4_returns_output() { 145 | let program = vec![4, 2, 99]; 146 | let (_answer, output) = run_intcode(program, None); 147 | assert_eq!(output, vec![99]); 148 | } 149 | 150 | #[test] 151 | #[should_panic(expected = "Unknown opcode: 42")] 152 | fn unknown_opcode_panics() { 153 | let program = vec![42]; 154 | run_intcode(program, None); 155 | } 156 | 157 | #[test] 158 | fn interpret_parameter_modes_all_position_mode() { 159 | let inst = instruction(2); 160 | assert_eq!(inst.opcode, 2); 161 | assert_eq!(inst.mode(0), Mode::Position); 162 | assert_eq!(inst.mode(1), Mode::Position); 163 | assert_eq!(inst.mode(2), Mode::Position); 164 | 165 | let inst = instruction(4); 166 | assert_eq!(inst.opcode, 4); 167 | assert_eq!(inst.mode(0), Mode::Position); 168 | assert_eq!(inst.mode(1), Mode::Position); 169 | assert_eq!(inst.mode(2), Mode::Position); 170 | 171 | let inst = instruction(99); 172 | assert_eq!(inst.opcode, 99); 173 | } 174 | 175 | #[test] 176 | fn interpret_parameter_modes_that_have_some_immediate_mode() { 177 | let inst = instruction(104); 178 | assert_eq!(inst.opcode, 4); 179 | assert_eq!(inst.mode(0), Mode::Immediate); 180 | 181 | let inst = instruction(1002); 182 | assert_eq!(inst.opcode, 2); 183 | assert_eq!(inst.mode(0), Mode::Position); 184 | assert_eq!(inst.mode(1), Mode::Immediate); 185 | assert_eq!(inst.mode(2), Mode::Position); 186 | } 187 | 188 | #[test] 189 | fn use_parameter_modes_in_programs() { 190 | let program = vec![1002, 4, 3, 4, 33]; 191 | let (answer, _output) = run_intcode(program, None); 192 | assert_eq!(answer, vec![1002, 4, 3, 4, 99]); 193 | } 194 | 195 | #[test] 196 | fn get_value_helper_function() { 197 | let program = vec![1, 0, 0, 0, 99]; 198 | let inst = instruction(program[0]); 199 | let instruction_pointer = 0; 200 | 201 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 1); 202 | 203 | let program = vec![104, 18, 99]; 204 | let inst = instruction(program[0]); 205 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 18); 206 | } 207 | } 208 | 209 | fn get_value(program: &[i32], instruction_pointer: usize, inst: &Instruction, parameter_index: usize) -> i32 { 210 | let parameter_location = instruction_pointer + parameter_index + 1; 211 | 212 | match inst.mode(parameter_index) { 213 | Mode::Position => program[program[parameter_location] as usize], 214 | Mode::Immediate => program[parameter_location], 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /aoc-03-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | use std::error::Error; 3 | use std::fs; 4 | 5 | fn main() -> Result<(), Box> { 6 | let input = fs::read_to_string("input")?; 7 | let mut lines = input.lines(); 8 | 9 | let w1 = lines 10 | .next() 11 | .expect("Should have been at least 1 line in the input"); 12 | let w2 = lines 13 | .next() 14 | .expect("Should have been at least 2 lines in the input"); 15 | 16 | let closest_crossed_wires = closest_crossed_wires(&w1, &w2); 17 | 18 | println!( 19 | "Distance to the closest crossed wires is {}", 20 | closest_crossed_wires 21 | ); 22 | 23 | let min_steps = min_steps_to_crossed_wires(&w1, &w2); 24 | 25 | println!("Min steps to the closest crossed wires is {}", min_steps); 26 | 27 | Ok(()) 28 | } 29 | 30 | // ## Assumptions/thoughts 31 | // 32 | // - The central port is at (0, 0) 33 | // - Right and Up amounts can be represented by positive numbers 34 | // - Left and Down amounts can be represented by negative numbers 35 | // - Right and Left are in the X direction 36 | // - Up and Down are in the Y direction 37 | // 38 | // ## Plan 39 | // 40 | // - Write code to parse "R2,D5" strings into a more convenient data structure 41 | // - Write code that can turn paths into a list of points that each wire touches 42 | // - Find the points that both wires have in their list of points 43 | // - The Manhattan distance of any point to (0, 0) is x + y 44 | // - Sort the intersection points by Manhattan distance and take the min 45 | 46 | #[derive(Debug, PartialEq)] 47 | enum PathPart { 48 | X(i32), 49 | Y(i32), 50 | } 51 | use PathPart::{X, Y}; 52 | 53 | #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] 54 | struct Location { 55 | x: i32, 56 | y: i32, 57 | } 58 | 59 | impl From<(i32, i32)> for Location { 60 | fn from(f: (i32, i32)) -> Location { 61 | Location { x: f.0, y: f.1 } 62 | } 63 | } 64 | 65 | fn locations_from_path(path: Vec) -> HashMap { 66 | let mut current_location = Location { x: 0, y: 0 }; 67 | let mut steps = 0; 68 | let mut locations = HashMap::new(); 69 | 70 | for part in path { 71 | match part { 72 | X(x) => { 73 | let (range, amount) = if x > 0 { (0..x, 1) } else { (x..0, -1) }; 74 | 75 | for _ in range { 76 | current_location = Location { 77 | x: current_location.x + amount, 78 | ..current_location 79 | }; 80 | steps += 1; 81 | locations.insert(current_location, steps); 82 | } 83 | } 84 | Y(y) => { 85 | let (range, amount) = if y > 0 { (0..y, 1) } else { (y..0, -1) }; 86 | 87 | for _ in range { 88 | current_location = Location { 89 | y: current_location.y + amount, 90 | ..current_location 91 | }; 92 | steps += 1; 93 | locations.insert(current_location, steps); 94 | } 95 | } 96 | } 97 | } 98 | 99 | locations 100 | } 101 | 102 | fn min_manhattan_distance(points: &HashSet) -> i32 { 103 | points 104 | .iter() 105 | .map(|point| point.x.abs() + point.y.abs()) 106 | .min() 107 | .expect("List should have had items in it") 108 | } 109 | 110 | fn parse_path(path_str: &str) -> Vec { 111 | path_str 112 | .split(",") 113 | .map(|segment| { 114 | let mut chars = segment.chars(); 115 | let direction = chars.next().expect(&format!( 116 | "Segment should have had a direction char: [{}]", 117 | segment 118 | )); 119 | let magnitude: i32 = chars.collect::().parse().expect(&format!( 120 | "Segment after direction char should have parsed as an i32: [{}]", 121 | segment 122 | )); 123 | 124 | match direction { 125 | 'R' => X(magnitude), 126 | 'L' => X(-magnitude), 127 | 'U' => Y(magnitude), 128 | 'D' => Y(-magnitude), 129 | _ => panic!("Unknown direction: [{}]", direction), 130 | } 131 | }) 132 | .collect() 133 | } 134 | 135 | fn closest_crossed_wires(path_str1: &str, path_str2: &str) -> i32 { 136 | let path1 = parse_path(path_str1); 137 | let path2 = parse_path(path_str2); 138 | 139 | let locations1_with_steps = locations_from_path(path1); 140 | let locations2_with_steps = locations_from_path(path2); 141 | 142 | let locations1: HashSet<_> = locations1_with_steps.keys().cloned().collect(); 143 | let locations2: HashSet<_> = locations2_with_steps.keys().cloned().collect(); 144 | 145 | let intersections: HashSet<_> = locations1.intersection(&locations2).cloned().collect(); 146 | 147 | min_manhattan_distance(&intersections) 148 | } 149 | 150 | fn min_steps( 151 | intersections: &HashSet, 152 | loc_steps1: &HashMap, 153 | loc_steps2: &HashMap, 154 | ) -> i32 { 155 | intersections 156 | .iter() 157 | .map(|i| { 158 | let steps1 = loc_steps1.get(&i).expect("Intersection must be in path1"); 159 | let steps2 = loc_steps2.get(&i).expect("Intersection must be in path2"); 160 | steps1 + steps2 161 | }) 162 | .min() 163 | .expect("Must be at least 1 intersection") 164 | } 165 | 166 | fn min_steps_to_crossed_wires(path_str1: &str, path_str2: &str) -> i32 { 167 | let path1 = parse_path(path_str1); 168 | let path2 = parse_path(path_str2); 169 | 170 | let locations1_with_steps = locations_from_path(path1); 171 | let locations2_with_steps = locations_from_path(path2); 172 | 173 | let locations1: HashSet<_> = locations1_with_steps.keys().cloned().collect(); 174 | let locations2: HashSet<_> = locations2_with_steps.keys().cloned().collect(); 175 | 176 | let intersections: HashSet<_> = locations1.intersection(&locations2).cloned().collect(); 177 | min_steps( 178 | &intersections, 179 | &locations1_with_steps, 180 | &locations2_with_steps, 181 | ) 182 | } 183 | 184 | #[cfg(test)] 185 | mod tests { 186 | use super::*; 187 | 188 | #[test] 189 | fn right() { 190 | let path = vec![X(1)]; 191 | let locations = locations_from_path(path); 192 | assert_eq!(locations.len(), 1); 193 | assert_eq!(locations.get(&(1, 0).into()), Some(&1)); 194 | } 195 | 196 | #[test] 197 | fn left() { 198 | let path = vec![X(-1)]; 199 | let locations = locations_from_path(path); 200 | assert_eq!(locations.len(), 1); 201 | assert_eq!(locations.get(&(-1, 0).into()), Some(&1)); 202 | } 203 | 204 | #[test] 205 | fn up() { 206 | let path = vec![Y(1)]; 207 | let locations = locations_from_path(path); 208 | assert_eq!(locations.len(), 1); 209 | assert_eq!(locations.get(&(0, 1).into()), Some(&1)); 210 | } 211 | 212 | #[test] 213 | fn down() { 214 | let path = vec![Y(-1)]; 215 | let locations = locations_from_path(path); 216 | assert_eq!(locations.len(), 1); 217 | assert_eq!(locations.get(&(0, -1).into()), Some(&1)); 218 | } 219 | 220 | #[test] 221 | fn example_from_problem_description() { 222 | let wire1_path_string = "R8,U5,L5,D3"; 223 | let wire2_path_string = "U7,R6,D4,L4"; 224 | 225 | let wire1_path = parse_path(wire1_path_string); 226 | assert_eq!(wire1_path, vec![X(8), Y(5), X(-5), Y(-3)]); 227 | 228 | let wire2_path = parse_path(wire2_path_string); 229 | assert_eq!(wire2_path, vec![Y(7), X(6), Y(-4), X(-4)]); 230 | 231 | let locations1_with_steps = locations_from_path(wire1_path); 232 | let locations2_with_steps = locations_from_path(wire2_path); 233 | 234 | let wire1_locations: HashSet<_> = locations1_with_steps.keys().cloned().collect(); 235 | let wire2_locations: HashSet<_> = locations2_with_steps.keys().cloned().collect(); 236 | 237 | let intersections: HashSet<_> = wire1_locations 238 | .intersection(&wire2_locations) 239 | .cloned() 240 | .collect(); 241 | let expected: HashSet<_> = [(3, 3).into(), (6, 5).into()].iter().cloned().collect(); 242 | assert_eq!(intersections, expected); 243 | 244 | assert_eq!(min_manhattan_distance(&intersections), 6); 245 | assert_eq!( 246 | min_steps( 247 | &intersections, 248 | &locations1_with_steps, 249 | &locations2_with_steps 250 | ), 251 | 30 252 | ); 253 | } 254 | 255 | #[test] 256 | fn example_from_problem_description_all_at_once() { 257 | let wire1_path_string = "R8,U5,L5,D3"; 258 | let wire2_path_string = "U7,R6,D4,L4"; 259 | 260 | let closest_crossed_wires = closest_crossed_wires(wire1_path_string, wire2_path_string); 261 | assert_eq!(closest_crossed_wires, 6); 262 | 263 | let min_steps_to_crossed_wires = 264 | min_steps_to_crossed_wires(wire1_path_string, wire2_path_string); 265 | assert_eq!(min_steps_to_crossed_wires, 30); 266 | } 267 | 268 | #[test] 269 | fn other_examples_from_problem_description() { 270 | let w1 = "R75,D30,R83,U83,L12,D49,R71,U7,L72"; 271 | let w2 = "U62,R66,U55,R34,D71,R55,D58,R83"; 272 | 273 | let closest = closest_crossed_wires(w1, w2); 274 | assert_eq!(closest, 159); 275 | 276 | let min_steps = min_steps_to_crossed_wires(w1, w2); 277 | assert_eq!(min_steps, 610); 278 | 279 | let w1 = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51"; 280 | let w2 = "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7"; 281 | 282 | let closest = closest_crossed_wires(w1, w2); 283 | assert_eq!(closest, 135); 284 | 285 | let min_steps = min_steps_to_crossed_wires(w1, w2); 286 | assert_eq!(min_steps, 410); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /aoc-05-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fs; 3 | 4 | fn main() -> Result<(), Box> { 5 | let program_input = fs::read_to_string("input")?; 6 | let program: Vec<_> = program_input 7 | .trim() 8 | .split(",") 9 | .map(|n| n.parse().expect("input should have been a number")) 10 | .collect(); 11 | 12 | let simulated_stdin = Some(5); 13 | let (_answer, output) = run_intcode(program, simulated_stdin); 14 | println!("{:?}", output); 15 | 16 | Ok(()) 17 | } 18 | 19 | fn run_intcode(mut program: Vec, input: Option) -> (Vec, Vec) { 20 | let mut current_position = 0; 21 | let mut current_inst = instruction(program[current_position]); 22 | let mut output = vec![]; 23 | 24 | while current_inst.opcode != 99 { 25 | match current_inst.opcode { 26 | 1 => { 27 | let output_position = program[current_position + 3] as usize; 28 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 29 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 30 | let answer = input1 + input2; 31 | program[output_position] = answer; 32 | current_position += 4; 33 | } 34 | 2 => { 35 | let output_position = program[current_position + 3] as usize; 36 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 37 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 38 | let answer = input1 * input2; 39 | program[output_position] = answer; 40 | current_position += 4; 41 | } 42 | 3 => { 43 | let output_position = program[current_position + 1] as usize; 44 | program[output_position] = input.expect("Should have had input for opcode 3"); 45 | current_position += 2; 46 | } 47 | 4 => { 48 | let printing_value = get_value(&program, current_position, ¤t_inst, 0); 49 | output.push(printing_value); 50 | current_position += 2; 51 | } 52 | 5 => { // jump-if-true 53 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 54 | if test_value != 0 { 55 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 56 | current_position = jump_location as usize; 57 | } else { 58 | current_position += 3; 59 | } 60 | } 61 | 6 => { // jump-if-false 62 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 63 | if test_value == 0 { 64 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 65 | current_position = jump_location as usize; 66 | } else { 67 | current_position += 3; 68 | } 69 | } 70 | 7 => { // less-than 71 | let output_position = program[current_position + 3] as usize; 72 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 73 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 74 | let answer = if input1 < input2 { 1 } else { 0 }; 75 | program[output_position] = answer; 76 | current_position += 4; 77 | } 78 | 8 => { // equals 79 | let output_position = program[current_position + 3] as usize; 80 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 81 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 82 | let answer = if input1 == input2 { 1 } else { 0 }; 83 | program[output_position] = answer; 84 | current_position += 4; 85 | } 86 | other => panic!("Unknown opcode: {}", other), 87 | } 88 | current_inst = instruction(program[current_position]); 89 | } 90 | 91 | (program, output) 92 | } 93 | 94 | #[derive(Debug, PartialEq, Clone, Copy)] 95 | enum Mode { 96 | Position, 97 | Immediate, 98 | } 99 | 100 | #[derive(Debug, PartialEq)] 101 | struct Instruction { 102 | opcode: i32, 103 | modes: Vec, 104 | } 105 | 106 | impl Instruction { 107 | fn mode(&self, parameter: usize) -> Mode { 108 | self.modes.get(parameter).copied().unwrap_or(Mode::Position) 109 | } 110 | } 111 | 112 | fn instruction(mut full_opcode: i32) -> Instruction { 113 | let opcode = full_opcode % 100; 114 | full_opcode /= 100; 115 | 116 | let mut modes = vec![]; 117 | 118 | while full_opcode > 0 { 119 | let mode = match full_opcode % 10 { 120 | 0 => Mode::Position, 121 | 1 => Mode::Immediate, 122 | other => panic!("Unexpected parameter mode: {}", other), 123 | }; 124 | modes.push(mode); 125 | full_opcode /= 10; 126 | } 127 | 128 | Instruction { opcode, modes } 129 | } 130 | 131 | #[cfg(test)] 132 | mod tests { 133 | use super::*; 134 | 135 | #[test] 136 | fn opcode_99_ends() { 137 | let program = vec![99]; 138 | let (answer, _output) = run_intcode(program, None); 139 | assert_eq!(answer, vec![99]); 140 | } 141 | 142 | #[test] 143 | fn opcode_1_adds() { 144 | let program = vec![1, 0, 0, 0, 99]; 145 | let (answer, _output) = run_intcode(program, None); 146 | assert_eq!(answer, vec![2, 0, 0, 0, 99]); 147 | } 148 | 149 | #[test] 150 | fn opcode_2_multiplies() { 151 | let program = vec![2, 3, 0, 3, 99]; 152 | let (answer, _output) = run_intcode(program, None); 153 | assert_eq!(answer, vec![2, 3, 0, 6, 99]); 154 | } 155 | 156 | #[test] 157 | fn multiply_and_store_after_program() { 158 | let program = vec![2, 4, 4, 5, 99, 0]; 159 | let (answer, _output) = run_intcode(program, None); 160 | assert_eq!(answer, vec![2, 4, 4, 5, 99, 9801]); 161 | } 162 | 163 | #[test] 164 | fn program_keeps_going_if_an_instruction_changes() { 165 | let program = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; 166 | let (answer, _output) = run_intcode(program, None); 167 | assert_eq!(answer, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); 168 | } 169 | 170 | #[test] 171 | fn opcode_3_takes_input() { 172 | let program = vec![3, 0, 99]; 173 | let (answer, _output) = run_intcode(program, Some(7)); 174 | assert_eq!(answer, vec![7, 0, 99]); 175 | } 176 | 177 | #[test] 178 | fn opcode_4_returns_output() { 179 | let program = vec![4, 2, 99]; 180 | let (_answer, output) = run_intcode(program, None); 181 | assert_eq!(output, vec![99]); 182 | } 183 | 184 | #[test] 185 | fn opcode_5_jumps_if_true() { 186 | // Test value is false; 42 gets printed 187 | let program = vec![1005, 6, 5, 104, 42, 99, 0]; 188 | let (_answer, output) = run_intcode(program, None); 189 | assert_eq!(output, vec![42]); 190 | 191 | // Test value is true; print gets jumped over 192 | let program = vec![1005, 6, 5, 104, 42, 99, 3]; 193 | let (_answer, output) = run_intcode(program, None); 194 | assert_eq!(output, vec![]); 195 | } 196 | 197 | #[test] 198 | fn opcode_6_jumps_if_false() { 199 | // Test value is false; print gets jumped over 200 | let program = vec![1006, 6, 5, 104, 42, 99, 0]; 201 | let (_answer, output) = run_intcode(program, None); 202 | assert_eq!(output, vec![]); 203 | 204 | // Test value is true; 42 gets printed 205 | let program = vec![1006, 6, 5, 104, 42, 99, 3]; 206 | let (_answer, output) = run_intcode(program, None); 207 | assert_eq!(output, vec![42]); 208 | } 209 | 210 | #[test] 211 | fn opcode_7_less_than() { 212 | let program = vec![1107, 4, 5, 3, 99]; 213 | let (answer, _output) = run_intcode(program, None); 214 | assert_eq!(answer, vec![1107, 4, 5, 1, 99]); 215 | 216 | let program = vec![1107, 5, 4, 3, 99]; 217 | let (answer, _output) = run_intcode(program, None); 218 | assert_eq!(answer, vec![1107, 5, 4, 0, 99]); 219 | } 220 | 221 | #[test] 222 | fn opcode_8_equals() { 223 | let program = vec![1108, 4, 4, 3, 99]; 224 | let (answer, _output) = run_intcode(program, None); 225 | assert_eq!(answer, vec![1108, 4, 4, 1, 99]); 226 | 227 | let program = vec![1108, 5, 4, 3, 99]; 228 | let (answer, _output) = run_intcode(program, None); 229 | assert_eq!(answer, vec![1108, 5, 4, 0, 99]); 230 | } 231 | 232 | #[test] 233 | #[should_panic(expected = "Unknown opcode: 42")] 234 | fn unknown_opcode_panics() { 235 | let program = vec![42]; 236 | run_intcode(program, None); 237 | } 238 | 239 | #[test] 240 | fn interpret_parameter_modes_all_position_mode() { 241 | let inst = instruction(2); 242 | assert_eq!(inst.opcode, 2); 243 | assert_eq!(inst.mode(0), Mode::Position); 244 | assert_eq!(inst.mode(1), Mode::Position); 245 | assert_eq!(inst.mode(2), Mode::Position); 246 | 247 | let inst = instruction(4); 248 | assert_eq!(inst.opcode, 4); 249 | assert_eq!(inst.mode(0), Mode::Position); 250 | assert_eq!(inst.mode(1), Mode::Position); 251 | assert_eq!(inst.mode(2), Mode::Position); 252 | 253 | let inst = instruction(99); 254 | assert_eq!(inst.opcode, 99); 255 | } 256 | 257 | #[test] 258 | fn interpret_parameter_modes_that_have_some_immediate_mode() { 259 | let inst = instruction(104); 260 | assert_eq!(inst.opcode, 4); 261 | assert_eq!(inst.mode(0), Mode::Immediate); 262 | 263 | let inst = instruction(1002); 264 | assert_eq!(inst.opcode, 2); 265 | assert_eq!(inst.mode(0), Mode::Position); 266 | assert_eq!(inst.mode(1), Mode::Immediate); 267 | assert_eq!(inst.mode(2), Mode::Position); 268 | } 269 | 270 | #[test] 271 | fn use_parameter_modes_in_programs() { 272 | let program = vec![1002, 4, 3, 4, 33]; 273 | let (answer, _output) = run_intcode(program, None); 274 | assert_eq!(answer, vec![1002, 4, 3, 4, 99]); 275 | } 276 | 277 | #[test] 278 | fn get_value_helper_function() { 279 | let program = vec![1, 0, 0, 0, 99]; 280 | let inst = instruction(program[0]); 281 | let instruction_pointer = 0; 282 | 283 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 1); 284 | 285 | let program = vec![104, 18, 99]; 286 | let inst = instruction(program[0]); 287 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 18); 288 | } 289 | } 290 | 291 | fn get_value(program: &[i32], instruction_pointer: usize, inst: &Instruction, parameter_index: usize) -> i32 { 292 | let parameter_location = instruction_pointer + parameter_index + 1; 293 | 294 | match inst.mode(parameter_index) { 295 | Mode::Position => program[program[parameter_location] as usize], 296 | Mode::Immediate => program[parameter_location], 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /aoc-07-02/src/main.rs: -------------------------------------------------------------------------------- 1 | use permute::permute; 2 | use std::error::Error; 3 | use std::fs; 4 | use std::sync::mpsc::{channel, Receiver, Sender}; 5 | use std::thread; 6 | 7 | fn main() -> Result<(), Box> { 8 | let program_input = fs::read_to_string("input")?; 9 | let program: Vec = program_input 10 | .trim() 11 | .split(",") 12 | .map(|n| n.parse().expect("input should have been a number")) 13 | .collect(); 14 | 15 | let phase_settings = [5, 6, 7, 8, 9]; 16 | let max = max_signal(&program, &phase_settings); 17 | 18 | println!("{:?}", max); 19 | 20 | Ok(()) 21 | } 22 | 23 | fn run_intcode(mut program: Vec, input: Receiver, output: Sender) { 24 | let mut current_position = 0; 25 | let mut current_inst = instruction(program[current_position]); 26 | 27 | while current_inst.opcode != 99 { 28 | match current_inst.opcode { 29 | 1 => { 30 | let output_position = program[current_position + 3] as usize; 31 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 32 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 33 | let answer = input1 + input2; 34 | program[output_position] = answer; 35 | current_position += 4; 36 | } 37 | 2 => { 38 | let output_position = program[current_position + 3] as usize; 39 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 40 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 41 | let answer = input1 * input2; 42 | program[output_position] = answer; 43 | current_position += 4; 44 | } 45 | 3 => { 46 | let output_position = program[current_position + 1] as usize; 47 | program[output_position] = input 48 | .recv() 49 | .expect("Should have had enough input for opcode 3"); 50 | current_position += 2; 51 | } 52 | 4 => { 53 | let printing_value = get_value(&program, current_position, ¤t_inst, 0); 54 | output 55 | .send(printing_value) 56 | .expect("Sender shouldn't be closed"); 57 | current_position += 2; 58 | } 59 | 5 => { 60 | // jump-if-true 61 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 62 | if test_value != 0 { 63 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 64 | current_position = jump_location as usize; 65 | } else { 66 | current_position += 3; 67 | } 68 | } 69 | 6 => { 70 | // jump-if-false 71 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 72 | if test_value == 0 { 73 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 74 | current_position = jump_location as usize; 75 | } else { 76 | current_position += 3; 77 | } 78 | } 79 | 7 => { 80 | // less-than 81 | let output_position = program[current_position + 3] as usize; 82 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 83 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 84 | let answer = if input1 < input2 { 1 } else { 0 }; 85 | program[output_position] = answer; 86 | current_position += 4; 87 | } 88 | 8 => { 89 | // equals 90 | let output_position = program[current_position + 3] as usize; 91 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 92 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 93 | let answer = if input1 == input2 { 1 } else { 0 }; 94 | program[output_position] = answer; 95 | current_position += 4; 96 | } 97 | other => panic!("Unknown opcode: {}", other), 98 | } 99 | current_inst = instruction(program[current_position]); 100 | } 101 | } 102 | 103 | #[derive(Debug, PartialEq, Clone, Copy)] 104 | enum Mode { 105 | Position, 106 | Immediate, 107 | } 108 | 109 | #[derive(Debug, PartialEq)] 110 | struct Instruction { 111 | opcode: i32, 112 | modes: Vec, 113 | } 114 | 115 | impl Instruction { 116 | fn mode(&self, parameter: usize) -> Mode { 117 | self.modes.get(parameter).copied().unwrap_or(Mode::Position) 118 | } 119 | } 120 | 121 | fn instruction(mut full_opcode: i32) -> Instruction { 122 | let opcode = full_opcode % 100; 123 | full_opcode /= 100; 124 | 125 | let mut modes = vec![]; 126 | 127 | while full_opcode > 0 { 128 | let mode = match full_opcode % 10 { 129 | 0 => Mode::Position, 130 | 1 => Mode::Immediate, 131 | other => panic!("Unexpected parameter mode: {}", other), 132 | }; 133 | modes.push(mode); 134 | full_opcode /= 10; 135 | } 136 | 137 | Instruction { opcode, modes } 138 | } 139 | 140 | fn get_value( 141 | program: &[i32], 142 | instruction_pointer: usize, 143 | inst: &Instruction, 144 | parameter_index: usize, 145 | ) -> i32 { 146 | let parameter_location = instruction_pointer + parameter_index + 1; 147 | 148 | match inst.mode(parameter_index) { 149 | Mode::Position => program[program[parameter_location] as usize], 150 | Mode::Immediate => program[parameter_location], 151 | } 152 | } 153 | 154 | #[cfg(test)] 155 | mod tests { 156 | use super::*; 157 | use std::sync::mpsc::channel; 158 | use std::thread; 159 | 160 | #[test] 161 | fn run_intcode_with_channels() { 162 | let (send_input, receive_input) = channel(); 163 | let (send_output, receive_output) = channel(); 164 | 165 | thread::spawn(move || { 166 | let program = vec![3, 12, 4, 12, 1001, 12, -1, 12, 1005, 12, 2, 99, -1]; 167 | run_intcode(program, receive_input, send_output); 168 | }); 169 | 170 | send_input.send(3).unwrap(); 171 | 172 | assert_eq!(receive_output.recv().unwrap(), 3); 173 | assert_eq!(receive_output.recv().unwrap(), 2); 174 | assert_eq!(receive_output.recv().unwrap(), 1); 175 | assert!(receive_output.recv().is_err()); 176 | } 177 | 178 | #[test] 179 | fn run_intcode_that_expects_multiple_inputs_and_sends_multiple_outputs() { 180 | let (send_input, receive_input) = channel(); 181 | let (send_output, receive_output) = channel(); 182 | 183 | thread::spawn(move || { 184 | let program = vec![ 185 | 3, 18, 3, 19, 1002, 19, 2, 19, 4, 19, 1001, 18, -1, 18, 1005, 18, 2, 99, -1, -2, 186 | ]; 187 | run_intcode(program, receive_input, send_output); 188 | }); 189 | 190 | // Run loop 3 times 191 | send_input.send(3).unwrap(); 192 | 193 | send_input.send(5).unwrap(); 194 | assert_eq!(receive_output.recv().unwrap(), 10); 195 | 196 | send_input.send(25).unwrap(); 197 | assert_eq!(receive_output.recv().unwrap(), 50); 198 | 199 | send_input.send(1).unwrap(); 200 | assert_eq!(receive_output.recv().unwrap(), 2); 201 | 202 | assert!(receive_output.recv().is_err()); 203 | } 204 | 205 | #[test] 206 | fn run_looped_channel_intcode_computers() { 207 | let (send_input_original, receive_input1) = channel(); 208 | let (send_output1, receive_input2) = channel(); 209 | let (send_output2, receive_output_spy) = channel(); 210 | 211 | let program1 = vec![ 212 | 3, 20, 4, 20, 3, 21, 1002, 21, 2, 21, 4, 21, 1001, 20, -1, 20, 1005, 20, 4, 99, -1, -2, 213 | ]; 214 | let program2 = program1.clone(); 215 | 216 | thread::spawn(move || { 217 | run_intcode(program1, receive_input1, send_output1); 218 | }); 219 | 220 | thread::spawn(move || { 221 | run_intcode(program2, receive_input2, send_output2); 222 | }); 223 | 224 | // Run loop 3 times, which also sends 3 around to be doubled 225 | send_input_original.send(3).unwrap(); 226 | 227 | let mut final_value = -1; 228 | 229 | while let Ok(received_value) = receive_output_spy.recv() { 230 | let _ = send_input_original.send(received_value); 231 | final_value = received_value; 232 | } 233 | 234 | assert_eq!(final_value, 192); 235 | } 236 | 237 | #[test] 238 | fn run_example_in_looped_incode_computers() { 239 | let phase_settings = [5, 6, 7, 8, 9]; 240 | 241 | let program = vec![ 242 | 3, 26, 1001, 26, -4, 26, 3, 27, 1002, 27, 2, 27, 1, 27, 26, 27, 4, 27, 1001, 28, -1, 243 | 28, 1005, 28, 6, 99, 0, 0, 5, 244 | ]; 245 | let answer = max_signal(&program, &phase_settings); 246 | assert_eq!(answer, 139629729); 247 | 248 | let program = vec![ 249 | 3, 52, 1001, 52, -5, 52, 3, 53, 1, 52, 56, 54, 1007, 54, 5, 55, 1005, 55, 26, 1001, 54, 250 | -5, 54, 1105, 1, 12, 1, 53, 54, 53, 1008, 54, 0, 55, 1001, 55, 1, 55, 2, 53, 55, 53, 4, 251 | 53, 1001, 56, -1, 56, 1005, 56, 6, 99, 0, 0, 0, 0, 10, 252 | ]; 253 | let answer = max_signal(&program, &phase_settings); 254 | assert_eq!(answer, 18216); 255 | } 256 | } 257 | 258 | fn max_signal(program: &[i32], phase_settings: &[i32]) -> i32 { 259 | permute(phase_settings.to_owned()) 260 | .iter() 261 | .map(|setting_ordering| run_with_phase_settings(program, setting_ordering)) 262 | .max() 263 | .expect("Must have had orderings") 264 | } 265 | 266 | fn run_with_phase_settings(program: &[i32], phase_settings: &[i32]) -> i32 { 267 | let (send_from_main, receive_in_amp_a) = channel(); 268 | let (send_from_amp_a, receive_in_amp_b) = channel(); 269 | let (send_from_amp_b, receive_in_amp_c) = channel(); 270 | let (send_from_amp_c, receive_in_amp_d) = channel(); 271 | let (send_from_amp_d, receive_in_amp_e) = channel(); 272 | let (send_from_amp_e, receive_in_main) = channel(); 273 | 274 | // Send phase settings 275 | send_from_main.send(phase_settings[0]).unwrap(); 276 | send_from_amp_a.send(phase_settings[1]).unwrap(); 277 | send_from_amp_b.send(phase_settings[2]).unwrap(); 278 | send_from_amp_c.send(phase_settings[3]).unwrap(); 279 | send_from_amp_d.send(phase_settings[4]).unwrap(); 280 | 281 | // Set up threads 282 | let program_a = program.to_vec(); 283 | thread::spawn(move || { 284 | run_intcode(program_a, receive_in_amp_a, send_from_amp_a); 285 | }); 286 | 287 | let program_b = program.to_vec(); 288 | thread::spawn(move || { 289 | run_intcode(program_b, receive_in_amp_b, send_from_amp_b); 290 | }); 291 | 292 | let program_c = program.to_vec(); 293 | thread::spawn(move || { 294 | run_intcode(program_c, receive_in_amp_c, send_from_amp_c); 295 | }); 296 | 297 | let program_d = program.to_vec(); 298 | thread::spawn(move || { 299 | run_intcode(program_d, receive_in_amp_d, send_from_amp_d); 300 | }); 301 | 302 | let program_e = program.to_vec(); 303 | thread::spawn(move || { 304 | run_intcode(program_e, receive_in_amp_e, send_from_amp_e); 305 | }); 306 | 307 | // Send initial signal 308 | send_from_main.send(0).unwrap(); 309 | 310 | // Loop until feedback stops 311 | let mut final_value = -1; 312 | 313 | while let Ok(received_value) = receive_in_main.recv() { 314 | let _ = send_from_main.send(received_value); 315 | final_value = received_value; 316 | } 317 | 318 | final_value 319 | } 320 | -------------------------------------------------------------------------------- /aoc-13-02-wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | use std::collections::HashMap; 3 | use std::fmt; 4 | 5 | #[wasm_bindgen] 6 | #[repr(u8)] 7 | #[derive(PartialEq, Copy, Clone, Debug, Eq)] 8 | pub enum Tile { 9 | Empty = 0, 10 | Wall = 1, 11 | Block = 2, 12 | Paddle = 3, 13 | Ball = 4, 14 | } 15 | 16 | impl From for Tile { 17 | fn from(val: i64) -> Self { 18 | match val { 19 | 0 => Tile::Empty, 20 | 1 => Tile::Wall, 21 | 2 => Tile::Block, 22 | 3 => Tile::Paddle, 23 | 4 => Tile::Ball, 24 | other => panic!("Unknown tile: {}", other), 25 | } 26 | } 27 | } 28 | 29 | #[wasm_bindgen] 30 | #[repr(u8)] 31 | #[derive(Copy, Clone, PartialEq, Debug, Eq)] 32 | pub enum Joystick { 33 | Left = 0, 34 | Neutral = 1, 35 | Right = 2, 36 | } 37 | 38 | impl Joystick { 39 | fn as_intcode_value(&self) -> i64 { 40 | *self as i64 - 1 41 | } 42 | } 43 | 44 | const SCREEN_WIDTH: usize = 36; 45 | const SCREEN_HEIGHT: usize = 24; 46 | 47 | #[wasm_bindgen] 48 | pub struct Screen { 49 | width: usize, 50 | height: usize, 51 | data: Vec, 52 | intcode_computer: Computer, 53 | } 54 | 55 | #[wasm_bindgen] 56 | impl Screen { 57 | pub fn new() -> Screen { 58 | Screen { 59 | width: SCREEN_WIDTH, 60 | height: SCREEN_HEIGHT, 61 | data: vec![Tile::Empty; SCREEN_WIDTH * SCREEN_HEIGHT], 62 | intcode_computer: Computer::new(), 63 | } 64 | } 65 | 66 | pub fn run(&mut self) -> bool { 67 | self.intcode_computer.run(&mut self.data) 68 | } 69 | 70 | pub fn render(&self) -> String { 71 | self.to_string() 72 | } 73 | 74 | pub fn width(&self) -> u32 { 75 | self.width as u32 76 | } 77 | 78 | pub fn height(&self) -> u32 { 79 | self.height as u32 80 | } 81 | 82 | pub fn tiles(&self) -> *const Tile { 83 | self.data.as_ptr() 84 | } 85 | 86 | pub fn score(&self) -> i64 { 87 | self.intcode_computer.score 88 | } 89 | 90 | pub fn set_joystick(&mut self, joystick: Joystick) { 91 | self.intcode_computer.set_joystick(joystick); 92 | } 93 | } 94 | 95 | impl fmt::Display for Screen { 96 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 97 | for line in self.data.as_slice().chunks(self.width as usize) { 98 | for &tile in line { 99 | let symbol = match tile { 100 | Tile::Empty => " ", 101 | Tile::Wall => "█", 102 | Tile::Block => "□", 103 | Tile::Paddle => "_", 104 | Tile::Ball => "o", 105 | }; 106 | write!(f, "{}", symbol)?; 107 | } 108 | write!(f, "\n")?; 109 | } 110 | 111 | Ok(()) 112 | } 113 | } 114 | 115 | 116 | struct Computer { 117 | program: HashMap, 118 | current_position: usize, 119 | relative_base: usize, 120 | output_x: Option, 121 | output_y: Option, 122 | score: i64, 123 | initial_render_complete: bool, 124 | joystick: Joystick, 125 | } 126 | 127 | impl Computer { 128 | fn new() -> Computer { 129 | let program_input = include_str!("../input"); 130 | let program: HashMap = program_input 131 | .trim() 132 | .split(",") 133 | .map(|n| n.parse().expect("input should have been a number")) 134 | .enumerate() 135 | .collect(); 136 | 137 | Computer { 138 | program, 139 | current_position: 0, 140 | relative_base: 0, 141 | output_x: None, 142 | output_y: None, 143 | score: 0, 144 | initial_render_complete: false, 145 | joystick: Joystick::Neutral, 146 | } 147 | } 148 | 149 | fn set_joystick(&mut self, joystick: Joystick) { 150 | self.joystick = joystick; 151 | } 152 | 153 | fn run(&mut self, data: &mut [Tile]) -> bool { 154 | let mut current_inst = self.current_instruction(); 155 | 156 | while current_inst.opcode != 99 { 157 | match current_inst.opcode { 158 | 1 => { 159 | let input1 = self.get_value(0); 160 | let input2 = self.get_value(1); 161 | let answer = input1 + input2; 162 | self.set_value(2, answer); 163 | self.current_position += 4; 164 | } 165 | 2 => { 166 | let input1 = self.get_value(0); 167 | let input2 = self.get_value(1); 168 | let answer = input1 * input2; 169 | self.set_value(2, answer); 170 | self.current_position += 4; 171 | } 172 | 3 => { 173 | self.set_value(0, self.joystick.as_intcode_value()); 174 | self.current_position += 2; 175 | } 176 | 4 => { 177 | let value = self.get_value(0); 178 | self.current_position += 2; 179 | 180 | match (self.output_x, self.output_y) { 181 | (None, None) => { 182 | self.output_x = Some(value); 183 | } 184 | (Some(_), None) => { 185 | self.output_y = Some(value); 186 | } 187 | (Some(-1), Some(0)) => { 188 | self.score = value; 189 | 190 | self.output_x = None; 191 | self.output_y = None; 192 | } 193 | (Some(x), Some(y)) => { 194 | let tile_value: Tile = value.into(); 195 | 196 | let index = y as usize * SCREEN_WIDTH + x as usize; 197 | data[index] = tile_value; 198 | 199 | self.output_x = None; 200 | self.output_y = None; 201 | 202 | if self.initial_render_complete { 203 | return false; 204 | } else { 205 | if index == data.len() - 1 { 206 | self.initial_render_complete = true; 207 | } 208 | } 209 | } 210 | _ => unreachable!(), 211 | } 212 | } 213 | 5 => { 214 | // jump-if-true 215 | let test_value = self.get_value(0); 216 | if test_value != 0 { 217 | let jump_location = self.get_value(1); 218 | self.current_position = jump_location as usize; 219 | } else { 220 | self.current_position += 3; 221 | } 222 | } 223 | 6 => { 224 | // jump-if-false 225 | let test_value = self.get_value(0); 226 | if test_value == 0 { 227 | let jump_location = self.get_value(1); 228 | self.current_position = jump_location as usize; 229 | } else { 230 | self.current_position += 3; 231 | } 232 | } 233 | 7 => { 234 | // less-than 235 | let input1 = self.get_value(0); 236 | let input2 = self.get_value(1); 237 | let answer = if input1 < input2 { 1 } else { 0 }; 238 | self.set_value(2, answer); 239 | self.current_position += 4; 240 | } 241 | 8 => { 242 | // equals 243 | let input1 = self.get_value(0); 244 | let input2 = self.get_value(1); 245 | let answer = if input1 == input2 { 1 } else { 0 }; 246 | self.set_value(2, answer); 247 | self.current_position += 4; 248 | } 249 | 9 => { 250 | // relative base adjustment 251 | let input1 = self.get_value(0); 252 | let new_rel_base = self.relative_base as i64 + input1; 253 | self.relative_base = new_rel_base as usize; 254 | self.current_position += 2; 255 | } 256 | other => panic!("Unknown opcode: {}", other), 257 | } 258 | current_inst = self.current_instruction(); 259 | } 260 | 261 | return true; 262 | } 263 | } 264 | 265 | impl Computer { 266 | fn current_instruction(&self) -> Instruction { 267 | instruction(self.read_at(self.current_position)) 268 | } 269 | 270 | fn get_value(&self, parameter_index: usize) -> i64 { 271 | get_value(&self.program, self.current_position, &self.current_instruction(), parameter_index, self.relative_base) 272 | } 273 | 274 | fn set_value(&mut self, parameter_index: usize, value: i64) { 275 | let instruction = self.current_instruction(); 276 | set_value(&mut self.program, self.current_position, &instruction, parameter_index, self.relative_base, value); 277 | } 278 | 279 | fn read_at(&self, index: usize) -> i64 { 280 | self.program.get(&index).copied().unwrap_or(0) 281 | } 282 | } 283 | 284 | #[derive(Debug, PartialEq, Clone, Copy)] 285 | enum Mode { 286 | Position, 287 | Immediate, 288 | Relative, 289 | } 290 | 291 | #[derive(Debug, PartialEq)] 292 | struct Instruction { 293 | opcode: i64, 294 | modes: Vec, 295 | } 296 | 297 | impl Instruction { 298 | fn mode(&self, parameter: usize) -> Mode { 299 | self.modes.get(parameter).copied().unwrap_or(Mode::Position) 300 | } 301 | } 302 | 303 | fn instruction(mut full_opcode: i64) -> Instruction { 304 | let opcode = full_opcode % 100; 305 | full_opcode /= 100; 306 | 307 | let mut modes = vec![]; 308 | 309 | while full_opcode > 0 { 310 | let mode = match full_opcode % 10 { 311 | 0 => Mode::Position, 312 | 1 => Mode::Immediate, 313 | 2 => Mode::Relative, 314 | other => panic!("Unexpected parameter mode: {}", other), 315 | }; 316 | modes.push(mode); 317 | full_opcode /= 10; 318 | } 319 | 320 | Instruction { opcode, modes } 321 | } 322 | 323 | fn get_value( 324 | program: &HashMap, 325 | instruction_pointer: usize, 326 | inst: &Instruction, 327 | parameter_index: usize, 328 | relative_base: usize, 329 | ) -> i64 { 330 | let parameter_location = instruction_pointer + parameter_index + 1; 331 | 332 | match inst.mode(parameter_index) { 333 | Mode::Position => { 334 | let position = program.get(¶meter_location).copied().unwrap_or(0) as usize; 335 | program.get(&position).copied().unwrap_or(0) 336 | }, 337 | Mode::Immediate => program.get(¶meter_location).copied().unwrap_or(0), 338 | Mode::Relative => { 339 | let offset = program.get(¶meter_location).copied().unwrap_or(0); 340 | let memory_location = offset + relative_base as i64; 341 | if memory_location < 0 { 342 | panic!("Cannot access memory at {}", memory_location); 343 | } 344 | program.get(&(memory_location as usize)).copied().unwrap_or(0) 345 | }, 346 | } 347 | } 348 | 349 | fn set_value( 350 | program: &mut HashMap, 351 | instruction_pointer: usize, 352 | inst: &Instruction, 353 | parameter_index: usize, 354 | relative_base: usize, 355 | value: i64, 356 | ) { 357 | let parameter_location = instruction_pointer + parameter_index + 1; 358 | 359 | match inst.mode(parameter_index) { 360 | Mode::Position => { 361 | let position = program.get(¶meter_location).copied().unwrap_or(0) as usize; 362 | program.insert(position, value); 363 | }, 364 | Mode::Immediate => unreachable!("Can't set values in immediate mode"), 365 | Mode::Relative => { 366 | let offset = program.get(¶meter_location).copied().unwrap_or(0); 367 | let memory_location = offset + relative_base as i64; 368 | if memory_location < 0 { 369 | panic!("Cannot access memory at {}", memory_location); 370 | } 371 | program.insert(memory_location as usize, value); 372 | }, 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /aoc-07-01/src/main.rs: -------------------------------------------------------------------------------- 1 | use permute::permute; 2 | use std::error::Error; 3 | use std::fs; 4 | 5 | fn main() -> Result<(), Box> { 6 | let program_input = fs::read_to_string("input")?; 7 | let program: Vec<_> = program_input 8 | .trim() 9 | .split(",") 10 | .map(|n| n.parse().expect("input should have been a number")) 11 | .collect(); 12 | 13 | let phase_settings = [0, 1, 2, 3, 4]; 14 | let max = max_signal(&program, &phase_settings); 15 | 16 | println!("{:?}", max); 17 | 18 | Ok(()) 19 | } 20 | 21 | fn run_intcode(mut program: Vec, mut input: Vec) -> (Vec, Vec) { 22 | let mut current_position = 0; 23 | let mut current_inst = instruction(program[current_position]); 24 | let mut output = vec![]; 25 | input = input.into_iter().rev().collect(); 26 | 27 | while current_inst.opcode != 99 { 28 | match current_inst.opcode { 29 | 1 => { 30 | let output_position = program[current_position + 3] as usize; 31 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 32 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 33 | let answer = input1 + input2; 34 | program[output_position] = answer; 35 | current_position += 4; 36 | } 37 | 2 => { 38 | let output_position = program[current_position + 3] as usize; 39 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 40 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 41 | let answer = input1 * input2; 42 | program[output_position] = answer; 43 | current_position += 4; 44 | } 45 | 3 => { 46 | let output_position = program[current_position + 1] as usize; 47 | program[output_position] = input 48 | .pop() 49 | .expect("Should have had enough input for opcode 3"); 50 | current_position += 2; 51 | } 52 | 4 => { 53 | let printing_value = get_value(&program, current_position, ¤t_inst, 0); 54 | output.push(printing_value); 55 | current_position += 2; 56 | } 57 | 5 => { 58 | // jump-if-true 59 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 60 | if test_value != 0 { 61 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 62 | current_position = jump_location as usize; 63 | } else { 64 | current_position += 3; 65 | } 66 | } 67 | 6 => { 68 | // jump-if-false 69 | let test_value = get_value(&program, current_position, ¤t_inst, 0); 70 | if test_value == 0 { 71 | let jump_location = get_value(&program, current_position, ¤t_inst, 1); 72 | current_position = jump_location as usize; 73 | } else { 74 | current_position += 3; 75 | } 76 | } 77 | 7 => { 78 | // less-than 79 | let output_position = program[current_position + 3] as usize; 80 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 81 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 82 | let answer = if input1 < input2 { 1 } else { 0 }; 83 | program[output_position] = answer; 84 | current_position += 4; 85 | } 86 | 8 => { 87 | // equals 88 | let output_position = program[current_position + 3] as usize; 89 | let input1 = get_value(&program, current_position, ¤t_inst, 0); 90 | let input2 = get_value(&program, current_position, ¤t_inst, 1); 91 | let answer = if input1 == input2 { 1 } else { 0 }; 92 | program[output_position] = answer; 93 | current_position += 4; 94 | } 95 | other => panic!("Unknown opcode: {}", other), 96 | } 97 | current_inst = instruction(program[current_position]); 98 | } 99 | 100 | (program, output) 101 | } 102 | 103 | #[derive(Debug, PartialEq, Clone, Copy)] 104 | enum Mode { 105 | Position, 106 | Immediate, 107 | } 108 | 109 | #[derive(Debug, PartialEq)] 110 | struct Instruction { 111 | opcode: i32, 112 | modes: Vec, 113 | } 114 | 115 | impl Instruction { 116 | fn mode(&self, parameter: usize) -> Mode { 117 | self.modes.get(parameter).copied().unwrap_or(Mode::Position) 118 | } 119 | } 120 | 121 | fn instruction(mut full_opcode: i32) -> Instruction { 122 | let opcode = full_opcode % 100; 123 | full_opcode /= 100; 124 | 125 | let mut modes = vec![]; 126 | 127 | while full_opcode > 0 { 128 | let mode = match full_opcode % 10 { 129 | 0 => Mode::Position, 130 | 1 => Mode::Immediate, 131 | other => panic!("Unexpected parameter mode: {}", other), 132 | }; 133 | modes.push(mode); 134 | full_opcode /= 10; 135 | } 136 | 137 | Instruction { opcode, modes } 138 | } 139 | 140 | fn get_value( 141 | program: &[i32], 142 | instruction_pointer: usize, 143 | inst: &Instruction, 144 | parameter_index: usize, 145 | ) -> i32 { 146 | let parameter_location = instruction_pointer + parameter_index + 1; 147 | 148 | match inst.mode(parameter_index) { 149 | Mode::Position => program[program[parameter_location] as usize], 150 | Mode::Immediate => program[parameter_location], 151 | } 152 | } 153 | 154 | #[cfg(test)] 155 | mod tests { 156 | use super::*; 157 | 158 | #[test] 159 | fn opcode_99_ends() { 160 | let program = vec![99]; 161 | let (answer, _output) = run_intcode(program, vec![]); 162 | assert_eq!(answer, vec![99]); 163 | } 164 | 165 | #[test] 166 | fn opcode_1_adds() { 167 | let program = vec![1, 0, 0, 0, 99]; 168 | let (answer, _output) = run_intcode(program, vec![]); 169 | assert_eq!(answer, vec![2, 0, 0, 0, 99]); 170 | } 171 | 172 | #[test] 173 | fn opcode_2_multiplies() { 174 | let program = vec![2, 3, 0, 3, 99]; 175 | let (answer, _output) = run_intcode(program, vec![]); 176 | assert_eq!(answer, vec![2, 3, 0, 6, 99]); 177 | } 178 | 179 | #[test] 180 | fn multiply_and_store_after_program() { 181 | let program = vec![2, 4, 4, 5, 99, 0]; 182 | let (answer, _output) = run_intcode(program, vec![]); 183 | assert_eq!(answer, vec![2, 4, 4, 5, 99, 9801]); 184 | } 185 | 186 | #[test] 187 | fn program_keeps_going_if_an_instruction_changes() { 188 | let program = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; 189 | let (answer, _output) = run_intcode(program, vec![]); 190 | assert_eq!(answer, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); 191 | } 192 | 193 | #[test] 194 | fn opcode_3_takes_input() { 195 | let program = vec![3, 0, 99]; 196 | let (answer, _output) = run_intcode(program, vec![7]); 197 | assert_eq!(answer, vec![7, 0, 99]); 198 | } 199 | 200 | #[test] 201 | fn programs_can_have_arbitrary_numbers_of_opcode_3_with_enough_input() { 202 | let program = vec![3, 0, 3, 1, 99]; 203 | let (answer, _output) = run_intcode(program, vec![7, 8]); 204 | assert_eq!(answer, vec![7, 8, 3, 1, 99]); 205 | } 206 | 207 | #[test] 208 | #[should_panic(expected = "Should have had enough input for opcode 3")] 209 | fn programs_panics_if_opcode_3_doesnt_have_input() { 210 | let program = vec![3, 0, 3, 1, 99]; 211 | run_intcode(program, vec![7]); 212 | } 213 | 214 | #[test] 215 | fn opcode_4_returns_output() { 216 | let program = vec![4, 2, 99]; 217 | let (_answer, output) = run_intcode(program, vec![]); 218 | assert_eq!(output, vec![99]); 219 | } 220 | 221 | #[test] 222 | fn opcode_5_jumps_if_true() { 223 | // Test value is false; 42 gets printed 224 | let program = vec![1005, 6, 5, 104, 42, 99, 0]; 225 | let (_answer, output) = run_intcode(program, vec![]); 226 | assert_eq!(output, vec![42]); 227 | 228 | // Test value is true; print gets jumped over 229 | let program = vec![1005, 6, 5, 104, 42, 99, 3]; 230 | let (_answer, output) = run_intcode(program, vec![]); 231 | assert_eq!(output, vec![]); 232 | } 233 | 234 | #[test] 235 | fn opcode_6_jumps_if_false() { 236 | // Test value is false; print gets jumped over 237 | let program = vec![1006, 6, 5, 104, 42, 99, 0]; 238 | let (_answer, output) = run_intcode(program, vec![]); 239 | assert_eq!(output, vec![]); 240 | 241 | // Test value is true; 42 gets printed 242 | let program = vec![1006, 6, 5, 104, 42, 99, 3]; 243 | let (_answer, output) = run_intcode(program, vec![]); 244 | assert_eq!(output, vec![42]); 245 | } 246 | 247 | #[test] 248 | fn opcode_7_less_than() { 249 | let program = vec![1107, 4, 5, 3, 99]; 250 | let (answer, _output) = run_intcode(program, vec![]); 251 | assert_eq!(answer, vec![1107, 4, 5, 1, 99]); 252 | 253 | let program = vec![1107, 5, 4, 3, 99]; 254 | let (answer, _output) = run_intcode(program, vec![]); 255 | assert_eq!(answer, vec![1107, 5, 4, 0, 99]); 256 | } 257 | 258 | #[test] 259 | fn opcode_8_equals() { 260 | let program = vec![1108, 4, 4, 3, 99]; 261 | let (answer, _output) = run_intcode(program, vec![]); 262 | assert_eq!(answer, vec![1108, 4, 4, 1, 99]); 263 | 264 | let program = vec![1108, 5, 4, 3, 99]; 265 | let (answer, _output) = run_intcode(program, vec![]); 266 | assert_eq!(answer, vec![1108, 5, 4, 0, 99]); 267 | } 268 | 269 | #[test] 270 | #[should_panic(expected = "Unknown opcode: 42")] 271 | fn unknown_opcode_panics() { 272 | let program = vec![42]; 273 | run_intcode(program, vec![]); 274 | } 275 | 276 | #[test] 277 | fn interpret_parameter_modes_all_position_mode() { 278 | let inst = instruction(2); 279 | assert_eq!(inst.opcode, 2); 280 | assert_eq!(inst.mode(0), Mode::Position); 281 | assert_eq!(inst.mode(1), Mode::Position); 282 | assert_eq!(inst.mode(2), Mode::Position); 283 | 284 | let inst = instruction(4); 285 | assert_eq!(inst.opcode, 4); 286 | assert_eq!(inst.mode(0), Mode::Position); 287 | assert_eq!(inst.mode(1), Mode::Position); 288 | assert_eq!(inst.mode(2), Mode::Position); 289 | 290 | let inst = instruction(99); 291 | assert_eq!(inst.opcode, 99); 292 | } 293 | 294 | #[test] 295 | fn interpret_parameter_modes_that_have_some_immediate_mode() { 296 | let inst = instruction(104); 297 | assert_eq!(inst.opcode, 4); 298 | assert_eq!(inst.mode(0), Mode::Immediate); 299 | 300 | let inst = instruction(1002); 301 | assert_eq!(inst.opcode, 2); 302 | assert_eq!(inst.mode(0), Mode::Position); 303 | assert_eq!(inst.mode(1), Mode::Immediate); 304 | assert_eq!(inst.mode(2), Mode::Position); 305 | } 306 | 307 | #[test] 308 | fn use_parameter_modes_in_programs() { 309 | let program = vec![1002, 4, 3, 4, 33]; 310 | let (answer, _output) = run_intcode(program, vec![]); 311 | assert_eq!(answer, vec![1002, 4, 3, 4, 99]); 312 | } 313 | 314 | #[test] 315 | fn get_value_helper_function() { 316 | let program = vec![1, 0, 0, 0, 99]; 317 | let inst = instruction(program[0]); 318 | let instruction_pointer = 0; 319 | 320 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 1); 321 | 322 | let program = vec![104, 18, 99]; 323 | let inst = instruction(program[0]); 324 | assert_eq!(get_value(&program, instruction_pointer, &inst, 0), 18); 325 | } 326 | 327 | #[test] 328 | fn chain_intcode_runs() { 329 | let program = vec![3, 11, 3, 12, 1, 11, 12, 13, 4, 13, 99, -1, -2, -3]; 330 | let phase_settings = [20, 22, 24]; 331 | let output = run_with_phase_settings(&program, &phase_settings); 332 | assert_eq!(output, 66); 333 | } 334 | 335 | #[test] 336 | fn max_value_from_all_phase_setting_orders() { 337 | let phase_settings = [0, 1, 2, 3, 4]; 338 | 339 | let program = vec![ 340 | 3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0, 341 | ]; 342 | let max = max_signal(&program, &phase_settings); 343 | assert_eq!(max, 43210); 344 | 345 | let program = vec![ 346 | 3, 23, 3, 24, 1002, 24, 10, 24, 1002, 23, -1, 23, 101, 5, 23, 23, 1, 24, 23, 23, 4, 23, 347 | 99, 0, 0, 348 | ]; 349 | let max = max_signal(&program, &phase_settings); 350 | assert_eq!(max, 54321); 351 | 352 | let program = vec![ 353 | 3, 31, 3, 32, 1002, 32, 10, 32, 1001, 31, -2, 31, 1007, 31, 0, 33, 1002, 33, 7, 33, 1, 354 | 33, 31, 31, 1, 32, 31, 31, 4, 31, 99, 0, 0, 0, 355 | ]; 356 | let max = max_signal(&program, &phase_settings); 357 | assert_eq!(max, 65210); 358 | } 359 | } 360 | 361 | fn run_with_phase_settings(program: &[i32], phase_settings: &[i32]) -> i32 { 362 | let mut carried_input = 0; 363 | 364 | for &setting in phase_settings { 365 | let inputs = vec![setting, carried_input]; 366 | 367 | let (_answer, output) = run_intcode(program.to_owned(), inputs); 368 | carried_input = *output.first().expect("Program must return some output"); 369 | } 370 | 371 | carried_input 372 | } 373 | 374 | fn max_signal(program: &[i32], phase_settings: &[i32]) -> i32 { 375 | permute(phase_settings.to_owned()) 376 | .iter() 377 | .map(|setting_ordering| run_with_phase_settings(program, setting_ordering)) 378 | .max() 379 | .expect("Must have had orderings") 380 | } 381 | -------------------------------------------------------------------------------- /aoc-08-01/input: -------------------------------------------------------------------------------- 1 | 222222222222222120222222220212222222022222222222222222221222212222022222012202022022212222122202222222222200022220222222202202122212222122122222222222212222222222222121222220222202222222222222222222222222221222212222122222002212022022202222122222212222222201122221222222212202222222222022022222222222212222222222222220222221222202222222222222222222222222220222212222222222212202022022212222122202212222222200022220222222212222022212222022222222222222222222222222222220222221221202222222222222222222222222220222212222222222022212122122212222222222202222222222022220222222202202222222222022122222222222212222222222222021222221222202222222222222222222222222222222222222122222102212122022202222122202212222222200222222222222202202222212222222122222222222212222222222222022222222220212222222222222222222222222211202212202121222022210222122222222022222222222222211222220222222222202122202222022222222222222222222222222222022222220221202222222122222222222222222222222222222120222122212122022202222222212202222222211122221222222202212122202220122022222222222222222222222222220222222222212222222122222222222222222001212212212022222122220222222202222222222212222222220222221222222202212222212220222122222222222202222222222222120222220222212222222122222222222222222121212222202221222112220222122212222022202212222222201122220222222212202122222220222122222222222212222222222222021222220221222222222222222222222222222120202222202122222222210122222202222022202222222222222022221222222222202122202222022122222222222212222222222222021222220222222222222022222222222222222112222202222022222012201122222222222122212202220222220222222222222222222022212222022122222222222202222222222222222222220022202222222122222222222222222121222212222220222122221222022212222122212202221222100022221222222202202222222222022222222222222222222222222222221222222022212220222122222222222202222102212202202222222112221122222222222222202202221222022022221222220202222122212220222222222222222212222222222222122222222222212221222022222222222222222212202212202022222112210122222212222222222202221222112122220222220222202122202220120122222222222012222222222222120222222220222221222222222222222202222111222202222120222002200222022202222222222212222222000222221222220222212122212221121022222222222102222222222222021222222222222220222122222222222202222112222202212021222002202022022212222222222212210222012022221222222202222112202222022222222222222222222222222222021222220021222221222022222222222212222221222222202121222112210122122012222222222202212222120222221222222222222002212222220222222222222102222122222222021222221020222221222122222222222212222210212212222021222022212222122202222222212212220222011222221222222212202012202221120122222222222202222022222222022222222121222222222022222222222202222212212222202220222202200222222122222122212222221222001122221222221202212122202221121122222222222102222122222222121222221020212220222020222222220222222122222202202220222012210122122022222022222222202222202222220222221202202212212222120222222222222012222022222222221222120221202221222021222222220202222102222222212022222122202222122122222022212222222222020022221222221222202222202221120202222222222122222122222222121222022020202220222221222222220222222210222202222121222002210022122112222122212212212222000222222222221222202002222222121102222222222102222122222222122222122222212221222021222222220222222101212202202221222012211022122002222022222202221222120222222222222202212002202222122022222222222022222022222222120222122221212221222120220222221202222222222202212022222112211022022002222222202202201222022122222222220222202002202220222202222222222002222122222222022222220021222221222121221222222212222212202212222221222002220022022212222222212212220222112122221222222212202222202222220122222222222122222022222222220222120021202222222020222222220222222210222202202120222222212122122022222022202222200222110222222222222202202012202221121112222222222222222222222222020222120020212222222221222222222222222200212212222120222222211222122002222022222222211222212122221222221202212222202220021022222222222102222122222222122222121120212221222220222222202212222011212212202221222202210122122212222022202202221222121122222222221212222122212222222112222222222011222222222022221222222122212220222020221222210202222101212202012120222012202122022202222122202202210222120222222222220202222202222221120012222222222012222022222022120222122122202221222122212222212202222200202222222021222202211122022222222222202202210222101022222222222222202022222220221012222222222012222022222120022222120222222222222022202222201202222202202222212121222122210022122012222122222202211222021222221022221222222102222221220112222222222020222222222121121222220022212222222122220222200212222212222202002221012010200022222122222022222222201222010222220022222222222102222221122022222222222121222122222120020222022020202221222021201222221221222101202212102022020100212022122122222022222222222222011122221022222202222022222220222122222222222110222022222021222222220022222221222220220222212210222202222212112220010100221222022022222022222212202222112022221222222202222202212220120122222212022102222022222220221222220222222221222021212222210212222012202212102222100120212222022112222022222212200222121022220022220212202102202220122202222202222222222222222020221222221120222221222221202222222220222012202212012121020012202122122012222122212202221222201222221022220202222102202221021012222202122211222122222121120222121121212221222121212222222200222202202202122020110222201222022012122022202202221222020122220022221212212002222221222202222202122201222122222121120222122221222220222020211222200211222012212212202021112220201222022112022222222222210222222022220122220212222122202220222112222222022020222222222021021222222121212220222220212222212201222122212222122220102022221122022222122122212202210222110122222122220222222012202221021012222202222212222122222121022222120222212221222020210222210202222001212212012000200101201222122122222122222222212222101222222122210212222222202222121012222222222121222222212121122222020122212220222222210222220200222221222202102222211001202122022012122022202222200222121222220222202202202002222221221222222202222020222222212022222222020021202221222222212222222201222222212212002010111002221222222112222222202212202222111222222222201212202002212222022202222222222112222222202120021222120220202220222122202222222221222202212202112222021110220022122122122122222222202222221022221122212222212012202220021122222212222021222222212120121222222221222222222220201222211200222102212222102121010100212222022112122222202202200222011222220022211202222022202222222202222222122001222222222022222222021221222220222021211222212200222100212212022101221020212222122022022222212222202222211222220022202222202212202221221002222202122220222022212222120222022122202220222020212222221220222020212212202112101020200022222102222122202202210022112022220022200202222022212220221212222202222001222122202122120222021121202220202222202222202220222211222212202120120211201222022202122222212202201022112022221122221202222212212222222102222202222211222022220122220222022021202221212222222222222210222122222222022122001211222122022012122122202202212122200002220022211212222012212221020212222222222121222222200220020222120120202220202120210222222222222101222202002101200022222222222012122022222222211122201202221222210212202212202221120020222222122012222222220022122222120222202220202222201222220221222220222212212110000110200022122212022122212202220122021202221022221222222022202220020200222202222221222022212222021222220222212221212221201222200222222210202212112212022200210222022002022022212222200022222212220222222202222202202221221002220012122102222122211120200222020221202220222222220222211222222002212202102112112102202222222002022022222222202022201202221222201222212102222221220002220112022022222022201120002222122220222222222022012222211202222220222212202202102110201222022102022022112222201022211222221122200212202022222222121222221222122020222222222122102222022121222220222120002222202220222112202222022110012121202122122202122222112212211022201122220122222200212112222212022201221102222212222122212221222222021120222222222221201222222220202220202212122122200120211122222122222222112212221022020122220122200200222002222202220020220112122001222222220022211222122020002220202020121222212221202112202212222022001100220122122122222022222212222222021122221122220221202112212201022012222102222010222222210120012222122122212221212121102222211202212100202212112101202221221122222202122122012212211022002202222222200202202212202222222020222022222022222222221121121222020021012222212122221222222211202200212202002112010202200122222012022222202202200022122212221222212111222122202212020211222022022122222122222122012222121121202221222020011222202211212200212202022220112020210122022122122122202202222222020022221122200220212222212202122021212022022021222122210120222222222122112220202020112222221202202202222202102120212121212022222222122022102202220022220122220222222122222102222212220102220102022222222222210222202222020121102220222222000222222201212210222222202012012011201122122222022222102212211222002022221022211210212202222201222200200002012011222222202121121222020221002222212121220222222200222110222202002101021122221022222102222222222202201222020222222222200210212122212220120010200112222022222022201020121222022221002222202022120222201201222010212222002220112100211022122112022122002222201222112102221022202202212202212212220211200102212011222122211122221222122021122220202121221222201222212021222202202022201202210122222212022022112212222222100122221222222002212022222200121022202222112121222022211222121222222020022222202020222222201221202010202222012210001020222122022012022022022202220022100112222022200221212022022211102220202212102010222222222122200222221022112222212022122222200200222101222212002211210000211222222202022122022112201122110212222022211201202112222210201202202022212022222022212021221222021121102220212122212222210211222212222202222210201112211102122012222222002212220022021112221022210100222112212220001111211102112212222222211020100222220220002222212222101222210221202022212212112212000022212102022002022022202202211122100002222020201211212022202212222110200022012210221022221021120222120220212120222122102222222220202102222212012101121120202002022122222222222002021022010112221120212122202012122211002010212012112121220212221020020222120022122122202022000222200201202202212202122201222221211022222102122122012222011022012102220021221022212112102200222210202122202212221012222211022222020120202021222221112222210221202222212212012012121211202202222122022122102222020022220122221220211122222012022202021012201012012122221022220102101220012021002121212021222222210212212102212212002012111101212202222122122122212202211122221002222020200121212112222220000122211012222222220022201121001220201220202120202021002222220220212120122202222201202020210002122222122122222012221222110212221020210100222012002211020222221222122001221102222100021222002220222122222222100222201212202002202222112110211200220222122012222222002112122122021112222021210022222122112210200211210012202021221011210111210222112020202022202120100222211212222222212222102200020111211102122112122022222022101022001002222222202221222022222210120112211002212210222100200101222222212222012220222121002222210200202022112202212212011120200022022112020122022002121122100202220121221110222202022220201212210102212200220121212112100222110221012222222121001222221221202122202202012200122011222022222002220122212012110222220221222021012000222222122222101211122222112210222202200021001221210020002121212022102222222211212212212212122000122200222112122122220122202012221222002020220120102121212212102220021122022222022010222211200000111221000120012120212222110222221221200110222222122120022102221002222022222222002002010122210202222120001101212122102200210222022212002010222222220111122222002120112020212222200220200200222101012212022110221202210122222222221122212212211022010122222220202012202002202201102222110222012121222220211120212222211021012122202020121221212202201120020212012210201002110112022122120022222212200222012120220222000102222202012211211112201010112012221002210022012221022120122020202020122220202210211111001202102012100200110002022002021022212202210022200221222120000112202022002212002121010120202111221102212000200222021222112121222222221222201201201121201212002001221122201012122112222022222212122122121012222122011110202022012212201001210100202022222221210221020222110121012121222120100220202221201112011222012012021210220122222022021122212002200122202122222120001000212122202220110201100022012222222201211222110222110021212120202121220222222211211220021212202010010010011102022002220222012112020122101212221121201111202112222201201222101000022111220101211110202221021120102021202022021222210202220120212222112120202111000022022202220222102122100122011122220122202100222012002211012222222002012222221012201201212222221122222122212022010020222211212011102212002200100211002112022212120122122222202022110212221022120221222002212212121102002001122022221122221110201220120220102022202122122021210220222202112222212101211112000002022022020122022112112220012212221221101200202202102201012222211102102022221100201101200222211120222021212022010022212210200111120212212121011000101122022102121122022102100222221110221120021220222122222201011202110011112220222212200002002221122022222021202121122121210212220212000212122010221210120202022222021022222012000120212220222021120122220202202221210221101221012222020201200002010201201222012120212021000221221221222201010222012111200202221012122112220222022012220122112122222021001102220012012212221110000020012010120002210212011222100122022120202121221222201201202202002222222222211110201202122212121022012011122222121000220122000102200022022210001122212221202201220101201002121200210022022221202120202121212212212010110202022222120211211122022012122122112212010222010220220220102100220202112222120100011200202110120221200210011200202022022022222222001222200210222110110222212020122002000222222212020122202122112121011000222021101202221222212222110100221120102010220020202111100222212022012022222220211222202222210002010222002201222110102022022112220020002001121222200211222220101100201102222222011201001221002220120220212112110211101022002120222021200122211202222021222212002011201011212021222112021022211202100120210200221022200212211102102212211122202021002020221001222022212220210021002220202022012211222221220001120202212201202210000201222212022222021202112120012212220120000110210012102211111200100010012010221222222121220202110222102120212120011102200202202202222112212201100201022201222102022220121020202021211001222120122102201102202212000202021101112202020200222221122202210122002022212112102202220212222121200002202202001211222012122012120221112121222022211210221121212200110122102220202111010220010201001201001100010120201012120201021020111021100120000200112010211101122001102102200110200200000121122212011022011112021022122210001101000112120101202 2 | --------------------------------------------------------------------------------