From 01c6b2cb42a4144a573ec43e9e25c6718741a272 Mon Sep 17 00:00:00 2001 From: omagdy Date: Sun, 8 Dec 2024 15:28:08 +0200 Subject: Some solutions to AOC 2020 --- 2020/Rust/src/day1.rs | 47 ++++++++++++++ 2020/Rust/src/day2.rs | 64 +++++++++++++++++++ 2020/Rust/src/day4.rs | 94 +++++++++++++++++++++++++++ 2020/Rust/src/day5.rs | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 379 insertions(+) create mode 100755 2020/Rust/src/day1.rs create mode 100755 2020/Rust/src/day2.rs create mode 100755 2020/Rust/src/day4.rs create mode 100644 2020/Rust/src/day5.rs (limited to '2020/Rust/src') diff --git a/2020/Rust/src/day1.rs b/2020/Rust/src/day1.rs new file mode 100755 index 0000000..9a84dd4 --- /dev/null +++ b/2020/Rust/src/day1.rs @@ -0,0 +1,47 @@ +use std::collections::HashSet; + +fn solve_part_one(input: &str) -> i32 { + let mut seen = HashSet::new(); + let numbers: Vec = input + .lines() + .map(|line| line.trim().parse().unwrap()) + .collect(); + + for &number in &numbers { + let complement = 2020 - number; + if seen.contains(&complement) { + return number * complement; + } + seen.insert(number); + } + panic!("No two numbers sum to 2020!"); +} + +fn solve_part_two(input: &str) -> i32 { + let numbers: Vec = input + .lines() + .map(|line| line.trim().parse().unwrap()) + .collect(); + + for (i, &first) in numbers.iter().enumerate() { + let mut seen = HashSet::new(); + let target_sum = 2020 - first; + for &second in &numbers[i + 1..] { + let complement = target_sum - second; + if seen.contains(&complement) { + return first * second * complement; + } + seen.insert(second); + } + } + panic!("No three numbers sum to 2020!"); +} + +fn main() { + let test = include_str!("../input/day_1.test"); + let prod = include_str!("../input/day_1.prod"); + println!("Test_1: {}", solve_part_one(test)); + println!("Prod_1: {}", solve_part_one(prod)); + println!("Test_2: {}", solve_part_two(test)); + println!("Prod_2: {}", solve_part_two(prod)); +} diff --git a/2020/Rust/src/day2.rs b/2020/Rust/src/day2.rs new file mode 100755 index 0000000..4785b3f --- /dev/null +++ b/2020/Rust/src/day2.rs @@ -0,0 +1,64 @@ +struct Policy { + min: u32, + max: u32, + letter: char, + password: String, +} + +impl From<&str> for Policy { + fn from(value: &str) -> Self { + let (left, right) = value.split_once(':').unwrap(); + let (range, letter) = left.split_once(' ').unwrap(); + let (min, max) = range.split_once("-").unwrap(); + let password = right.trim_start().to_string(); + + Policy { + min: min.parse::().unwrap(), + max: max.parse::().unwrap(), + letter: letter.chars().next().unwrap(), + password, + } + } +} + +fn check_policy(policy: &Policy) -> bool { + let count = policy.password.matches(policy.letter).count() as u32; + count >= policy.min && count <= policy.max +} + +fn check_policy_part_two(policy: &Policy) -> bool { + let mut count = 0; + let policy_password = policy.password.as_bytes(); + if policy_password[(policy.min - 1) as usize] == policy.letter as u8 { + count += 1; + } + if policy_password[(policy.max - 1) as usize] == policy.letter as u8 { + count += 1; + } + count == 1 +} + +fn solve_part_one(input: &str) -> usize { + input + .lines() + .map(|line| Policy::from(line)) + .filter(|policy| check_policy(policy)) + .count() +} + +fn solve_part_two(input: &str) -> usize { + input + .lines() + .map(|line| Policy::from(line)) + .filter(|policy| check_policy_part_two(policy)) + .count() +} + +fn main() { + let test = include_str!("../input/day_2.test"); + let prod = include_str!("../input/day_2.prod"); + println!("Test_1: {}", solve_part_one(test)); + println!("Prod_1: {}", solve_part_one(prod)); + println!("Test_2: {}", solve_part_two(test)); + println!("Prod_2: {}", solve_part_two(prod)); +} diff --git a/2020/Rust/src/day4.rs b/2020/Rust/src/day4.rs new file mode 100755 index 0000000..113e838 --- /dev/null +++ b/2020/Rust/src/day4.rs @@ -0,0 +1,94 @@ +#[derive(Debug)] +struct Passport { + byr: Option, + iyr: Option, + eyr: Option, + hgt: Option, + hcl: Option, + ecl: Option, + pid: Option, + cid: Option, +} + +impl Passport { + fn new() -> Self { + Self { + byr: None, + iyr: None, + eyr: None, + hgt: None, + hcl: None, + ecl: None, + pid: None, + cid: None, + } + } +} + +impl From<&str> for Passport { + fn from(value: &str) -> Self { + let mut passport = Passport::new(); + let v = value.replace("\n", " "); + let v: Vec<&str> = v.split(" ").collect(); + for ele in v { + if ele.is_empty() { + continue; + } + let (key, value) = ele.split_once(':').unwrap(); + match key { + "byr" => passport.byr = Some(value.parse::().unwrap()), + "iyr" => passport.iyr = Some(value.parse::().unwrap()), + "eyr" => passport.eyr = Some(value.parse::().unwrap()), + "hgt" => { + passport.hgt = Some( + value + .trim_end_matches(|c| c == 'c' || c == 'm' || c == 'i' || c == 'n') + .parse::() + .unwrap(), + ) + } + "hcl" => passport.hcl = Some(value.to_string()), + "ecl" => passport.ecl = Some(value.to_string()), + "pid" => passport.pid = Some(value.to_string()), + "cid" => passport.cid = Some(value.parse::().unwrap()), + _ => unreachable!(), + } + } + passport + } +} + +fn solve_part_one(input: &str) -> usize { + let mut cnt: usize = 0; + let passports: Vec = input + .split("\n\n") + .map(|pass| Passport::from(pass)) + .collect(); + for passport in passports { + if passport.byr == None + || passport.iyr == None + || passport.eyr == None + || passport.hgt == None + || passport.hcl == None + || passport.ecl == None + || passport.pid == None + { + continue; + } + cnt += 1; + } + cnt +} + +fn solve_part_two(input: &str) -> usize { + todo!() +} + +fn main() { + let test = include_str!("../input/day_4.test"); + let prod = include_str!("../input/day_4.prod"); + println!("Test_1: {}", solve_part_one(test)); + println!("Prod_1: {}", solve_part_one(prod)); + // println!("Test_2: {}", solve_part_two(test)); + // println!("Prod_2: {}", solve_part_two(prod)); +} diff --git a/2020/Rust/src/day5.rs b/2020/Rust/src/day5.rs new file mode 100644 index 0000000..ad48295 --- /dev/null +++ b/2020/Rust/src/day5.rs @@ -0,0 +1,174 @@ +use std::{ + fs::{self, File}, + io::{self, BufRead, BufReader, Write}, + sync::{Arc, Mutex}, + thread, +}; + +#[derive(Debug, Clone)] +enum TaskStatus { + Pending, + Completed, +} + +#[derive(Debug, Clone)] +struct Task { + id: usize, + description: String, + status: TaskStatus, +} + +impl Task { + fn new(id: usize, description: String) -> Self { + Self { + id, + description, + status: TaskStatus::Pending, + } + } + + fn mark_done(&mut self) { + self.status = TaskStatus::Completed; + } + + fn to_string(&self) -> String { + format!( + "{}|{}|{}", + self.id, + self.description, + match self.status { + TaskStatus::Pending => "Pending", + TaskStatus::Completed => "Completed", + } + ) + } + + fn from_string(data: &str) -> Option { + let parts: Vec<&str> = data.split('|').collect(); + if parts.len() != 3 { + return None; + } + let id = parts[0].parse().ok()?; + let description = parts[1].to_string(); + let status = match parts[2] { + "Pending" => TaskStatus::Pending, + "Completed" => TaskStatus::Completed, + _ => return None, + }; + + Some(Self { + id, + description, + status, + }) + } +} + +#[derive(Debug)] +struct TaskManager { + tasks: Vec, +} + +impl TaskManager { + fn new() -> Self { + Self { tasks: vec![] } + } + + fn add_task(&mut self, description: String) { + let id = self.tasks.len() + 1; + let task = Task::new(id, description); + self.tasks.push(task); + } + + fn mark_task_done(&mut self, id: usize) -> Result<(), String> { + match self.tasks.iter_mut().find(|t| t.id == id) { + Some(task) => { + task.mark_done(); + Ok(()) + } + None => Err(format!("Task with ID {} not found.", id)), + } + } + + fn list_tasks(&self) { + for task in &self.tasks { + println!( + "ID: {}, Description: {}, Status: {:?}", + task.id, task.description, task.status + ); + } + } + + fn save_to_file(&self, filename: &str) -> io::Result<()> { + let mut file = File::create(filename)?; + for task in &self.tasks { + writeln!(file, "{}", task.to_string())?; + } + Ok(()) + } + + fn load_from_file(&mut self, filename: &str) -> io::Result<()> { + self.tasks.clear(); + let file = File::open(filename)?; + let reader = BufReader::new(file); + for line in reader.lines() { + if let Ok(line) = line { + if let Some(task) = Task::from_string(&line) { + self.tasks.push(task); + } + } + } + Ok(()) + } +} + +fn add(x: i32, y: i32, z: i32) -> i32 { + x + y + z +} + +fn main() { + let task_manager = Arc::new(Mutex::new(TaskManager::new())); + + let xay = 5; + let yay = 6; + let x = xay + yay + add(xay, yay, 3); + let y = 2; + + // let z = add(x, y); + + let tm_clone = Arc::clone(&task_manager); + println!( + "tm_clone: {:?}, Arc::clone(&task_manager): {:?}", + tm_clone, + Arc::clone(&task_manager) + ); + thread::spawn(move || { + let mut tm = tm_clone.lock().unwrap(); + tm.add_task("Learn Rust".to_string()); + tm.add_task("Build a project".to_string()); + tm.list_tasks(); + }) + .join() + .unwrap(); + + let tm_clone = Arc::clone(&task_manager); + thread::spawn(move || { + let mut tm = tm_clone.lock().unwrap(); + tm.mark_task_done(1) + .unwrap_or_else(|err| println!("{}", err)); + tm.list_tasks(); + }) + .join() + .unwrap(); + + let tm_clone = Arc::clone(&task_manager); + thread::spawn(move || { + let mut tm = tm_clone.lock().unwrap(); + let filename = "tasks.txt"; + tm.save_to_file(filename).expect("Failed to save tasks"); + tm.load_from_file(filename).expect("Failed to load tasks"); + tm.list_tasks(); + }) + .join() + .unwrap(); +} -- cgit v1.2.3