first commit
This commit is contained in:
commit
33b031c8da
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**/*.input
|
||||||
|
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
*/debug/
|
||||||
|
*/target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
*/Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
6
day01/Cargo.toml
Normal file
6
day01/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day01"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
54
day01/src/main.rs
Normal file
54
day01/src/main.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::env;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, AoC day 01!");
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
println!("wrong number of arguments!");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = &args[1];
|
||||||
|
|
||||||
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
let mut first: Vec<i32> = Vec::new();
|
||||||
|
let mut second: Vec<i32> = Vec::new();
|
||||||
|
|
||||||
|
let mut counts: HashMap<i32, i32> = HashMap::new();
|
||||||
|
|
||||||
|
for line in contents.lines() {
|
||||||
|
let numbers: Vec<_> = line.split_whitespace().collect();
|
||||||
|
let (first_str, second_str) = (numbers[0], numbers[1]);
|
||||||
|
let (first_num, second_num) = (first_str.parse().unwrap(), second_str.parse().unwrap());
|
||||||
|
|
||||||
|
first.push(first_num);
|
||||||
|
second.push(second_num);
|
||||||
|
|
||||||
|
let count = counts.entry(second_num).or_insert(0);
|
||||||
|
*count = *count + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
first.sort();
|
||||||
|
second.sort();
|
||||||
|
|
||||||
|
let mut sum:i32 = 0;
|
||||||
|
for (first_num, second_num) in iter::zip(first.iter(), second.iter()) {
|
||||||
|
let difference = (first_num - second_num).abs();
|
||||||
|
|
||||||
|
sum = sum + difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("the sum of the differences is {sum}");
|
||||||
|
|
||||||
|
let mut similarity: i32 = 0;
|
||||||
|
for num in first {
|
||||||
|
similarity += num * counts.get(&num).unwrap_or(&0);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("similarity score is {similarity}");
|
||||||
|
}
|
6
day02/Cargo.toml
Normal file
6
day02/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day02"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
71
day02/src/main.rs
Normal file
71
day02/src/main.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, AoC day 02!");
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
println!("wrong number of arguments!");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = &args[1];
|
||||||
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
|
||||||
|
let mut safe_reports: i32 = 0;
|
||||||
|
let mut safe_reports_with_dampener: i32 = 0;
|
||||||
|
|
||||||
|
for line in contents.lines() {
|
||||||
|
let report: Vec<i32> = line.split_whitespace().map(|s| s.parse().unwrap()).collect();
|
||||||
|
|
||||||
|
let safe = is_safe(&report);
|
||||||
|
|
||||||
|
if safe {
|
||||||
|
safe_reports += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..report.len() {
|
||||||
|
let skipped = [ &report[..i], &report[(i+1)..] ].concat();
|
||||||
|
|
||||||
|
if is_safe(&skipped) || safe {
|
||||||
|
safe_reports_with_dampener += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("there were {safe_reports} safe reports");
|
||||||
|
println!("there were {safe_reports_with_dampener} safe reports with the dampener turned on");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_safe(report: &[i32]) -> bool {
|
||||||
|
let mut increasing = false;
|
||||||
|
let mut last_value = 0;
|
||||||
|
|
||||||
|
for (i, &value) in report.iter().enumerate() {
|
||||||
|
if i == 0 {
|
||||||
|
last_value = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if i == 1 {
|
||||||
|
increasing = value > last_value;
|
||||||
|
} else {
|
||||||
|
if increasing && (value < last_value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if !increasing && (value > last_value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let difference = (value - last_value).abs();
|
||||||
|
if difference < 1 || difference > 3 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
7
day03/Cargo.toml
Normal file
7
day03/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "day03"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
regex = "1.11.1"
|
70
day03/src/main.rs
Normal file
70
day03/src/main.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::env;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, AoC day 03!");
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
println!("wrong number of arguments!");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = &args[1];
|
||||||
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
|
||||||
|
let mul_instructions = Regex::new(r"mul\(([0-9]{1,3}),([0-9]{1,3})\)").unwrap();
|
||||||
|
let mut sum = 0;
|
||||||
|
for (_, [a, b]) in mul_instructions.captures_iter(&contents).map(|n| n.extract()) {
|
||||||
|
let (first, second): (i32, i32) = (a.parse().unwrap(), b.parse().unwrap());
|
||||||
|
sum = sum + first*second;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("the sum is {sum}");
|
||||||
|
|
||||||
|
let initial_dont = Regex::new(r"^don't()").unwrap();
|
||||||
|
|
||||||
|
let donts = contents.match_indices("don't()");
|
||||||
|
let dos = contents.match_indices("do()");
|
||||||
|
|
||||||
|
let donts_indices = donts.map(|(i, _sep)| i);
|
||||||
|
let dos_indices = dos.map(|(i, _sep)| i);
|
||||||
|
let mut dos_and_donts_indices: Vec<usize> =
|
||||||
|
donts_indices
|
||||||
|
.chain(dos_indices)
|
||||||
|
.chain([contents.len()]) // just to make sure the last segment gets caught!
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
dos_and_donts_indices.sort();
|
||||||
|
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut last_index = 0;
|
||||||
|
for current_index in dos_and_donts_indices {
|
||||||
|
let current_slice = &contents[last_index..current_index];
|
||||||
|
last_index = current_index;
|
||||||
|
|
||||||
|
if initial_dont.is_match(current_slice) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, [a, b]) in mul_instructions.captures_iter(current_slice).map(|n| n.extract()) {
|
||||||
|
let (first, second): (i32, i32) = (a.parse().unwrap(), b.parse().unwrap());
|
||||||
|
sum = sum + first * second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("the sum for part b is {sum}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
6
day04/Cargo.toml
Normal file
6
day04/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day04"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
82
day04/src/main.rs
Normal file
82
day04/src/main.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::env;
|
||||||
|
use crate::Dir::{North, South, East, West, NorthEast, NorthWest, SouthEast, SouthWest};
|
||||||
|
|
||||||
|
// nodes are (coord, direction) pairs.
|
||||||
|
// neighbors are step1+turnleft, step2+turnleft, step3+turnleft, step1+turnright, etc
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
enum Dir { North, South, East, West, NorthEast, NorthWest, SouthEast, SouthWest }
|
||||||
|
|
||||||
|
fn step(start: &Coord, d: Dir, steps: i32) -> Coord {
|
||||||
|
match d {
|
||||||
|
North => (start.0, start.1 - steps),
|
||||||
|
South => (start.0, start.1 + steps),
|
||||||
|
East => (start.0 + steps, start.1),
|
||||||
|
West => (start.0 - steps, start.1),
|
||||||
|
NorthEast => (start.0 + steps, start.1 - steps),
|
||||||
|
NorthWest => (start.0 - steps, start.1 - steps),
|
||||||
|
SouthEast => (start.0 + steps, start.1 + steps),
|
||||||
|
SouthWest => (start.0 - steps, start.1 + steps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Coord = (i32, i32);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, AoC day 04!");
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
println!("wrong number of arguments!");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = &args[1];
|
||||||
|
|
||||||
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
let mut grid: HashMap<Coord, char> = HashMap::new();
|
||||||
|
|
||||||
|
let mut x;
|
||||||
|
// build our grid!
|
||||||
|
let mut y = 0;
|
||||||
|
for line in contents.lines() {
|
||||||
|
x = 0;
|
||||||
|
for c in line.chars() {
|
||||||
|
grid.insert((x,y), c);
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut xsum = 0;
|
||||||
|
|
||||||
|
let directions = vec![North, South, East, West, NorthEast, NorthWest, SouthEast, SouthWest];
|
||||||
|
for (position, _letter) in &grid {
|
||||||
|
for dir in &directions {
|
||||||
|
if check(position, &grid, *dir) { sum += 1 }
|
||||||
|
}
|
||||||
|
if xcheck(position, &grid) { xsum += 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("there are {sum} xmases");
|
||||||
|
println!("there are {xsum} x-mases");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(position: &Coord, grid: &HashMap<Coord, char>, direction: Dir) -> bool {
|
||||||
|
if grid.get(&step(position, direction, 0)) != Some(&'X') { return false; }
|
||||||
|
if grid.get(&step(position, direction, 1)) != Some(&'M') { return false; }
|
||||||
|
if grid.get(&step(position, direction, 2)) != Some(&'A') { return false; }
|
||||||
|
if grid.get(&step(position, direction, 3)) != Some(&'S') { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xcheck(position: &Coord, grid: &HashMap<Coord, char>) -> bool {
|
||||||
|
if grid.get(position) != Some(&'A') { return false; }
|
||||||
|
let a = (grid.get(&step(position, NorthEast, 1)), grid.get(&step(position, SouthWest, 1)));
|
||||||
|
let b = (grid.get(&step(position, SouthEast, 1)), grid.get(&step(position, NorthWest, 1)));
|
||||||
|
if a != (Some(&'M'), Some(&'S')) && a != (Some(&'S'), Some(&'M')) { return false; }
|
||||||
|
if b != (Some(&'M'), Some(&'S')) && b != (Some(&'S'), Some(&'M')) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
8
day05/Cargo.toml
Normal file
8
day05/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "day05"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
regex = "1.11.1"
|
||||||
|
topological-sort = "0.2.2"
|
70
day05/src/main.rs
Normal file
70
day05/src/main.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use std::iter;
|
||||||
|
use std::fs;
|
||||||
|
use std::env;
|
||||||
|
use topological_sort::TopologicalSort;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
struct Rule ( i32, i32 );
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, AoC day 05!");
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
println!("wrong number of arguments!");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = &args[1];
|
||||||
|
|
||||||
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
let (first, second) = contents.split_once("\n\n").unwrap();
|
||||||
|
|
||||||
|
let rules: Vec<Rule> = first
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let (before, after) = line.split_once("|").unwrap();
|
||||||
|
Rule(before.parse().unwrap(), after.parse().unwrap())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let updates = second.lines();
|
||||||
|
|
||||||
|
let mut good_sum: i32 = 0;
|
||||||
|
let mut bad_sum: i32 = 0;
|
||||||
|
for update in updates {
|
||||||
|
let pages: Vec<i32> = update
|
||||||
|
.split(",")
|
||||||
|
.map(|page| page.parse::<i32>().unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut my_sort: TopologicalSort::<i32> = TopologicalSort::new();
|
||||||
|
|
||||||
|
rules
|
||||||
|
.iter()
|
||||||
|
.filter(|&Rule(a, b)| pages.contains(a) && pages.contains(b))
|
||||||
|
.for_each(|&Rule(a, b)| my_sort.add_dependency(a, b));
|
||||||
|
|
||||||
|
let true_pages: Vec<i32> = iter::from_fn(|| my_sort.pop())
|
||||||
|
.filter(|p| pages.contains(p))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let middle: i32 = *halfway(&true_pages).expect("error finding the halfway point");
|
||||||
|
|
||||||
|
if iter::zip(pages.iter(), true_pages.iter()).all(|(a, b)| a==b) {
|
||||||
|
// it's good!
|
||||||
|
good_sum += middle;
|
||||||
|
} else {
|
||||||
|
// it's bad!
|
||||||
|
bad_sum += middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("the sum of middle pages of good updates is {good_sum}");
|
||||||
|
println!("and the bad updates is {bad_sum}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn halfway<T>(v: &[T]) -> Option<&T> {
|
||||||
|
if v.len() == 0 { return None; }
|
||||||
|
return v.get((v.len() - 1) / 2)
|
||||||
|
}
|
6
day06/Cargo.toml
Normal file
6
day06/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day06"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
3
day06/src/main.rs
Normal file
3
day06/src/main.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user