Skip to content

Commit

Permalink
Day 10! 🪈
Browse files Browse the repository at this point in the history
  • Loading branch information
bozdoz committed Dec 13, 2023
1 parent f375c62 commit 1a53d01
Show file tree
Hide file tree
Showing 7 changed files with 581 additions and 0 deletions.
172 changes: 172 additions & 0 deletions BLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,177 @@
# What Am I Learning Each Day?

### Day 10

**Difficulty: 6/10 ★★★★★★☆☆☆☆**

**Time: ~2 hrs**

**Run Time: ~11.5ms**

Had a few issues trying to figure out how to do something like this:

```rust
// iterate cells somehow as a mutable variable
if let Some(v) = cells.get_mut(&starting_cell) {
// iterate cells somehow as immutable 🦀❗️
if let Some(v2) = cells.get(&v.neighbours[0]) {
```

But I "cannot borrow `cells` as immutable because it is also borrowed as mutable". This is something that I could unquestionably do in any other language, and I have no idea how to go about it now.

I've decided to do this, and maybe I'm better for it?

```rust
// find starting point neighbours
let mut starting_point_neighbours: Vec<Point> = vec![];
let top = starting_cell + Point { x: 0, y: -1 };
let bottom = starting_cell + Point { x: 0, y: 1 };
let left = starting_cell + Point { x: -1, y: 0 };
let right = starting_cell + Point { x: 1, y: 0 };

for neigh in [top, bottom, left, right] {
if let Some(v2) = cells.get(&neigh) {
if v2.neighbours.iter().any(|x| *x == starting_cell) {
starting_point_neighbours.push(neigh);
}
}
}

if let Some(v) = cells.get_mut(&starting_cell) {
v.neighbours = starting_point_neighbours
}
```

I learned about `vec.retain`:

```rust
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&T) -> bool,

// Retains only the elements specified by the predicate
```

I had a loop for part one; for part two I realized I needed to loop again, but not for the same reason. Borrowing from the iterator I created for Day 3, I converted my loop into an iterator:

```rust
// a loop
fn walk(&self) -> usize {
// move from starting_point
let start = self.get_cell(&self.starting_cell);
let mut prev = &self.starting_cell;
let mut cur = &start.neighbours[0];
let mut value = self.get_cell(cur);
let mut i = 1;

loop {
// get neighbour that isn't previous point
let next = value.neighbours.iter().find(|x| {
*x != prev
}).unwrap();

if *next == self.starting_cell {
return i + 1;
}

prev = cur;
cur = next;
value = self.get_cell(cur);

i += 1;
}
}
```

And here's the same code, implemented as an iterator (notice the lack of coupling with the count):

```rust
// Iterator
struct GridLoop<'a> {
grid: &'a Grid,
prev: Option<Point>,
cur: Option<Point>,
}

// double lifetime
impl<'a> GridLoop<'a> {
fn new(grid: &'a Grid) -> Self {
GridLoop { grid, prev: None, cur: None }
}
}

impl Iterator for GridLoop<'_> {
type Item = Point;

fn next(&mut self) -> Option<Self::Item> {
let start = self.grid.starting_cell;

if self.prev.is_none() {
// start with cell next to starting cell
self.prev = Some(start);
self.cur = Some(self.grid.get_cell(&start).neighbours[0]);

return self.cur;
}

let cur = self.cur.unwrap();

// finish if we reach the start
if cur == start {
return None;
}

// get next
let prev = self.prev.unwrap();
let value = self.grid.get_cell(&cur);
let next = value.neighbours.iter().find(|x| {
// double de-reference again...
**x != prev
}).unwrap();

self.prev = Some(cur);
self.cur = Some(*next);

self.cur
}
}
```

And now the `walk` function can just be:

```rust
fn walk_iter(&self) -> usize {
GridLoop::new(self).into_iter().count()
}
```

I'm realizing I need to get better at reading math. I find it hard to recognize sum and multiples and absolute numbers in the math notation.

Oh, I also moved the Point struct to the shared lib:

```rust
use core::ops::Add;

#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub struct Point {
pub x: isize,
pub y: isize,
}

impl Add for Point {
type Output = Point;

fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
```

