Day 15: Warehouse Woes

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

  • ystael@beehaw.org
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    9 days ago

    J

    Nothing much to say about today’s. I think I wrote basically the same code you’d write in Python, just with fewer characters, more of which are punctuation. I did learn a little bit more about how to use J’s step debugger, and that / is specifically a right fold, so you can use it on a dyad with arguments of different types as long as the list argument is the left one.

    data_file_name =: '15.data'
    lines =: cutopen fread data_file_name
    NB. instructions start with the first line not containing a # character
    start_of_moves =: 0 i.~ '#' e."1 > lines
    grid =: ,. > start_of_moves {. lines
    start_row =: 1 i.~ '@' e."1 grid
    start_col =: '@' i.~ start_row { grid
    pos =: start_row, start_col
    grid =: '.' ( start_of_moves }. lines
    translate_move =: monad define"0
       if. y = '>' do. 0 1
       elseif. y = '^' do. _1 0
       elseif. y = '<' do. 0 _1
       elseif. y = 'v' do. 1 0
       else. 0 0 end.
    )
    moves =: translate_move move_instructions
    NB. pos step move updates grid as needed and returns the new position
    step =: dyad define"1 1
       new_pos =. x + y
       if. '#' = (< new_pos) { grid do. x  NB. obstructed by wall
       elseif. '.' = (< new_pos) { grid do. new_pos  NB. free to move
       else.  NB. it's 'O', need to push a stack
          p =. new_pos  NB. pointer to box at end of stack
          while. 'O' = (< p) { grid do. p =. p + y end.
          if. '#' = (< p) { grid do. x  NB. stack is blocked
          else.  NB. move stack
             grid =: 'O.' (< p ,: new_pos)} grid
             new_pos
          end.
       end.
    )
    score =: dyad define"0 2
       +/ ; ((<"0) 100 * i.#y) +&.> (< @: I. @: = & x)"1 y
    )
    final_pos =: step~/ |. pos , moves  NB. / is a right fold
    result1 =: 'O' score grid
    
    translate_cell =: monad define"0
       if. y = '#' do. '##'
       elseif. y = '.' do. '..'
       elseif. y = 'O' do. '[]'
       else. '@.' end.
    )
    grid2 =: (,/ @: translate_cell)"1 ,. > start_of_moves {. lines
    start_row2 =: 1 i.~ '@' e."1 grid2
    start_col2 =: '@' i.~ start_row { grid2
    pos =: start_row2, start_col2
    grid2 =: '.' (< pos)} grid2  NB. erase the @
    NB. (grid; box_pos) try_push dir attempts to push the box at box_pos one
    NB. cell in direction dir. box_pos can be either the left or right cell of
    NB. the box. it returns (grid; success) where grid is the maybe-changed grid
    NB. and success is whether the box moved. if any box that would be pushed
    NB. cannot move, this box cannot move either and the grid does not change.
    try_push =: dyad define"1 1
       'grid pos' =. x
       if. ']' = (< pos) { grid do. pos =. pos + 0 _1 end.  NB. make pos left cell
       source_cells =. pos ,: pos + 0 1
       if. 0 = {: y do.  NB. moving up or down
          target_cells =. (pos + y) ,: (pos + y + 0 1)  NB. cells we move into
       elseif. y -: 0 _1 do. target_cells =. 1 2 $ pos + y  NB. moving left
       else. target_cells =. 1 2 $ pos + y + 0 1 end.  NB. moving right
       NB. Have to check target cells one at a time because pushing a box up or
       NB. down may vacate the other target cell, or it may not
       trial_grid =. grid
       for_tc. target_cells do.
          NB. if a target cell is blocked by wall, fail
          if. '#' = (< tc) { trial_grid do. grid; 0 return.
          elseif. '[]' e.~ (< tc) { trial_grid do.
             'trial_grid success' =. (trial_grid; tc) try_push y
             if. -. success do. grid; 0 return. end.
          end.
       end.
       NB. at this point either target_cells are clear or we have returned failure,
       NB. so push the box
       grid =. '[]' (<"1 source_cells +"1 y)} '.' (<"1 source_cells)} trial_grid
       grid; 1
    )
    NB. (grid; pos) step2 move executes the move and returns new (grid; pos)
    step2 =: dyad define"1 1
       'grid pos' =. x
       new_pos =. pos + y
       if. '#' = (< new_pos) { grid do. grid; pos  NB. obstructed by wall
       elseif. '.' = (< new_pos) { grid do. grid; new_pos  NB. free to move
       else.  NB. need to push a box
          'new_grid success' =. (grid; new_pos) try_push y
          if. success do. new_grid; new_pos else. grid; pos end.
       end.
    )
    'final_grid final_pos' =: > (step2~ &.>)/ (<"1 |. moves) , <(grid2; pos)
    result2 =: '[' score final_grid