CLASS ztoboggan DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES
      if_oo_adt_classrun.
    TYPES: BEGIN OF ENUM ty_orientation,
             right,
             left,
             down,
             up,
           END OF ENUM ty_orientation,
           BEGIN OF ty_slope_part,
             course TYPE ty_orientation,
             length TYPE i,
           END OF ty_slope_part,
           BEGIN OF ty_pointer,
             x TYPE i,
             y TYPE i,
           END OF ty_pointer,
           ty_slope    TYPE STANDARD TABLE OF ty_slope_part WITH EMPTY KEY,
           ty_map      TYPE STANDARD TABLE OF string_table WITH EMPTY KEY.

    METHODS set_map
      IMPORTING
        i_map TYPE string.
    METHODS traverse.

    METHODS set_slope
      IMPORTING i_slope TYPE ty_slope.
    METHODS count_trees
      IMPORTING
        i_tree_type  TYPE any OPTIONAL
      RETURNING
        VALUE(trees) TYPE i.
    METHODS traverse_slope
      IMPORTING
        map          TYPE string
        slope        TYPE ztoboggan=>ty_slope
      RETURNING
        VALUE(trees) TYPE int8.

  PROTECTED SECTION.
  PRIVATE SECTION.
    DATA map TYPE ty_map.
    DATA slope TYPE ty_slope.
    DATA: pointer TYPE ztoboggan=>ty_pointer.
    METHODS convert_str_to_itab
      IMPORTING
        i_map          TYPE string
      RETURNING
        VALUE(map_tab) TYPE ty_map.
    METHODS get_map
      RETURNING
        VALUE(str_map) TYPE string.
    METHODS convert_itab_to_str
      IMPORTING
        i_map          TYPE ztoboggan=>ty_map
      RETURNING
        VALUE(str_map) TYPE string.
    METHODS get_riddle_input
      RETURNING
        VALUE(riddle) TYPE string.

ENDCLASS.



