You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
3.6 KiB
Rust
148 lines
3.6 KiB
Rust
|
|
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<i32, i32>
|
|
}
|
|
|
|
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<SubMap>,
|
|
}
|
|
|
|
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<i32>, HashMap<String, Map>) // String is the map name
|
|
{
|
|
let mut seeds: Vec<i32> = Vec::new();
|
|
|
|
let mut maps: HashMap<String, Map> = 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::<i32>().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::<i32>().expect(&format!("Failed to parse dest value: {}", vals[0]));
|
|
sub_map.source_start = vals[1].parse::<i32>().expect(&format!("Failed to parse source value: {}", vals[1]));
|
|
sub_map.length = vals[2].parse::<i32>().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;
|
|
} |