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