g | x | w | all
Bytes Lang Time Link
070Dyalog APL250808T195753ZAaron
243C gcc200729T153200ZNoodle9
198Python 2200728T003326Zfireflam
130JavaScript ES7200728T075629ZArnauld
109J200728T135634Zxash
070Charcoal200727T235410ZNeil

Dyalog APL, 70 chars

{(⍸0=⍵)(⍺{1≠≢n←c/⍨⊃{(∨/¨⍵)/⍵}⍺⍺=⊂⍵[c←⍸⍺{1=+/|⍺-⍵}¨⍳⍴⍵]:⍺⋄n∇-∘1@n⊢⍵})⍵}

Tied Charcoal, yusssss. Takes robot's program on the left and the grid on the right.

{(⍸0=⍵)(⍺{1≠≢n←c/⍨⊃{(∨/¨⍵)/⍵}⍺⍺=⊂⍵[c←⍸⍺{1=+/|⍺-⍵}¨⍳⍴⍵]:⍺⋄n∇-∘1@n⊢⍵})⍵}­⁡​‎‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁢⁡⁡⁣‏⁠‎⁡⁠⁢⁡⁡⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁡⁢⁡‏⁠‎⁡⁠⁢⁡⁢⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣⁢⁣‏⁠‎⁡⁠⁣⁢⁤‏⁠‎⁡⁠⁤⁡⁡‏⁠‎⁡⁠⁤⁡⁢‏⁠‎⁡⁠⁤⁡⁣‏⁠‎⁡⁠⁤⁡⁤‏⁠‎⁡⁠⁤⁢⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣⁣⁡‏⁠‎⁡⁠⁣⁣⁢‏⁠‎⁡⁠⁣⁣⁣‏⁠‎⁡⁠⁣⁣⁤‏⁠‎⁡⁠⁣⁤⁡‏⁠‎⁡⁠⁣⁤⁢‏⁠‎⁡⁠⁣⁤⁣‏⁠‎⁡⁠⁣⁤⁤‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁡⁤‏⁠‎⁡⁠⁣⁢⁡‏⁠‎⁡⁠⁣⁢⁢‏‏​⁡⁠⁡‌⁢⁢​‎⁠‎⁡⁠⁣⁡⁢‏⁠‎⁡⁠⁣⁡⁣‏⁠‎⁡⁠⁤⁢⁢‏‏​⁡⁠⁡‌⁢⁣​‎⁠‎⁡⁠⁢⁤⁢‏⁠‎⁡⁠⁢⁤⁣‏⁠‎⁡⁠⁢⁤⁤‏⁠‎⁡⁠⁣⁡⁡‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁢⁡⁤‏⁠‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏⁠‎⁡⁠⁢⁢⁤‏⁠‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏⁠‎⁡⁠⁢⁣⁣‏⁠‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢⁣‏⁠‎⁡⁠⁤⁢⁤‏‏​⁡⁠⁡‌⁣⁤​‎‎⁡⁠⁤⁣⁢‏⁠‎⁡⁠⁤⁣⁣‏‏​⁡⁠⁡‌⁤⁡​‎‎⁡⁠⁤⁣⁤‏⁠‎⁡⁠⁤⁤⁡‏⁠‎⁡⁠⁤⁤⁢‏⁠‎⁡⁠⁤⁤⁣‏⁠‎⁡⁠⁤⁤⁤‏⁠‎⁡⁠⁢⁡⁡⁡‏⁠‎⁡⁠⁢⁡⁡⁢‏‏​⁡⁠⁡‌­
       (⍺{                                                        })    # ‎⁡Binds the original left arg as the left operand of this inner function
{(⍸0=⍵)                                                             ⍵}  # ‎⁢Find index of 0 in input which will become of the left argument of the inner function
                                      ⍺{        }¨⍳⍴⍵                   # ‎⁣For each of the indices of input matrix
                                        1=+/|⍺-⍵                        # ‎⁤Find if the sum of the absolute difference of their indices from the left arg equals 1 (orthogonal neighbor)
                                   c←⍸                                  # ‎⁢⁡Find which indices those correspond to and store in c
                                 ⍵[                  ]                  # ‎⁢⁢Select those from the original input (the number of gems)
                             ⍺⍺=⊂                                       # ‎⁢⁣See where each of those is equal to one of the elements of the robot's program
                   {(∨/¨⍵)/⍵}                                           # ‎⁢⁤Filter out any empty ones
               c/⍨⊃                                                     # ‎⁣⁡And take it from the set of coordinates saved earlier so we know where to send the robot
             n←                                                         # ‎⁣⁢Save that in n (new location)
          1≠≢                                         :⍺                # ‎⁣⁣And while I'm here, check if the length is 1.  If its not, return the left argument (the robot's position) because we cannot move again
                                                         n∇             # ‎⁣⁤Call this function again with the left argument the new location and
                                                           -∘1@n⊢⍵      # ‎⁤⁡the right argument as the original input subtracting 1 gem from the location we're moving to
💎

Created with the help of Luminespire.

C (gcc), 289 \$\cdots\$ 246 243 bytes

Saved a whopping 37 41 43 46 bytes thanks to ceilingcat!!!

q;c;v;s;d;i;b;u;r;f(g,e,w,p,n)int*g,*p;{r=wcslen(g);for(c=d=0;c-n&&!d;!d&c<n&&--g[r=s])for(c=n,b=4;b--;d=v?q<c?c=q,s=u,0:q>c?d:1:d)for(i=~-(b&2)*(b&1?1:w),v=g[u=r+i]*(u>=0&u<e)*(r%w|~i&&r%w-w+1|i-1),q=0,i=n;i--;)q+=v-p[i]?0:i;*g=r/w;g[1]=r%w;}

Try it online!

Inputs the grid as a flat array, the length of that array, the grid width, the program as an array of integers and the length of the program.
Returns the robot's final position (as zero-based row and column) by storing them in the first two positions of the grid.

Before golfing

new_rank;current_rank;new_value;current_pos;has_doubled;i;news_bits;new_pos;robot_pos;
f(grid,grid_end,grid_width,prog,prog_end)int*grid,*prog;{
    for(robot_pos=0;grid[robot_pos];++robot_pos);
    for(current_rank=has_doubled=0; current_rank!=prog_end && has_doubled == 0;) {
        for(current_rank=prog_end,news_bits=0; news_bits<4; ++news_bits) {
            i = (news_bits&2 - 1)*(news_bits&1?1:grid_width);
            new_pos = robot_pos + i;
            new_value = new_pos >= 0 && new_pos < grid_end?grid[new_pos]:0;
            if((robot_pos%grid_width == 0 && i == -1) ||
               (robot_pos%grid_width == grid_width-1 && i == 1))
                new_value = 0;
            for(i = 0; i < prog_end; ++i)
                if(new_value == prog[i])
                    new_rank = i;
            if(new_value > 0 && new_rank == current_rank) {
                has_doubled = 1;
            }
            if(new_value > 0 && new_rank < current_rank) {
                current_rank = new_rank;
                current_pos = new_pos;
                has_doubled = 0;
            }
        }
        if (has_doubled == 0 && current_rank < prog_end) {
            robot_pos = current_pos;
            --grid[robot_pos];
        }
    }
    grid[0]=robot_pos/grid_width;
    grid[1]=robot_pos%grid_width;
}

Python 2, 205 198 bytes

def s(g,w,r):
 p=g.index(0)
 while 1:
    a=[((r+[0]).index(v),n)for n,v in enumerate(g)if(abs(n-p)in[1,w])>(p-n)%w*(p/w!=n/w)];m,n=min(a)
    if~-sum(k[0]==m<len(r)for k in a):return p/w,p%w
    p=n;g[p]-=1

-6 bytes thanks to @ovs

-1 byte thanks to @user202729

Try it online!

Take the input grid as a flattened list with width also passed. Outputs 0-indexed (x,y) coordinates of the final position (I doubt index in the flattened list would be acceptable).

Explanation:

# Function of flattened grid g, width w, pRiorities r
def s(g,w,r):
    # starting position p
    p = g.index(0)
    while 1:
        a = [
            # pair (priority rank of the cell, cell id)
            # priority rank is n for v=0
            ((r+[0]).index(v),n)
            # for each adjacent cell id n with v gems
            for n,v in enumerate(g) if abs(n-p) in [1,w] and (p%w==n%w or p/w==n/w)
        ];
        # min comparison is done by tuple, so it selects one with minimum priority rank
        # m = min priority rank; n = corresponding cell id
        m,n = min(a)
        if sum( # how many adjacent cells
            k[0]==m # have priority rank equal to m
            <len(r) # and the cell value is not 0
            for k in a
        ) ^ 1: # If this count is not 1, then the robot is stuck; return
            return(p/w, p%w)
        # Otherwise, continue with updated position,
        p = n;
        # and take one gem
        g[p] -= 1

JavaScript (ES7),  142  130 bytes

Expects (program)(matrix), with highest precedence coming first for the program. Returns [column, row], both 0-indexed.

p=>m=>(g=(a,X,Y)=>a.some(k=>m.map((r,y)=>r.map((v,x)=>(X-x)**2+(Y-y)**2-1|v^k||(H=x,V=y,n--)),n=1)|!n)?g(p,H,V,m[V][H]--):[X,Y])``

Try it online!

Commented

p => m => (             // p[] = program, m[] = matrix
g = (                   // g is a recursive function taking:
  a,                    //   a[] = list of possible neighbor values,
                        //         from most to least preferred
  X, Y                  //   (X, Y) = current position
) =>                    //
  a.some(k =>           // for each value k in a[]:
    m.map((r, y) =>     //   for each row r[] at position y in m[]:
      r.map((v, x) =>   //     for each value v in r[]:
        (X - x) ** 2 +  //       compute the squared distance
        (Y - y) ** 2    //       between (X, Y) and (x, y)
        - 1 |           //       abort if it's not equal to 1
        v ^ k ||        //       or v is not equal to k
        (               //       otherwise:
          H = x, V = y, //         save (x, y) in (H, V)
          n--           //         decrement n
        )               //
      ),                //     end of inner map()
      n = 1             //     start with n = 1
    )                   //   end of outer map()
    | !n                //   yield a truthy value if n = 0
  ) ?                   // end of some(); if truthy:
    g(                  //   do a recursive call to g:
      p,                //     using a[] = p[]
      H, V,             //     using (X, Y) = (H, V)
      m[V][H]--         //     decrement the cell at (H, V)
    )                   //   end of recursive call
  :                     // else:
    [ X, Y ]            //   we're stuck: return (X, Y)
)``                     // initial call to g with a[] = ['']

Because g is first called with a = [''] and both X and Y undefined, the test on the squared distance is disabled (because it's always NaN'ish) and v ^ k is equal to 0 only if v == 0. So the first recursive call is triggered on the 0 cell as expected.

J, 109 bytes

Takes in the program on the left, the grid on the right, and returns the 1-based end position.

($-_2&u)@((](r@|.~d{.@/:])`[@.(]2=/@{./:~)[i.(d=:(,-)=i.2){::])^:_)0(]|.~u=:$@]#:(i.~,))_1(r=:-1$!.0~$)@,._,]

Try it online!

How it works

Because I didn't want to handle 3 arguments (program + grid + current position) as this is awkward in tacit J definitions, this approach shifts the grid around with the upper left tile having the robot. A fix point _2 to reconstruct the end position is in the padding.

 _1(r=:…)@,._,]

Pad with _ on the top, and _1 on the left.

 r=:-1$!.0~$

This subtracts one from the top left tile. That makes the _1 to a _2, and as we'll use this later again, assign this function to r.

 0(]|.~u=:$@]#:(i.~,))

This is a bit longer than needed, but in this version we can assign x u y to find the position of x in the grid y. Here we use it to shift the grid so the 0 is at the top left – later we'll use it to search for the _2.

 (…)^:_

Until the output of does not change, i.e. until the robots moves:

 (d=:(,-)=i.2)

The 4 directions, saved as d.

 (d=:…){::]

Get the numbers at the directions, e.g. 0 0 3 1.

 [i.

Find their position in the program with non-found numbers like 0 _ _1 having program length + 1, e.g. with 1 2 3: 3 3 2 0.

 ](…)`[@.(]2=/@{./:~)

If the first 2 items of the sorted indices 0 2 3 3 -> 0 2 are equal, return the grid (stop moving), otherwise …

 r@|.~d{.@/:]

Sort the directions based on the indices. Take the first one, shift the grid by it and call r to subtract 1 from the top left, i.e. the robots takes a gem.

 ($-_2&u)@

After the robot stopped moving, find the _2 and subtract its position from the grid size to get the final result.

Charcoal, 70 bytes

≔⪪S¹θWS⊞υι≔⪫υ¶ηPη…η⌕η0≔EKV⌕θιυW⁼¹№υ⌈υ«M✳⁻χ⊗⌕υ⌈υPI⊖KK≔EKV⌕θκυ»≔⟦ⅈⅉ⟧υ⎚Iυ

Try it online! Link is to verbose version of code. Takes input as the program in ascending order of priority and then the newline-terminated grid and outputs 0-indexed coordinates. Explanation:

≔⪪S¹θ

Input the program as separate characters.

WS⊞υι≔⪫υ¶η

Input the grid.

Pη…η⌕η0

Print the grid without moving the cursor, then print the part up to the 0 so that the cursor is now at the starting cell.

≔EKV⌕θιυ

Get the priorities of the neighbours of the starting cell (or -1 for directions that lie outside the grid).

W⁼¹№υ⌈υ«

Repeat while there is exactly one neighbouring cell of highest priority.

M✳⁻χ⊗⌕υ⌈υ

Move to that neighbour.

PI⊖KK

Decrement its value.

≔EKV⌕θκυ

Get the priorities of the neighbours of the new cell (or -1 for illegal directions).

»≔⟦ⅈⅉ⟧υ

Capture the final position.

⎚Iυ

Clear the grid and output the position.