Uni-Dimensional String Golf

6

Introduction

You have to simulate playing golf over an input string that represents the green. The 2-character substring () represents the hole, and is guaranteed to appear only once in the string.

This is a sample green:

ABCDEFGHIJKLM()NOPQRSTUVWXYZ

The simulation consists of outputting the characters that the ball falls on after a series of hits that are also passed to your function.

Each hit is represented by a positive integer indicating how many characters the ball will travel, relative to previous position.

Example

The following input results in the output G(o).

7,7,ABCDEFGHIJKLM()NOPQRSTUVWXYZ

Explanation

The input represents two hits of length 7. The output is a string of characters, showing the intermediate positions of the ball. The ball starts to the left of the string, and travels 7 characters to the right, landing on the G. As such, that character is the first part of the output.

Then the ball is hit for the second time, and it lands in the hole. In this case, the hole is output with the ball inside, like this: (o).

9,7,1,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
I(o)N

The output represents the characters the ball has landed on in the same order as in the string.

Notes

  1. The width of the hole is 2. If the ball lands on either parenthesis, the hole is hit.
  2. The direction of the hit is always towards the hole, so when the ball ends up to the right of the hole, the next hit will cause the ball to move to the left (and vice versa).
  3. The ball might not reach the hole, in which case the position of the ball after the last hit must be output next to the character (in the direction of the hole) the ball is on at the end of the hits. The hole is still included in the output.

example:

28,26,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
B12()Z

First 28 hit lands on Z at the right of the hole , next 26 hit is as always thowards the hole (left) and lands on B. No more hits left so the distance to the hole (12 characters) is shown next to B

  1. If the hits cause the ball to leave the green at some point, discard all remaining hits, and prepend ^ if the ball exits the green to the left, and append $ if the ball leaves the green via the right side.
  2. There might be hits after the putt, in which case those should be discarded, and the hole in the output should not contain an o, but an X.

Test cases

15,10,3,TOURING()MACHINE
I(o)N

7,HOLEIN()NE
(o)

9,7,1,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
I(o)N

7,7,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
G(o)

28,26,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
B12()Z

2,25,26,27,ABCDEFGHIJKLM()NOPQRSTUVWXYZ
AB()Y13Z

1,1,6,SH()RT
SH()$

2,4,6,TOO()HARD
^O()H

4,8,1,3,3,3,3,3,TAKEIT()ASITCOMES
E(X)IT

You have to write a program or function wich accepts a series of positive numbres representing the hits and a [A..Z] string with one hole "()" representig the green. Make clear if your input format is different form 7,7,ABCDEFGHIJKLM()NOPQRSTUVWXYZ

This is code golf, so the submission with the smallest amount of bytes per language wins!

marcosm

Posted 2017-03-17T12:32:22.267

Reputation: 986

Answers

2

Python 2 - 380 bytes

Try it online

Shorter answer, thanks to @ovs. This one requires list of integers and string as input. Example: 28,26,"ABCDEFGHIJKLM()NOPQRSTUVWXYZ". Check edits for older version, that accepts plain string like "28,26,ABCDEFGHIJKLM()NOPQRSTUVWXYZ"

I=input()
c=-1
G=I[c]
I=map(int,I[:c])
u=r=""
L=[u]*len(G)
H=len(G.split('(')[0])
L[H:H+1]='()'
d=1
s=0
f="".join
for h in I:
 s+=1;c+=h*d;d=(1,-1)[H-c<0];T=f(L)
 if H<=c<H+2:u='o'if s==len(I)else'X';break
 if c<0:r="^"+T;break
 if c>len(G):r=T+"$";break
 L[c]=G[c]
else:
 m=H-c if~d else c-H-1
 if d>0:c+=1
 L=L[:c]+[str(m)]+L[c:];r=f(L)
print r or("%s)"%u).join(f(L).split(')'))

Explanation (for older version, but approach is same):