A lot of this was copied directly from the documentation; though they use generics, and I'd like to avoid public module generics as much as possible, since my frustration with using it with **go**.

### Day 9

**Difficulty: 1/10 ★☆☆☆☆☆☆☆☆☆**
Expand Down
7 changes: 7 additions & 0 deletions createDay.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,12 @@ mod tests {
assert_eq!(ans, 0);
}
#[test]
fn test_part_two() {
let ans = part_two();
assert_eq!(ans, 0);
}
}
EOF
9 changes: 9 additions & 0 deletions day-10/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "day-10"
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" }
104 changes: 104 additions & 0 deletions day-10/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
--- Day 10: Pipe Maze ---

You use the hang glider to ride the hot air from Desert Island all the way up to the floating metal island. This island is surprisingly cold and there definitely aren't any thermals to glide on, so you leave your hang glider behind.

You wander around for a while, but you don't find any people or animals. However, you do occasionally find signposts labeled "Hot Springs" pointing in a seemingly consistent direction; maybe you can find someone at the hot springs and ask them where the desert-machine parts are made.

The landscape here is alien; even the flowers and trees are made of metal. As you stop to admire some metal grass, you notice something metallic scurry away in your peripheral vision and jump into a big pipe! It didn't look like any animal you've ever seen; if you want a better look, you'll need to get ahead of it.

Scanning the area, you discover that the entire field you're standing on is densely packed with pipes; it was hard to tell at first because they're the same metallic silver color as the "ground". You make a quick sketch of all of the surface pipes you can see (your puzzle input).

The pipes are arranged in a two-dimensional grid of tiles:

| is a vertical pipe connecting north and south.
- is a horizontal pipe connecting east and west.
L is a 90-degree bend connecting north and east.
J is a 90-degree bend connecting north and west.
7 is a 90-degree bend connecting south and west.
F is a 90-degree bend connecting south and east.
. is ground; there is no pipe in this tile.
S is the starting position of the animal; there is a pipe on this tile, but your sketch doesn't show what shape the pipe has.

Based on the acoustics of the animal's scurrying, you're confident the pipe that contains the animal is one large, continuous loop.

For example, here is a square loop of pipe:

.....
.F-7.
.|.|.
.L-J.
.....

If the animal had entered this loop in the northwest corner, the sketch would instead look like this:

.....
.S-7.
.|.|.
.L-J.
.....

In the above diagram, the S tile is still a 90-degree F bend: you can tell because of how the adjacent pipes connect to it.

Unfortunately, there are also many pipes that aren't connected to the loop! This sketch shows the same loop as above:

-L|F7
7S-7|
L|7||
-L-J|
L|-JF

In the above diagram, you can still figure out which pipes form the main loop: they're the ones connected to S, pipes those pipes connect to, pipes those pipes connect to, and so on. Every pipe in the main loop connects to its two neighbors (including S, which will have exactly two pipes connecting to it, and which is assumed to connect back to those two pipes).

Here is a sketch that contains a slightly more complex main loop:

..F7.
.FJ|.
SJ.L7
|F--J
LJ...

Here's the same example sketch with the extra, non-main-loop pipe tiles also shown:

7-F7-
.FJ|7
SJLL7
|F--J
LJ.LJ

If you want to get out ahead of the animal, you should find the tile in the loop that is farthest from the starting position. Because the animal is in the pipe, it doesn't make sense to measure this by direct distance. Instead, you need to find the tile that would take the longest number of steps along the loop to reach from the starting point - regardless of which way around the loop the animal went.

In the first example with the square loop:

.....
.S-7.
.|.|.
.L-J.
.....

You can count the distance each tile in the loop is from the starting point like this:

.....
.012.
.1.3.
.234.
.....

In this example, the farthest point from the start is 4 steps away.

Here's the more complex loop again:

..F7.
.FJ|.
SJ.L7
|F--J
LJ...

Here are the distances for each tile on that loop:

..45.
.236.
01.78
14567
23...

Find the single giant loop starting at S. How many steps along the loop does it take to get from the starting position to the point farthest from the starting position?
5 changes: 5 additions & 0 deletions day-10/src/example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
7-F7-
.FJ|7
SJLL7
|F--J
LJ.LJ
Loading

0 comments on commit 1a53d01

Please sign in to comment.