g | x | w | all
Bytes Lang Time Link
118Desmos230816T175403Zfwoosh
165Ruby230731T135355Zgrizzthe
104Perl 5230804T161644ZToto
129Swift230720T005304ZBbrk24
189Rust230719T074145Zmousetai
116Java 8230720T083542ZKevin Cr
019x86 assembly Linux230722T030447ZSaladin
082Python230719T071912ZSuperSto
03205AB1E230721T075853ZKevin Cr
233Racket230719T133702ZEd The &
061C clang230719T165522Zc--
nanVyxal230719T062046Zlyxαl
116Excel ms365230719T101249ZJvdV
043Charcoal230719T102424ZNeil
067JavaScript ES6230719T090032ZArnauld

Desmos, 118 bytes

Expects an array in variable A and a number in variable n (explained later).

Code in ticker

\left\{0<v<120:k->k+1\right\},f(\left\{v=60:-1,v=62,v=94:-n,v=118:n,v=0:d\right\})

Everything else

i=1
d=0
k=0
v=A[i]
f(x)=d->x,i->i+x

Try it on Desmos!


Input, explained

Desmos neither supports characters nor multidimensional arrays, so input is instead recieved as a 1D array A containing the rows of the matrix, along with an integer n containing the length of a row. For example, the test case

[['>', 0,  0, 'v','<'],
 [ 0, '>','x','<', 0 ]]

Turns into

n=5
A=[62,0,0,118,60,0,62,120,60,0]

To speed things up you can use this conversion tool to automagically convert the input format for you.

After you enter your input into the program (see the "testcases" folder), reset the variables (run the action at the bottom of the page), and then start the ticker to run the program.

Once the program finishes, the result should be stored in k.

Program code, explained

Program code:

i=1                 pointer to current position
d=0                 direction of travel
k=0                 number of arrows
v=A[i]              shorthand for current value under the pointer
f(x)=d->x,i->i+x    change the direction and also increment the pointer in that direction

Ticker code (prettified for readability):

{0<v<120:k->k+1},f({v=60:-1,v=62,v=94:-n,v=118:n,v=0:d})
{0<v<120:k->k+1},                                           increment k if this is an arrow
                 f({                                  })    change the direction to...
                    v=60:-1,                                ...left if '<'
                            v=62,                           ...right if '>'
                                 v=94:-n,                   ...up if '^'
                                         v=118:n,           ...down if `v`
                                                 v=0:d      ...no change if 0

As a result of the fact that i points to a 1D array, the row number of i can be changed by adding/subtracting n, which is why the direction changes to ±n for '^' and 'v'.

Ruby - 165 characters

No deviations from the rules. Uses 0 as the no-op. You can test the code here.

s,i,j,x,y=0,0,0,0,0
loop do
c = p[i][j]
break if c=='x'
if c!=0
if c=='v'||c=='^'
y=0
x=c=='v'?1:-1
elsif c=='>'||c=='<'
x=0
y=c=='>'?1:-1
end
s+=1
end
i+=x
j+=y
end

The readable version:

par_5 = [
  ['v',0,'>','v',0,0,0],
  [0,0,0,'>','v',0,0],
  ['>',0,'^',0,'v',0,0],
  ['>',0,0,0,'x','<','<'],
  [0,0,0,0,0,0,'^']
]

strokes = 0
i = 0
j = 0
i_inc = 0
j_inc = 0

loop do
  shot = par_5[i][j]

  if shot == 'x'
    break
  end
  
  unless shot == 0
    if shot == 'v' || shot == '^'
      j_inc = 0
      i_inc = shot == 'v' ? 1 : -1
    elsif shot == '>' || shot == '<'
      i_inc =  0
      j_inc = shot == '>' ? 1 : -1
    end
    strokes += 1
  end

  i += i_inc
  j += j_inc
end

puts "You had #{strokes} shots!"

Output:

You had 8 shots!

Perl 5, 104 bytes

while(($_=$p[$i][$j])ne"x"){$i+=$b=/v/?1:/\^/?-1:/0/?$b:0;$j+=$d=/>/?1:/</?-1:/0/?$d:0;$t++if$_}print$t
@p = (
  ['v',0,'>','v',0,0,0],
  [0,0,0,'>','v',0,0],
  ['>',0,'^',0,'v',0,0],
  ['>',0,0,0,'x','<','<'],
  [0,0,0,0,0,0,'^']
);
#@p=(['>',0,0,'v','<'],[0,'>','x','<',0]);

