From 646925298c110a3acb460cac5363e8c5baae7e1f Mon Sep 17 00:00:00 2001 From: Lars Martens Date: Fri, 1 Dec 2023 11:50:28 +0100 Subject: [PATCH] Solve day 1 --- .gitignore | 4 ++ Cargo.lock | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 ++++ README.md | 21 +++++++ input/01-test | 4 ++ input/01-test-2 | 7 +++ justfile | 28 +++++++++ src/bin/01.rs | 83 +++++++++++++++++++++++++ src/lib.rs | 1 + 9 files changed, 316 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 input/01-test create mode 100644 input/01-test-2 create mode 100644 justfile create mode 100644 src/bin/01.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..feb3290 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +output/ +.idea/ +.env diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2dc881a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,157 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "aoc2023" +version = "0.0.0" +dependencies = [ + "anyhow", + "itertools", + "regex", + "serde", + "serde_json", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..871da03 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "aoc2023" +version = "0.0.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.75" +itertools = "0.12.0" +regex = "1.10.2" +serde = { version = "1.0.193", features = ["derive"] } +serde_json = "1.0.108" diff --git a/README.md b/README.md new file mode 100644 index 0000000..87ffe84 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Advent Of Code 2023 + +My solutions for [Advent Of Code](https://adventofcode.com) 2023. + +## Usage + +This project uses [`just`](https://github.com/casey/just) . For some commands to work a session token needs to be provided in the `AOC_SESSION` environment variable. The easiest way to set it is to create the file `.env` with `AOC_SESSION=your token` inside in the root of this repository. The token can be received by reading the session cookie from the AOC website. + +Download the puzzle input, create a file for the current day and open it in RustRover: + +```shell +just begin # Prepare the current day +just day=09 begin # Prepare day 9 +``` + +Run: + +```shell +just # Runs the current day +just day=09 # Runs day 9 +``` diff --git a/input/01-test b/input/01-test new file mode 100644 index 0000000..1ba8437 --- /dev/null +++ b/input/01-test @@ -0,0 +1,4 @@ +1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet \ No newline at end of file diff --git a/input/01-test-2 b/input/01-test-2 new file mode 100644 index 0000000..4316a6b --- /dev/null +++ b/input/01-test-2 @@ -0,0 +1,7 @@ +two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen \ No newline at end of file diff --git a/justfile b/justfile new file mode 100644 index 0000000..02be014 --- /dev/null +++ b/justfile @@ -0,0 +1,28 @@ +set dotenv-load + +day := `date +%d` +dayWithout0 := trim_start_match(day, "0") +year := "2023" +file := "src/bin/" + day + ".rs" + +# Format, lint, and run the program for today. +run: _output-folder + rustfmt src/bin/{{day}}.rs + cargo clippy + # Hide warning here because we just ran clippy + RUSTFLAGS=-Awarnings cargo run --release --bin {{day}} | tee "output/{{day}}.log" + +# Begin working on todays problem. Downloads input, creates template and opens the problem and code. +begin: _input-folder + echo "use aoc2023::*; const INPUT: &str = include_str!(\"../../input/{{day}}\"); const TEST_INPUT: &str = include_str!(\"../../input/{{day}}-test\"); fn main() {}" >> {{file}} + rustfmt {{file}} + curl --silent "https://adventofcode.com/{{year}}/day/{{dayWithout0}}/input" -H "Cookie: session=$AOC_SESSION" > "input/{{day}}" + touch input/{{day}}-test + rustrover {{file}} + open "https://adventofcode.com/{{year}}/day/{{dayWithout0}}" + +_output-folder: + mkdir -p output + +_input-folder: + mkdir -p input diff --git a/src/bin/01.rs b/src/bin/01.rs new file mode 100644 index 0000000..177d2a7 --- /dev/null +++ b/src/bin/01.rs @@ -0,0 +1,83 @@ +use itertools::assert_equal; + +const INPUT: &str = include_str!("../../input/01"); +const TEST_INPUT: &str = include_str!("../../input/01-test"); +const TEST_INPUT2: &str = include_str!("../../input/01-test-2"); + +fn main() { + assert_eq!(part1(TEST_INPUT), 142); + println!("Part 1: {}", part1(INPUT)); + + assert_equal(replace_with_digits("eightwothree"), [8, 2, 3]); + assert_equal(replace_with_digits("zoneight234"), [1, 8, 2, 3, 4]); + + assert_eq!(part2(TEST_INPUT2), 281); + println!("Part 2: {}", part2(INPUT)); +} + +fn part1(input: &str) -> u32 { + input + .lines() + .map(parse_digits) + .map(calibration_value_from_line) + .sum() +} + +fn part2(input: &str) -> u32 { + input + .lines() + .map(replace_with_digits) + .map(calibration_value_from_line) + .sum() +} + +fn calibration_value_from_line(line: Vec) -> u32 { + let first = line.first().copied().unwrap(); + let last = line.last().copied().unwrap_or(first); + first * 10 + last +} + +/// Parse all digits from the input +fn parse_digits(line: &str) -> Vec { + line.chars().flat_map(|c| c.to_digit(10)).collect() +} + +/// Replace all words with digits, keep digits and discard everything else. +fn replace_with_digits(line: &str) -> Vec { + let replacements = [ + ("one", 1), + ("two", 2), + ("three", 3), + ("four", 4), + ("five", 5), + ("six", 6), + ("seven", 7), + ("eight", 8), + ("nine", 9), + ]; + + let mut result = Vec::new(); + let mut buf = line.to_string(); + + while !buf.is_empty() { + if let Some(c) = buf.chars().next() { + if let Some(num) = c.to_digit(10) { + result.push(num); + buf.remove(0); + continue; + } + } + + for (find, replace) in replacements { + if buf.starts_with(find) { + result.push(replace); + buf.remove(0); + continue; + } + } + + buf.remove(0); + } + + result +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +