23
\$\begingroup\$

My first code golf question post! Hope u like it ;-)

The task is simple. Write either an stdin-stdout program or a function. Input is a 2D array which contains only either characters or the integer 0. You are allowed to replace the integers with the character '0' or null instead in any language (kudos to @SuperStormer for suggesting the "any" part) if you think it makes the problem easier or allows for decreasing code length.

Each element of the array contains 0, '>', '<', '^', 'v', or 'x'. You play golf in the grid by starting at the indices (0,0), and then moving in the direction indicated by the arrows. There is always an arrow at (0,0). 0 is the no-op. The code stops when you get to 'x', the golf hole.

Each of the arrows that you encounter represents a stroke in golf. However, obviously not all arrows will be used. Your mission is to find how many strokes you did before you get to the hole.

TL;DR: Find the number of arrows in your path from (0,0) to 'x'.

Examples:

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

> 0 0 v <
0 > x < 0

gives 3.

[['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,'^']]

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 ^

gives 8.

You do not need to consider handling cases which do not correspond to the input requirements.

Example code: (Python 3.8, 149 bytes, and yeah I'm so noob...)

def f(g):
    x=y=r=0
    while 1:
        if(n:=g[x][y])=='x':return r
        if n:a,b=(0,1)if n=='>'else(0,-1)if n=='<'else(-1,0)if n=='^'else(1,0);r+=1
        x+=a;y+=b

Have fun golfing!

Additional note: Changing the input values to things like "12345" is allowed if you are able to take advantage of language features by doing so. However you must mark your answer and the input code you used if you choose to do so ;-)

Additional additional note: Thanks to Unrelated String for this. "The next stroke taken is always the closest in the direction".

\$\endgroup\$
14
  • 6
    \$\begingroup\$ This seems to be a nice challenge! For future reference though we recommend asking for feedback in the sandbox just so people can point out any issues. I don't see any major problems though in this case \$\endgroup\$
    – mousetail
    Jul 19 at 5:50
  • 6
    \$\begingroup\$ Would it be possible to allow using '0' or any falsy value even if the language supports mixed types in arrays? Could you also provide a few more test cases (especially for edge cases like a single-element array, etc)? \$\endgroup\$ Jul 19 at 5:54
  • 1
    \$\begingroup\$ @SuperStormer That's allowed. '0' the char is actually my original idea but I thought bool(0)==False so I'd use 0 to make stuff easier for mixed type languages. As for more test cases, thanks for the suggestion. I'll make more of them later on when I have time. Oh and single-element arrays are against the rules because there must be an 'x' in the array, but (0,0) must be an arrow. \$\endgroup\$ Jul 19 at 6:17
  • 1
    \$\begingroup\$ @TheThonnu Thank you for your encouragement! \$\endgroup\$ Jul 19 at 6:18
  • 1
    \$\begingroup\$ Although the second test case makes it pretty clear, it might be worth specifying that the next stroke taken is always the closest in the direction. \$\endgroup\$ Jul 19 at 14:40

15 Answers 15

11
\$\begingroup\$

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!

\$\endgroup\$
9
\$\begingroup\$

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:

  • The starting cell as 'i';
  • The starting direction as 's';
  • The starting count as 'c', being zero at the 1st iteration.

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'.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Nice! You can save a byte by replacing i<>0 with i>0. \$\endgroup\$ Jul 19 at 11:27
  • \$\begingroup\$ Thanks @JosWoolley, I've spend quite some time thinking about avoiding SWITCH() twice. I could not crack this yet. Ideas? It just looks like it can be avoided =) \$\endgroup\$
    – JvdV
    Jul 19 at 12:02
  • 1
    \$\begingroup\$ Can't see a way to improve it massively, though the zeroes passed as the final parameter to the two SWITCH calls can be omitted, so that's another two bytes. \$\endgroup\$ Jul 19 at 12:16
  • 1
    \$\begingroup\$ And you can save another removing the zero from the worksheet call: =Z(A1,A1,) \$\endgroup\$ Jul 19 at 12:32
  • 1
    \$\begingroup\$ @JosWoolley, cool. However I did not include the bytes from the the call itself, just the function as I've noticed that is what people seem to count on other answers across Code Golf. Thanks for the extra pair of eyes! \$\endgroup\$
    – JvdV
    Jul 19 at 12:34
8
\$\begingroup\$

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.

\$\endgroup\$
4
  • \$\begingroup\$ Cool use of ord! \$\endgroup\$ Jul 19 at 7:30
  • \$\begingroup\$ n%3+(138|n)%3*w+~w saves five (a golf of n%3-1+((138|n)%3-1)*w). You can then save seven more with a recursive lambda like this. \$\endgroup\$ Jul 19 at 22:10
  • \$\begingroup\$ ...in fact the somewhat more straightforward, n%3+n//14%3*w+~w saves two more. \$\endgroup\$ Jul 19 at 22:22
  • \$\begingroup\$ This lambda is recursive, so you need to include the f= in the lambda definition. (In general, you need to include the definition if the lambda wouldn't work if you named it something different) \$\endgroup\$
    – noodle man
    Jul 21 at 22:03
7
\$\begingroup\$

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.

\$\endgroup\$
7
\$\begingroup\$

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

\$\endgroup\$
6
\$\begingroup\$

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.

\$\endgroup\$
2
  • 3
    \$\begingroup\$ New SIGBOVIK paper topic idea: Is it possible to smash the keyboard without creating valid Vyxal? (Idea from [mcmillen.dev/sigbovik/2019.pdf]) \$\endgroup\$ Jul 19 at 6:29
  • 1
    \$\begingroup\$ @ShiranYuan If you hit ALT while keyboard smashing, it's pretty likely that character isn't in Vyxal's codepage. \$\endgroup\$
    – noodle man
    Jul 19 at 11:50
6
\$\begingroup\$

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])
  ...)
  • lst is the input list.
  • x and y are the indices at which the ball is currently at.
  • dx and dy are the directions that the ball is traveling to.
    • Used when a 0 or any unrecognizable symbol is seen.
  • hits are the number of hits/strokes that have occurred.

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!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Glad you enjoyed it! Thanks for the detailed explanation, and hope you a nice week for you too :-D \$\endgroup\$ Jul 19 at 14:07
  • 1
    \$\begingroup\$ 233 bytes, you don't need #!racket as it's not necessary to run the program \$\endgroup\$ Jul 19 at 17:59
  • 1
    \$\begingroup\$ @SuperStormer, thank you :D I originally added the statement as OP asked for a full program or function. :) Have a great week further! \$\endgroup\$ Jul 20 at 11:25