while(($_=$p[$i][$j])ne"x"){
    $i+=$b=/v/?1:/\^/?-1:/0/?$b:0;
    $j+=$d=/>;/?1:/<;/?-1:/0/?$d:0;
    $t++if$_
}
print$t

Try it online!

Swift, 166 157 135 129 bytes

{var x=0,y=0,u=0,v=0,s=0
while 0<1{let i=$0[y][x]
if i>119{return s}
if i>0{(u,v)=i>63 ?(0,i>95 ?1:-1):(i-61,0)
s+=1}
x+=u
y+=v}}

Inspired by @mousetail's Rust answer. Takes a 2D array of ASCII values.
Try it on SwiftFiddle!

Explanation:

{ (arr: [[Int]]) -> Int in
  // Create some working variables.
  var x = 0
  var y = 0
  var dx = 0
  var dy = 0
  var strokes = 0
  // Swift has no dedicated 'loop' keyword
  while true {
    let currentValue = arr[y][x]
    // Swift uses switch/case rather than match, so these ifs are shorter
    if currentValue > 119 {
      // It must be 120, 'x'
      return strokes
    }
    if currentValue > 0 {
      (dx, dy) = currentValue > 63
        ? // It may be 'v' or '^'
          // 'v' = 118, '^' = 94
          (dx: 0, dy: currentValue > 95 ? 1 : -1)
        : // It may be '<' or '>'
          (dx: currentValue - 61, dy: 0)
      strokes += 1
    }
    y += dy
    x += dx
  }
}

It might be possible to further optimize those ifs.

Original answer:

{a in var c=(0,0),d=(0,0,0)
var i:Int{a[c.0][c.1]}
while 0<1{if i>119{return d.2}
if i>0{if i>63{d.1=0
d.0=i>95 ?1:-1}else{d.0=0
d.1=i-61}
d.2+=1}
c.0+=d.0
c.1+=d.1}}

Rust, 189 bytes

|a|{let(mut c,mut d)=((0,0),(0,0,0));loop{d=match a[c.0 as usize][c.1 as usize]{60=>(0,-1,d.2+1),62=>(0,1,d.2+1),94=>(-1,0,d.2+1),118=>(1,0,d.2+1),120=>break d.2,_=>d};c=(c.0+d.0,c.1+d.1)}}

Attempt This Online!

Hate needing to do explicit type conversions from signed to unsigned.

Takes input as ASCII character codes.

Rust, 147 143 bytes

|a,b|{let(mut c,mut d)=(0,(0,0));loop{d=match a[c as usize]%9{6=>(-1,d.1+1),8=>(1,d.1+1),4=>(-b,d.1+1),1=>(b,d.1+1),3=>break d.1,_=>d};c+=d.0}}

Attempt This Online!

Same as above but takes input as a flattened array and length

Java 8, 129 119 118 117 116 bytes

m->{int c=0,p=0,l=m[0].length,d=0,t=0;for(;t<120;p+=d>99?l:d>93?-l:d/62*2-1)d=(t=m[p/l][p%l])>0?t+0*c--:d;return~c;}

-1 byte thanks to @ceilingcat.

Uses ␀-bytes ('\0') instead of 0 for the no-ops.
Input as a character-matrix.

Try it online.

Explanation:

m->{                  // Method with char-matrix parameter and integer return-type
  int c=0,            //  Arrow-counter, starting at 0
      p=0,            //  Position, starting at {0,0}
      l=m[0].length,  //  Width of the input-matrix
      d=0,            //  Direction, starting initialized at anything
                      //  (since the cell at {0,0} is guaranteed to contain an arrow)
      t=0;            //  Current character, starting at 0
  for(;t<120          //  Loop until the current character is 'x':
      ;               //    After every iteration:
       p+=            //     Update the position by increasing by:
          d>99?       //      If the direction is 'v':
               l      //       Increase by the matrix-width: {x,y}→{x,y+1}
          :d>93?      //      Else-if the direction is '^':
                -l    //       Decrease by the matrix-width: {x,y}→{x,y-1}
          :           //      Else (the direction is '>' or '<'):
           d/62*2-1)  //       If the direction is '>': increase by 1: {x,y}→{x+1,y}
                      //       If the direction is '<': decrease by 1: {x,y}→{x-1,y}
    d=(t=m[p/l][p%l]) //   Set `t` to the value of the current position
      >0?             //   If `t` is an arrow (or 'x'):
         t            //    Update the direction to this `t`
         +0*c--       //    And decrease the arrow-counter by 1
        :             //   Else:
         d;           //    Keep the direction the same
  return~c;}          //  After the loop, return -c-1 as result,
                      //  where the -1 is to subtract 'x', since it isn't an arrow

x86 assembly (Linux), 19 bytes

This solution is a bit cheeky on the input. It expects a pointer to a M×N 2d array with the following symbols:

Which is, of course, the offset in bytes to the next element in the pointed-to direction, allowing us to just add the values. As the dimensions of the golf field is encoded into the field itself, we cannot have fields with rows larger than 127 bytes.

If the row length is a limitation, just design the field to use all the columns you'd like. Who wants a square golf course anyway?

; int golf(char *ptr) __attribute__((fastcall));

00000000 <golf>:
   0:   83 c8 ff                or     $0xffffffff,%eax ; int result = -1
                                                        ; do {
00000003 <loop>:
   3:   80 39 00                cmpb   $0x0,(%ecx)      ;   if (*ptr) {
   6:   74 04                   je     c <skip>
   8:   0f be 11                movsbl (%ecx),%edx      ;     int step = *ptr;
   b:   40                      inc    %eax             ;     result++;
                                                        ;   }
0000000c <skip>:
   c:   01 d1                   add    %edx,%ecx        ;   ptr += step;
   e:   83 fa 80                cmp    $0xffffff80,%edx ; } while (step != -128)
  11:   75 f0                   jne    3 <loop>
  13:   c3                      ret                     ; return result;

I can save an additional byte by making the input an array of ints rather than chars, but (to me) that violates the rule that:

[The input array] contains only either characters or the integer 0.

I admit the distinction may be pointless when dealing with assembly.

Try it online!

Python, 82 bytes

-12 bytes thanks to Jonathan Allan

