From 88be9a39a0d208901b9bb24bdd1e5c9fd1a3b1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Ludwig?= Date: Tue, 8 Aug 2023 20:28:37 +0200 Subject: [PATCH] Improve Pos --- data/day22/example01.txt | 14 ++ data/day22/input.txt | 202 ++++++++++++++++++++++ src/common/direction.rs | 4 +- src/common/pos.rs | 113 ++++++++----- src/days/day22/mod.rs | 357 +++++++++++++++++++++++++++++++++++++++ src/days/mod.rs | 4 +- 6 files changed, 649 insertions(+), 45 deletions(-) create mode 100644 data/day22/example01.txt create mode 100644 data/day22/input.txt create mode 100644 src/days/day22/mod.rs diff --git a/data/day22/example01.txt b/data/day22/example01.txt new file mode 100644 index 0000000..6e06946 --- /dev/null +++ b/data/day22/example01.txt @@ -0,0 +1,14 @@ + ...# + .#.. + #... + .... +...#.......# +........#... +..#....#.... +..........#. + ...#.... + .....#.. + .#...... + ......#. + +10R5L5R10L4R5L5 \ No newline at end of file diff --git a/data/day22/input.txt b/data/day22/input.txt new file mode 100644 index 0000000..851f4a1 --- /dev/null +++ b/data/day22/input.txt @@ -0,0 +1,202 @@ + ........................#.#...........#........#.#.......#......#......#........#..#........#....... + ....#.........#....##....#......#................................................................#.. + ....#...#.#................##...#..#.....#.#..#.............#...........#...#..##......##.....#.#... + .#.......#.........#...##....#.............#..#...#....#..........#.......#.............#........... + .##..............#.#.#.....#........#.##.#.........#.........#.......#.....#........#.....#.#....... + ........#.........................#..........#..............#.........#...#...............#........# + ......#...#...........##.................#.....#....##.....#.............#.......#..#........#...... + .............#.........#.#.....#.......#....#.............#..#.##.......#....#...............#...... + #.............................#........#........#.......#...........#..#....#................#...... + .......................##...#.#.........#..............#............................................ + ...........................#.#...#..#....#..#.....#.........................#...............#......# + ..#..#......#.#..................................##.......#.............#....#.#.................... + ....#.....#.#..................#..................#...#........#..#............................#.#.. + ...................#.#........#.........#.#...........#......#............#..#...................... + ..............##..###.................................................#.......##.................... + .....#.#.....#.......#..........#...#.##....#.........#.....#.........#.........................##.. + .#.......#................#.....#.....#..##........#..................#.....##.........#.....#...... + ........#................#.....#..##.....#..............................#...#.............#...#..#.. + .#.................##.#.......#........................#.#...................#.#...#........#.#..... + .........#..#...................................#...#...........#..#.#.............#...#............ + #..#......#........#.......................#...................#......................#............. + ...........................#.............#.......#.....#......#..#.......#...#........#.#...#..#.... + ....#.#...........#................##...............#...#...#......#..#............................. + ......#.........##...##..................#.........#.................#.............................. + ....................#......................#.#......#.......#.....#..#.............................. + ...................#....#....................#................................................#..... + #..#......#...........#....................#................#.......#...#...........#.........#..... + ..............#............#....................#.#..#.............#.............#..#...........#... + ..........#..#.##..........#....................#....#...#......................#.................#. + ............#...............#......##............................................#........#......... + ....#..#...................#..#......#.....#...#.#....#.........#..#........#...........#.........#. + ..........#...........#.#......................#..........................#.#....................... + #................#.....#...#.......................#...............#........#.#.....#..........#.... + .......#...........................#......................#...#.#..............#.....#.............. + ...#.....#.....................#.........#....#.....#....#........##.........#.#.#.................# + ####............#.#............#...#........#....#...#.......#..................#............##..... + ..........................#...................................#...............#........#...#........ + .......#....#.........................#...#............................#.......................#.... + ........#.....................#..#...#.............#..##.#...#....#..#..........#.#.............#... + ....#............#...#............#.............................#...................#....#......#.#. + ........#.........#...#.#........#..#.......#..........#..........#..#...#..........#............... + ........#.............................#...............#............#.......................#..#..#.. + #............#.....#..................#.............##.#............#...#..#.#........#............. + ............................#..........................#.........#.................#.......#....#... + ..#.#..............................................#...................#......#..#........#........# + ..#.....#.#............#.#.#.#.............#...........................#...........#.#.#...#........ + ....#...#.........##.........#..#......#...........#.........##......................#.............. + .#.....#................#............##..#........#....#.#...............#.##...#...........#......# + ...#.......#...........................#..................#.#..##.#...#.#........................... + ..............................#.....#...#.......#.........#...........#.......#..................... + ...........#.....#........#.........#.....#.....#. + ...........#.........#....................#....... + ...........#...........#.........................# + ...#......#......#............#................... + ........#............................#.#.........# + #..................#...................#.#........ + ...#................#...#...#..#.......#.#......#. + ...#.......#............#...#..................... + ........#.................##...................... + .#...#.........#..........#.......#.......#....... + ..................##.##.........#................. + .#.#..............................#.....##..#..#.. + ..........................#....##...#.......#.#... + .........#....#.....#..........................#.. + .......#.....#.................#.#.##............. + .............#..........#.....#................... + .......#.#.........#.....#................###.#... + .................................#................ + ..............#...#..#............................ + .............#........#..........#....#........... + ................#..........#..#...##....#........# + .......#.#.......................#....#..........# + .................................................. + ...........................#.......#...#.....#.... + ........##..............#.#...#.......##..#....... + .....................#.....#........#............. + ...#.......................#.......#.....#..#..#.. + ..##...........#................#.#............... + .........................#.#....#.#.........##.... + ..#......#........#...#....#..#...#.............#. + .....#.......#............###...................#. + ...#............#...........#.......#......#...... + .........#.....##..........##............#........ + ..#..##...#..................#.#.........#....#... + .......#....#............................#..#..... + ...#....#...........#.#........#.................# + ......#........#.....#........#................... + ............#..........#....#..#...........#...... + ................#....#.....#........#...........#. + ...##....#................#.#.....#.............#. + ..............................................#..# + ..#..#..#..#..#................................... + .............#..............................#..... + ..#...#....#...........##......#..............#... + .........##....#...........................#.....# + ...........................##.........#........#.. + ......#.............#........#..........#....#.... + ................................#............#.... + ...........#..#...........#...#.#.........#....... + ...................#.#.#........#.............##.. +.#..........#..............................#..........#...#.#..#...#.......#............##.......... +..##...........#.........#.........................##......#.............#................#......... +#.#.........#.....#.#............#.........#.#.#....##..............#........#.#..#................. +..............................#..#.......................................#....##.....#........#..... +............................##....#..##.....###.....#.......##...#...............................#.. +...........#....#...........#.......#..........#.........#........#.............#.........#......... +.............................#...........................#.........#..................#....##....... +.................#...................#...........#.............#...............#.................... +..............#................#.............#......#....#..........#.#..#.......................#.. +.#........#...##.......#.#...#......#...........#...................#....#......##...#.............. +............#..#.#......#..#.................#....#.....#.#..#.......................#.............. +#.#..#.#.........#........#...........#.#.....#...#..#........#..#........#.......#.#.......#....... +.......##.......#.........#..#.......#...........#...............#.................................. +...........#.........#.................#.......#..#.#......#...............#.#...................... +.............#........#..........##.......................#...#..............#....................#. +......#...#.#....#......#........#.......#.................#.....#....#..#..#.....#.......#......... +.......#.##.............##.#...##....#.#........#.........#..............#...#......#............... +...#..................#.#.......#.............#.............#......................................# +.#............#..........#...........#.#.............#..#.......................................#... +.....#.##...#...#...............#.....................#...#.#.....#....................#............ +........#......................................#...........#......#..#..##...........#....#..#...... +..#...................#................#.................................#.......................... +.#.......................#.......#......#.........................#................................. +...#...#...................#...........#....#........#....#..............#.......#.................. +.....#....................#..........#..#........#...........................#..#...#.......#...#..# +.........#...........#...#...#............#...................#.............#....................#.# +..#....#.....#.#.......#................#...#.............#.............##......#.................## +....##...#...............##..........#....#.........#.....#...............#........#...............# +.....#.................#.......#.................#.............#.#....#....................#.#...... +.........#...#...#......................................#.....................#..................... +.........#..............#.....#.............................#....#.....#............#.............#. +............#.#......#.....#...........................#........##.......................#....#..#.. +........................#.............#..........#.#...........#..#....................#.##....#.... +........##.#....#................##.........................#........#...........#.......#.........# +.#..........#....#...........#...........#..........................#.........##...........#........ +...#....#..#.................................#......#.........#.#....#.........##.....#.......#..... +#.....#....#......#...#.........#...........#..#............###........#...........##......##.#...#. +.......#.#.....#....................................#....#....................##.#.................. +#....................................##.....................##....#...........#..........#.......... +.........................#......#....#...........#..#......#.........#........#..#...............#.. +...#....#.........#..................#..................................#.....#.......#.#.#......... +........................#....................#..#...............#............#......#............#.# +#.................#......................#..........#.........#.......................#.......#..... +..#....................#.................#.....#..........#...............##.#............#......... +...........................#......#..............#.....#...#......................................#. +..................#..#..#...................#..#...#......#..#.........#..##..#...#....#............ +...#........#.#......#....#...................#........#.#...#..................#............#...... +....................#..........#..#........#....#.......#..........................#.........#...... +.......#...#..........................#........##............#..#................................#.. +........##.......#................#.....##..#...........##.............#...##........#.....#.......# +#.................#....#..............#...#....... +..............................#..................# +#........................#....##...#........##.... +............#..................................... +............#....................................# +...#.#..............#..............#.............. +...........................##....................# +......#.#.......#..................#.....#...##..# +......#..............#..#.............#........... +.....#.....##.....#............................... +.............................#....#...#........... +........#......................................... +................#..........................##..... +.#............##.#..............#.#...#........#.. +.......#....#...#.....##.#...#...#................ +................#.#...................##.......... +..............................#................... +..............##.................#..........#..#.. +..#..................................#............ +..........................................#..#.... +...#......#...#....#..............#.............#. +.#....#..#...............................#........ +.......#.#.....................#.......#.......... +....#................#............................ +.......##.....##....#................#............ +...#........#........#......#...#.#.........#..... +......##.#................#...............#.#..... +....#.#........#................#...........##.... +..#......................#....#.................#. +..................#.............#..........#...... +....#.....#....................................... +....#.......##..#.#..#.......................#.... +.................#...........#.....#.....#......#. +.......#.........#.......#.##....#........#....... +................#.......#...................#..... +#.#..................................#......#.#... +#........#..##.......##..#........#............#.. +#..............................................#.. +.#.....#.......#..##........#..#..............#... +.........#.......#...#.....#.#...#................ +.................................#..........#..... +#...#..............##..............#....#......... +.............................#........#....#...#.. +...#....#..............#...........#......#....... +....#......................#.......#...#.......... +...#.............#......#.#.......#..#.......#..## +.......#...........................#............#. +........#.......................#................. +..........#..#...#......##.........#........##.... +.#.....#....###.............#.##.................. + +16L48L13R34L44L21R31R17R42R37R48L39L40R16R29L12R23R8L42R19L26L31L34R8L37R35R22R22L34R4L11R28L42L30L42L24L40R31L14L2L46L1L15R45R4L44R6L13R20L38R16R26L8L6R15L47R10L13R30R27L21L5R16R23R24L23L13L3R14R3R41R17R18R35R45R50L10R28R28R23R29R43R33R6R10R3R49R48R17R18R10L10R36L24R43L41L15R35L16R47R27L1R24L6R50R30L35R46R9L5R8L49R45L9R41L29L25L46R17L47L32R25L7R24R33L23L20L12R43L16L8R38L9L30L33R4R41L6L41L49L36L34L41R12L12R41R23R29L24R39L17L9R4R17L10L30R43R27L29R39R44L16L24R28L14L14L45L6R4L26R17L22L28L31L33R14L21R24L10R20L17R5R18L41L20L1R39R23R8R21L47R21L12R5R1L14L23R50L2L43L45L14L15L50R18R21L39L24R8R7L13R33L15L40R29L34R38R42L5L17R28R49R35L45L4L1R8L33R22L12R37R26L48R45L47R39R35L50R18L22L19R31R10L7L10L27L28R6R28L48R28L44L11L37R48R33L13L23L45L7R34L24R10R47R21R39L11R12R14R7R39L50R39R40R50R3L20L15R6L14R31R30L19R14L2L23R6R5R50R42L4L13R18L45R4R44R15R28R27L35L25R15R18L37R31L38L23L21L36L7R17R24L22L18R19L43L7L1R26L6R42R2R38L9L30R13R37R34L41R20L39R44R11R27L48R30R37L19L30L34L44R17R50R49L46L37L15R35R42R25L19L44L40R5L47R19R44L6R39L1R11R42L27L37R37L41R6R36L47L4R31R34R3R32R7L46R8R3R48L33R39L29R43R40R39L5L25R42L37R15R32R50L36R38L29L30R6L22L17R28R21L42L44L41R35L40L45L22R28R24L2R29L14L7R31L40L14L13L21R12L40L23R34R22L37L24R34L23R33L41R26R18R34L27L15L21L29R21R30R10L10L19L45L42R3R9R18L39R14L21R6L24R44L7R16R24L23L14L28R34R33L26L44R36L23L17L40L23R10L49L8L2L22L45R34L46L1R41L37R26L22L31R12R29R24R44R26L22R20R9L6L36R23R21R44L26R9R32L9R23R15L10L28L48L41R45R35L30L25R41R29L25R23R3R29L30L28L34L29R40L30R40L3R19L36R11L26R48L17L48R12R32R35L26L42R15R6R42R8L49R30R3R14L16L44L8R10L50R18R32R1R29R34R32L24R50R44L13R48L4R20L14L50L15L21R47R3L7R37L15R42R5L40R27L18R3R44L4R47R7R35L46R40R45R24R23R48R9R48R21R7L15L42R27R14R30R48L5L38R5R16L25R22L28R48R17L27R10L25L13R6L7L21R47L43L41R33R6R40R31L32L20L1L16L19R23L28R16R44L26R21R9R29L6L37L31L16L9R37L24L4L19L20R40L3L38L39R17L38L21L26R6R19R12L34L15L31L23L1R8L35R13L23L2L21L20L22R16L49R41R30R13L46R26R50R1R42R40R40R42L22L19R31R4L4L1L45R8L39R3L42R4L44L29R10L17R19L24L43L50R28R8R3L49L8R25R11R14R41L39L47R28R45L34L29R49R38L43L3R15R38L17L37R49R11L8L15L28R3L1R7R1R1L7R17L47L1R28L49L18L20R43R30L20L37R18L3L16R32L9R48L21L22R35L46L31R20L13L16R46R9R49L32L38R42L13L1R16R10L14L45L27L1R4R10R6L38R42L25L33L15L11R17R34L12R47L46R41L42L19L26R22R28R37L26R41L21R8L25R18R26R37R18L38R5R3R8L25R20R2R38R50R17L36L9L6R44R23R5L38L37L1L1L30R28L19L33L25R35R23R32L50L46L42L4L9R12L46L7L2L2R45R11L19R2R47R33R11R25R42R8R41L24R36R7L45L29L20L35L28R3R43R33R25R25L1R33R2R34R25R24R35L46R6L48R37L21R45R5L41L44R32R46L17R5R19R47R39L4R20R26R8R24L30L15R29R5R7R33R30L49R34L48L2L47R1L15L1L25L47R15L14R1R15R20R42R10R44L7L46L28L15R42L3L44L49R14L28R43R33R33R26R3R9R36R24L1L45L26L25L39L15L1R40R47R30L7R25L50R38R6L33R48R28L2L11L41L14R43L48L11L47L39L18R15L23R26R44L27L17L45L21R6R16L37L6L37R50L39L34R34L19R19R32R14R43L16L19L20L44L40L11R49R2L19L17R1L42R9L21L5R2R47L39L29L25L41R19R43R26L41R49R46R9L2R38L22R43R6L5L14R29R27R34R43L25L46R22R13R1R18R28L24R34L45R27L43R6L32L12L35L39L38R16R39L13L36R22L19L20R33L3R13R15R28L45L5R25R9R32L32L34L23R25R43R13L23L45R34R46L9R13R15R9R16R21L38L7L32R1R22R34R44R18L39R43R5R7L19L16L39L26L28L23R41L32R18R22R41L46L34R6L44L29R25R26L5L18R6R44R48R22L47L50R29R24R41L8R48L5R50L49L38R47L39R7L15R23R36R14R48R17R14R32L25L36R10L36R17L30L22R15L19L10L3L24R36R1L6L26L39L48R15L3L26R11R49R2R46R28R18R13L50R39L5R29L31L40L44L43R49L6L26L33L49L30R48R10L4R6L26L15L18L31R20L48R7R17L40R36L41R49L25L21L5R48R19R3L48R46R22R22L50L39R18R17L13L4R5L28R10R40L30R40R19R11R49R9R32L25R48R47L26L40L38R44R22L22R37R3L16R34R11R48L47R2L29R48R31L4R44L40R20L40R30R15R11R43L30R5R40L45R42R39R19R49L41R26L18R17R15L39L26L10R15L30L38L44L47R35R42R40L26R46R11R22R25R28L12R35R1R38L2R40R3L5L15R18R21R46R1R26R42L7L38L11R4L17R45L46L11R39R45R27L8L35R3L50R25R14R3R5R46L6L31R40L28R12L35L1L33L32R49R48L16L20L3R20R50R8L29R44L12R17L12R4L7R2R1R50L30L4L17R12R43L17R4L20L32R46R39L42L18L30L19R15R37L14L5L3R36L31L16L10L10L26R45R19R38L30R49L6L25L30R27L41L17R27R47L37L28R22L44R18L48L44R2L33R2R9L13L1R13L30R43L50R17R32R14R28L1R29L6L2L37R40R12R1L16R32L31L35R10R4R18R41L15L29R3R43L24L29R43L37R33R16L5L12L32R43R43R2R39R41R20R39R6L35R21R44R44L25L31L7L49R42R20L24L3L7R26R35L4L46L37L33R38L33R25L4L1L50L19R3R3R9L25L2R15L7L10R37L5L18R50L23R4L16L19R8R5R36L25L27R18R26L50L46R10R31R31R30R29L24L8L14R40R4R47R5R37R46R35R48L14R23R1L21L47R45R10L8L15R48R15R11L24L39L3R7L38L8L47R37R10R38L34R42R26L17R24R30R41L11L9R50L16L48R5L7R44L11L6R11R22R44R50L5R18R38L46L35L45R9L45L19R22L40R21R23R29L14R35L47R8L8R27R33R22L3L2R19L7R41L33L46L26R9L9L22L15L45L36L46L28R40R10L40R26L47L1R47L25R3R44L35R21L36L43R28L4L21R20L6R2R1R42R10L11R33R44L1R37R48L26L46R11R45L22R18L34R43L26L41L27L14R9R14L2R41R19R47L1R42L11R17R21L12L33L10L30R43R46R47L9R17L14L15L6L43R44L22L40L50L2L19R30L38R48L1R23L32R33R31L45R5L47R1R19R15L40L17R7L10R19R40L29R26R10R21R47L33L22R23L10L1R29R39R14L35L21R18R25L20L46R15L42R6R33R26R10R9R31R32L48R49L15R48L39L41L12L35R24L2L9L27R34L32R6R25L16R47L24R14L48R2R39L2L19L21L23R50R29L44L16R15L14L50R39L13R15L19R46R16R38L8R34R44L46L38L49R7L5R32R47R4R29L24R7R4L30R34R8R15L4R34L25L24L8L10L6R36L18R21R13R50R17L12L50R48L2R31L22L12R31L1L39R19L8R43L15L37L32L34R15R48R39R26L40R20L26L33R21L39R8L38R10L14R41L35R32R23R19R25R26R25L27R26L43R12L45L15L19L39R14L26L9R25R16R33R44R33L17L37R13R29L18L24L2L39L32R17R46L41R31R23R5R17R26R6L36L40R5L33R4R43L45L45R26R47L2L35L36L42R8R32L35L30R42R50R10L44L9L46L25L45L7R18L15R22L47R44L41R41L1R36R19L16R33R40R45R31L23R34L47R13L42L2L32L23R40L14L19R29R50R47L11R40L26L13L1L39R29R43R40R41R4L24R45L8L47L23L45R13L47L25L35L5L23R5L7L5R47R16L34L36L22L31L8R5R21L44R41L41L46R5L7R11R7R44R10L15L48L22L11L9R36L34R25L34R33R33L17R2L50L45L14R12R17L10L47L15R33R25R1R46R20R3L5R42R13R27L22L8L37R3R2R46L3L12R27L5L4R33L18R4R26L30R5L44L10 \ No newline at end of file diff --git a/src/common/direction.rs b/src/common/direction.rs index 77c2e00..9c5118f 100644 --- a/src/common/direction.rs +++ b/src/common/direction.rs @@ -89,9 +89,9 @@ where fn from(value: Direction) -> Self { match value { East => Pos2D::new(T::one(), T::zero()), - North => Pos2D::new(T::zero(), T::one()), + North => Pos2D::new(T::zero(), -T::one()), West => Pos2D::new(-T::one(), T::zero()), - South => Pos2D::new(T::zero(), -T::one()), + South => Pos2D::new(T::zero(), T::one()), } } } diff --git a/src/common/pos.rs b/src/common/pos.rs index ddc51fe..a5cd42d 100644 --- a/src/common/pos.rs +++ b/src/common/pos.rs @@ -1,15 +1,18 @@ +use super::direction::Direction; use super::math::gcd; -use num_traits::{Float, Num, NumCast, Signed}; +use num_traits::{CheckedAdd, CheckedSub, Float, Num, NumCast, Signed}; use std::fmt; use std::ops::{Add, Div, Mul, Sub}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] -pub struct Pos2D([T; 2]); +pub type Pos2D = Pos; -impl Pos2D { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct Pos([T; 2]); + +impl Pos { #[inline] - pub fn new(x: T, y: T) -> Pos2D { - Pos2D([x, y]) + pub fn new(x: T, y: T) -> Pos { + Pos([x, y]) } pub fn get_x(&self) -> &T { @@ -21,34 +24,34 @@ impl Pos2D { } } -impl From<&[T]> for Pos2D { +impl From<&[T]> for Pos { fn from(value: &[T]) -> Self { match value.len() { - 0 => Pos2D::new(T::default(), T::default()), - 1 => Pos2D::new(value[0], T::default()), - _ => Pos2D::new(value[0], value[1]), + 0 => Pos::new(T::default(), T::default()), + 1 => Pos::new(value[0], T::default()), + _ => Pos::new(value[0], value[1]), } } } -impl From<[T; 2]> for Pos2D { +impl From<[T; 2]> for Pos { fn from(value: [T; 2]) -> Self { - Pos2D(value) + Pos(value) } } -impl From<(T, T)> for Pos2D { +impl From<(T, T)> for Pos { fn from(value: (T, T)) -> Self { - Pos2D([value.0, value.1]) + Pos([value.0, value.1]) } } -impl Pos2D +impl Pos where T: Copy, { - pub fn splat(v: T) -> Pos2D { - Pos2D::new(v, v) + pub fn splat(v: T) -> Pos { + Pos::new(v, v) } pub fn x(&self) -> T { @@ -60,26 +63,26 @@ where } } -impl Pos2D +impl Pos where T: Num + Ord + Copy, { - pub fn normalize(self) -> Result<(Pos2D, T), Pos2D> { + pub fn normalize(self) -> Result<(Pos, T), Pos> { if self.x().is_zero() && self.y().is_zero() { Err(self) } else { gcd(self.x(), self.y()) - .map(|ggt| (Pos2D::new(self.x() / ggt, self.y() / ggt), ggt)) + .map(|ggt| (Pos::new(self.x() / ggt, self.y() / ggt), ggt)) .ok_or(self) } } } -impl Pos2D +impl Pos where T: Float, { - pub fn normal(self) -> Result<(Pos2D, T), Pos2D> { + pub fn normal(self) -> Result<(Pos, T), Pos> { let length = self.length(); if length == T::zero() { Err(self) @@ -89,7 +92,7 @@ where } } -impl Pos2D +impl Pos where T: Num + NumCast, { @@ -110,20 +113,20 @@ where } } -impl Pos2D +impl Pos where T: Ord + Copy, { - pub fn max_components(self, other: Pos2D) -> Self { - Pos2D::new(self.x().max(other.x()), self.y().max(other.y())) + pub fn max_components(self, other: Pos) -> Self { + Pos::new(self.x().max(other.x()), self.y().max(other.y())) } - pub fn min_components(self, other: Pos2D) -> Self { - Pos2D::new(self.x().min(other.x()), self.y().min(other.y())) + pub fn min_components(self, other: Pos) -> Self { + Pos::new(self.x().min(other.x()), self.y().min(other.y())) } } -impl Pos2D +impl Pos where T: Signed, { @@ -132,7 +135,7 @@ where } } -impl Pos2D +impl Pos where T: Float, { @@ -141,7 +144,7 @@ where } } -impl fmt::Display for Pos2D +impl fmt::Display for Pos where T: Num + fmt::Display, { @@ -150,53 +153,79 @@ where } } -impl<'a, T, P: Into>> Add