5
\$\begingroup\$

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)
\$\endgroup\$
3
\$\begingroup\$

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:

  • 0 -> 0
  • x -> -128
  • < -> -1
  • > -> 1
  • ^ -> -M
  • v -> M

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!

\$\endgroup\$
3
\$\begingroup\$

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
\$\endgroup\$
0
3
\$\begingroup\$

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}}
  • -9 by using a constant inside the loop rather than a computed local outside it
  • -22 by using several variables rather than tuples
  • -6 by combining the assignments to u and v into a single statement
\$\endgroup\$
2
\$\begingroup\$

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)
  • Ç+Z< is [-1,8,5,7,5,1] for [0,"^",">","v","<","x"] respectively (only 1 is truthy in 05AB1E);
  • Ç+11%4% (the 4% is implicit due to modular indexing) is [2,3,0,1] for ["^",">","v","<"] respectively.
\$\endgroup\$
2
\$\begingroup\$

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!

\$\endgroup\$
5
  • \$\begingroup\$ It's recommended you leave a link where people can test your code out (like tio.run or something), otherwise, great answer! \$\endgroup\$ Jul 31 at 14:14
  • 1
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! \$\endgroup\$
    – The Thonnu
    Jul 31 at 14:26
  • \$\begingroup\$ Thanks @joyoforigami - I have added link to tio.run \$\endgroup\$
    – grizzthedj
    Jul 31 at 14:32
  • \$\begingroup\$ @grizzthedj To save you some time in the future, you can click the link icon in the top left corner and copy the item that says "Code Golf submission (Stack Exchange)" It does all the formatting and stuff for you and all you have to do is explain/add test cases etc. \$\endgroup\$ Jul 31 at 14:35
  • 1
    \$\begingroup\$ Also, in general we don't hardcode inputs. Add a p=gets or something in your code to define p. \$\endgroup\$ Jul 31 at 14:38
1
\$\begingroup\$

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'.

\$\endgroup\$
4
  • \$\begingroup\$ This is awesome. I was just wondering, is it possible to graph the path to the hole, like what desmos is actually good at? \$\endgroup\$ Aug 17 at 0:16
  • \$\begingroup\$ @ShiranYuan I think so. I'll give it a try! \$\endgroup\$
    – fwoosh
    Aug 17 at 0:54
  • \$\begingroup\$ Alright here it is with the path drawing \$\endgroup\$
    – fwoosh
    Aug 17 at 1:12
  • 1
    \$\begingroup\$ Wow this is awesome \$\endgroup\$ Aug 17 at 1:36
0
\$\begingroup\$

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!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.