f=lambda g,w,a=0,x=0:(n:=g[x])<119and(n>0)+f(g,w,a:=[a,n%3+n//14%3*w+~w][n>0],x+a)

Attempt This Online!

Takes input as a flattened list of codepoints, plus the width of a row.

05AB1E, 37 32 bytes

Ç[¬нZ<#©Āi¼®U}©À®€Á®Á®€À)X11%è}¾

Uses 0 like in the challenge description.

Try it online or verify all test cases.

Explanation:

Since 05AB1E lacks a multidimensional index builtins, I instead rotate the entire matrix, so the cell at coordinate {0,0} will always contain the current value.

Ç           # Convert all characters in the (implicit) input-matrix to codepoint
            # integers (0s remain 0s)
 [          # Start an infinite loop:
  ¬         #  Push the first row (without popping the matrix)
   н        #  Pop this list and push its first value
    Z       #  Push its maximum digit (without popping the value)
     <      #  Decrease it by 1
      #     #  Pop this maxDigit-1, and if it's 1: stop the infinite loop
            #  (which is only the case for 'x'=120)
  ©         #  Store the current value in variable `®` (without popping the value)
   Āi   }   #  Pop the value, and if it's NOT 0:
     ¼      #   Increase counter `¾` by 1 (starts initially at 0)
      ®U    #   And store `®` in variable `X`
  ©         #  Store the current matrix in variable `®` now (without popping the matrix)
   À        #  Rotate its rows once towards the left
  ®         #  Push the matrix `®` again
   €Á       #  Rotate the values in each of its rows once towards the right
  ®Á        #  Similar, but rotate its rows once towards the right
  ®€À       #  Similar, but rotate the values in each of its rows once towards the left
     )      #  Wrap all four rotated matrix into a list
      X     #  Push the current direction codepoint-integer `X`
       11%  #  Modulo-11
          è #  (0-based) modular index it into the list of four matrices
 }¾         # After the infinite loop: push counter `¾`
            # (which is output implicitly as result)

Racket, 233 bytes

(display(let P([L(read)][x 0][y 0][X 0][Y 0][H 0][a add1])(match(list-ref(list-ref L y)x)['x H]['>(P L(a x)y 1 0(a H)a)]['<(P L(- x 1)y -1 0(a H)a)]['^(P L x(- y 1)0 -1(a H)a)]['v(P L x(a y)0 1(a H)a)][_(P L(+ x X)(+ y Y)X Y H a)])))

Try it online!

Input is a two-dimensional list of symbols:

((> > 0 0 0 v)
 (v < 0 ^ < 0)
 (0 ^ 0 0 > V)
 (> 0 v 0 x <)
 (0 0 > 0 ^ 0))

(That is, you don't need to use double quotes. Racket lists use parentheses () instead of brackets [] and don't use commas ,.)

Output is displayed on STDOUT. If the ball hits the edges, the program crashes with an index too large error.


Changelog

  1. Removed #!racket (-9 bytes). Thanks a lot @SuperStormer!

Explanation

Our program consists of a recursive function. At the initial run, we receive inputs and configure the initial variables. Note that for the golfed version I added an extra variable a that is shorthand for add1. It isn't necessary for the explanation.

(let program ([lst (read)] [x 0] [y 0] [dx 0] [dy 0] [hits 0])
  ...)

We then use Racket's match statement to determine the action we must do. The first argument of the match statement is the symbol we are matching to. To get the current symbol we can think of the two-dimensional list as a table of rows and columns. Each row is selected with the y variable and inside of the row are columns which are selected with the x variable.

(let program ([lst (read)] [x 0] [y 0] [dx 0] [dy 0] [hits 0])
  (match (list-ref (list-ref lst y) x)
    ...))

In the body of the match statement, we have our cases. The cases are in the for of [if-match? do-this]. If the symbol is an x, we return the number of hits. If it is an arrow, we rerun the program with modified arguments. If is anything else (_ in the statement), we rerun the program, but we set x and y according to dx and dy respectively.

(let program ([lst (read)] [x 0] [y 0] [dx 0] [dy 0] [hits 0])
  (match (list-ref (list-ref lst y) x)
    ['x hits]
    ['> (program lst (add1 x) y 1 0 (add1 hits))]
    ['< (program lst (- x 1) y -1 0 (add1 hits))]
    ['^ (program lst x (- y 1) 0 -1 (add1 hits))]
    ['v (program lst x (add1 y) 0 1 (add1 hits))]
    [_ (program lst (+ x dx) (+ y dy) dx dy hits)]))

To display the results, we surround the let statement with a display statement.

(display
  (let program (...)
    ...))

Conclusion

This was a fun code golf to solve! I learnt something new in the process (the match statement) and got a new view on how to see two-dimensional lists (rows and columns).

Hope you all have an amazing week further!

C (clang), 61 bytes

Expects an array containing 0, '>', '<', '^', 'v', or 'x'

d;f(*a,m){d=*a?:d;return'x'-d?!!*a+f(a+d%3+d/14%3*m+~m,m):0;}

Try it online!

Explanation

a tracks our current position, m is the side length of the array, and d is the direction we're going (which changes anytime a != 0). In each call to f() we update the value of a going one step in the direction of d.

Commented

d;        // int d;
f(*a,m){  // function f() takes a pointer to int (a) and an int (m)
d=*a?:d;  // if *a != 0 then d = *a
return    //
 'x'-d?   // if d != 'x':
  !!*a+   //  add one if we're changing direction (*a != 0)
   f(...) //  to the result of calling f() recursively
 :        // else
  0;}     //  we're at the end (return 0)

Vyxal, 225 bitsv1, 28.125 bytes

00"£{?¥ṘÞi:\x≠|¨^÷N":∑¬ß_:&+}!‹

Try it Online!

Less of a mess than before. Takes 0s as "0"

Explained

00"£{?¥ṘÞi:\x≠|¨^÷N":∑¬ß_:&+}_!­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁢‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏‏​⁡⁠⁡‌⁢⁤​‎‏​⁢⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏⁠‎⁡⁠⁢⁡⁤‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁢⁢⁤‏⁠‎⁡⁠⁢⁣⁡‏‏​⁡⁠⁡‌⁣⁤​‎‎⁡⁠⁢⁣⁢‏⁠‎⁡⁠⁢⁣⁣‏⁠‎⁡⁠⁢⁣⁤‏‏​⁡⁠⁡‌⁤⁡​‎‏​⁢⁠⁡‌⁤⁢​‎‎⁡⁠⁢⁤⁢‏⁠‎⁡⁠⁢⁤⁣‏‏​⁡⁠⁡‌­
00"£                             # ‎⁡Put the list [0, 0] into the register. The register will act as the current character pointer
    {         |                  # ‎⁢While:
      ¥ṘÞi                       # ‎⁣  Indexing the register
     ?                           # ‎⁤  Into the input
          :\x≠                   # ‎⁢⁡  Does not give "x" (leaving an extra copy of the retrieved character)
              |                  # ‎⁢⁢Do:
               ¨^                # ‎⁢⁣  Convert the retrieved character to the offsets that character represents. E.g. > maps to [1, 0] as it indicates incrementing the x coordinate.
# ‎⁢⁤Characters not in "^<>v" are mapped to [0,0]
                 ÷N"             # ‎⁣⁡  Due to a goofy logic bug, ^ and v have their y-offset inverted, so un-invert it
                    :∑¬          # ‎⁣⁢  Check whether the sum of the offsets is not 0 (i.e. that the character is indeed a direction arrow)
                       ß_        # ‎⁣⁣  If it isn't a direction arrow, ignore the direction of the character. Otherwise, leave the offsets on the stack
                         :&+     # ‎⁣⁤  Add whatever offset is on the top of the stack (either a new arrow or the previous direction) to the register. This leaves a copy on the stack.
# ‎⁤⁡This act of leaving the copy on the stack is how the number of arrows is determined. Every time an arrow is encountered, it's direction is pushed permanently to the stack.
                             _!  # ‎⁤⁢Remove the last item (which will be "x" due to the nature of the while loop stopping with an extra copy) and then push the length of the stack.
💎

Created with the help of Luminespire.

Excel (ms365), 119, 116 bytes

-3 Bytes thanks to @JosWooley

enter image description here

enter image description here

Formula in I1:

=Z(A1,A1,0)

Explaination:

Z() refers to a custom function:

=LAMBDA(i,s,c,LET(y,IF(i=0,s,i),IF(i="x",c,Z(OFFSET(i,SWITCH(y,"^",-1,"v",1,),SWITCH(y,"<",-1,">",1,)),y,c+(i>0)))))

This is a recursive LAMBDA() with 3 parameters:

If the current cell ('i') equals 'x' the recursion stops and the function will output the current value of 'c'.

If the current cell <> 'x' this means we need to call Z() and use the new cell as 'i' which is acquired via OFFSET() using the current direction. The 's' will always be equal to the 'y' parameter found while we need to add one to our counter 'c'.

Charcoal, 43 bytes

WS⊞υιP⪫υ¶≔⁰θW⌕x <v>^KK«F‹¹ι«≔⊗ιφ≦⊕θ»M✳φ»⎚Iθ

Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings of spaces, arrows and an x. Explanation:

WS⊞υιP⪫υ¶

Copy the input to the canvas without moving the cursor.

≔⁰θ

Start with 0 strokes.

W⌕x <v>^KK«

Repeat until the ball goes in the hole.

F‹¹ι«

If the current character is an arrow, then...

≔⊗ιφ

... change the current direction, and...

≦⊕θ

... increment the number of strokes.

»M✳φ

Move the cursor in the current direction.

»⎚Iθ

Output the final count.

JavaScript (ES6), 67 bytes

Expects a matrix filled with 0 for no-op and the ASCII codes of the other characters.

f=(m,x=y=0)=>(q=m[y][x])-120&&(q?c=q:0)/c+f(m,x+c%3-1,y+=~-c%5%3-1)

Try it online!


JavaScript (ES6), 62 bytes

Using the custom mapping of <^>vx0 to [-1,0,1,2,3,4].

f=(m,x=y=0)=>(q=m[y][x])-3&&(q<3&&(c=q,1))+f(m,x+c%2,y+=~-c%2)

Try it online!