I=input().split(',')             # split input
G=I[-1]                          # last element - Green
I=map(int,I[:-1])                # convert all other (hits) to int
L=[""]*len(G)                    # empty list of same length as Green, used to ouput
H=len(G.split('(')[0])           # index of hole
L[H]='('                         # hole is always printed
L[H+1]=')'
c=-1                             # current index on Green
d=1                              # direction of hit
u=r=""                           # strings for output and in-hole marker (X)/(o)
s=0                              # number of current hit
for h in I:
    s+=1
    c+=h*d                       # move current by hit * direction
    d=(1,-1)[H-c<0]              # calculate new direction
    T="".join(L)                 # used to remove code duplication 
    if H<=c<H+2:                 # if in hole
        u='o'if s==len(I)else'X' # check whether it is last hit or not
        break
    if c<0:                      # if out of Green on the left
        r="^"+T                  # add '^' and join all visited indices
        break
    if c>len(G):                 # if out of Green on the right
        r=T+"$"                  # add '&' after join all visited indices
        break
    L[c]=G[c]                    # mark visited index
else:                            # rare occasion of for-else construction - executes if never break out of loop
                                 # which means, that we are out of hits and not in hole
    m=H-c if~d else c-H-1        # calculate distance to hole
    if d>0:
        c+=1
    L=L[:c]+[str(m)]+L[c:]       # expand L list with distance
    r="".join(L)                 # join list
t="".join(L).split(')')          
if r:
    print r                      # ouput r in all cases exept in-hole
else:
    print t[0]+"%s)"%u+t[1]      # output for in-hole cases 

Dead Possum

Posted 2017-03-17T12:32:22.267

Reputation: 3 256

1some minor improvements – ovs – 2017-03-17T15:35:51.783

1even more – ovs – 2017-03-17T15:40:28.617

@ovs Thanks! Clever golfing, also I managed to cut another 5 bytes from your last improvement: here

But this approach requires list as input. It's not clear, if it is accepted

– Dead Possum – 2017-03-17T15:54:55.067

@ovs and -1 more byte, since x is not really needed – Dead Possum – 2017-03-17T16:12:09.437

1

Röda, 308 299 bytes

f g{a=indexOf("()",g)g=g[:a].."oo"..g[a+2:]o=[""]*#g
s=""e=""i=-1{|j|o[i]="X"if[i>=a,i<=a+1]else{i+=j if[i<a]else i-=j if[i>a+1]
{s="^";[]_}if[i<0]else{e="$";[]_}if[i>=#g]else o[i]=g[i:i+1]}}_
o[i].=s..a-i if[i<a,i>=0]
o[i]=i-a-1..o[i]if[i>a+1,i<#g]
[s..o[:a]&""..`(${o[a:a+2]&""})`..o[a+2:]&""..e]}

Try it online!

Saved 8 bytes thanks to Kritixi Lithos!

Ungolfed:

function f(green) {
    /* find the hole */
    hole := indexOf("()", green)
    /* replace () with oo in the green string */
    green := green[:hole].."oo"..green[hole+2:]
    /* initializes the output array: contains an empty string for each yet unvisited place on the green */
    out := [""]*#green
    start := ""
    end := ""
    i := -1
    /* for each number in the stream */
    for j do
        /* if the ball is in the hole, change the output to X */
        if [ i=hole or i=hole+1 ] do
            out[i]="X"
        else
            /* add or subtract the number */
            i+=j if [ i < hole ] else i-=j if [ i > hole+1 ]
            /* if the ball has left the green, stop looping */
            if [ i < 0 ] do
                start = "^"
                break
            done
            if [ i >= #green ] do
                end = "$"
                break
            done
            /* add the visited character to the output array */
            out[i] = green[i:i+1]
        done
    done
    /* add a number next to the last character visited */
    out[i] .= ""..hole-i if [ i < hole and i >= 0 ]
    out[i] = i-hole-1..o[i] if [ i > hole+1 and i < #green ]

    /* return the output */
    return start..out[:hole]&""..`(${out[hole:hole+2]&""})`..out[hole+2:]&""..end
}

fergusq

Posted 2017-03-17T12:32:22.267

Reputation: 4 867

I think you can replace and with , – user41805 – 2017-03-31T16:34:10.660

@KritixiLithos You are right! Thanks. – fergusq – 2017-03-31T16:55:35.217