use std::{io::prelude::*, fs::File, path::Path, io, collections::HashMap }; #[derive(Clone, Debug)] struct SubMap { destination_start: i32, source_start: i32, length: i32, map: HashMap } impl SubMap { fn new() -> SubMap { SubMap { destination_start: 0, source_start: 0, length: 0, map: HashMap::new() } } fn map_values(&mut self) { for i in 0..self.length { self.map.insert(self.source_start + i, self.destination_start + i); } } } #[derive(Clone, Debug)] struct Map { name: String, sub_maps: Vec, } impl Map { fn new(name: &str) -> Map { Map { name: name.to_string(), sub_maps: Vec::new() } } fn map_input(&self, input: i32) -> i32 { for sub_map in &self.sub_maps { if sub_map.map.contains_key(&input) { return sub_map.map[&input]; } } return input; } } fn main() { let input = load_data("data/test_input"); let (seeds, maps) = parse_input(&input); println!("SEEDS: {:#?}, MAPS: {:#?}", seeds, maps); } fn parse_input(input: &str) -> (Vec, HashMap) // String is the map name { let mut seeds: Vec = Vec::new(); let mut maps: HashMap = HashMap::new(); let mut current_map = ""; for (idx, line) in input.to_ascii_lowercase().split("\n").into_iter().enumerate() { // stupid windows dumb line ending non-sense if line.starts_with("\r") { continue; } // SEEDS if line.contains("seeds:") { 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); } continue; } // NEW MAP if line.contains("map:") { let name = line.trim_end_matches("map:"); current_map = name.clone(); let map = Map::new(¤t_map); maps.insert(current_map.to_string(), map.clone()); continue; } // NEW SUB MAP let mut sub_map = SubMap::new(); let vals: Vec<&str> = line.trim().split(" ").collect(); if vals.len() < 3 { println!("========INVALID SUBMAP FOR {}: {:#?}========", current_map, vals); continue; } 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(); if let Some(map) = maps.get_mut(current_map) { map.sub_maps.push(sub_map.clone()); } else { println!("========CURRENT MAP NOT FOUND IN MAP: {}========", current_map); } } (seeds, maps) } fn load_data(file_name: &str) -> String { let mut file = match File::open(Path::new(file_name)) { Ok(file) => file, Err(why) => panic!("Could not open file {}: {}", Path::new(file_name).display(), why), }; let mut s = String::new(); let file_contents = match file.read_to_string(&mut s) { Err(why) => panic!("couldn't read {}: {}", Path::new(file_name).display(), why), Ok(_) => s, }; return file_contents; }