Ryan is an engineer in the Sacramento Area with a focus in Python, Ruby, and Rust. Bash/Python Exercism mentor. Coding, physics, calculus, music, woodworking. Looking for work!
I want to come back to this exercise after Advent is over and refactor, because I think I could make my solution really nice now, but for right now, I'm delirious and need sleep. Here's what I've got. It's not pretty, but it gets stars and that's all that matters.
/// Day 6: Chronal Coordinates/// /// Calculate Manhattan Distances on the X-Y planeusestd::collections::HashMap;usestd::collections::HashSet;/// A grid of X-Y coordinates and unclaimed points/// /// coords is a vector of Coordinates. Their index is their "ID number"/// points is a vector of unclaimed points. Their value is the ID of the /// closest CoordinatestructGrid{coords:Vec<Coordinate>,points:Vec<Option<usize>>,width:usize,height:usize,}implGrid{pubfnnew()->Self{Self{coords:vec![],points:vec![],width:0,height:0}}/// Loads a grid from text, building each coordinate and calculating/// most of part 1pubfnfrom_text(text:&str)->Self{letmutgrid=Grid::new();forlineintext.lines(){letmutcoord=Coordinate::from_str(line);coord.id=grid.coords.len();grid.coords.push(coord);}let(height,width)=grid.bounds();grid.height=height;grid.width=width;grid.points.resize(width*height,None);grid.calculate_closest_coords();grid}/// Calculates the width and height of the gridfnbounds(&self)->(usize,usize){letmax_row=self.coords.iter().map(|coord|coord.y).max().unwrap();letmax_col=self.coords.iter().map(|coord|coord.x).max().unwrap();(max_row,max_col)}/// For each point on the Grid, calculates the closest Coordinate to/// that point/// /// Ties count as nothing!fncalculate_closest_coords(&mutself){foryin0..self.height{forxin0..self.width{letmutmin_dist=self.width+self.height;forcoordinself.coords.iter(){letdist=coord.manhattan_distance_to(x+1,y+1);ifdist<min_dist{min_dist=dist;self.points[x+y*self.width]=Some(coord.id);}elseifdist==min_dist{// It's a tie. No one gets itself.points[x+y*self.width]=None;}}}}}/// Checks whether or not a coordinate is internal/// /// Internal coordinates are completely fenced in by other/// coordinates. No infinite boundaries (i.e. not touching the edges)/// /// This could probably be batched in the contructor rather than done in a loop.fnis_internal(&self,id:usize)->bool{letmutexternal:HashSet<usize>=HashSet::new();// Left and right sideforyin0..self.height{letleft=self.points[0+y*self.width];letright=self.points[y*self.width+self.width-1];ifleft.is_some(){external.insert(left.unwrap());}ifright.is_some(){external.insert(right.unwrap());}}// Top and bottomforxin0..self.width{lettop=self.points[x];letbottom=self.points[x+(self.height-1)*self.width];iftop.is_some(){external.insert(top.unwrap());}ifbottom.is_some(){external.insert(bottom.unwrap());}}!external.contains(&id)}/// Calculates the area of the internal coordinate that claims the most areapubfnmost_claimed_area(&self)->usize{letmutcounter:HashMap<usize,usize>=HashMap::new();forpointinself.points.iter(){ifpoint.is_some(){*counter.entry(point.unwrap()).or_insert(0)+=1;}}*counter.iter().filter(|(id,_count)|self.is_internal(**id)).map(|(_id,count)|count).max().unwrap()}/// Counts how many points have a total manhattan distance less than/// a threshold when checked against all Coordinatespubfnsquares_closer_than(&self,dist:usize)->usize{letmutdistances:Vec<usize>=vec![];foryin0..self.height{forxin0..self.width{lettotal=self.coords.iter().fold(0,|acc,coord|acc+coord.manhattan_distance_to(x,y));iftotal<dist{distances.push(total);}}}distances.iter().count()}}/// An X-Y coordinate on a GridstructCoordinate{id:usize,x:usize,y:usize,}implCoordinate{pubfnnew(x:usize,y:usize)->Self{Self{id:0,x,y}}/// Loads data from a line of text, essentially a CSV linepubfnfrom_str(text:&str)->Self{letmutparts=text.split(',');letx=parts.next().unwrap().trim().parse().unwrap();lety=parts.next().unwrap().trim().parse().unwrap();Self{id:0,x,y}}/// Calculate manhattan distance from here to any X-Y pairpubfnmanhattan_distance_to(&self,x:usize,y:usize)->usize{letx1=self.xasi32;letx2=xasi32;lety1=self.yasi32;lety2=yasi32;((x2-x1).abs()+(y2-y1).abs())asusize}}/// Part 1pubfnlargest_finite_area(text:&str)->usize{letgrid=Grid::from_text(text);grid.most_claimed_area()}/// Part 2pubfnsquares_closer_than(text:&str,dist:usize)->usize{letgrid=Grid::from_text(text);grid.squares_closer_than(dist)}
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I want to come back to this exercise after Advent is over and refactor, because I think I could make my solution really nice now, but for right now, I'm delirious and need sleep. Here's what I've got. It's not pretty, but it gets stars and that's all that matters.