summaryrefslogtreecommitdiff
path: root/2020/Rust/src
diff options
context:
space:
mode:
Diffstat (limited to '2020/Rust/src')
-rwxr-xr-x2020/Rust/src/day1.rs47
-rwxr-xr-x2020/Rust/src/day2.rs64
-rwxr-xr-x2020/Rust/src/day4.rs94
-rw-r--r--2020/Rust/src/day5.rs174
4 files changed, 379 insertions, 0 deletions
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<i32> = 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<i32> = 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::<u32>().unwrap(),
+ max: max.parse::<u32>().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<usize>,
+ iyr: Option<usize>,
+ eyr: Option<usize>,
+ hgt: Option<usize>,
+ hcl: Option<String>,
+ ecl: Option<String>,
+ pid: Option<String>,
+ cid: Option<usize>,
+}
+
+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::<usize>().unwrap()),
+ "iyr" => passport.iyr = Some(value.parse::<usize>().unwrap()),
+ "eyr" => passport.eyr = Some(value.parse::<usize>().unwrap()),
+ "hgt" => {
+ passport.hgt = Some(
+ value
+ .trim_end_matches(|c| c == 'c' || c == 'm' || c == 'i' || c == 'n')
+ .parse::<usize>()
+ .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::<usize>().unwrap()),
+ _ => unreachable!(),
+ }
+ }
+ passport
+ }
+}
+
+fn solve_part_one(input: &str) -> usize {
+ let mut cnt: usize = 0;
+ let passports: Vec<Passport> = 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<Self> {
+ 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<Task>,
+}
+
+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();
+}