CLASS ztoboggan IMPLEMENTATION.

  METHOD set_map.
    map = convert_str_to_itab( i_map ).
  ENDMETHOD.

  METHOD get_map.
    str_map = convert_itab_to_str( map ).
  ENDMETHOD.

  METHOD set_slope.
    slope = i_slope.
  ENDMETHOD.

  METHOD traverse.
    IF slope IS INITIAL.
      RETURN.
    ENDIF.

    DATA(shadow_map) = map.
    pointer = VALUE ty_pointer( x = 1 y = 1 ).

    DO.
      pointer-y += VALUE #( slope[ course = ztoboggan=>down ]-length DEFAULT 0 ).
      pointer-y -= VALUE #( slope[ course = ztoboggan=>up ]-length DEFAULT 0 ).
      pointer-x += VALUE #( slope[ course = ztoboggan=>right ]-length DEFAULT 0 ).
      pointer-x -= VALUE #( slope[ course = ztoboggan=>left ]-length DEFAULT 0 ).
      TRY.
          map[ pointer-y ][ pointer-x ] = SWITCH #( map[ pointer-y ][ pointer-x ]
                                                    WHEN '.' THEN 'O'
                                                    WHEN '#' THEN 'X' ).
        CATCH CX_SY_ITAB_LINE_NOT_FOUND INTO DATA(cx).

          IF pointer-x >= lines( map[ 1 ] ).
            DATA(columns) = lines( shadow_map[ 1 ] ).
            DATA(y) = 1.
            LOOP AT map ASSIGNING FIELD-SYMBOL(<row>).
              DO columns TIMES.
                APPEND shadow_map[ y ][ sy-index ] TO <row>.
              ENDDO.
              y += 1.
            ENDLOOP.
          ENDIF.

          IF pointer-y > lines( map ).
            EXIT.
          ELSEIF pointer-y = lines( map ).
            map[ pointer-y ][ pointer-x ] = SWITCH #( map[ pointer-y ][ pointer-x ]
                                                      WHEN '.' THEN 'O'
                                                      WHEN '#' THEN 'X' ).
            EXIT.
          ENDIF.
          map[ pointer-y ][ pointer-x ] = SWITCH #( map[ pointer-y ][ pointer-x ]
                                                    WHEN '.' THEN 'O'
                                                    WHEN '#' THEN 'X' ).
      ENDTRY.
    ENDDO.

  ENDMETHOD.


  METHOD convert_str_to_itab.
    SPLIT i_map AT cl_abap_char_utilities=>newline INTO TABLE DATA(string_map).

    DATA map_line TYPE string_table.
    LOOP AT string_map INTO DATA(string_line).
      DO strlen( string_line ) TIMES.
        DATA(square) = substring( val = string_line off = sy-index - 1 len = 1 ).
        APPEND square TO map_line.
      ENDDO.
      APPEND map_line TO map_tab.
      CLEAR map_line.
    ENDLOOP.
  ENDMETHOD.


  METHOD convert_itab_to_str.
    str_map = REDUCE #( INIT str = ||
                        FOR map_line IN i_map INDEX INTO i NEXT
                        str = str && REDUCE #( INIT str_line = ||
                                               FOR line IN map_line NEXT
                                               str_line = str_line && line )
                                  && COND #( WHEN i < lines( i_map )
                                             THEN cl_abap_char_utilities=>newline ) ).
  ENDMETHOD.

  METHOD count_trees.
    DATA(string_map) = convert_itab_to_str( map ).
    trees = count( val = string_map sub = i_tree_type ).
  ENDMETHOD.

  METHOD if_oo_adt_classrun~main.
    set_map( get_riddle_input( ) ).
    set_slope( VALUE #( ( course = down length = 1 )
                        ( course = right length = 3 ) ) ).
    traverse( ).
    out->write( |Part 1 - Trees: | && count_trees( |X| ) ).

    DATA(trees) = CONV int8( 1 ).
    DATA(slope) = VALUE ztoboggan=>ty_slope( ( course = ztoboggan=>right length = 1 )
                                             ( course = ztoboggan=>down length = 1 ) ).
    trees *= traverse_slope( map = get_riddle_input( ) slope = slope ).


    slope = VALUE ztoboggan=>ty_slope( ( course = ztoboggan=>right length = 3 )
                                       ( course = ztoboggan=>down length = 1 ) ).
    trees *= traverse_slope( map = get_riddle_input( ) slope = slope ).

    slope = VALUE ztoboggan=>ty_slope( ( course = ztoboggan=>right length = 5 )
                                       ( course = ztoboggan=>down length = 1 ) ).
    trees *= traverse_slope( map = get_riddle_input( ) slope = slope ).

    slope = VALUE ztoboggan=>ty_slope( ( course = ztoboggan=>right length = 7 )
                                       ( course = ztoboggan=>down length = 1 ) ).
    trees *= traverse_slope( map = get_riddle_input( ) slope = slope ).

    slope = VALUE ztoboggan=>ty_slope( ( course = ztoboggan=>right length = 1 )
                                       ( course = ztoboggan=>down length = 2 ) ).
    trees *= traverse_slope( map = get_riddle_input( ) slope = slope ).
    out->write( |Part 2 - Trees multiplied: | && trees ).
  ENDMETHOD.

  METHOD get_riddle_input.
    riddle =
      |........#....#..##..#...#.....#\n| &&
      |...............#....##........#\n| &&
      |.#....##...##..#...............\n| &&
      |.#.......#......#.##..##...#...\n| &&
      |.....#.#....#..##...#.....#....\n| &&
      |...#.#..##...###......#..#..#.#\n| &&
      |.....#..##........#.##......#..\n| &&
      |..##.....###.........##........\n| &&
      |..............##..#.#.#.#......\n| &&
      |.#....##..#.##.#....#..#.#..#..\n| &&
      |.#.#....#.##.#...#....#.....#..\n| &&
      |..#...#.#.....#....#.......##..\n| &&
      |.#.#..##.....#...........#.....\n| &&
      |.#.##...#.....#......#.##......\n| &&
      |..#..#..........#.....#..###.#.\n| &&
      |##....##....#.#...........#..#.\n| &&
      |.....#.#.......#.#.#..#.##....#\n| &&
      |...##.#....#..#.....#.........#\n| &&
      |.....#........#.##...#.........\n| &&
      |.....#................#.#...#..\n| &&
      |...#....##.....##....#.......#.\n| &&
      |....##.#.....#.#.......#.......\n| &&
      |#...............#..#...........\n| &&
      |.......###.#.......#.##....#.#.\n| &&
      |..#........###........#......#.\n| &&
      |.#.......#...##.....####....##.\n| &&
      |..##.#....#.....#..#....#......\n| &&
      |..#...#..#.#..##...#.....#.....\n| &&
      |.#.......###.......#....#......\n| &&
      |...#...#.......#........#...#.#\n| &&
      |..#....#...#.......#.#..##.....\n| &&
      |##............#.#..#..........#\n| &&
      |.......###...##..#.....#....#..\n| &&
      |##..######.#..#.......###....##\n| &&
      |###..#...#.##......##....#...#.\n| &&
      |..............##.###..........#\n| &&
      |.....#........##.#.###....#....\n| &&
      |..#...#.....##.#......#.#..#.#.\n| &&
      |#....#.............#.#.........\n| &&
      |.........##.#........#...#.....\n| &&
      |..........#..##.#.#.....#..##..\n| &&
      |........##......#..#..#...#.#..\n| &&
      |.##.......#..#.#...#.####..#...\n| &&
      |##...#........#.###...##....#..\n| &&
      |....###.####...#..#..#......###\n| &&
      |#....#....#.#.....##.........#.\n| &&
      |#.......#....#....##...........\n| &&
      |##...##.#.......#....#...#....#\n| &&
      |....#....#........##..#.#..#.#.\n| &&
      |..##.....##...#..........#...#.\n| &&
      |.#.#.#...#.....##..#........#..\n| &&
      |#....#.....#..........#....#...\n| &&
      |...##.#.......#.#.........#....\n| &&
      |##.##.........##.....##.....##.\n| &&
      |##.#..##..#...##........##.....\n| &&
      |.........##.......#....#...#...\n| &&
      |.#.....#........####.#.#.....#.\n| &&
      |...........##..#.###...........\n| &&
      |..#....##....#...#.............\n| &&
      |#.#............#.......#.......\n| &&
      |.##........#...#..##.....#.#...\n| &&
      |#.##..............##..##.......\n| &&
      |##.........#......#......#..#..\n| &&
      |##.#....#...#....##....#..#.##.\n| &&
      |......#...#..#.#...#.#....#.##.\n| &&
      |##.......#.....#.........#.....\n| &&
      |...##...#................#.#...\n| &&
      |....#.####...#.#.....##....##.#\n| &&
      |#...#..#.#.##................##\n| &&
      |.........##.....##...#..#......\n| &&
      |......####....#.##.#.....#.....\n| &&
      |...#..#.#....#.#.#..#..........\n| &&
      |.....#........##...#.##....#.#.\n| &&
      |..##......#...................#\n| &&
      |.....#..#...............#..#...\n| &&
      |....#........#..#.#...##...#.##\n| &&
      |..#.#.......#.##.........#...#.\n| &&
      |...##......#.#.................\n| &&
      |.#....#...#.............##.#...\n| &&
      |........#.##...#..#...###.....#\n| &&
      |#....#.#........##....#......##\n| &&
      |.###.......#..#..........#..#..\n| &&
      |#....#..#....#........#...#...#\n| &&
      |##.#.###.##.#...##.#......#.#.#\n| &&
      |#..#..#..##........#..###.#...#\n| &&
      |....#..#..#.....#...##....#...#\n| &&
      |.......##.......#..#.##...##..#\n| &&
      |.##....#..###................##\n| &&
      |#...#.##.##...#.##......##.....\n| &&
      |...##.....##..##...#..#........\n| &&
      |...............##.....##.......\n| &&
      |.#..#.#..#....#.....#..#...#...\n| &&
      |.#....#..#........#.#...#.....#\n| &&
      |##.....####..#......#..........\n| &&
      |........#.........#.........#..\n| &&
      |#...####....#.##...#....#...##.\n| &&
      |.#....####..#...##..#......####\n| &&
      |...........##.##..#.##...##....\n| &&
      |..#..#.......#.##....#.#...#.##\n| &&
      |#...........#..#...............\n| &&
      |.......#.##..#.....##......#...\n| &&
      |....##.#.##.....#...........#.#\n| &&
      |.............#.##..#...#......#\n| &&
      |#......#...........#........#..\n| &&
      |#.#..#.............#...#.......\n| &&
      |#.........##...#....#...##.....\n| &&
      |##...#..#..#..#....#...........\n| &&
      |.#.....#........#.....#.##..#.#\n| &&
      |...#..............##.####.#..#.\n| &&
      |##.....#..#.#..#..##...........\n| &&
      |...#...#.......#...............\n| &&
      |..#..................###..#..##\n| &&
      |....###..........#.#..#...#.#.#\n| &&
      |..#..#..#.#..........#.#......#\n| &&
      |....#....#.#...#.###...##..#...\n| &&
      |....#.......#...#....##........\n| &&
      |.#.....#.......###....#........\n| &&
      |....#..#..#.....#......#.......\n| &&
      |......#...#..#....#.#.......#..\n| &&
      |.##.#..#...#.#.#...........#...\n| &&
      |..#....##.#....#.#....#...#.#.#\n| &&
      |...##..#.......#....#.#.....##.\n| &&
      |##.#......#.#.......##...#.....\n| &&
      |......#...#.##..............#..\n| &&
      |.##.........#......##.#..#....#\n| &&
      |#.......#.....#...##...#..#...#\n| &&
      |..#..##.......#......#......##.\n| &&
      |#..##...###.#.#...........#....\n| &&
      |##......#.....####..#..#....#.#\n| &&
      |.......##...##.#...#...........\n| &&
      |....#..#.##.#.....#.#....#.#...\n| &&
      |....#.....#.....####...#..#.##.\n| &&
      |.##..#..#..###...#....#.##.#.#.\n| &&
      |..#.#.##..........##...........\n| &&
      |#.##.#.#....#.##....#..#...##.#\n| &&
      |#...#....#...###....#.......#..\n| &&
      |.......#..#............#.......\n| &&
      |................##.#.#.....#..#\n| &&
      |..........................#....\n| &&
      |.##....##...#.#....####..#....#\n| &&
      |......#...#....#...#.##..###.#.\n| &&
      |.........#............#.......#\n| &&
      |.#.#..#........#..#.........#..\n| &&
      |#..#...#......#.#....#..#.#....\n| &&
      |...........#.................#.\n| &&
      |.#.#..#...##..###......##....##\n| &&
      |.#.#.##......####.........##...\n| &&
      |..#....#.#..#................#.\n| &&
      |##.......#....#.........##.#.#.\n| &&
      |##..#.###...........#..#.#..#.#\n| &&
      |...#............##.#....#......\n| &&
      |...#................##.#..#....\n| &&
      |....#..##.#...#.#.....#.......#\n| &&
      |......#......#.#........#..##..\n| &&
      |...##...#.....#.##.......#.....\n| &&
      |##...#...#.............#..#....\n| &&
      |..#...##.....#..........#..#.##\n| &&
      |#.##...#..................#.###\n| &&
      |.........#..........#.###...#.#\n| &&
      |#..#.....#.#.#....#......#...#.\n| &&
      |.............#.##..###.....#.##\n| &&
      |..#..#.....#..#.............#..\n| &&
      |.#.....##.#.#..#.........#.....\n| &&
      |..#.......#....#.....##.#......\n| &&
      |.#.........#..#....##...#.##...\n| &&
      |.##..##................###....#\n| &&
      |.#..##..............#...#......\n| &&
      |.#..............#.##....##.....\n| &&
      |.#......#..#..##..#...###.....#\n| &&
      |................##...#.#..#...#\n| &&
      |##.#.......#...................\n| &&
      |....#.#.......#..#.##..........\n| &&
      |....###............##...#......\n| &&
      |.......#....#.#.....##.#.....#.\n| &&
      |....#...............#.#........\n| &&
      |..#.##....#.#.#......##..#.....\n| &&
      |.##......#...#.#..#..#.......#.\n| &&
      |....#...#........#.#..##.......\n| &&
      |.##...###.#....#..........##..#\n| &&
      |..#.......##..#.....###......#.\n| &&
      |...#.#..##.#.#...........#.....\n| &&
      |##........#.#..##.........#..#.\n| &&
      |.....###.......#..#.#.....##.#.\n| &&
      |..#...##.#..............#......\n| &&
      |......#...#...............##.#.\n| &&
      |##...#..#....#...#.####.##.....\n| &&
      |...#............#.##...........\n| &&
      |...#........##.#.##.......#....\n| &&
      |...#..#..##....#...#......#..#.\n| &&
      |#.....#..#......#.#.....##.#.#.\n| &&
      |.....#.##......#...#..#..###..#\n| &&
      |...........##..##.#.#..........\n| &&
      |...#........##........##..##.#.\n| &&
      |......###...#.....#..###.#..#..\n| &&
      |#.....#.#....#...##....##.....#\n| &&
      |.##....#......#.....#.#..##.##.\n| &&
      |##....###.......#...##.......##\n| &&
      |...##......#....###............\n| &&
      |..#...#...#.#..#..........##.#.\n| &&
      |#.#.###...#..#.....#....#.###..\n| &&
      |..##.....#.#.#.......#.........\n| &&
      |...####..#....#..#.........#...\n| &&
      |.##...........#.##.#...#.#.##..\n| &&
      |...#.#....#.##......#........#.\n| &&
      |##....##....#..#...#..#.#......\n| &&
      |#......#..#...#...#.#.#.#.####.\n| &&
      |....##.#.#.....#.###........#..\n| &&
      |....##..#.#.#.#....#....#.#..#.\n| &&
      |..#.###..#............##..#.#..\n| &&
      |...#...#..#...#.#.#.....#.....#\n| &&
      |..........#.....#..#.......##.#\n| &&
      |..............##...........#...\n| &&
      |.......#.....#...#.....#.....#.\n| &&
      |.#.###.....##......##....#...#.\n| &&
      |.....#.........#.#....#........\n| &&
      |..#.#....#.##...#.##....##...#.\n| &&
      |...#......#.#.....#.......###..\n| &&
      |#.##....##.....#.#.#...#......#\n| &&
      |#..#...#..........#.........##.\n| &&
      |....#.#.#.#.....#...###........\n| &&
      |#.#..#...#......#...#.##...####\n| &&
      |.#...#......#....##...#........\n| &&
      |..#.........#............#...#.\n| &&
      |##......#..#...#....#.##....#..\n| &&
      |.#...##..#..##.#.#.#........#.#\n| &&
      |.##.........###...#......#..###\n| &&
      |...##.....##..#.#.........#....\n| &&
      |...........##........#...#.....\n| &&
      |..##..#...#..#..#.....#......#.\n| &&
      |..#..#.#....#.....#..#.##...#..\n| &&
      |#....#........##..........#.###\n| &&
      |......#...#...#....#...##.#....\n| &&
      |...#......#.#.....##......##...\n| &&
      |#....#..##............#....#.#.\n| &&
      |...#...##.#..........##........\n| &&
      |......#.###......#...#.#.......\n| &&
      |..................#.##..#..#..#\n| &&
      |....#.....#...#.....#...#....#.\n| &&
      |.#....##.#..#..#.....###.##...#\n| &&
      |#.......#..#....##.##.#.....##.\n| &&
      |..##........##...#.....#....##.\n| &&
      |#.........#...........##.#.....\n| &&
      |.#....#.#...##..###..........#.\n| &&
      |....##..##....####...#......#..\n| &&
      |##.##..#..#....#....####...#...\n| &&
      |..#...............#.##.........\n| &&
      |...#.#....#..#....#......#.....\n| &&
      |.#..#...#........#...#.....##..\n| &&
      |#.....###.......#.....#........\n| &&
      |...#.##..#.......#....#........\n| &&
      |....##..###.##...#.#....#.#....\n| &&
      |#.####...#.......#.....#.#....#\n| &&
      |#.......#......#.......#.#.#...\n| &&
      |##....#......#..#...#..#..####.\n| &&
      |.##.....#........#..#...#......\n| &&
      |#.#.#....#....#...#.##..##.....\n| &&
      |....#..#.........###.##.##.....\n| &&
      |...##...##.###..#..##.....#.###\n| &&
      |..###.......................#..\n| &&
      |......##..#.#.........#......#.\n| &&
      |.###......##....#.....#.......#\n| &&
      |.....#..#..##........#......##.\n| &&
      |..##.....#....#.#.............#\n| &&
      |..##.........##.#..#.........##\n| &&
      |......#......#.#......#........\n| &&
      |.#...#..#......##...#..#....#..\n| &&
      |...............###............#\n| &&
      |#.####.#....#...#...........#.#\n| &&
      |............................#.#\n| &&
      |.#..#...#.#.#.###..##.....##...\n| &&
      |....##...#.................##..\n| &&
      |......##....#...............##.\n| &&
      |.#......#.##.#..#.....##...##..\n| &&
      |.............#........#......#.\n| &&
      |#..........#.#....#####.#...#.#\n| &&
      |.#.#...##..#.#...#.#..#.#..#...\n| &&
      |#.##.......##......#.#.#....#..\n| &&
      |##.....##.#.#.##..........##..#\n| &&
      |....##..#.#.......#....#.##....\n| &&
      |..#.#.#...#.....#.......#......\n| &&
      |.#....#..#...........###.......\n| &&
      |#.#...#.....#......#...#.....#.\n| &&
      |#........#.#..........#...#.#..\n| &&
      |...#...#....#.........#........\n| &&
      |.....................#..##.....\n| &&
      |...#......##........#.##.#.#.##\n| &&
      |.............###...#.#...#..#..\n| &&
      |.#..##........##....#...###..##\n| &&
      |.#..#.#...............#.....##.\n| &&
      |...........##.#....#..##.#....#\n| &&
      |.##.#.#..#.#..#...#.#.#..#.#.##\n| &&
      |.......#.#..#..#..#..#...#.....\n| &&
      |.#......##............#.#..#...\n| &&
      |..#...#..##..#..#...##......#..\n| &&
      |...##......##....#............#\n| &&
      |.......#.....##...##.#...#..#..\n| &&
      |......#.......#..##.........#..\n| &&
      |..#...#.#.....#.#.......#.#...#\n| &&
      |.#......##.##.#.#.#.##..#....##\n| &&
      |#.....#.........#.#....#....##.\n| &&
      |.......#.........#....#..#.#.##\n| &&
      |.....##....#..#.#.#...#.....##.\n| &&
      |#####.#.......######......#....\n| &&
      |..##.#.......#.#..............#\n| &&
      |..#.##....#.....#...#.#...##...\n| &&
      |.....#...#..#....#.#..#........\n| &&
      |.#....#.#..#.#.#.##..#.......#.\n| &&
      |....#..#..#..........##...#....\n| &&
      |.......#.#......#........#.....\n| &&
      |##.#.#.###....##.#..#..#....#..\n| &&
      |#.##......#..#.......#.#...#...\n| &&
      |..##...#.......#.......#...#...\n| &&
      |........##.........#.#....#.#..\n| &&
      |..#...#..##.#.#.#...#....#.....\n| &&
      |.###......#........#....#...#..\n| &&
      |.#.......##......###..##.......\n| &&
      |#....#.#....#.##.........####..\n| &&
      |......#..........#..##.....#...\n| &&
      |.............#......#..##.#....\n| &&
      |...................#....#...#..\n| &&
      |.#..........#...#.#..##...#....\n| &&
      |.....#...#..........##.##......\n| &&
      |#...#..#.##........#...#.......|.
  ENDMETHOD.

  METHOD traverse_slope.
    set_map( map ).
    set_slope( slope ).
    traverse( ).
    trees = count_trees( |X| ).
  ENDMETHOD.

ENDCLASS.
