for Error {
fn from(e: std::num::ParseIntError) -> Self {
Error::ParseIntError(e)
}
}
pub fn read_file(path: P) -> Result where P: AsRef{
let f = File::open(path)?;
let mut s = String::new();
BufReader::new(f).read_to_string(&mut s)?;
Ok(s)
}
pub fn write_file(path: P,value:String) -> Result<(), Error> where P: AsRef{
let f = File::create(path)?;
let mut w = BufWriter::new(f);
w.write_all(value.as_bytes())?;
Ok(())
}<|repo_name|>torkelr/antenna<|file_sep|>/src/main.rs
extern crate clap;
extern crate regex;
use clap::{Arg,App};
use std::{env};
use regex::{Regex};
use std::{error};
mod utils;
mod instructions;
fn main() -> Result<(), Box> {
let matches = App::new("Antenna")
.version("0.1")
.author("Torkel Rasmussen")
.about("Program to solve the antenna problem.")
.arg(Arg::with_name("input")
.short("i")
.long("input")
.value_name("FILE")
.help("Sets the input file to use")
.takes_value(true))
.arg(Arg::with_name("output")
.short("o")
.long("output")
.value_name("FILE")
.help("Sets the output file to use")
.takes_value(true))
.get_matches();
let input = matches.value_of("input").unwrap_or_else(|| "input.txt");
let output = matches.value_of("output").unwrap_or_else(|| "output.txt");
let input_string = utils::read_file(input)?;
// Create vector of lines
let mut lines : Vec<&str>= input_string.split("n").collect();
// Remove empty lines and trim spaces
lines.retain(|&s| !s.is_empty());
lines.iter_mut().for_each(|line| *line= line.trim());
// Get first line (number of instructions)
let mut instructions_line = lines.remove(0);
// Parse number of instructions
let num_instructions = match instructions_line.parse::() {
Ok(num) => num,
Err(_) => panic!("Failed to parse number of instructions"),
};
if num_instructions != lines.len() {
panic!("Number of instructions does not match number of lines");
}
fn calculate_antenna_distance(lines:&Vec<&str>,x:&mut isize,y:&mut isize,dx:&mut isize,dy:&mut isize) -> Result<(), Box> {
let re = Regex::new(r"^(move|up|down)s+(d+)$").unwrap();
for line in lines.iter() {
if re.is_match(line) {
let cap = re.captures(line).unwrap();
match &cap[1] {
"move" => {
*dx += &cap[2].parse::().unwrap();
},
"up" => {
*dy += &cap[2].parse::().unwrap();
},
"down" => {
*dy -= &cap[2].parse::().unwrap();
},
_ => panic!("Unknown instruction"),
}
} else {
return Err(format!("Invalid instruction {}",line).into());
}
}
Ok(())
}
fn calculate_manhattan_distance(x:isize,y:isize) -> usize {
(x.abs() + y.abs()) as usize
}
fn calculate_min_manhattan_distance(lines:&Vec<&str>,x:&mut isize,y:&mut isize,dx:&mut isize,dy:&mut isize) -> Result> {
let mut min_distance : Option= None;
for line in lines.iter() {
if calculate_antenna_distance(&vec![line],x,y,dx,dy)? != (0,0) {
let distance = calculate_manhattan_distance(*x,*y);
if min_distance.is_none() || distance < min_distance.unwrap() {
min_distance = Some(distance);
}
}
*dx=0;
*dy=0;
}
match min_distance{
Some(distance)=> Ok(distance),
None=>Err(format!("No valid move found").into()),
}
}
fn calculate_max_steps(lines:&Vec<&str>,x:&mut isize,y:&mut isize,dx:&mut isize,dy:&mut isize) -> Result> {
let mut max_steps : Option= None;
for line in lines.iter() {
if calculate_antenna_distance(&vec![line],x,y,dx,dy)? != (0,0) {
let steps = calculate_steps(*x,*y);
if max_steps.is_none() || steps > max_steps.unwrap() {
max_steps = Some(steps);
}
}
*dx=0;
*dy=0;
}
match max_steps{
Some(steps)=> Ok(steps),
None=>Err(format!("No valid move found").into()),
}
}
fn calculate_steps(x:isize,y:isize) -> usize {
let mut steps : usize=0;
while x !=0 || y !=0{
if x >0 { x-=1; steps+=1;}
else if x<0 { x+=1; steps+=1;}
if y >0 { y-=1; steps+=1;}
else if y<0 { y+=1; steps+=1;}
}
steps
}
// Instructions and functions that need to be implemented
//let result_1 = instructions_1(&lines);
//let result_2 = instructions_2(&lines);
// Write output file
//utils::write_file(output,&format!("{}",result_1));
//utils::write_file(output,&format!("{}",result_2));
}
<|file_sep|>[package]
name = "antenna"
version = "0.1.0"
authors = ["Torkel Rasmussen"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap="^2"
regex="^1"<|file_sep|># antenna
Program to solve the antenna problem.
## Build
bash
cargo build --release
## Run
bash
cargo run --release -i input.txt -o output.txt
<|repo_name|>torkelr/antenna<|file_sep|>/src/instructions.rs
use super::*;
pub fn instructions_1(lines : &Vec<&str>) -> String{
let (result_1,result_2) = run(lines);
result_1.to_string()
}
pub fn instructions_2(lines : &Vec<&str>) -> String{
let (result_1,result_2) = run(lines);
result_2.to_string()
}
fn run(lines : &Vec<&str>) -> (usize,String){
let (min_distance,max_steps) =
calculate_min_max_steps(&lines);
(min_distance,max_steps.to_string())
}
fn calculate_min_max_steps(lines : &Vec<&str>) -> (usize,(usize,String)){
let mut min_distance : Option= None;
let mut max_steps : Option<(usize,String)> = None;
for i in range(1..lines.len()+1){
let sub_lines=&lines[0..i];
let (distance,message)=calculate_min_max_message(sub_lines);
if min_distance.is_none() || distancemax_steps.unwrap().1.len(){
max_steps=Some((i,message));
}
}
let result_1=min_distance.unwrap();
let