1
0
mirror of https://gitlab.com/MisterBiggs/aoc-2023-rust.git synced 2025-07-23 22:51:32 +00:00

day 1 leggoo

This commit is contained in:
2023-12-01 00:13:19 -07:00
parent 4d197e403a
commit 9cbaf311d9
14 changed files with 1083 additions and 7080 deletions

View File

@@ -1,4 +1,4 @@
use itertools::Itertools;
// use itertools::Itertools;
use std::fs;
pub fn run() {
@@ -9,32 +9,69 @@ pub fn run() {
println!("\tPart 2: {}", part2(&input));
}
fn part1(food_input: &str) -> usize {
food_input
.split("\n\n")
.into_iter()
.map(|elf| {
elf.split_whitespace()
.map(|food| food.parse::<usize>().unwrap())
.sum()
fn part1(calibration_input: &str) -> usize {
calibration_input
.split("\n")
.map(|line| {
let digits = line.chars().filter(|c| c.is_digit(10)).collect::<String>();
if digits.len() == 1 {
digits.parse::<usize>().unwrap() * 11
} else {
let tens = digits.chars().nth(0).unwrap().to_digit(10).unwrap();
let ones = digits.chars().last().unwrap().to_digit(10).unwrap();
(tens * 10 + ones) as usize
}
})
.into_iter()
.max()
.unwrap()
.sum()
}
fn part2(food_input: &str) -> usize {
food_input
.split("\n\n")
.collect::<Vec<&str>>()
.into_iter()
.map(|elf| {
elf.split_whitespace()
.map(|food| food.parse::<usize>().unwrap())
.sum::<usize>()
fn part2(calibration_input: &str) -> usize {
let word_to_digit_map: [(&str, usize); 9] = [
("one", 1),
("two", 2),
("three", 3),
("four", 4),
("five", 5),
("six", 6),
("seven", 7),
("eight", 8),
("nine", 9),
];
calibration_input
.split("\n")
.map(|line| {
let mut index_and_digit: Vec<(usize, usize)> = vec![];
for (word, digit) in word_to_digit_map {
for (index, _) in line.match_indices(word).collect::<Vec<_>>() {
index_and_digit.push((index, digit));
}
}
for (index, c) in line.chars().enumerate() {
match c.to_digit(10) {
Some(digit) => index_and_digit.push((index, digit as usize)),
None => continue,
}
}
if index_and_digit.len() == 1 {
index_and_digit[0].1 * 11
} else {
index_and_digit.sort_by(|a, b| a.0.cmp(&b.0));
println!(
"{} {}",
&line,
index_and_digit[0].1 * 10 + index_and_digit.last().unwrap().1
);
index_and_digit[0].1 * 10 + index_and_digit.last().unwrap().1
}
})
.sorted()
.rev()
.take(3)
.into_iter()
.sum()
}
@@ -44,41 +81,24 @@ mod tests {
#[test]
fn test_1() {
let input = "1000
2000
3000
let input = "1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet";
4000
5000
6000
7000
8000
9000
10000";
assert_eq!(part1(input), 24000);
assert_eq!(part1(input), 142);
}
#[test]
fn test_2() {
let input = "1000
2000
3000
let input = "two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen";
4000
5000
6000
7000
8000
9000
10000";
assert_eq!(part2(input), 45000);
assert_eq!(part2(input), 281);
}
}

View File

@@ -1,110 +0,0 @@
use itertools::Itertools;
use std::fs;
pub fn run() {
println!("Day 2:");
let input = fs::read_to_string("./inputs/day2.txt").expect("Could not read file");
println!("\tPart 1: {}", part1(&input));
println!("\tPart 2: {}", part2(&input));
}
#[derive(PartialEq, Clone, Copy)]
enum Hand {
Rock = 1,
Paper,
Scissors,
}
#[derive(Clone, Copy)]
enum Outcome {
Lost = 0,
Draw = 3,
Win = 6,
}
fn part1(input: &str) -> usize {
input
.trim()
.split('\n')
.map(|round_str| {
let round = round_str.split_once(' ').unwrap();
let opponent = match round.0 {
"A" => Hand::Rock,
"B" => Hand::Paper,
"C" => Hand::Scissors,
_ => panic!(),
};
let me = match round.1 {
"X" => Hand::Rock,
"Y" => Hand::Paper,
"Z" => Hand::Scissors,
_ => panic!(),
};
let outcome = match (opponent, me) {
(l, r) if l == r => Outcome::Draw,
(Hand::Rock, Hand::Paper) => Outcome::Win,
(Hand::Paper, Hand::Scissors) => Outcome::Win,
(Hand::Scissors, Hand::Rock) => Outcome::Win,
_ => Outcome::Lost,
};
outcome as usize + me as usize
})
.sum()
}
fn part2(input: &str) -> usize {
input
.trim()
.split('\n')
.map(|round_str| {
let round = round_str.split_once(' ').unwrap();
let opponent = match round.0 {
"A" => Hand::Rock,
"B" => Hand::Paper,
"C" => Hand::Scissors,
_ => panic!(),
};
let outcome = match round.1 {
"X" => Outcome::Lost,
"Y" => Outcome::Draw,
"Z" => Outcome::Win,
_ => panic!(),
};
let me = match (outcome, opponent) {
(Outcome::Draw, _) => opponent,
(Outcome::Win, Hand::Rock) => Hand::Paper,
(Outcome::Win, Hand::Paper) => Hand::Scissors,
(Outcome::Win, Hand::Scissors) => Hand::Rock,
(Outcome::Lost, Hand::Rock) => Hand::Scissors,
(Outcome::Lost, Hand::Paper) => Hand::Rock,
(Outcome::Lost, Hand::Scissors) => Hand::Paper,
};
outcome as usize + me as usize
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input = "A Y
B X
C Z";
assert_eq!(part1(input), 15);
}
#[test]
fn test_2() {
let input = "A Y
B X
C Z";
assert_eq!(part2(input), 12);
}
}

View File

@@ -1,112 +0,0 @@
use itertools::Itertools;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fs;
pub fn run() {
println!("Day 3:");
let input = fs::read_to_string("./inputs/day3.txt").expect("Could not read file");
println!("\tPart 1: {}", part1(&input));
println!("\tPart 2: {}", part2(&input));
}
fn part1(input: &str) -> usize {
let mut alphabet_map = HashMap::new();
let alph = "abcdefghijklmnopqrstuvwxyz";
for (value, letter) in format!("{}{}", alph, alph.to_uppercase())
.chars()
.enumerate()
{
alphabet_map.insert(letter, value + 1);
}
input
.split_whitespace()
.map(|line| {
let (left, right) = line.split_at(line.len() / 2);
assert!(left.len() == right.len());
let bag_intersection = left
.chars()
.collect::<HashSet<char>>()
.intersection(&right.chars().collect::<HashSet<char>>())
.collect::<HashSet<&char>>()
.into_iter()
.copied()
.collect::<Vec<char>>();
assert!(bag_intersection.len() == 1);
alphabet_map.get(&bag_intersection[0]).unwrap()
})
.sum()
}
fn part2(input: &str) -> usize {
let mut alphabet_map = HashMap::new();
let alph = "abcdefghijklmnopqrstuvwxyz";
for (value, letter) in format!("{}{}", alph, alph.to_uppercase())
.chars()
.enumerate()
{
alphabet_map.insert(letter, value + 1);
}
input
.split_whitespace()
.collect::<Vec<&str>>()
.into_iter()
.tuples()
.map(|line| {
let (left, mid, right) = line;
let bag_intersection = left
.chars()
.collect::<HashSet<char>>()
.intersection(&right.chars().collect::<HashSet<char>>())
.collect::<HashSet<&char>>()
.into_iter()
.copied()
.collect::<HashSet<char>>()
.intersection(&mid.chars().collect::<HashSet<char>>())
.collect::<HashSet<&char>>()
.into_iter()
.copied()
.collect::<Vec<char>>();
assert!(bag_intersection.len() == 1);
alphabet_map.get(&bag_intersection[0]).unwrap()
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input = "vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw";
assert_eq!(part1(input), 157);
}
#[test]
fn test_2() {
let input = "vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw";
assert_eq!(part2(input), 70);
}
}

View File

@@ -1,84 +0,0 @@
use std::collections::HashSet;
use std::fs;
pub fn run() {
println!("Day 4:");
let input = fs::read_to_string("./inputs/day4.txt").expect("Could not read file");
println!("\tPart 1: {}", part1(&input));
println!("\tPart 2: {}", part2(&input));
}
struct SectionAssignment {
left: HashSet<usize>,
right: HashSet<usize>,
}
fn deserialize(line: &str) -> SectionAssignment {
let (left, right) = line.split_once(',').unwrap();
let left = left
.split_once('-')
.map(|(l, r)| l.parse().unwrap()..=r.parse().unwrap())
.unwrap()
.collect();
let right = right
.split_once('-')
.map(|(l, r)| l.parse().unwrap()..=r.parse().unwrap())
.unwrap()
.collect();
SectionAssignment { left, right }
}
fn part1(input: &str) -> usize {
let assignments = input.split_whitespace().map(deserialize);
let mut sum = 0;
for assignment in assignments {
if assignment.left.is_subset(&assignment.right)
|| assignment.right.is_subset(&assignment.left)
{
sum += 1;
}
}
sum
}
fn part2(input: &str) -> usize {
let assignments = input.split_whitespace().map(deserialize);
let mut sum = 0;
for assignment in assignments {
if assignment.left.intersection(&assignment.right).count() >= 1 {
sum += 1;
}
}
sum
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input = "2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8";
assert_eq!(part1(input), 2);
}
#[test]
fn test_2() {
let input = "2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8";
assert_eq!(part2(input), 4);
}
}

View File

@@ -1,163 +0,0 @@
use std::collections::{HashMap, VecDeque};
use std::fmt::format;
use std::fs;
use itertools::Itertools;
pub fn run() {
println!("Day 5:");
let input = fs::read_to_string("./inputs/day5.txt").expect("Could not read file");
println!("\tPart 1: {}", part1(&input));
println!("\tPart 2: {}", part2(&input));
}
#[derive(Debug)]
struct Command {
amount: usize,
from: usize,
to: usize,
}
fn part1(input: &str) -> String {
let (stack_input, moves_input) = input.split_once("\n\n").unwrap();
let mut containers: HashMap<usize, VecDeque<char>> = HashMap::new();
for row in stack_input.lines() {
for (column, (lbracket, container, _rbracket, _)) in
format!("{} ", row).chars().tuples().enumerate()
{
if lbracket == '[' && !container.is_whitespace() {
containers
.entry(column + 1)
.or_insert_with(VecDeque::new)
.push_back(container);
}
}
}
let commands = moves_input.lines().map(|line| {
let (amount, from, to) =
scan_fmt!(line, "move {} from {} to {}", usize, usize, usize).unwrap();
Command { amount, from, to }
});
for command in commands {
for _ in 0..command.amount {
let container = containers
.entry(command.from)
.or_insert_with(VecDeque::new)
.pop_front()
.unwrap_or(' ');
if container != ' ' {
containers
.entry(command.to)
.or_insert_with(VecDeque::new)
.push_front(container)
}
}
}
let mut answer = "".to_string();
for column in 1..=containers.len() {
answer = format!(
"{}{}",
answer,
containers.get(&column).unwrap().front().unwrap()
);
}
answer
}
fn part2(input: &str) -> String {
let (stack_input, moves_input) = input.split_once("\n\n").unwrap();
let mut containers: HashMap<usize, VecDeque<char>> = HashMap::new();
for row in stack_input.lines() {
for (column, (lbracket, container, _rbracket, _)) in
format!("{} ", row).chars().tuples().enumerate()
{
if lbracket == '[' && !container.is_whitespace() {
containers
.entry(column + 1)
.or_insert_with(VecDeque::new)
.push_back(container);
}
}
}
let commands = moves_input.lines().map(|line| {
let (amount, from, to) =
scan_fmt!(line, "move {} from {} to {}", usize, usize, usize).unwrap();
Command { amount, from, to }
});
let mut crane = VecDeque::new();
for command in commands {
for _ in 0..command.amount {
let container = containers
.entry(command.from)
.or_insert_with(VecDeque::new)
.pop_front()
.unwrap_or(' ');
crane.push_back(container);
}
for _ in 0..command.amount {
let container = crane.pop_back().unwrap();
if container != ' ' {
containers
.entry(command.to)
.or_insert_with(VecDeque::new)
.push_front(container)
}
}
}
let mut answer = "".to_string();
for column in 1..=containers.len() {
answer = format!(
"{}{}",
answer,
containers.get(&column).unwrap().front().unwrap()
);
}
answer
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input = " [D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2";
assert_eq!(part1(input), "CMZ");
}
#[test]
fn test_2() {
let input = " [D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2";
assert_eq!(part2(input), "MCD");
}
}

View File

@@ -1,16 +1,9 @@
#[macro_use]
// #[macro_use]
extern crate scan_fmt;
mod day1;
mod day2;
mod day3;
mod day4;
mod day5;
fn main() {
println!("Running Advent of Code 2022");
println!("Running Advent of Code 2023");
day1::run();
day2::run();
day3::run();
day4::run();
day5::run();
}