moved code around so each year is a package.
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name="aoc2024"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
@@ -0,0 +1,81 @@
|
||||
use std::{fs, io};
|
||||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
|
||||
/// Given 2 lists, sort the lists smallest to largest and then compare each pair of digits,
|
||||
/// finding the difference between the two.
|
||||
///
|
||||
/// Ex:
|
||||
///
|
||||
/// 3 4 -> 1 3 = 2
|
||||
/// 4 3 -> 2 3 = 1
|
||||
/// 2 5 -> 3 3 = 0
|
||||
/// 1 3 -> 3 4 = 1
|
||||
/// 3 9 -> 3 5 = 2
|
||||
/// 3 3 -> 4 9 = 5
|
||||
/// SUM 11
|
||||
///
|
||||
///
|
||||
|
||||
fn bubble_sort(mut nums: Vec<i32>) -> Vec<i32> {
|
||||
let n = nums.len();
|
||||
let mut swapped = true;
|
||||
|
||||
while swapped {
|
||||
swapped = false;
|
||||
for i in 1..n {
|
||||
if nums[i - 1] > nums[i] {
|
||||
nums.swap(i - 1, i);
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nums
|
||||
}
|
||||
|
||||
fn read_two_columns<P: AsRef<Path>>(filename: P) -> io::Result<(Vec<i32>, Vec<i32>)> {
|
||||
let file = File::open(filename)?;
|
||||
let reader = io::BufReader::new(file);
|
||||
|
||||
let mut col1 = Vec::new();
|
||||
let mut col2 = Vec::new();
|
||||
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() == 2 {
|
||||
let a: i32 = parts[0].parse().unwrap_or(0);
|
||||
let b: i32 = parts[1].parse().unwrap_or(0);
|
||||
col1.push(a);
|
||||
col2.push(b);
|
||||
}
|
||||
}
|
||||
|
||||
Ok((col1, col2))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Loading Data...");
|
||||
|
||||
let input_file = format!("{}/{}" ,
|
||||
std::env::var("CARGO_MANIFEST_DIR").unwrap(),
|
||||
"data/01_data.txt"
|
||||
);
|
||||
|
||||
let (mut list1, mut list2) = read_two_columns(input_file).unwrap();
|
||||
list1 = bubble_sort(list1);
|
||||
list2 = bubble_sort(list2);
|
||||
|
||||
let mut running_total = 0;
|
||||
for index in 0..list1.len() {
|
||||
let n1 = list1[index].max(list2[index]);
|
||||
let n2 = list1[index].min(list2[index]);
|
||||
|
||||
running_total += n1 - n2;
|
||||
}
|
||||
|
||||
println!("Total = {}", running_total);
|
||||
}
|
||||
// 2375403
|
||||
@@ -0,0 +1,102 @@
|
||||
use std::{fs, io};
|
||||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
|
||||
// Your analysis only confirmed what everyone feared: the two lists of location IDs are indeed
|
||||
// very different.
|
||||
//
|
||||
// Or are they?
|
||||
//
|
||||
// The Historians can't agree on which group made the mistakes or how to read most of the Chief's
|
||||
// handwriting, but in the commotion you notice an interesting detail: a lot of location IDs appear
|
||||
// in both lists! Maybe the other numbers aren't location IDs at all but rather misinterpreted
|
||||
// handwriting.
|
||||
//
|
||||
// This time, you'll need to figure out exactly how often each number from the left list appears in
|
||||
// the right list. Calculate a total similarity score by adding up each number in the left list
|
||||
// after multiplying it by the number of times that number appears in the right list.
|
||||
//
|
||||
// Here are the same example lists again:
|
||||
//
|
||||
// 3 4
|
||||
// 4 3
|
||||
// 2 5
|
||||
// 1 3
|
||||
// 3 9
|
||||
// 3 3
|
||||
// For these example lists, here is the process of finding the similarity score:
|
||||
//
|
||||
// The first number in the left list is 3. It appears in the right list three times, so the
|
||||
// similarity score increases by 3 * 3 = 9.
|
||||
// The second number in the left list is 4. It appears in the right list once, so the similarity
|
||||
// score increases by 4 * 1 = 4.
|
||||
// The third number in the left list is 2. It does not appear in the right list, so the similarity
|
||||
// score does not increase (2 * 0 = 0).
|
||||
// The fourth number, 1, also does not appear in the right list.
|
||||
// The fifth number, 3, appears in the right list three times; the similarity score increases by 9.
|
||||
// The last number, 3, appears in the right list three times; the similarity score again increases
|
||||
// by 9.
|
||||
// So, for these example lists, the similarity score at the end of this process is
|
||||
// 31 (9 + 4 + 0 + 0 + 9 + 9).
|
||||
//
|
||||
// Once again consider your left and right lists. What is their similarity score?
|
||||
|
||||
fn num_in_list(needle: i32, haystack: &Vec<i32>) -> i32 {
|
||||
let mut working = 0;
|
||||
for straw in haystack {
|
||||
if *straw == needle {
|
||||
working += 1;
|
||||
}
|
||||
}
|
||||
|
||||
working
|
||||
}
|
||||
|
||||
fn count_occurances_in_list(needles: &Vec<i32>, haystack: &Vec<i32>) -> i32 {
|
||||
// looking for a needle in a haystack...lets go!
|
||||
|
||||
let mut working = 0;
|
||||
|
||||
for needle in needles {
|
||||
let num_in_list = num_in_list(*needle, haystack);
|
||||
println!("Found {}, {} times. / {}", needle, num_in_list, working);
|
||||
working += needle * num_in_list;
|
||||
}
|
||||
|
||||
working
|
||||
}
|
||||
|
||||
fn read_two_columns<P: AsRef<Path>>(filename: P) -> io::Result<(Vec<i32>, Vec<i32>)> {
|
||||
let file = File::open(filename)?;
|
||||
let reader = io::BufReader::new(file);
|
||||
|
||||
let mut col1 = Vec::new();
|
||||
let mut col2 = Vec::new();
|
||||
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() == 2 {
|
||||
let a: i32 = parts[0].parse().unwrap_or(0);
|
||||
let b: i32 = parts[1].parse().unwrap_or(0);
|
||||
col1.push(a);
|
||||
col2.push(b);
|
||||
}
|
||||
}
|
||||
|
||||
Ok((col1, col2))
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
println!("Loading Data...");
|
||||
let file_path = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
let (list1, list2) = read_two_columns(format!("{}/data/01_data.txt", file_path)).unwrap();
|
||||
println!("List 1 -> {:?}", list1);
|
||||
|
||||
let final_value = count_occurances_in_list(&list1, &list2);
|
||||
println!("Final value = {final_value}");
|
||||
}
|
||||
// 23082277
|
||||
@@ -0,0 +1,103 @@
|
||||
// Fortunately, the first location The Historians want to search isn't a long walk from the Chief
|
||||
// Historian's office.
|
||||
//
|
||||
// While the Red-Nosed Reindeer nuclear fusion/fission plant appears to contain no sign of the
|
||||
// Chief Historian, the engineers there run up to you as soon as they see you. Apparently, they
|
||||
// still talk about the time Rudolph was saved through molecular synthesis from a single electron.
|
||||
//
|
||||
// They're quick to add that - since you're already here - they'd really appreciate your help
|
||||
// analyzing some unusual data from the Red-Nosed reactor. You turn to check if The Historians are
|
||||
// waiting for you, but they seem to have already divided into groups that are currently searching
|
||||
// every corner of the facility. You offer to help with the unusual data.
|
||||
//
|
||||
// The unusual data (your puzzle input) consists of many reports, one report per line. Each report
|
||||
// is a list of numbers called levels that are separated by spaces. For example:
|
||||
//
|
||||
// 7 6 4 2 1
|
||||
// 1 2 7 8 9
|
||||
// 9 7 6 2 1
|
||||
// 1 3 2 4 5
|
||||
// 8 6 4 4 1
|
||||
// 1 3 6 7 9
|
||||
// This example data contains six reports each containing five levels.
|
||||
//
|
||||
// The engineers are trying to figure out which reports are safe. The Red-Nosed reactor safety
|
||||
// systems can only tolerate levels that are either gradually increasing or gradually decreasing.
|
||||
// So, a report only counts as safe if both of the following are true:
|
||||
//
|
||||
// The levels are either all increasing or all decreasing.
|
||||
// Any two adjacent levels differ by at least one and at most three.
|
||||
// In the example above, the reports can be found safe or unsafe by checking those rules:
|
||||
//
|
||||
// 7 6 4 2 1: Safe because the levels are all decreasing by 1 or 2.
|
||||
// 1 2 7 8 9: Unsafe because 2 7 is an increase of 5.
|
||||
// 9 7 6 2 1: Unsafe because 6 2 is a decrease of 4.
|
||||
// 1 3 2 4 5: Unsafe because 1 3 is increasing but 3 2 is decreasing.
|
||||
// 8 6 4 4 1: Unsafe because 4 4 is neither an increase or a decrease.
|
||||
// 1 3 6 7 9: Safe because the levels are all increasing by 1, 2, or 3.
|
||||
// So, in this example, 2 reports are safe.
|
||||
|
||||
use std::{env, fs};
|
||||
|
||||
fn min_max(num1: u32, num2: u32) -> (u32, u32) {
|
||||
(num1.min(num2), num1.max(num2))
|
||||
}
|
||||
|
||||
fn in_range(min: u32, max:u32, target: u32) -> bool {
|
||||
min <= target && target <= max
|
||||
}
|
||||
|
||||
fn parse_numbers(s: &str) -> Vec<u32> {
|
||||
s.split_whitespace() // split on whitespace
|
||||
.filter_map(|num| num.parse::<u32>().ok()) // try to parse each piece
|
||||
.collect()
|
||||
}
|
||||
fn is_safe(report: &str) -> bool {
|
||||
let mut is_safe = true;
|
||||
let mut last_reading = 0;
|
||||
|
||||
let numbers = parse_numbers(report);
|
||||
println!("numbers: {:?}", numbers);
|
||||
let mut is_increasing = numbers[0] < numbers[1];
|
||||
|
||||
println!("Checking report {report}");
|
||||
println!("Found is_increasing = {is_increasing} from {}/{}", numbers[0], numbers[1]);
|
||||
|
||||
for (index, reading) in numbers.iter().enumerate() {
|
||||
println!("Checking {index}->{reading} in {report} / {is_increasing}");
|
||||
}
|
||||
|
||||
// for (index, reading) in numbers.enumerate() {
|
||||
// let reading_u32: u32 = reading.parse().unwrap();
|
||||
// if index == 0 {
|
||||
// // prime it for the report
|
||||
// last_reading = reading_u32;
|
||||
// } else if index == 1 {
|
||||
// if last_reading > reading_u32 {
|
||||
// is_increasing = false;
|
||||
// }
|
||||
// } else {
|
||||
// let (min,max) = min_max(last_reading as u32, reading_u32);
|
||||
//
|
||||
// // changing too fast
|
||||
// if (max - min) > 2 { is_safe = false; }
|
||||
// }
|
||||
// }
|
||||
is_safe
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input_file = format!("{}/{}" ,
|
||||
std::env::var("CARGO_MANIFEST_DIR").unwrap(),
|
||||
"data/02_data.txt"
|
||||
);
|
||||
|
||||
let binding = fs::read_to_string(input_file).unwrap();
|
||||
let reports = binding.lines();
|
||||
|
||||
for report in reports {
|
||||
if is_safe(report) {
|
||||
println!("Handling report of {report} -> Safe: {}", is_safe(report));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user