Skip to content

Commit

Permalink
2024 Day1-7
Browse files Browse the repository at this point in the history
  • Loading branch information
hsaikia committed Dec 7, 2024
1 parent 980e4af commit abb3870
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/bin/2022_16/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct Graph<'a> {
pub flow_rate: HashMap<&'a str, i64>,
}

impl<'a> Graph<'a> {
impl Graph<'_> {
fn new() -> Self {
Graph {
connections: HashMap::new(),
Expand Down
47 changes: 47 additions & 0 deletions src/bin/2024_01/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use aoc::common;
use aoc::io;

fn solve<const PART: usize>(input: &str) -> usize {
let mut lst1 = Vec::new();
let mut lst2 = Vec::new();
for line in input.lines() {
let nums = io::tokenize(line, " ");
let a: usize = io::parse_num(nums[0]);
let b: usize = io::parse_num(nums[1]);
lst1.push(a);
lst2.push(b);
}
lst1.sort();
lst2.sort();
let mut ans = 0;
if PART == 1 {
for (a, b) in lst1.iter().zip(lst2.iter()) {
ans += a.max(b) - a.min(b);
}
} else {
ans = lst1
.iter()
.map(|n| lst2.iter().filter(|x| *x == n).count() * n)
.sum();
}

ans
}

fn main() {
let input = common::get_input();
common::timed(&input, solve::<1>, true);
common::timed(&input, solve::<2>, false);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_samples() {
let sample_input = "3 4\n4 3\n2 5\n1 3\n3 9\n3 3";
assert_eq!(solve::<1>(sample_input), 11);
assert_eq!(solve::<2>(sample_input), 31);
}
}
69 changes: 69 additions & 0 deletions src/bin/2024_02/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use aoc::common;
use aoc::io;

fn diff_vec(seq: &[usize]) -> Vec<i32> {
let mut num_diffs: Vec<i32> = Vec::new();
for i in 1..seq.len() {
num_diffs.push(seq[i] as i32 - seq[i - 1] as i32);
}
num_diffs
}

fn good_difference(seq: &[usize]) -> bool {
let diff_seq = diff_vec(seq);
const ALLOWED_DIFF_POS: [i32; 3] = [1, 2, 3];
const ALLOWED_DIFF_NEG: [i32; 3] = [-1, -2, -3];
diff_seq.iter().all(|x| ALLOWED_DIFF_POS.contains(x))
|| diff_seq.iter().all(|x| ALLOWED_DIFF_NEG.contains(x))
}

fn good_sequence<const PART: usize>(seq: &[usize]) -> bool {
if good_difference(seq) {
return true;
} else if PART == 2 {
for drop_idx in 0..seq.len() {
let mut seq_new = seq.to_vec();
seq_new.remove(drop_idx);
if good_difference(&seq_new) {
return true;
}
}
}
false
}

fn solve<const PART: usize>(input: &str) -> usize {
let mut ans = 0;
for report in input.lines() {
let sequence_str = io::tokenize(report, " ");
let sequence = sequence_str
.iter()
.map(|x| io::parse_num(x))
.collect::<Vec<usize>>();
ans += if good_sequence::<PART>(&sequence) {
1
} else {
0
};
}
ans
}

fn main() {
let input = common::get_input();
//println!("{input:?}");
common::timed(&input, solve::<1>, true);
common::timed(&input, solve::<2>, false);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_samples() {
let sample_input = "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9";
assert_eq!(solve::<1>(sample_input), 2);
assert_eq!(solve::<2>(sample_input), 4);
}
}
78 changes: 78 additions & 0 deletions src/bin/2024_03/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use aoc::common;
use aoc::io;
use itertools::Itertools;

fn is_num(s: &str) -> bool {
s.chars().all(|x| x.is_ascii_digit())
}

// the ....mul(X,Y)...... part
fn solve_muls(input: &str) -> usize {
let mut ans = 0;
for pattern in io::tokenize(input, "mul(") {
let tokens1 = io::tokenize(pattern, ",");
let num1 = tokens1.first().unwrap();
// check if num1 has all digits
if is_num(num1) {
let n1: usize = io::parse_num(num1);
let tokens2 = io::tokenize(tokens1[1], ")");
let num2 = tokens2.first().unwrap();
if is_num(num2) {
let n2: usize = io::parse_num(num2);
ans += n1 * n2;
}
}
}
ans
}

fn solve<const PART: usize>(input: &str) -> usize {
let mut ans = 0;

if PART == 1 {
ans = solve_muls(input);
} else {
let indices = input
.match_indices("do()")
.chain(input.match_indices("don't()"))
.sorted_by_key(|x| x.0);

let mut last_idx = 0;
let mut yes: bool = true;
for (idx, ins) in indices {
if yes {
ans += solve_muls(&input[last_idx..idx]);
}
last_idx = idx;
yes = ins == "do()";
}

if yes {
ans += solve_muls(&input[last_idx..]);
}
}

ans
}

fn main() {
let input = common::get_input();
println!("{input:?}");
common::timed(&input, solve::<1>, true);
common::timed(&input, solve::<2>, false);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_samples() {
let sample_input1 =
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))";
let sample_input2 =
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
assert_eq!(solve::<1>(sample_input1), 161);
assert_eq!(solve::<2>(sample_input2), 48);
}
}
91 changes: 91 additions & 0 deletions src/bin/2024_04/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use aoc::{common, grid::Grid};

fn solve2(input: &str) -> usize {
let mut ans = 0;
let grid = Grid::from_str(input, |c| c);

const DIRS: [(i32, i32); 4] = [(1, 1), (-1, 1), (-1, -1), (1, -1)];
const ADJ_DIRS: [(usize, usize); 4] = [(0, 1), (1, 2), (2, 3), (3, 0)];

let a_positions = grid.positions('A');

for a_pos in a_positions.iter() {
for (i1, i2) in ADJ_DIRS.iter() {
let m_pos = [DIRS[*i1], DIRS[*i2]];
let s_pos = [DIRS[(*i1 + 2) % 4], DIRS[(*i2 + 2) % 4]];

let num_desired_m_pos = grid
.adjacent_in_dir(a_pos, &m_pos)
.iter()
.filter(|x| grid.get(x) == 'M')
.count();
let num_desired_s_pos = grid
.adjacent_in_dir(a_pos, &s_pos)
.iter()
.filter(|x| grid.get(x) == 'S')
.count();

if num_desired_m_pos == 2 && num_desired_s_pos == 2 {
ans += 1;
}
}
}

ans
}

fn solve1(input: &str) -> usize {
let mut ans = 0;
let grid = Grid::from_str(input, |c| c);

const DIRS: [(i32, i32); 8] = [
(-1, 0),
(0, -1),
(1, 0),
(0, 1),
(-1, 1),
(1, -1),
(1, 1),
(-1, -1),
];

for x_pos in grid.positions('X').iter() {
for dir in DIRS {
let mut pos = vec![*x_pos];
let mut count = 0;
for ch in ['M', 'A', 'S'] {
pos = grid.adjacent_in_dir(&pos[0], &[dir]);
if pos.is_empty() || grid.get(&pos[0]) != ch {
break;
}
count += 1;
}

if count == 3 {
ans += 1;
}
}
}

ans
}

fn main() {
let input = common::get_input();
//println!("{input:?}");
common::timed(&input, solve1, true);
common::timed(&input, solve2, false);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_samples() {
let sample_input =
"MMMSXXMASM\nMSAMXMSMSA\nAMXSXMAAMM\nMSAMASMSMX\nXMASAMXAMM\nXXAMMXXAMA\nSMSMSASXSS\nSAXAMASAAA\nMAMMMXMMMM\nMXMXAXMASX";
assert_eq!(solve1(sample_input), 18);
assert_eq!(solve2(sample_input), 9);
}
}
84 changes: 84 additions & 0 deletions src/bin/2024_05/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use aoc::{common, io};

// Only works when the input page_orderings have ALL NxN relationships / or all relationships
// that occur in the page_sequences. Otherwise all transitive relationships, such as A->C
// given A->B and B->C should be additionally added to the page_orderings to make this algorithm work.
fn solve<const PART: usize>(input: &str) -> usize {
let mut page_orderings: Vec<(usize, usize)> = Vec::new();
let mut page_sequences: Vec<Vec<usize>> = Vec::new();

for line in input.lines() {
if line.is_empty() {
continue;
}
if line.chars().any(|x| x == '|') {
let page_nums: Vec<usize> = io::tokenize(line, "|")
.into_iter()
.map(io::parse_num)
.collect();
page_orderings.push((page_nums[0], page_nums[1]));
} else {
let seq: Vec<usize> = io::tokenize(line, ",")
.into_iter()
.map(io::parse_num)
.collect();
page_sequences.push(seq);
}
}

let mut ans = 0;
for seq in page_sequences {
let l = seq.len();

let mut ordered = true;
for i in 1..l {
if !page_orderings.contains(&(seq[i - 1], seq[i])) {
ordered = false;
}
}

if ordered {
if PART == 1 {
ans += seq[l / 2];
}
} else if PART == 2 {
let mut new_seq = seq.clone();
while !ordered {
ordered = true;
for i in 1..l {
if !page_orderings.contains(&(new_seq[i - 1], new_seq[i])) {
new_seq.swap(i - 1, i);
ordered = false;
break;
}
}

if ordered {
ans += new_seq[l / 2];
}
}
}
}

ans
}

fn main() {
let input = common::get_input();
//println!("{input:?}");
common::timed(&input, solve::<1>, true);
common::timed(&input, solve::<2>, false);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_samples() {
let sample_input =
"47|53\n97|13\n97|61\n97|47\n75|29\n61|13\n75|53\n29|13\n97|29\n53|29\n61|53\n97|53\n61|29\n47|13\n75|47\n97|75\n47|61\n75|61\n47|29\n75|13\n53|13\n\n75,47,61,53,29\n97,61,53,29,13\n75,29,13\n75,97,47,61,53\n61,13,29\n97,13,75,29,47";
assert_eq!(solve::<1>(sample_input), 143);
assert_eq!(solve::<2>(sample_input), 123);
}
}
Loading

0 comments on commit abb3870

Please sign in to comment.