diff --git a/day_5/src/main.rs b/day_5/src/main.rs index e0ff566..7b966ed 100644 --- a/day_5/src/main.rs +++ b/day_5/src/main.rs @@ -1,5 +1,5 @@ -use std::{io::prelude::*, fs::File, path::Path, collections::HashMap }; +use std::{io::prelude::*, fs::File, path::Path, collections::HashMap, thread::current }; ///////////////////////////////////////////////////////////////////// @@ -46,6 +46,18 @@ impl SubMap return self.destination_start + distance; } + + fn map_reverse(&self, val: i64) -> i64 + { + if val >= self.destination_start && val <= self.destination_start + self.length + { + let distance = val - self.destination_start; + return self.source_start + distance; + } + + return -1; + } + } #[derive(Clone, Debug)] @@ -53,13 +65,14 @@ struct Map { name: String, sub_maps: Vec, + lowest_dest_value: i64, } impl Map { fn new(name: &str) -> Map { - Map { name: name.to_string(), sub_maps: Vec::new() } + Map { name: name.to_string(), sub_maps: Vec::new(), lowest_dest_value: i64::MAX } } fn map_input(&self, input: i64) -> i64 @@ -74,6 +87,35 @@ impl Map return input; } + + fn map_reverse(&self, input: i64) -> i64 + { + for sub_map in &self.sub_maps + { + let source = sub_map.map_reverse(input); + + if source > -1 + { + return source; + } + } + + return input; + } +} + +struct SeedRange +{ + start: i64, + length: i64, +} + +impl SeedRange +{ + fn new(start: i64, length: i64) -> SeedRange + { + SeedRange { start, length } + } } ///////////////////////////////////////////////////////////////////// @@ -81,8 +123,8 @@ impl Map ///////////////////////////////////////////////////////////////////// fn main() { - let input = load_data("data/input"); - let (seeds, maps) = parse_input(&input); + let input = load_data("data/test_input"); + let (seeds, maps, seed_ranges) = parse_input(&input); // TEST STUFF // println!("SEEDS: {:#?}, MAPS: {:#?}", seeds, maps); @@ -93,10 +135,116 @@ fn main() // println!("=========TESTS:\n\tseed-to-soil {} maps to {}\n\n\tseed-to-soil {} maps to {}\n\n\tseed-to-soil {} maps to {}\n", // 99, test_1, 53, test_2, 47, test_3); - // + + // let location_map_idx = maps.len() -1; + // for (idx, sub_map) in maps[location_map_idx].sub_maps.iter().enumerate() + // { + // println!("map index: {} -- Location dest_start: {}", idx, sub_map.destination_start); + // } + let location = find_closest_location(&seeds, &maps); - println!("Closest location: {}", location); + println!("================= Closest location: {} =================", location); + + let l2 = find_closest_location_from_ranges(&seed_ranges, &maps); + println!("================= Closest location from ranges: {} =================", l2); +} + +fn find_closest_location_from_ranges(seed_ranges: &Vec, maps: &Vec) -> i64 +{ + // let mut closest_location = i64::MAX; + + // for seed_range in seed_ranges + // { + // println!("Checking next seed range (start {}, {} length)...", seed_range.start, seed_range.length); + // for seed in seed_range.start..seed_range.start + seed_range.length + 1 + // { + // let location = find_seed_location(seed, maps); + + // if location < closest_location + // { + // closest_location = location; + // // best_seed = *seed; + + // // let idx = maps.len() - 1; + // // if maps[idx].lowest_dest_value == closest_location + // // { + // // return closest_location; + // // } + // } + // } + // } + + // closest_location + + + + for location in 0..52510811 + { + // println!("Current Location: {}", location); + if location >= 52510810 + { + println!("FAILED: location value greater than known max!"); + return -1; + } + + // if location == 46 + // { + // println!("LOCATOIN 46!"); + // } + + let seed = get_seed_from_location(location, maps, seed_ranges); + + if seed > -1 + { + return location; + } + } + + return -1; + +} + +fn get_seed_from_location(location: i64, maps: &Vec, seed_ranges: &Vec) -> i64 +{ + // let mut skip_first = true; + let mut current_type_value = location; + for map in maps.iter().rev() + { + // Don't actually want to skip because we need to map + // the location dest to it's source + // if skip_first + // { + // skip_first = false; + // continue; + // } + + current_type_value = map.map_reverse(current_type_value); + if current_type_value < 0 + { + return -1; + } + } + + if is_valid_seed(current_type_value, seed_ranges) + { + return current_type_value; + } + + return -1; +} + +fn is_valid_seed(value: i64, seed_ranges: &Vec) -> bool +{ + for range in seed_ranges + { + if value >= range.start && value <= range.start + range.length + { + return true; + } + } + + false } fn find_closest_location(seeds: &Vec, maps: &Vec) -> i64 @@ -104,9 +252,9 @@ fn find_closest_location(seeds: &Vec, maps: &Vec) -> i64 // let mut best_seed = 0; let mut closest_location = i64::MAX; - for seed in seeds + for (idx, seed) in seeds.iter().enumerate() { - println!("Checking seed: {}", seed); + println!("Checking seed: {} ({} of {})", seed, idx + 1, seeds.len()); let location = find_seed_location(*seed, maps); if location < closest_location @@ -125,7 +273,7 @@ fn find_seed_location(seed: i64, maps: &Vec) -> i64 let mut current_value = seed; for map in maps { - println!("Mapping {}...", map.name); + // println!("Mapping {}...", map.name); current_value = map.map_input(current_value); } @@ -135,9 +283,10 @@ fn find_seed_location(seed: i64, maps: &Vec) -> i64 ///////////////////////////////////////////////////////////////////// // INPUT PARSING ///////////////////////////////////////////////////////////////////// -fn parse_input(input: &str) -> (Vec, Vec) // String is the map name +fn parse_input(input: &str) -> (Vec, Vec, Vec) // String is the map name { let mut seeds: Vec = Vec::new(); + let mut seed_ranges: Vec = Vec::new(); let mut maps: Vec = Vec::new(); let mut current_map = ""; @@ -154,10 +303,20 @@ fn parse_input(input: &str) -> (Vec, Vec) // String is the map name if line.contains("seeds:") { println!("Parseing seed input..."); + let mut start_seed: i64 = -1; for val in line.trim_start_matches("seeds:").trim().split(" ") { let num = val.parse::().expect(&format!("Failed to parse seed value: {}", val)); seeds.push(num); + + if start_seed == -1 + { + start_seed = num; + continue; + } + + seed_ranges.push(SeedRange::new(start_seed, num)); + start_seed = -1; } continue; @@ -167,6 +326,12 @@ fn parse_input(input: &str) -> (Vec, Vec) // String is the map name // NEW MAP if line.contains("map:") { + if maps.len() > 0 + { + let idx = maps.len() - 1; + maps[idx].sub_maps.sort_by(|a, b| a.destination_start.partial_cmp(&b.destination_start).unwrap()); + } + sub_map_idx = 0; current_map = line.trim().trim_end_matches("map:").trim(); println!("Parsing map: {}", current_map); @@ -179,7 +344,7 @@ fn parse_input(input: &str) -> (Vec, Vec) // String is the map name // NEW SUB MAP let mut sub_map = SubMap::new(); let vals: Vec<&str> = line.trim().split(" ").collect(); - println!("Parsing sub map: {}", sub_map_idx); + // println!("Parsing sub map: {}", sub_map_idx); if vals.len() < 3 { @@ -190,8 +355,15 @@ fn parse_input(input: &str) -> (Vec, Vec) // String is the map name sub_map.destination_start = vals[0].parse::().expect(&format!("Failed to parse dest value: {}", vals[0])); sub_map.source_start = vals[1].parse::().expect(&format!("Failed to parse source value: {}", vals[1])); sub_map.length = vals[2].parse::().expect(&format!("Failed to parse length value: {}", vals[2])); + + //sub_map.map_values(); let idx = maps.len() - 1; + if sub_map.destination_start < maps[idx].lowest_dest_value + { + maps[idx].lowest_dest_value = sub_map.destination_start; + } + maps[idx].sub_maps.push(sub_map.clone()); sub_map_idx += 1; // if let Some(map) = maps.get_mut(current_map) @@ -204,7 +376,10 @@ fn parse_input(input: &str) -> (Vec, Vec) // String is the map name // } } - (seeds, maps) + let idx = maps.len() - 1; + maps[idx].sub_maps.sort_by(|a, b| a.destination_start.partial_cmp(&b.destination_start).unwrap()); + + (seeds, maps, seed_ranges) }