Skip to content

Instantly share code, notes, and snippets.

@progheal
Last active December 22, 2022 20:03
Show Gist options
  • Save progheal/a0339ab6d171a1dee13998708fbf792a to your computer and use it in GitHub Desktop.
Save progheal/a0339ab6d171a1dee13998708fbf792a to your computer and use it in GitHub Desktop.
Advent of Code 2022 Day 22: Monkey Maps, cube folding algorithm

Let's start from our designated starting point, the "top left" of the first cube face, going right. This means we are going clockwise along the edge of the net.

We want to trace the edge and trying to match the "edge cells", which is represented by a cell, and its direction when we traversed them clockwisely. Using the sample as example, the first edge is (1,9,>). If the current edge does not match other edge, we simply push that into a stack.

We go along the edge, stopping every N times to determine which turn do we take on the net. This is done by going one step out and check myself and my left. Here are the three possible transition from face to face:

           1111111
  1234567890123456
             ─┐
 1        ...# ↓ (EDGERIGHT, both blank)
 2        .#..
 3        #...
 4        .... │
 5...#.......# ↓ (EDGESTRAIGHT, myself non blank but my left is blank)
 6........#...
 7..#....#.... │ (EDGELEFT, both non blank)
 8..........#. └→
 9        ...#....
10        .....#..
11        .#......
12        ......#.
  1234567891111111
           0123456

Each time we transition the face, the turn must be checked to ensure we are matching correct edges.

EDGELEFT is the simplest; we go back to currently unmatched edge and match them. So in the example, the edges before this EDGELEFT are (5,12,v), (6,12,v), (7,12,v), (8,12,v). Then we encounter EDGELEFT so the next face should be matching those on stack, So (9,13,>) matches (8,12,v), (9,14,>) matches (7,12,v), (9,15,>) matches (6,12,v), (9,16,>) matches (5,12,v).

EDGESTRIGHT and EDGERIGHT should match each other: the EDGESTRIGHT transition will fold up forming a caveat letting a EDGERIGHT to fit in. Continuing the example, next turn is EDGERIGHT, matches the EDGESTRAIGHT marked above. So we continue matching into the stack, giving (9,16,v) matches (4,12,v), etc., to (12,16,v) matches (1,12,v)

When we encounter two EDGERIGHT matching, they form a EDGESTRAIGHT and we leave matching mode. This corresponding to the cube corner that comes from three part of the net. Still continuing example, next turn is EDGERIGHT, but the last unmatched turn is also EDGERIGHT (shown above), so we exit matching mode, relabel the turn to EDGESTRAIGHT, and continue pushing (12,16,<) etc. into the unmatched edge stack.

Now, what if we matched an corner, but the unmatched edge runs out? That means (1,start,>) is matched. Since nothing left to match, we also exit matching mode and start pushing next edges in. In the example, this happened after (5,4,>) matches (1,9,>) and go EDGESTRAIGHT, which matched the initial EDGERIGHT. (The initial turn before (1,start,>) is always EDGERIGHT; I'll leave the reason why as an exercise.) So we exit matching mode, record EDGESTRAIGHT as last unmatched turn, and continue pushing (5,5,>) etc. into stack.

Next, we want to turn each matched edge to the actual traverse direction. Take the A and B in the example, that is (6,12,v) and (9,15,>). The traverse direction is then: A turning left (6,12,>) becomes B turning right (9,15,v), and B turning left (9,15,^) becomes A turning right (6,12,>). C and D are similar: they are (12,11,<) and (8,2,<), So C turning left (12,11,v) becomes D turning right (8,2,^), and D turning left (8,2,v) becomes C turning right (12,11,^). We store these mapping separately for later use.

Finally we have a edge map. To walk on it we just check the mapping first, if there's entry that's the result, otherwise we are not on edge so just walk normally.

The coordinate in the program uses C++ convention (0-based), which is one lower than what's written above (1-based).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment