Golfcoder FAQ LOGIN
Error

Advent of Code Leaderboard 2024 / Day 12

View puzzle on adventofcode.com

Submit solution



Leaderboard

Name Language Tokens Sum Tokens Part 1 Tokens Part 2 Last change
1 Profile imageMichael Böiers Kotlin 10215 215 - 9 days ago
2 Profile imagedbasden C 10344 344 - 9 days ago
3 Profile imageMechazawa Rust 11183 1183 - 9 days ago

Rules

  • You're welcome to participate alone or in a team.
  • You may submit multiple solutions and explore different programming languages.
  • Stick to the standard library of your language, no further dependencies/libraries, except the ones which OneCompiler provides (e.g. NumPy for Python).
  • Ensure your code aligns to the template (Python, Rust, Go, Kotlin, JavaScript, C#, TypeScript, C++, Java, C, Swift, Scala, Ruby, Bash), reading the puzzle input from stdin (terminated with end-of-file), and printing the solution to stdout.
  • Please refrain from making network requests, reading data from files, or storing data in variable/function/class names for reflection.
  • Your code must be able to process all valid Advent of Code inputs. Golfcoder might reevaluate correctness of your solution with different inputs after your submission.

1183 tokens in Rust for part 1 by Mechazawa

Download solution

usestd::fmt::Display;
usestd::io::{stdin,Read};

constMAPPED_CHAR:char='.';

#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq,PartialOrd)]
structPoint(usize,usize);

implPoint{
pubfnneighbours(&self)->Vec<Point>{
vec![
Point(self.0.wrapping_sub(1),self.1),// Up
Point(self.0,self.1.wrapping_sub(1)),// Left
Point(self.0.saturating_add(1),self.1),// Down
Point(self.0,self.1.saturating_add(1)),// Right
]
}
}

#[derive(Debug)]
structGrid{
rows:usize,
cols:usize,
data:Vec<char>,
}

implGrid{
pubfnfrom_str(data:&str)->Self{
letrows=data.lines().count();
letcols=data.lines().next().map_or(0,|line|line.chars().count());
letdata=data.lines().flat_map(|line|line.chars()).collect();

Self{rows,cols,data}
}

pubfnget(&self,point:Point)->Option<char>{
ifpoint.0<self.rows&&point.1<self.cols{
Some(self.data[point.0*self.cols+point.1])
}else{
None
}
}

pubfnset(&mutself,point:Point,value:char){
ifpoint.0<self.rows&&point.1<self.cols{
self.data[point.0*self.cols+point.1]=value;
}
}

pubfnfind_unmapped(&self)->Option<Point>{
forrowin0..self.rows{
forcolin0..self.cols{
letpoint=Point(row,col);

ifself.get(point).unwrap()!=MAPPED_CHAR{
returnSome(point);
}
}
}

None
}

pubfnget_region(&self,start:Point)->Option<Region>{
letmutregion=Region::new(self.get(start)?);
letmutstack=vec![start];

whileletSome(point)=stack.pop(){
ifletSome(c)=self.get(point){
ifc==region.name&&!region.points.contains(&point){
stack.extend(point.neighbours());

region.points.push(point);
}
}
}

Some(region)
}

pubfntake_region(&mutself,start:Point)->Option<Region>{
letregion=self.get_region(start)?;

region
.points
.iter()
.for_each(|point|self.set(*point,MAPPED_CHAR));

Some(region)
}
}

implDisplayforGrid{
fnfmt(&self,f:&mutstd::fmt::Formatter<'_>)->std::fmt::Result{
forrowin0..self.rows{
forcolin0..self.cols{
write!(f,"{}",self.get(Point(row,col)).unwrap())?;
}
writeln!(f)?;
}

Ok(())
}
}

#[derive(Debug)]
structRegion{
name:char,
points:Vec<Point>,
}

implRegion{
pubfnnew(name:char)->Self{
Self{
name,
points:Vec::new(),
}
}

pubfnarea(&self)->usize{
self.points.len()
}

pubfnperimeter(&self)->usize{
letmutperimeter=0;

forpointin&self.points{
letmutneighbours=0;

forneighbourinpoint.neighbours(){
ifself.points.contains(&neighbour){
neighbours+=1;
}
}

perimeter+=4-neighbours;
}

perimeter
}

fnbottom_right(&self)->Point{
letmax_row=self.points.iter().map(|p|p.0).max().unwrap();
letmax_col=self.points.iter().map(|p|p.1).max().unwrap();

Point(max_row,max_col)
}

pubfnsides(&self)->usize{
letmuttotal_sides=0;
letbottom_right=self.bottom_right();

constLEFT:usize=1;
constRIGHT:usize=3;

fordirectionin0..4{
letmutvisited=vec![];

forpointin&self.points{
ifvisited.contains(point)||self.points.contains(&point.neighbours()[direction]){
continue;
}

total_sides+=1;
visited.push(*point);

forsidein&[LEFT,RIGHT]{
letmutcurrent=point.clone();

whilecurrent<=bottom_right
&&self.points.contains(&current)
&&!self.points.contains(&current.neighbours()[direction])
{
visited.push(current);
current=current.neighbours()[(direction+side)%4];
}
}
}
}

total_sides
}
}

fnmain(){
letmutinput=String::new();
stdin().lock().read_to_string(&mutinput).unwrap();

letmutgrid=Grid::from_str(&input);
letmutpart1=0;
letmutpart2=0;

whileletSome(point)=grid.find_unmapped(){
letregion=grid.take_region(point).unwrap();

part1+=region.area()*region.perimeter();
part2+=region.area()*region.sides();
}

// println!("Part 1: {}", part1);
// println!("Part 2: {}", part2);

println!("{}",part1);
}