for Pos2D +impl<'a, T, P: Into>> Add

for Pos where T: Num + Copy, { type Output = Self; fn add(self, rhs: P) -> Self::Output { let rhs = rhs.into(); - Pos2D::new(self.x() + rhs.x(), self.y() + rhs.y()) + Pos::new(self.x() + rhs.x(), self.y() + rhs.y()) } } -impl>> Sub

for Pos2D +impl>> Sub

for Pos where T: Num + Copy, { - type Output = Pos2D; + type Output = Pos; fn sub(self, rhs: P) -> Self::Output { let rhs = rhs.into(); - Pos2D::new(self.x() - rhs.x(), self.y() - rhs.y()) + Pos::new(self.x() - rhs.x(), self.y() - rhs.y()) } } -impl Mul for Pos2D +impl Mul for Pos where T: Num + Copy, { type Output = Self; fn mul(self, rhs: T) -> Self::Output { - Pos2D::new(self.x() * rhs, self.y() * rhs) + Pos::new(self.x() * rhs, self.y() * rhs) } } -impl Div for Pos2D +impl Div for Pos where T: Num + Copy, { type Output = Self; fn div(self, rhs: T) -> Self::Output { - Pos2D::new(self.x() / rhs, self.y() / rhs) + Pos::new(self.x() / rhs, self.y() / rhs) } } -impl Pos2D +impl Pos where T: Num + Signed + Copy, { - pub fn taxicab_between(self, other: Pos2D) -> T { + pub fn taxicab_between(self, other: Pos) -> T { (self - other).abs() } } + +impl Pos +where + T: Num + Copy + CheckedAdd + CheckedSub, +{ + pub fn check_add(self, direction: Direction) -> Option { + match direction { + Direction::East => self + .x() + .checked_add(&T::one()) + .map(|x| Pos::new(x, self.y())), + Direction::North => self + .y() + .checked_sub(&T::one()) + .map(|y| Pos::new(self.x(), y)), + Direction::West => self + .x() + .checked_sub(&T::one()) + .map(|x| Pos::new(x, self.y())), + Direction::South => self + .y() + .checked_add(&T::one()) + .map(|y| Pos::new(self.x(), y)), + } + } +} diff --git a/src/days/day22/mod.rs b/src/days/day22/mod.rs new file mode 100644 index 0000000..cb584be --- /dev/null +++ b/src/days/day22/mod.rs @@ -0,0 +1,357 @@ +use super::template::{DayTrait, ResultType}; +use crate::common::{ + direction::Direction, + parser::{eol_terminated, extract_result, ignore, usize}, + pos::Pos2D, +}; +use nom::{ + branch::alt, + character::complete::{char, multispace0}, + combinator::value, + error::Error, + multi::many1, + Err, IResult, Parser, +}; +use std::str::FromStr; +use thiserror::Error; + +const DAY_NUMBER: usize = 22; + +pub struct Day; + +impl DayTrait for Day { + fn get_day_number(&self) -> usize { + DAY_NUMBER + } + + fn part1(&self, lines: &str) -> anyhow::Result { + let (world_map, instructions) = Day::parse(lines)?; + let world = WrappingWorld::new(world_map); + let walker = Walker::walk_all(&world, instructions)?; + Ok(ResultType::Integer(walker.value())) + } + + fn part2(&self, lines: &str) -> anyhow::Result { + let (world_map, instructions) = Day::parse(lines)?; + let world = CubeWorld::new(world_map); + let walker = Walker::walk_all(&world, instructions)?; + Ok(ResultType::Integer(walker.value())) + } +} + +impl Day { + fn parse(input: &str) -> Result<(WorldMap, Vec), WorldError> { + let (input, world) = WorldMap::parse(input)?; + let input = ignore(multispace0)(input)?; + let instructions = extract_result(Instruction::parse)(input)?; + Ok((world, instructions)) + } +} + +#[derive(Debug, Error)] +enum WorldError { + #[error("Not a valid description: {0}")] + ParsingError(String), + #[error("No Starting Point found")] + NoStartingPoint, +} + +impl From>> for WorldError { + fn from(error: Err>) -> Self { + WorldError::ParsingError(error.to_string()) + } +} + +struct WorldMap { + tiles: Vec>>, +} + +impl FromStr for WorldMap { + type Err = WorldError; + + fn from_str(input: &str) -> Result { + Ok(extract_result(WorldMap::parse)(input)?) + } +} + +impl WorldMap { + pub fn new(tiles: Vec>>) -> Self { + Self { tiles } + } + + fn parse(input: &str) -> IResult<&str, WorldMap> { + let tile = alt(( + value(Some(false), char('#')), + value(Some(true), char('.')), + value(None, char(' ')), + )); + let line = eol_terminated(many1(tile)); + let mut lines = many1(line).map(|tiles| WorldMap::new(tiles)); + lines.parse(input) + } + + fn get_first(&self, pos: Pos2D, facing: Direction) -> Option> { + match facing { + Direction::East => self.tiles.get(pos.y()).and_then(|row| { + row.iter() + .position(|t| t.is_some()) + .map(|x| Pos2D::new(x, pos.y())) + }), + Direction::West => self.tiles.get(pos.y()).and_then(|row| { + row.iter() + .rposition(|t| t.is_some()) + .map(|x| Pos2D::new(x, pos.y())) + }), + Direction::South => self + .tiles + .iter() + .position(|row| pos.x() < row.len() && row[pos.x()].is_some()) + .map(|y| Pos2D::new(pos.x(), y)), + Direction::North => self + .tiles + .iter() + .rposition(|row| pos.x() < row.len() && row[pos.x()].is_some()) + .map(|y| Pos2D::new(pos.x(), y)), + } + } + + fn get_tile(&self, pos: Pos2D) -> Option { + self.tiles + .get(pos.y()) + .and_then(|row| row.get(pos.x())) + .copied() + .flatten() + } +} + +trait World { + fn get_map(&self) -> &WorldMap; + + fn wrap(&self, pos: Pos2D, facing: Direction) -> Option<(Pos2D, Direction)>; + + fn get_start(&self, pos: Pos2D, facing: Direction) -> Option> { + self.get_map().get_first(pos, facing) + } + + fn step(&self, pos: Pos2D, facing: Direction) -> Option<(Pos2D, Direction)> { + let Some(pos) = pos.check_add(facing) else { + return self.wrap(pos, facing); + }; + + match self.get_map().get_tile(pos) { + Some(true) => Some((pos, facing)), + Some(false) => None, + None => self.wrap(pos, facing), + } + } +} + +struct WrappingWorld { + map: WorldMap, +} +impl WrappingWorld { + fn new(world_map: WorldMap) -> Self { + WrappingWorld { map: world_map } + } +} + +impl World for WrappingWorld { + fn get_map(&self) -> &WorldMap { + &self.map + } + + fn wrap(&self, pos: Pos2D, facing: Direction) -> Option<(Pos2D, Direction)> { + if let Some(pos) = self.map.get_first(pos, facing) { + match self.map.get_tile(pos) { + Some(true) => Some((pos, facing)), + Some(false) => None, + None => unreachable!(), + } + } else { + unreachable!(); + } + } +} + +struct CubeWorld { + map: WorldMap, +} +impl CubeWorld { + fn new(world_map: WorldMap) -> Self { + CubeWorld { map: world_map } + } +} + +impl World for CubeWorld { + fn get_map(&self) -> &WorldMap { + &self.map + } + + fn wrap(&self, pos: Pos2D, facing: Direction) -> Option<(Pos2D, Direction)> { + if let Some(pos) = self.map.get_first(pos, facing) { + match self.map.get_tile(pos) { + Some(true) => Some((pos, facing)), + Some(false) => None, + None => unreachable!(), + } + } else { + unreachable!(); + } + } +} + +#[derive(Debug, Clone)] +enum Instruction { + Walk(usize), + Right, + Left, +} + +impl Instruction { + fn parse(input: &str) -> IResult<&str, Vec> { + many1(alt(( + usize.map(|v| Instruction::Walk(v)), + value(Instruction::Right, char('R')), + value(Instruction::Left, char('L')), + ))) + .parse(input) + } +} + +struct Walker { + pos: Pos2D, + facing: Direction, +} + +impl Walker { + fn new(world: &W) -> Result { + let facing = Direction::East; + if let Some(pos) = world.get_start(Pos2D::new(0, 0), facing) { + Ok(Walker { pos, facing }) + } else { + Err(WorldError::NoStartingPoint) + } + } + + fn value(&self) -> i64 { + (self.pos.y() + 1) as i64 * 1000 + + (self.pos.x() + 1) as i64 * 4 + + Walker::face_value(self.facing) + } + + fn face_value(facing: Direction) -> i64 { + match facing { + Direction::East => 0, + Direction::North => 3, + Direction::West => 2, + Direction::South => 1, + } + } + + fn act(mut self, world: &W, instruction: Instruction) -> Self { + match instruction { + Instruction::Right => self.facing = self.facing.turn_right(), + Instruction::Left => self.facing = self.facing.turn_left(), + Instruction::Walk(steps) => { + for _ in 0..steps { + let Some((next_pos, next_facing)) = world.step(self.pos, self.facing) else { + break; + }; + self.pos = next_pos; + self.facing = next_facing; + } + } + } + self + } + + pub fn walk_all( + world: &W, + instructions: Vec, + ) -> Result { + let mut walker = Walker::new(world)?; + + for instruction in instructions { + walker = walker.act(world, instruction); + } + Ok(walker) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::common::file::read_string; + use anyhow::Result; + + #[test] + fn test_part1() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let expected = ResultType::Integer(6032); + let result = day.part1(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn test_part2() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let expected = ResultType::Nothing; + let result = day.part2(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn parse() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let (world, instructions) = Day::parse(&lines)?; + + assert_eq!(world.tiles.len(), 12); + assert_eq!(instructions.len(), 13); + + Ok(()) + } + + #[test] + fn walk() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let (world_map, _) = Day::parse(&lines)?; + + let world = WrappingWorld::new(world_map); + + let mut walker = Walker::new(&world)?; + assert_eq!(walker.pos, Pos2D::new(8, 0)); + + walker = walker.act(&world, Instruction::Walk(10)); + assert_eq!(walker.pos, Pos2D::new(10, 0)); + + walker = walker.act(&world, Instruction::Left); + + walker = walker.act(&world, Instruction::Walk(2)); + assert_eq!(walker.pos, Pos2D::new(10, 10)); + + Ok(()) + } + + #[test] + fn walk_all() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let (world_map, instructions) = Day::parse(&lines)?; + let world = WrappingWorld::new(world_map); + + let walker = Walker::walk_all(&world, instructions)?; + assert_eq!(walker.pos, Pos2D::new(7, 5)); + assert_eq!(walker.facing, Direction::East); + assert_eq!(walker.value(), 6032); + + Ok(()) + } +} diff --git a/src/days/mod.rs b/src/days/mod.rs index 1982c46..ac8442e 100644 --- a/src/days/mod.rs +++ b/src/days/mod.rs @@ -19,6 +19,7 @@ mod day18; mod day19; mod day20; mod day21; +mod day22; mod template; pub use template::DayTrait; @@ -28,7 +29,7 @@ pub mod day_provider { use super::*; use thiserror::Error; - const MAX_DAY: usize = 21; + const MAX_DAY: usize = 22; pub fn get_day(day_num: usize) -> Result, ProviderError> { match day_num { @@ -53,6 +54,7 @@ pub mod day_provider { 19 => Ok(Box::new(day19::Day)), 20 => Ok(Box::new(day20::Day)), 21 => Ok(Box::new(day21::Day)), + 22 => Ok(Box::new(day22::Day)), _ => Err(ProviderError::InvalidNumber(day_num)), } }