Skip to content

Commit

Permalink
Day 18! 🏡
Browse files Browse the repository at this point in the history
  • Loading branch information
bozdoz committed Dec 19, 2023
1 parent 8cd0903 commit 8d84002
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 0 deletions.
53 changes: 53 additions & 0 deletions BLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,58 @@
# What Am I Learning Each Day?

### Day 18

**Difficulty: 3/10 ★★★☆☆☆☆☆☆☆**

**Time: ~1 hrs**

**Run Time: ~774.292µs**

**Part One** was copy paste from Day 10: Pick your Shoelaces. I think I had to order the cells (should follow up on that): so I lazily created a Vec in addition to a HashMap. Absolutely nothing remarkable about Part One.

**Part Two**: refactor wasn't too bad.

Ran into a lifetime issue I was able to resolve by myself:

```rust
let get_instructions = if part == 1 {
|parts: Vec<&str>| {
let dir = parts[0].to_owned();
let steps = parts[1].parse::<isize>().expect("steps are a number");

(dir, steps)
}
} else {
|parts: Vec<&str>| {
let color = parts[2];
let dir = color[2..=7].to_owned();
let steps = color[8..].parse::<isize>().expect("thought it was a number");

(dir, steps)
}
};
```

Here, the secret was the `to_owned` method on the `&str`. Otherwise the references don't live long enough, and the error message was a bit ambiguous to figure out how to resolve it. ChatGPT also had no clue.

Learned how to parse hexadecimal in rust today:

```rust
let color = parts[2];
let dir = usize::from_str_radix(&color[7..8], 16).expect("direction to be a number");
let dir = match dir {
0 => "R",
1 => "D",
2 => "L",
3 => "U",
_ => panic!("can't find dir!")
}.to_owned();
let steps = usize::from_str_radix(&color[2..7], 16).expect("steps to be a number") as isize;
```

Felt a bit weird.


### Day 16

**Difficulty: 4/10 ★★★★☆☆☆☆☆☆**
Expand Down
9 changes: 9 additions & 0 deletions day-18/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "day-18"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
lib = { version = "0.1.0", path = "../lib" }
14 changes: 14 additions & 0 deletions day-18/src/example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)
136 changes: 136 additions & 0 deletions day-18/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use core::panic;
use std::{time::Instant, fs, vec};
use lib::{get_part, Point};

struct Grid {
nodes: Vec<Point>,
boundary_count: usize,
}

impl Grid {
fn new(contents: &str, part: u8) -> Self {
let mut nodes = vec![];

let lines = contents.lines();
let mut cur = Point{x: 0, y: 0};
let mut boundary_count: usize = 0;

let get_instructions = if part == 1 {
|parts: Vec<&str>| {
let dir = parts[0].to_owned();
let steps = parts[1].parse::<isize>().expect("steps are a number");

(dir, steps)
}
} else {
|parts: Vec<&str>| {
let color = parts[2];
let dir = usize::from_str_radix(&color[7..8], 16).expect("direction to be a number");
let dir = match dir {
0 => "R",
1 => "D",
2 => "L",
3 => "U",
_ => panic!("can't find dir!")
}.to_owned();
let steps = usize::from_str_radix(&color[2..7], 16).expect("steps to be a number") as isize;

(dir, steps)
}
};

for line in lines {
let parts: Vec<&str> = line.split_whitespace().collect();

let (dir, steps) = get_instructions(parts);

let inc = match dir.as_str() {
"U" => Point{ x: 0, y: -steps },
"R" => Point{ x: steps, y: 0 },
"D" => Point{ x: 0, y: steps },
"L" => Point{ x: -steps, y: 0 },
_ => panic!("no direction?")
};

boundary_count += steps as usize;
cur = cur + inc;
nodes.push(cur);
}

Self { nodes, boundary_count }
}
// shoelace formula
fn area(&self) -> isize {
let mut points = self.nodes.clone();

// make sure it's closed
points.push(points[0]);

// 2A = (x1 * y2 - y1 * x2) + (x2 * y3...)...

let sum: isize = points
.windows(2)
.map(|p| { p[0].x * p[1].y - p[0].y * p[1].x })
.sum();

let boundary_count = self.boundary_count as isize;

// I don't know how to read math hieroglyphs
// effed up somewhere? seems too complicated
sum.abs() / 2 - boundary_count / 2 + 1 + boundary_count
}
}

fn part_one(grid: &Grid) -> isize {
grid.area()
}

fn part_two(grid: &Grid) -> isize {
grid.area()
}

fn main() {
let (one, two) = get_part();
let start = Instant::now();
let contents = fs::read_to_string("./src/input.txt").unwrap();


if one {
let now = Instant::now();
let grid = Grid::new(&contents, 1);
let ans = part_one(&grid);
println!("Part one: {:?} {:?}", ans, now.elapsed());
}

if two {
let now = Instant::now();
let grid = Grid::new(&contents, 2);
let ans = part_two(&grid);
println!("Part two: {:?} {:?}", ans, now.elapsed());
}

println!("Time: {:?}", start.elapsed())
}

#[cfg(test)]
mod tests {
use super::*;

const EXAMPLE: &str = include_str!("./example.txt");

#[test]
fn test_part_one() {
let grid = Grid::new(EXAMPLE, 1);
let ans = part_one(&grid);

assert_eq!(ans, 62);
}

#[test]
fn test_part_two() {
let grid = Grid::new(EXAMPLE, 2);
let ans = part_two(&grid);

assert_eq!(ans, 952408144115);
}
}

0 comments on commit 8d84002

Please sign in to comment.