diff --git a/Day05/rust/Cargo.toml b/Day05/rust/Cargo.toml
new file mode 100644
index 0000000..1ec6963
--- /dev/null
+++ b/Day05/rust/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "rust"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/Day05/rust/src/main.rs b/Day05/rust/src/main.rs
new file mode 100644
index 0000000..cf6fb36
--- /dev/null
+++ b/Day05/rust/src/main.rs
@@ -0,0 +1,105 @@
+use std::fs::File;
+use std::io::{self, BufRead};
+use std::path::Path;
+use std::str::FromStr;
+
+fn read_lines
(filename: P) -> io::Result>>
+where
+ P: AsRef,
+{
+ let file = File::open(filename)?;
+ Ok(io::BufReader::new(file).lines())
+}
+
+fn parse_input(file_path: &str) -> io::Result<(Vec<(i32, i32)>, Vec>)> {
+ let mut seeds_numbers = Vec::new();
+ let mut categories = Vec::new();
+ let mut current_category = Vec::new();
+ let mut is_seed_line = true;
+
+ for line in read_lines(file_path)? {
+ let line = line?;
+ if line.is_empty() {
+ if !current_category.is_empty() {
+ categories.push(current_category);
+ current_category = Vec::new();
+ }
+ is_seed_line = false;
+ continue;
+ }
+
+ if is_seed_line {
+ let seeds_ranges: Vec = line.split_whitespace()
+ .skip(1)
+ .filter_map(|s| i32::from_str(s).ok())
+ .collect();
+
+ for seeds in seeds_ranges.chunks(2) {
+ if seeds.len() == 2 {
+ seeds_numbers.extend((seeds[0]..seeds[0] + seeds[1]).map(|n| (n, n + 1)));
+ }
+ }
+ } else {
+ let numbers: Vec = line.split_whitespace()
+ .filter_map(|s| i32::from_str(s).ok())
+ .collect();
+ if numbers.len() == 3 {
+ current_category.push((numbers[0], numbers[1], numbers[2]));
+ }
+ }
+ }
+ if !current_category.is_empty() {
+ categories.push(current_category);
+ }
+
+ Ok((seeds_numbers, categories))
+}
+
+fn process_categories(mut seeds_numbers: Vec<(i32, i32)>, categories: Vec>) -> Vec<(i32, i32)> {
+ for category in categories {
+ let mut sources = Vec::new();
+ while let Some((start, end)) = seeds_numbers.pop() {
+ let mut is_mapped = false;
+ for &(destination, source, length) in &category {
+ let overlap_start = std::cmp::max(start, source);
+ let overlap_end = std::cmp::min(end, source + length);
+ if overlap_start < overlap_end {
+ sources.push((overlap_start - source + destination, overlap_end - source + destination));
+ if overlap_start > start {
+ seeds_numbers.push((start, overlap_start));
+ }
+ if end > overlap_end {
+ seeds_numbers.push((overlap_end, end));
+ }
+ is_mapped = true;
+ break;
+ }
+ }
+ if !is_mapped {
+ sources.push((start, end));
+ }
+ }
+ seeds_numbers = sources;
+ }
+ seeds_numbers
+}
+
+fn find_lowest_location(file_path: &str) -> io::Result {
+ let (seeds_numbers, categories) = parse_input(file_path)?;
+ let processed_seeds = process_categories(seeds_numbers, categories);
+ let lowest_location = processed_seeds.iter().map(|&(start, _)| start).min().unwrap();
+ Ok(lowest_location)
+}
+
+fn main() -> io::Result<()> {
+ // Test
+ let test_result = find_lowest_location("../test.txt")?;
+ assert_eq!(test_result, 46, "Test failed. Expected 46, got {}", test_result);
+ println!("Test passed.");
+
+ // Process actual input
+ let result = find_lowest_location("../input.txt")?;
+ println!("Total result from input.txt: {}", result);
+
+ Ok(())
+}