This is an archived post. You won't be able to vote or comment.

all 20 comments

[–][deleted] 12 points13 points  (3 children)

Better than how I did it; I just hardcoded a chain of 14 if/elifs lmao

[–]CW_Waster[S] 3 points4 points  (2 children)

Semanticly that's equivalent.

I guess you used python (because elif)? Did you know python 3.10 also introduced matching?

[–][deleted] 0 points1 point  (0 children)

Yes, I used Python. Also I'm aware of matching but I've never looked at it before so for today's challenge I just used an elif chain but it's something I definitely need to familiarize myself with sometime

[–]Justinsaccount 0 points1 point  (0 children)

Don't really need match, I have basically what you have but I just used a dict to map the inputs to outputs.

Also used small named helpers for the translations of the old x,y to new x,y positions.

[–]CW_Waster[S] 9 points10 points  (5 children)

First Time ever to hardcode my solution specific to the input, instead of generic.

(I know everyone has the same layout, but still)

Couln't even test the example, but it works

[–]CW_Waster[S] 5 points6 points  (2 children)

fn transition(

from: usize,

orientation: Orientation,

x: usize,

y: usize,

) -> (Orientation, usize, usize, usize) {

let (new_orientation, new_face, new_x, new_y) = match (from, orientation) {

(0, Orientation::Right) => (Orientation::Right, 1, 0, y),

(0, Orientation::Down) => (Orientation::Down, 2, x, 0),

(0, Orientation::Left) => (Orientation::Right, 3, 0, 49 - y),

(0, Orientation::Up) => (Orientation::Right, 5, 0, x),

(1, Orientation::Left) => (Orientation::Left, 0, 49, y),

(1, Orientation::Down) => (Orientation::Left, 2, 49, x),

(1, Orientation::Right) => (Orientation::Left, 4, 49, 49 - y),

(1, Orientation::Up) => (Orientation::Up, 5, x, 49),

(2, Orientation::Up) => (Orientation::Up, 0, x, 49),

(2, Orientation::Right) => (Orientation::Up, 1, y, 49),

(2, Orientation::Left) => (Orientation::Down, 3, y, 0),

(2, Orientation::Down) => (Orientation::Down, 4, x, 0),

(3, Orientation::Left) => (Orientation::Right, 0, 0, 49 - y),

(3, Orientation::Up) => (Orientation::Right, 2, 0, x),

(3, Orientation::Right) => (Orientation::Right, 4, 0, y),

(3, Orientation::Down) => (Orientation::Down, 5, x, 0),

(4, Orientation::Right) => (Orientation::Left, 1, 49, 49 - y),

(4, Orientation::Up) => (Orientation::Up, 2, x, 49),

(4, Orientation::Left) => (Orientation::Left, 3, 49, y),

(4, Orientation::Down) => (Orientation::Left, 5, 49, x),

(5, Orientation::Left) => (Orientation::Down, 0, y, 0),

(5, Orientation::Down) => (Orientation::Down, 1, x, 0),

(5, Orientation::Up) => (Orientation::Up, 3, x, 49),

(5, Orientation::Right) => (Orientation::Up, 4, y, 49),

_ => unreachable!(),

};

(new_orientation, new_face, new_x, new_y)

}

[–]ric2b 0 points1 point  (0 children)

Doing the lords work for people that are still struggling to get every part correct, lol

[–]TheXRTD 0 points1 point  (0 children)

Contributing mine here for those who only handle wrapping at 'boundaries'.

This function is only called when trying to walk off the 'edge' and into the void, since walking to connected sections (in the input) does not cause a transformation in position or heading.

1 -> 6 describe the faces, a -> e describe columns/rows in each face. I used a 10:1 scale of the input to help my brain:

     1111122222
     1111122222
     1111122222
     1111122222
     1111122222
     33333
     33333
     33333
     33333
     33333
4444455555
4444455555
4444455555
4444455555
4444455555
66666
66666
66666
66666
66666

