wycy's recent activity
-
Comment on Does your flag fail? CGP Grey grades the state flags of the USA! in ~design
-
Comment on The Verge complains about ubiquitous login prompts in ~tech
wycy On a somewhat related note, because I was involved in the LastPass breach, I've been changing my passwords for everything over the past couple days. In so doing, I've become absolutely astonished...On a somewhat related note, because I was involved in the LastPass breach, I've been changing my passwords for everything over the past couple days. In so doing, I've become absolutely astonished at how bad the authentication systems are practically everywhere. I've been using this as an opportunity to select strong, unique passwords everywhere, but SO MANY websites have a maximum character limit of 18 or 20 characters, including many banks. I can't fathom why so many sites would implement a maximum character limit, especially one so low.
It's absolutely insane to me that my Tildes account has a much stronger password than my Bank of America account.
-
Comment on Which web browser do you use? in ~tech
wycy Firefox at home and Chrome at work. I’d use Firefox at work but something about the work network or PC configuration makes it a little screwy, unfortunately.Firefox at home and Chrome at work. I’d use Firefox at work but something about the work network or PC configuration makes it a little screwy, unfortunately.
-
Comment on Day 24: Blizzard Basin in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::HashSet; use std::collections::VecDeque; use std::collections::BinaryHeap; use...Rust
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::HashSet; use std::collections::VecDeque; use std::collections::BinaryHeap; use std::cmp::Ordering; use point2d::point2d::Point2D; #[derive(Debug,Copy,Clone,Hash,Eq,PartialEq)] struct Blizzard { loc: Point2D, dir: BlizzardDirection, } #[derive(Debug,Copy,Clone,Hash,Eq,PartialEq)] enum BlizzardDirection { Up, Down, Left, Right, } impl From<char> for BlizzardDirection { fn from(c: char) -> Self { match c { '^' => Self::Up, 'v' => Self::Down, '<' => Self::Left, '>' => Self::Right, _ => panic!("Unexpected blizzard direction character: {c}"), } } } #[derive(PartialEq,Eq)] struct Path { pt: Point2D, steps: i64, } impl Ord for Path { fn cmp(&self, other: &Self) -> Ordering { other.steps.cmp(&self.steps) } } impl PartialOrd for Path { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(other.steps.cmp(&self.steps)) } } fn neighbor_addresses(pt: &Point2D) -> Vec<Point2D> { vec![Point2D { x: pt.x , y: pt.y-1 }, // up Point2D { x: pt.x+1, y: pt.y }, // right Point2D { x: pt.x , y: pt.y+1 }, // down Point2D { x: pt.x-1, y: pt.y }] // left } fn shortest_path(start: &Point2D, waypoints: &VecDeque<Point2D>, xmax: i64, ymax: i64, blizzards: &Vec<Blizzard>) -> i64 { // Prepare let mut ends = waypoints.clone(); let mut end = ends.pop_front().unwrap(); // Explore let mut heap: BinaryHeap<Path> = BinaryHeap::new(); let mut seen: HashSet<(Point2D,i64)> = HashSet::new(); heap.push(Path {pt: *start, steps: 0}); 'heap_lp: while let Some(path) = heap.pop() { // Current properties let (pt_now,time_now) = (path.pt,path.steps); // Determine future properties let new_time = time_now + 1; let new_blizzards = blizzards_at_time(&blizzards,new_time,xmax,ymax); // Consider waiting on this square IF blizzard will not be here next step if new_blizzards.iter().filter(|b| b.loc == pt_now).count() == 0 { if seen.insert((pt_now,new_time)) { heap.push(Path { pt: pt_now, steps: new_time }); } } 'n_loop: for n in neighbor_addresses(&pt_now) { // Check point is a waypoint, and check for next waypoint if n == end { if ends.len() > 0 { end = ends.pop_front().unwrap(); heap.clear(); seen.clear(); heap.push(Path {pt: n, steps: new_time }); continue 'heap_lp; } else { return new_time; } } // Check point is inside the walls if n.x <= 0 || n.x > xmax { continue 'n_loop; } if n.y <= 0 || n.y > ymax { continue 'n_loop; } // Check point will not be an active blizzard if new_blizzards.iter().filter(|b| b.loc == n).count() == 0 { if seen.insert((n,new_time)) { heap.push(Path { pt: n, steps: new_time }); } } } } i64::MAX } fn blizzards_at_time(blizzards: &Vec<Blizzard>, time: i64, xmax: i64, ymax: i64) -> Vec<Blizzard> { let mut adj_blizzards = blizzards.clone(); for mut blizz in &mut adj_blizzards { match blizz.dir { BlizzardDirection::Up => { blizz.loc.y = 1 + ((blizz.loc.y - 1 - time).rem_euclid(ymax)); }, BlizzardDirection::Down => { blizz.loc.y = 1 + ((blizz.loc.y - 1 + time).rem_euclid(ymax)); }, BlizzardDirection::Left => { blizz.loc.x = 1 + ((blizz.loc.x - 1 - time).rem_euclid(xmax)); }, BlizzardDirection::Right => { blizz.loc.x = 1 + ((blizz.loc.x - 1 + time).rem_euclid(xmax)); }, } } adj_blizzards } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Build blizzard map let mut blizzards: Vec<Blizzard> = Vec::new(); let mut start = Point2D { x: 0, y: 0 }; let mut end = start; for (y,line) in input.iter().enumerate() { for (x,ch) in line.chars().enumerate() { let pt = Point2D { x: x as i64, y: y as i64 }; if ch == '.' && y == 0 { start = pt; } if ch == '.' && y == input.len()-1 { end = pt; } match ch { '>' | '<' | '^' | 'v' => blizzards.push(Blizzard { loc: pt, dir: BlizzardDirection::from(ch) }), '.' | '#' => {}, _ => panic!("Unexpected character: {ch}"), } } } let (xmax,ymax) = (end.x,end.y-1); // Part 1 let mut waypoints: VecDeque<Point2D> = VecDeque::new(); waypoints.push_front(end); let part1 = shortest_path(&start,&waypoints,xmax,ymax,&blizzards); println!("Part 1: {part1}"); // 334 // Part 2 let mut waypoints: VecDeque<Point2D> = VecDeque::new(); waypoints.push_front(end); waypoints.push_front(start); waypoints.push_front(end); let part2 = shortest_path(&start,&waypoints,xmax,ymax,&blizzards); println!("Part 2: {part2}"); // 934 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 20: Grove Positioning System in ~comp.advent_of_code
wycy (edited )LinkI have a solution for part 1 (sample + my input) but just the sample for part 2. Ugh. I have no idea what could be wrong given it gets the sample perfectly. Edit: Figured out the problem, woohoo....I have a solution for part 1 (sample + my input) but just the sample for part 2. Ugh. I have no idea what could be wrong given it gets the sample perfectly.
Edit: Figured out the problem, woohoo. The problem was:
Spoiler
I had handling to skip doing any mixing when the actual value was 0, but didn't properly handle this when the *effective* number (when using mod) was 0. -
Comment on Day 21: Monkey Math in ~comp.advent_of_code
wycy Python Python #!/usr/bin/env python3 import sys from typing import List from typing import Tuple import re import sympy as sy def get_data(filename: str) -> List[str]: with open(filename,'r') as...Python
Python
#!/usr/bin/env python3 import sys from typing import List from typing import Tuple import re import sympy as sy def get_data(filename: str) -> List[str]: with open(filename,'r') as f: lines = f.read().splitlines() return lines equation_pattern = re.compile("([\w]{4}): ([\w]{4}) (.) ([\w]{4})") constant_pattern = re.compile("([\w]{4}): ([\d]+)") generic_pattern = re.compile("([\w]{4}): (.+)") class Equation(object): def __init__(self,line): matches = re.search(equation_pattern, line) self.name = matches[1] self.left = matches[2] self.right = matches[4] self.op = matches[3] def part1(): # Input input = get_data(sys.argv[1]) monkeys = {} equations = [] for line in input: if matches := re.search(constant_pattern,line): monkeys[matches[1]] = int(matches[2]) else: equations.append(Equation(line)) # Solve while len(equations) > 0: for eqn in equations: if eqn.left in monkeys and eqn.right in monkeys: monkeys[eqn.name] = int(eval(f"{monkeys[eqn.left]} {eqn.op} {monkeys[eqn.right]}")) equations = [eqn for eqn in equations if eqn.name not in monkeys] print(f"Part 1: {monkeys['root']}") # 152479825094094 def part2(): # Input input = get_data(sys.argv[1]) monkeys = {} for line in input: matches = re.search(generic_pattern,line) monkeys[matches[1]] = matches[2] # Build equation eq_l = monkeys['root'].split()[0] eq_r = monkeys['root'].split()[2] monkeys.pop('root') monkeys.pop('humn') while len(monkeys) > 0: for word in eq_l.split(): if word in monkeys: eq_l = eq_l.replace(word,'( '+monkeys[word]+' )') monkeys.pop(word) for word in eq_r.split(): if word in monkeys: eq_r = eq_r.replace(word,'( '+monkeys[word]+' )') monkeys.pop(word) # Solve eq_l = sy.parse_expr(eq_l) eq_r = sy.parse_expr(eq_r) x = sy.symbols('humn') part2 = sy.solve(eq_l - eq_r)[0] print(f"Part 2: {part2}") # 3360561285172 if __name__ == "__main__": part1() part2()
-
Comment on Day 18: Boiling Boulder in ~comp.advent_of_code
wycy Rust I'm way behind. I need to get back to day 16/17 now. Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::HashMap; use...Rust
I'm way behind. I need to get back to day 16/17 now.
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::HashMap; use point3d::point3d::Point3D; #[derive(Eq,PartialEq)] enum Voxel { Lava, Air, } fn neighbors(pt: &Point3D) -> Vec<Point3D> { vec![ Point3D { x: pt.x+1, y: pt.y , z: pt.z }, Point3D { x: pt.x-1, y: pt.y , z: pt.z }, Point3D { x: pt.x , y: pt.y+1, z: pt.z }, Point3D { x: pt.x , y: pt.y-1, z: pt.z }, Point3D { x: pt.x , y: pt.y , z: pt.z+1 }, Point3D { x: pt.x , y: pt.y , z: pt.z-1 }, ] } fn coords_voxel(s: &str) -> (Point3D,Voxel) { let coords: Vec<_> = s.split(",").collect(); let (x,y,z) = (coords[0].parse().unwrap(), coords[1].parse().unwrap(), coords[2].parse().unwrap()); (Point3D { x: x, y: y, z: z }, Voxel::Lava) } fn flood_fill(pt: &Point3D, map: &mut HashMap<Point3D,Voxel>, xrange: (i64,i64), yrange: (i64,i64), zrange: (i64,i64)) { let (xmin,xmax) = xrange; let (ymin,ymax) = yrange; let (zmin,zmax) = zrange; if pt.x == xmin || pt.x == xmax || pt.y == ymin || pt.y == ymax || pt.z == zmin || pt.z == zmax { return } match &map.get(&pt) { Some(Voxel::Lava) | Some(Voxel::Air) => return, _ => &map.insert(*pt,Voxel::Air), }; flood_fill(&Point3D { x: pt.x + 1, y: pt.y , z: pt.z }, map, xrange, yrange, zrange); flood_fill(&Point3D { x: pt.x - 1, y: pt.y , z: pt.z }, map, xrange, yrange, zrange); flood_fill(&Point3D { x: pt.x , y: pt.y + 1, z: pt.z }, map, xrange, yrange, zrange); flood_fill(&Point3D { x: pt.x , y: pt.y - 1, z: pt.z }, map, xrange, yrange, zrange); flood_fill(&Point3D { x: pt.x , y: pt.y , z: pt.z + 1}, map, xrange, yrange, zrange); flood_fill(&Point3D { x: pt.x , y: pt.y , z: pt.z - 1}, map, xrange, yrange, zrange); } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Build map let mut voxels: HashMap<Point3D,Voxel> = input.iter().map(|s| coords_voxel(s)).collect(); // Part 1 let part1 = &voxels.len()*6 - &voxels.iter().map(|(pt,_)| { neighbors(&pt).iter().map(|n| match &voxels.get(&n) { Some(_) => 1, None => 0, }).sum::<usize>() }).sum::<usize>(); println!("Part 1: {part1}"); // 3610 // Determine maximum extents let (xmin,xmax) = (&voxels.keys().map(|pt| pt.x).min().unwrap() - 2, &voxels.keys().map(|pt| pt.x).max().unwrap() + 2); let (ymin,ymax) = (&voxels.keys().map(|pt| pt.y).min().unwrap() - 2, &voxels.keys().map(|pt| pt.y).max().unwrap() + 2); let (zmin,zmax) = (&voxels.keys().map(|pt| pt.z).min().unwrap() - 2, &voxels.keys().map(|pt| pt.z).max().unwrap() + 2); // Flood the outer area with air flood_fill(&Point3D { x: xmin+1, y: ymin+1, z: zmin+1 },&mut voxels, (xmin,xmax), (ymin,ymax), (zmin,zmax)); // Calculate surface area let part2 = &voxels .iter() .filter(|(_,v)| **v == Voxel::Lava) .map(|(pt,_)| { neighbors(&pt).iter().map(|n| match &voxels.get(&n) { Some(Voxel::Air) => 1, _ => 0, }).sum::<usize>() }).sum::<usize>(); println!("Part 2: {part2}"); // 2082 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 14: Regolith Reservoir in ~comp.advent_of_code
wycy (edited )LinkRust I enjoyed this one. I was a bit afraid due to the problems reference to 2018 day 17, which I remember finding incredibly hard at the time, but this one wasn’t as bad. Rust use std::env; use...Rust
I enjoyed this one. I was a bit afraid due to the problems reference to 2018 day 17, which I remember finding incredibly hard at the time, but this one wasn’t as bad.
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::HashMap; use point2d::point2d::Point2D; const ORIGIN_X: i64 = 500; const ORIGIN_Y: i64 = 0; const ORIGIN: Point2D = Point2D { x: ORIGIN_X, y: ORIGIN_Y }; enum MapType { Origin, Rock, Sand, } fn can_move(sand_map: &HashMap<Point2D,MapType>, pt: &Point2D) -> bool { match sand_map.get(&pt) { None => true, Some(_) => false, } } fn drop_sand(sand_map: &mut HashMap<Point2D,MapType>, abyss: i64, part1: bool) -> bool { let mut new_pt = Point2D { x: ORIGIN_X, y: ORIGIN_Y }; loop { // Assess movements let try_down = Point2D { x: new_pt.x, y: new_pt.y+1 }; let try_left = Point2D { x: new_pt.x-1, y: new_pt.y+1 }; let try_right = Point2D { x: new_pt.x+1, y: new_pt.y+1 }; let can_down = can_move(&sand_map, &try_down); let can_left = can_move(&sand_map, &try_left); let can_right = can_move(&sand_map, &try_right); // Assign movements if can_down { new_pt = try_down; if part1 && new_pt.y + 1 == abyss { return false; } // Fell to the abyss } else if can_left { new_pt = try_left; } else if can_right { new_pt = try_right; } else { if !part1 && new_pt == ORIGIN { return false; } // Blocking origin sand_map.insert(new_pt,MapType::Sand); return true; // At rest } } } fn build_map(input: &Vec<String>) -> HashMap<Point2D,MapType> { let mut sand_map: HashMap<Point2D,MapType> = HashMap::new(); let origin = Point2D { x: ORIGIN_X, y: ORIGIN_Y }; sand_map.insert(origin, MapType::Origin); for line in input { let segments: Vec<_> = line.split("->").collect(); for segment in segments.windows(2) { let p1: Vec<_> = segment[0].split(",").map(|v| v.trim().parse::<i64>().unwrap()).collect(); let p2: Vec<_> = segment[1].split(",").map(|v| v.trim().parse::<i64>().unwrap()).collect(); let (x1,y1) = (p1[0], p1[1]); let (x2,y2) = (p2[0], p2[1]); let xrange = if x2 > x1 { x1..=x2 } else { x2..=x1 }; let yrange = if y2 > y1 { y1..=y2 } else { y2..=y1 }; for x in xrange.clone() { for y in yrange.clone() { sand_map.insert(Point2D { x: x, y: y }, MapType::Rock); } } } } sand_map } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Part 1 let mut sand_map = build_map(&input); // Identify the extent of the abyss let abyss = &sand_map.keys().map(|&pt| pt.y).max().unwrap() + 2; // Simulate sand 'sand_lp: for sand in 0.. { let result = drop_sand(&mut sand_map,abyss,true); if !result { println!("Part 1: {sand}"); break 'sand_lp; } // 1061 } // Part 2 (reset map) let mut sand_map = build_map(&input); // Build floor for x in 0..=1000 { sand_map.insert(Point2D { x: x, y: abyss },MapType::Rock); } 'sand_lp2: for sand in 1.. { let result = drop_sand(&mut sand_map,abyss,false); if !result { println!("Part 2: {sand}"); break 'sand_lp2; } // 25055 } Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 13: Distress Signal in ~comp.advent_of_code
wycy Python Python #!/usr/bin/env python3 import sys from typing import List from typing import Tuple from itertools import zip_longest from functools import cmp_to_key RAN_OUT = -9999999999 def...Python
Python
#!/usr/bin/env python3 import sys from typing import List from typing import Tuple from itertools import zip_longest from functools import cmp_to_key RAN_OUT = -9999999999 def get_data1(filename: str) -> List[str]: with open(filename,'r') as f: lines = f.read() lines = lines.split("\n\n") return lines def get_data2(filename: str) -> List[str]: with open(filename,'r') as f: lines = f.read().splitlines() return [l for l in lines if l != ''] def compare_packets(p1,p2) -> int: for v1,v2 in zip_longest(p1,p2,fillvalue=RAN_OUT): if v1 == RAN_OUT: return -1 if v2 == RAN_OUT: return +1 if type(v1) == int and type(v2) == int: if v1 < v2: return -1 if v1 > v2: return +1 elif type(v1) == list and type(v2) == list: outcome = compare_packets(v1,v2) if outcome is not None: return outcome elif type(v1) == list and type(v2) == int: outcome = compare_packets(v1,[v2]) if outcome is not None: return outcome elif type(v1) == int and type(v2) == list: outcome = compare_packets([v1],v2) if outcome is not None: return outcome else: quit(f"Error: Unknown types: v1={type(v1)}, v2={type(v2)}") def main(): # Part 1 input = get_data1(sys.argv[1]) part1 = 0 for ix,pair in enumerate(input): parts = pair.split("\n") first,second = parts[0], parts[1] first = eval(first) second = eval(second) if compare_packets(first,second) == -1: part1 += ix + 1 print(f"Part 1: {part1}") # 5760 # Part 2 input = get_data2(sys.argv[1]) input.append("[[2]]") input.append("[[6]]") packets = [eval(p) for p in input] packets = sorted(packets, key=cmp_to_key(compare_packets)) part2 = 1 for ix,packet in enumerate(packets): if packet == [[2]]: part2 *= (ix+1) if packet == [[6]]: part2 *= (ix+1) print(f"Part 2: {part2}") # 26670 if __name__=="__main__": main()
-
Comment on Day 12: Hill Climbing Algorithm in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::{HashMap,HashSet}; use std::collections::BinaryHeap; use std::cmp::Ordering; use...Rust
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::collections::{HashMap,HashSet}; use std::collections::BinaryHeap; use std::cmp::Ordering; use point2d::point2d::Point2D; fn elevation(ch: char) -> i64 { match ch { 'a'..='z' => { ch as i64 - 96 }, 'S'=> { 1 }, 'E'=> { 26 }, _ => panic!("Unknown character: {}", ch), } } #[derive(PartialEq,Eq)] struct Path { pt: Point2D, steps: i64, } impl Ord for Path { fn cmp(&self, other: &Self) -> Ordering { other.steps.cmp(&self.steps) } } impl PartialOrd for Path { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(other.steps.cmp(&self.steps)) } } fn neighbor_addresses(pt: &Point2D) -> Vec<Point2D> { vec![Point2D { x: pt.x , y: pt.y-1 }, // up Point2D { x: pt.x+1, y: pt.y }, // right Point2D { x: pt.x , y: pt.y+1 }, // down Point2D { x: pt.x-1, y: pt.y }] // left } fn shortest_path(map: &HashMap<Point2D,i64>, start: Point2D, end: Point2D) -> i64 { // Explore let mut visited: HashSet<Point2D> = HashSet::new(); let mut heap: BinaryHeap<Path> = BinaryHeap::new(); heap.push(Path{pt: start, steps: 0}); while heap.len() > 0 { let path = heap.pop().unwrap(); let (now,current_steps) = (path.pt, path.steps); let current_elevation = map.get(&now).unwrap(); 'neighbor_loop: for neighbor in neighbor_addresses(&now) { // Determine if visitable let new_elev = match map.get(&neighbor) { Some(e) => e, None => { continue 'neighbor_loop; }, // off the map }; if new_elev > &(current_elevation + 1) { continue 'neighbor_loop; } // Check already visited if visited.get(&neighbor).is_some() { continue 'neighbor_loop; } visited.insert(neighbor); // New steps let new_steps = current_steps + 1; // Found the end if neighbor == end { return new_steps; } heap.push(Path{pt: neighbor, steps: new_steps}); } } i64::MAX } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Build map let mut elev_map: HashMap<Point2D,i64> = HashMap::new(); let mut start = Point2D {x: 0, y: 0 }; let mut end = Point2D {x: 0, y: 0 }; let mut possible_starts: Vec<Point2D> = Vec::new(); for (y,line) in input.iter().enumerate() { for (x,elev_ch) in line.chars().enumerate() { let pt = Point2D { x: x as i64, y: y as i64 }; elev_map.insert(pt, elevation(elev_ch)); // Identify start and end points match elev_ch { 'a' => possible_starts.push(pt), 'S' => start = pt, 'E' => end = pt, _ => {}, } } } // Part 1 let part1 = shortest_path(&elev_map.clone(), start, end); println!("Part 1: {part1}"); // 380 // Part 2 let best = possible_starts.iter().map(|s| shortest_path(&elev_map,*s,end)).min().unwrap(); println!("Part 2: {best}"); // 375 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
Point2D
//#[macro_use] //extern crate text_io; pub mod point2d { use std::ops::{Add,AddAssign}; use std::iter::Sum; extern crate num_complex; use num_complex::Complex; #[derive(Debug, Copy, Clone, Hash)] pub struct Point2D { pub x: i64, pub y: i64, } impl Point2D { pub fn new(x: i64, y: i64) -> Self { Self { x: x, y: y, } } pub fn zeros() -> Self { Self { x: 0, y: 0, } } pub fn from_complex(cmplx: Complex<i64>) -> Self { Self { x: cmplx.re, y: cmplx.im, } } pub fn as_complex(self) -> Complex<i64> { Complex::new(self.x, self.y) } pub fn as_tuple(self) -> (i64,i64) { (self.x, self.y) } } impl Add for Point2D { type Output = Self; fn add(self, other: Self) -> Self { Self { x: self.x + other.x, y: self.y + other.y, } } } impl AddAssign for Point2D { fn add_assign(&mut self, other: Self) { *self = Self { x: self.x + other.x, y: self.y + other.y, }; } } impl PartialEq for Point2D { fn eq(&self, other: &Self) -> bool { self.x == other.x && self.y == other.y } } impl Eq for Point2D {} /*impl<'a> Sum<&'a Self> for Point2D { fn sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>, { iter.fold(Self { x: 0, y: 0 }, |a, b| Self { x: a.x + b.x, y: a.y + b.y, }) } }*/ impl Sum for Point2D { fn sum<I>(iter: I) -> Self where I: Iterator<Item = Self>, { iter.fold(Self { x: 0, y: 0 }, |a, b| Self { x: a.x + b.x, y: a.y + b.y, }) } } }
-
Comment on Day 11: Monkey in the Middle in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self}; extern crate regex; use regex::Regex; #[derive(Debug)] enum Operation { Add(i64), Multiply(i64), Square, } #[derive(Debug)] struct Monkey { pub items:...Rust
Rust
use std::env; use std::io::{self}; extern crate regex; use regex::Regex; #[derive(Debug)] enum Operation { Add(i64), Multiply(i64), Square, } #[derive(Debug)] struct Monkey { pub items: Vec<i64>, pub operation: Operation, pub test_value: i64, pub target_true: i64, pub target_false: i64, pub inspections: i64, } impl From<&str> for Monkey { fn from(s: &str) -> Self { let lines: Vec<_> = s.split("\n").collect(); // Regexes let re_starting = Regex::new(r"Starting items: ([0-9 ,]+)").unwrap(); let re_operation = Regex::new(r"Operation: new = old (\+|\*) (old|[\d]+)").unwrap(); let re_test = Regex::new(r"Test: divisible by ([\d]+)").unwrap(); let re_true = Regex::new(r"If true: throw to monkey ([\d]+)").unwrap(); let re_false = Regex::new(r"If false: throw to monkey ([\d]+)").unwrap(); // Captures let starting_captures = re_starting.captures(&lines[1]).unwrap(); let operate_captures = re_operation.captures(&lines[2]).unwrap(); let test_captures = re_test.captures(&lines[3]).unwrap(); let true_captures = re_true.captures(&lines[4]).unwrap(); let false_captures = re_false.captures(&lines[5]).unwrap(); // Data extractions let starting_items: Vec<i64> = starting_captures[1].split(",").map(|x| x.trim().parse().unwrap()).collect(); let operation = if &operate_captures[2] == "old" { Operation::Square } else { match &operate_captures[1] { "+" => Operation::Add (operate_captures[2].parse().unwrap()), "*" => Operation::Multiply(operate_captures[2].parse().unwrap()), other => panic!("Error: Unknown operation {other}"), } }; let test_value: i64 = test_captures[1].parse().unwrap(); let target_true = true_captures[1].parse().unwrap(); let target_false = false_captures[1].parse().unwrap(); // Construct object Self { items: starting_items, operation: operation, test_value: test_value, target_true: target_true, target_false: target_false, inspections: 0, } } } fn solve(input: &str, part2: bool) -> io::Result<()> { let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); let input: Vec<_> = input_str.split("\n\n").collect(); // Initialize let mut monkeys: Vec<_> = input.iter().map(|x| Monkey::from(*x)).collect(); let num_monkeys = &monkeys.len(); let lcm = &monkeys.iter().map(|x| x.test_value).product::<i64>(); // Turns let lcm = &monkeys.iter().map(|x| x.test_value).product::<i64>(); let rounds = if part2 { 10_000 } else { 20 }; for round in 0..rounds { for m_id in 0..*num_monkeys { for item_id in 0..monkeys[m_id].items.len() { monkeys[m_id].inspections += 1; match monkeys[m_id].operation { Operation::Add(v) => monkeys[m_id].items[item_id] += v, Operation::Multiply(v) => monkeys[m_id].items[item_id] *= v, Operation::Square => monkeys[m_id].items[item_id] *= monkeys[m_id].items[item_id], } if !part2 { monkeys[m_id].items[item_id] /= 3; } let target_monkey = if monkeys[m_id].items[item_id] % monkeys[m_id].test_value == 0 { monkeys[m_id].target_true } else { monkeys[m_id].target_false }; if part2 { monkeys[m_id].items[item_id] %= lcm; } let item_transferred = monkeys[m_id].items[item_id]; monkeys[target_monkey as usize].items.push(item_transferred); } monkeys[m_id].items.clear(); } } // Monkey Business monkeys.sort_by(|a, b| b.inspections.cmp(&a.inspections)); let top_two: i64 = monkeys.iter().take(2).map(|x| x.inspections).product(); let part = if part2 { 2 } else { 1 }; println!("Part {part}: {top_two}"); // Part 1: 120384 // Part 2: 32059801242 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename,false).unwrap(); solve(&filename,true).unwrap(); }
-
Comment on Day 10: Cathode-Ray Tube in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; enum Status { Waiting, Processing, Done, } enum InstKind { Noop, Addx, } struct Instruction { kind: InstKind,...Rust
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; enum Status { Waiting, Processing, Done, } enum InstKind { Noop, Addx, } struct Instruction { kind: InstKind, value: Option<i64>, status: Status, } impl Instruction { fn from(s: &String) -> Self { let parts: Vec<_> = s.split(" ").collect(); match parts[0] { "noop" => Self { kind: InstKind::Noop, value: None, status: Status::Waiting }, "addx" => Self { kind: InstKind::Addx, value: Some(parts[1].parse().unwrap()), status: Status::Waiting }, other => panic!("Unknown instruction: {other}"), } } } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Initializations let mut instructions: Vec<_> = input.iter().map(Instruction::from).collect(); let mut reg: i64 = 1; let mut instr: usize = 0; let mut part1: i64 = 0; const PIX_PER_ROW: usize = 40; const NUM_ROWS: usize = 6; let mut screen = [[false; PIX_PER_ROW]; NUM_ROWS]; // Processing 'main_lp: for cyc in 1.. { if instr >= instructions.len() { break 'main_lp; } let ins = &instructions[instr]; // Gather signal strengths match cyc { 20 | 60 | 100 | 140 | 180 | 220 => { println!("Cycle {cyc}, reg: {reg}, signal={}",cyc*reg); part1 += cyc * reg; }, _ => {}, } // Handle instruction match ins.kind { InstKind::Noop => { instr += 1 }, InstKind::Addx => { match ins.status { Status::Waiting => { instructions[instr].status = Status::Processing; }, Status::Processing => { reg += ins.value.unwrap(); instructions[instr].status = Status::Done; instr += 1; }, _ => panic!("Shouldn't be able to get here"), } }, } // Render image let row: usize = cyc as usize / PIX_PER_ROW; let col: usize = cyc as usize % PIX_PER_ROW; let coli = col as i64; let (px0,px1,px2) = (reg - 1, reg, reg + 1); if coli == px0 || coli == px1 || coli == px2 { screen[row][col] = true; } } println!("Part 1: {part1}"); // 13480 // Part 2 Output: EGJBGCFK for y in 0..NUM_ROWS { for x in 0..PIX_PER_ROW { if screen[y][x] { print!("█"); } else { print!(" "); } } println!(); } Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 8: Treetop Tree House in ~comp.advent_of_code
wycy Rust I'm not very happy with my code today. Feels like I violated DRY a lot. Ah well. Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; const DIM: usize = 99; //...Rust
I'm not very happy with my code today. Feels like I violated DRY a lot. Ah well.
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; const DIM: usize = 99; // Sample=5 fn visible_trees(tree_map: &Vec<Vec<u32>>) -> usize { let mut num_visible = 0; for y in 0..DIM { 'srch: for x in 0..DIM { // Handle edges if x == 0 || y == 0 || x == DIM-1 || y == DIM-1 { num_visible += 1; continue 'srch; } let v = tree_map[x][y]; // Scan -y let mut visible = true; 'ym: for y0 in 0..y { if tree_map[x][y0] >= v { visible = false; break 'ym; } } if visible { num_visible += 1; continue 'srch; } // Scan +y let mut visible = true; 'yp: for y0 in y+1..DIM { if tree_map[x][y0] >= v { visible = false; break 'yp; } } if visible { num_visible += 1; continue 'srch; } // Scan -x let mut visible = true; 'xm: for x0 in 0..x { if tree_map[x0][y] >= v { visible = false; break 'xm; } } if visible { num_visible += 1; continue 'srch; } // Scan +x let mut visible = true; 'xp: for x0 in x+1..DIM { if tree_map[x0][y] >= v { visible = false; break 'xp; } } if visible { num_visible += 1; continue 'srch; } } } num_visible } fn scenic_score(tree_map: &Vec<Vec<u32>>) -> usize { let mut max_scenic = 0; for y in 0..DIM { 'srch: for x in 0..DIM { // Handle edges if x == 0 || y == 0 || x == DIM-1 || y == DIM-1 { continue 'srch; } // Zero scenic let v = tree_map[x][y]; // Scan -y let mut dist_ym = 0; 'ym: for y0 in (0..y).rev() { if tree_map[x][y0] <= v { dist_ym += 1; } if tree_map[x][y0] >= v { break 'ym; } } // Scan +y let mut dist_yp = 0; 'yp: for y0 in y+1..DIM { if tree_map[x][y0] <= v { dist_yp += 1; } if tree_map[x][y0] >= v { break 'yp; } } // Scan -x let mut dist_xm = 0; 'xm: for x0 in (0..x).rev() { if tree_map[x0][y] <= v { dist_xm += 1; } if tree_map[x0][y] >= v { break 'xm; } } // Scan +x let mut dist_xp = 0; 'xp: for x0 in x+1..DIM { if tree_map[x0][y] <= v { dist_xp += 1; } if tree_map[x0][y] >= v { break 'xp; } } max_scenic = std::cmp::max(max_scenic, dist_ym * dist_yp * dist_xp * dist_xm); } } max_scenic } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Build tree map let mut tree_map = vec![vec![0; DIM]; DIM]; for (y,line) in input.iter().enumerate() { for (x,c) in line.chars().enumerate() { tree_map[x][y] = c.to_digit(10).unwrap(); } } // Outputs println!("Part 1: {}",visible_trees(&tree_map)); // 1693 println!("Part 2: {}",scenic_score(&tree_map)); // 422059 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 6: Tuning Trouble in ~comp.advent_of_code
wycy Rust use std::env; use std::io::{self}; use std::collections::HashSet; fn packet_start(s: &str) -> usize { const MARKER_SIZE: usize = 4; let mut start = MARKER_SIZE; for chs in...Rust
use std::env; use std::io::{self}; use std::collections::HashSet; fn packet_start(s: &str) -> usize { const MARKER_SIZE: usize = 4; let mut start = MARKER_SIZE; for chs in s.chars().collect::<Vec<_>>().windows(MARKER_SIZE) { let (a,b,c,d) = (chs[0],chs[1],chs[2],chs[3]); if a != b && a != c && a != d && b != c && b != d && c != d { break } else { start += 1; } } start } fn message_start(s: &str) -> usize { const MARKER_SIZE: usize = 14; let mut start = MARKER_SIZE; 'outer: for chs in s.chars().collect::<Vec<_>>().windows(MARKER_SIZE) { start += 1; let mut char_set: HashSet<char> = HashSet::new(); for ch in chs { if char_set.contains(ch) { continue 'outer; } else { char_set.insert(*ch); } } break; } start - 1 } fn solve(input: &str) -> io::Result<()> { // Input let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); // Output println!("Part 1: {}",packet_start(input_str)); // 1578 println!("Part 2: {}",message_start(input_str)); // 2178 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 5: Supply Stacks in ~comp.advent_of_code
wycy There have been previous years where the answer was not only text, but text based on ASCII renders of text, e.g. ███ ██ ███ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ ████ █ ███...There have been previous years where the answer was not only text, but text based on ASCII renders of text, e.g.
███ ██ ███ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ ████ █ ███ █ ███ █ ████ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ ████ █ █ █ █ █ █ ████
-
Comment on Let's talk about ChatGPT in ~tech
wycy POSSIBLE AOC DAY 5 SPOILERS I was struggling with the Rust borrow checker today (having not written any Rust since last year's Advent of Code), so I turned to ChatGPT and asked it "Write me a Rust...POSSIBLE AOC DAY 5 SPOILERS
I was struggling with the Rust borrow checker today (having not written any Rust since last year's Advent of Code), so I turned to ChatGPT and asked it "Write me a Rust function that removes the last character of a string and appends it to a different string" and it wrote out just the perfect function. I was in awe.
-
Comment on Day 5: Supply Stacks in ~comp.advent_of_code
wycy (edited )LinkRust Rust use std::env; use std::io::{self}; extern crate regex; use regex::Regex; #[macro_use] extern crate lazy_static; lazy_static! { static ref RE_MOVES: Regex = { Regex::new(r"move ([\d]+)...Rust
Rust
use std::env; use std::io::{self}; extern crate regex; use regex::Regex; #[macro_use] extern crate lazy_static; lazy_static! { static ref RE_MOVES: Regex = { Regex::new(r"move ([\d]+) from ([\d]+) to ([\d]+)").unwrap() }; } #[derive(Debug)] struct Move { qty: usize, from: usize, to: usize, } impl From<&str> for Move { fn from(s: &str) -> Self { let matches = RE_MOVES.captures(s).unwrap(); Self { qty: matches[1].parse().unwrap(), from: matches[2].parse().unwrap(), to: matches[3].parse().unwrap(), } } } const MAX_NUM_STACKS: usize = 9; fn move_last_n_chars(s1: &str, s2: &str, n: usize) -> (String, String) { let mut s1_chars: Vec<char> = s1.chars().collect(); let s2_chars: Vec<char> = s2.chars().collect(); let mut moved_chars: String = s1_chars.iter().rev().take(n).collect(); moved_chars = moved_chars.chars().rev().collect(); for _ in 0..n { s1_chars.pop().unwrap(); } let s1_new = s1_chars.into_iter().collect(); let mut s2_new: String = s2_chars.into_iter().collect(); s2_new.push_str(&moved_chars); (s1_new, s2_new) } fn solve(input: &str) -> io::Result<()> { let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); let input: Vec<_> = input_str.split("\n\n").collect(); // Initialize moves let moves: Vec<_> = input[1].split("\n").map(Move::from).collect(); // Initialize stacks let mut stacks: [String; MAX_NUM_STACKS] = Default::default(); for line in input[0].lines() { if line.chars().nth(1).unwrap() == '1' { continue } // Skip last line indexing the stacks for (ix,ch) in line.chars().enumerate() { match ix { 1 => if ch != ' ' { stacks[0].push_str(&ch.to_string()) }, 5 => if ch != ' ' { stacks[1].push_str(&ch.to_string()) }, 9 => if ch != ' ' { stacks[2].push_str(&ch.to_string()) }, 13 => if ch != ' ' { stacks[3].push_str(&ch.to_string()) }, 17 => if ch != ' ' { stacks[4].push_str(&ch.to_string()) }, 21 => if ch != ' ' { stacks[5].push_str(&ch.to_string()) }, 25 => if ch != ' ' { stacks[6].push_str(&ch.to_string()) }, 29 => if ch != ' ' { stacks[7].push_str(&ch.to_string()) }, 33 => if ch != ' ' { stacks[8].push_str(&ch.to_string()) }, _ => {}, } } } // Reverse the stacks for ix in 0..MAX_NUM_STACKS { stacks[ix] = stacks[ix].chars().rev().collect::<String>(); } // Copy original state for part 2 let stacks_copy = stacks.clone(); // Process part 1 moves for moved in &moves { let (qty,from,to) = (moved.qty,moved.from-1, moved.to-1); for _ in 0..qty { //(stacks[from],stacks[to]) = move_last_char(&stacks[from],&stacks[to]); (stacks[from],stacks[to]) = move_last_n_chars(&stacks[from],&stacks[to],1); } } // Part 1 Output print!("Part 1: "); // VGBBJCRMN for ix in 0..MAX_NUM_STACKS { print!("{}",stacks[ix].chars().last().unwrap()); } println!(); // Process part 2 moves stacks = stacks_copy; for moved in &moves { let (qty,from,to) = (moved.qty,moved.from-1, moved.to-1); (stacks[from],stacks[to]) = move_last_n_chars(&stacks[from],&stacks[to],qty); } // Part 2 Output print!("Part 2: "); // LBBVJBRMH for ix in 0..MAX_NUM_STACKS { print!("{}",stacks[ix].chars().last().unwrap()); } println!(); Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 4: Camp Cleanup in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::ops::RangeInclusive; extern crate regex; use regex::Regex; struct Team { elf1:...Rust
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; use std::ops::RangeInclusive; extern crate regex; use regex::Regex; struct Team { elf1: RangeInclusive<usize>, elf2: RangeInclusive<usize>, } impl Team { pub fn has_overlaps1(&self) -> bool { (self.elf1.contains(&self.elf2.start()) && self.elf1.contains(&self.elf2.end())) || (self.elf2.contains(&self.elf1.start()) && self.elf2.contains(&self.elf1.end())) } pub fn has_overlaps2(&self) -> bool { self.elf1.contains(&self.elf2.start()) || self.elf1.contains(&self.elf2.end()) || self.elf2.contains(&self.elf1.start()) || self.elf2.contains(&self.elf1.end()) } } impl From<&String> for Team { fn from(s: &String) -> Self { let re = Regex::new(r"(\d+)\-(\d+),(\d+)\-(\d+)").unwrap(); let matches = re.captures(s).unwrap(); Self { elf1: RangeInclusive::new(matches[1].parse().unwrap(),matches[2].parse().unwrap()), elf2: RangeInclusive::new(matches[3].parse().unwrap(),matches[4].parse().unwrap()), } } } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Part 1 let part1 = input .iter() .map(Team::from) .filter(|x| x.has_overlaps1()) .count(); println!("Part 1: {:?}", part1); // 450 // Part 2 let part2 = input .iter() .map(Team::from) .filter(|x| x.has_overlaps2()) .count(); println!("Part 2: {:?}", part2); // 837 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 2: Rock Paper Scissors in ~comp.advent_of_code
wycy (edited )LinkRust Rust use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; #[derive(Debug,PartialEq,Eq)] enum GameResult { Win = 6, Draw = 3, Lose = 0, } impl From<&str> for GameResult...Rust
Rust
use std::env; use std::io::{self, prelude::*, BufReader}; use std::fs::File; #[derive(Debug,PartialEq,Eq)] enum GameResult { Win = 6, Draw = 3, Lose = 0, } impl From<&str> for GameResult { fn from(c: &str) -> Self { match c { "X" => Self::Lose, "Y" => Self::Draw, "Z" => Self::Win, other => panic!("Unknown directive: {}",other), } } } #[derive(Copy,Clone,Debug,PartialEq,Eq)] enum Play { Rock = 1, Paper = 2, Scissors = 3, } impl From<&str> for Play { fn from(c: &str) -> Self { match c { "A" | "X" => Self::Rock, "B" | "Y" => Self::Paper, "C" | "Z" => Self::Scissors, other => panic!("Unknown play: {}",other), } } } // plays: (their play, my play) fn result(plays: &(Play,Play)) -> GameResult { use Play::*; use GameResult::*; match plays { (Rock,Rock) | (Paper,Paper) | (Scissors,Scissors) => { Draw }, (Rock,Paper) => { Win }, (Rock,Scissors) => { Lose }, (Paper,Rock) => { Lose }, (Paper,Scissors) => { Win }, (Scissors,Rock) => { Win }, (Scissors,Paper) => { Lose }, } } fn play_from_result(their_play: Play, result: &GameResult) -> Play { use Play::*; use GameResult::*; match result { Draw => their_play, Win => { match their_play { Rock => Paper, Paper => Scissors, Scissors => Rock, }}, Lose => { match their_play { Rock => Scissors, Paper => Rock, Scissors => Paper, }}, } } fn plays(s: &String) -> (Play,Play) { let plays: Vec<_> = s.split_whitespace().collect(); (Play::from(plays[0]), Play::from(plays[1])) } fn play_and_result(s: &String) -> (Play,GameResult) { let play_and_result: Vec<_> = s.split_whitespace().collect(); (Play::from(play_and_result[0]), GameResult::from(play_and_result[1])) } fn solve(input: &str) -> io::Result<()> { let file = File::open(input).expect("Input file not found."); let reader = BufReader::new(file); // Input let input: Vec<String> = match reader.lines().collect() { Err(err) => panic!("Unknown error reading input: {}", err), Ok(result) => result, }; // Part 1 let part1 = input .iter() .map(|x| { let (their_play,my_play) = plays(x); let result = result(&(their_play,my_play)); my_play as usize + result as usize }) .sum::<usize>(); println!("Part 1: {}", part1); // 11906 // Part 2 let part2 = input .iter() .map(|x| { let (play,result) = play_and_result(x); let my_play = play_from_result(play,&result); my_play as usize + result as usize }) .sum::<usize>(); println!("Part 2: {}", part2); // 11186 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
-
Comment on Day 1: Calorie Counting in ~comp.advent_of_code
wycy Rust Rust use std::env; use std::io::{self}; fn solve(input: &str) -> io::Result<()> { // Input let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); let...Rust
Rust
use std::env; use std::io::{self}; fn solve(input: &str) -> io::Result<()> { // Input let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); let input: Vec<_> = input_str.split("\n\n").collect(); // Get each Elf's calories let mut elf_snacks: Vec<usize> = input .iter() .map(|x| x .split("\n") .map(|y| y.parse::<usize>().unwrap()) .sum()) .collect(); elf_snacks.sort_by(|a, b| b.cmp(a)); // Calculate answers let part1 = elf_snacks.iter().max().unwrap(); let part2 = elf_snacks.iter().take(3).sum::<usize>(); println!("Part 1: {}", part1); // 72602 println!("Part 2: {}", part2); // 207410 Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }
Rhode Island’s has a word on it but I think it’s underrated. Should’ve been B-tier at least. It’s a great flag.
DC’s should’ve been officially on the roster, and should be S-tier not A-tier.
I might’ve also thrown in Chicago’s flag as an honorable mention A or S tier flag.