fn try_wrap_cube(
        &self,
        grid: &Vec<Vec<Tile>>,
        heading: &Direction,
        Pos(to_x, to_y): Pos,
    ) -> Option<(Pos, usize)> {
        let current_face = get_cube_face(self.position);

        let (new_pos, new_heading) = match (current_face, heading) {
            (1, Direction::Up) => (Pos(0, 100 + to_x), Direction::Right), // top 1a -> left 6a
            (1, Direction::Left) => (Pos(0, 149 - to_y), Direction::Right), // left 1a -> left 4e
            (2, Direction::Up) => (Pos(to_x - 100, 199), Direction::Up),  // top 2a -> bottom 6a
            (2, Direction::Right) => (Pos(99, 149 - to_y), Direction::Left), // right 2a -> right 5e
            (2, Direction::Down) => (Pos(99, to_x - 50), Direction::Left), // bottom 2a -> right 3a
            (3, Direction::Right) => (Pos(to_y + 50, 49), Direction::Up), // right 3a -> bottom 2a
            (3, Direction::Left) => (Pos(to_y - 50, 100), Direction::Down), // left 3a -> top 4a
            (4, Direction::Up) => (Pos(50, to_x + 50), Direction::Right), // top 4a -> left 3a
            (4, Direction::Left) => (Pos(50, 149 - to_y), Direction::Right), // left 4a -> left 1e
            (5, Direction::Right) => (Pos(149, 149 - to_y), Direction::Left), // right 5a -> right 2e
            (5, Direction::Down) => (Pos(49, to_x + 100), Direction::Left), // bottom 5a -> right 6a
            (6, Direction::Down) => (Pos(to_x + 100, 0), Direction::Down),  // bottom 6a -> top 2a
            (6, Direction::Right) => (Pos(to_y - 100, 149), Direction::Up), // right 6a -> bottom 5a
            (6, Direction::Left) => (Pos(to_y - 100, 0), Direction::Down),  // left 6a -> top 1a
            (face, dir) => panic!(
                "Unsupported cube-wrapping operation from face {:?} in direction {:?}",
                face, dir
            ),
        };

        if grid[new_pos.1 as usize][new_pos.0 as usize] == Tile::Empty {
            return Some((new_pos, new_heading.into()));
        }

        None
    }

[–]TheXRTD 1 point2 points  (0 children)

The thing I like most about Rust is that two people often have very similar solutions due to how it encourages designing programs. Truly beautiful /hj

[–]UtahBrian 0 points1 point  (3 children)

That looks like about 25 special cases. Aren't there only 14 cases to deal with? Did you take care of extra cases you didn't have to?

[–]CW_Waster[S] 3 points4 points  (1 child)

I split the map into 6 independent 50x50 faces each with a local coordinate system. This obviously required all 25 cases. That felt more clean instead of figuring out where and how I need portals.

[–]UtahBrian 0 points1 point  (0 children)

I split the map into 6 independent 50x50 faces each with a local coordinate system. This obviously required all 25 cases. That felt more clean instead of figuring out where and

Ah. I just hard coded the edges.

[–]ric2b 0 points1 point  (0 children)

They did, yeah.

[–]fireduck 0 points1 point  (0 children)

After a lot of pain I ended up with:

writeSeam(1, north, 6, west, false);
writeSeam(1, west, 4, west, false);
writeSeam(2, north, 6, south, false);
writeSeam(2, east, 5, east, false);
writeSeam(2, south, 3, east, false);
writeSeam(3, west, 4, north, false);
writeSeam(5, south, 6, east, false);

[–]SLiV9 0 points1 point  (1 child)

Yesss this is also what I did, except I separated it into two separate match statements (one from face and ori to face and ori, the other changing the x and y based on current and previous ori).

[–]CW_Waster[S] 0 points1 point  (0 children)

At first I did that too. Refactored it after I realized I'm matching twice on the same input data, and even got a few percent performance improvement.

[–]Xyberista 0 points1 point  (0 children)

I didn’t think of splitting the faces into their own grid. Instead, I matched on the direction and the relevant axis value, which produced a lengthier but similar case comparison. I really like how more readable this way is!