Código (Mini) Golf


50

Dada una vista lateral de un campo de minigolf y la potencia del swing, determine si la pelota llegará al hoyo.


Un curso tendrá este formato:

      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           

La pelota comienza directamente antes del primer pedazo de tierra a la izquierda y sigue el contorno del curso hasta llegar al hoyo (una mayúscula Udebajo del nivel actual del suelo). Si llega al agujero, genera un valor verdadero. El poder del swing será la velocidad inicial de la pelota. La bola se mueve al siguiente personaje a la derecha en cada iteración, luego la velocidad se altera dependiendo del personaje en el que se encuentre. Si la velocidad alcanza 0o menos antes del hoyo, genera un valor falsey.

  • _ disminuye la velocidad en 1
  • / disminuye la velocidad en 5
  • \ aumenta la velocidad en 4

Los cursos se pueden rellenar opcionalmente con espacios. El poder del swing siempre será un número entero positivo.

No necesita preocuparse de que la pelota vaya demasiado rápido para entrar en el hoyo, rodando hacia atrás o saltando / rebotando en las colinas.

Casos de prueba

Input: 27
      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           
Output: true

----------

Input: 26
      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           
Output: false

----------

Input: 1

U
Output: true

----------

Input: 1
_ 
 U
Output: false

----------

Input: 22

     /U
    /  
   /   
  /    
\/     
Output: true

----------

Input: 999
_       _
 \     / 
  \   /  
   \ /   
    U    
Output: true

----------

Input: 5
  /
/U 
Output: false

----------

Input: 9

/\/\/\/\/U
Output: false

----------

Input: 16

_/\                                         _
   \      __       /\/\/\                  / 
    \    /  \     /      \                /  
     \__/    \   /        \____________ _/   
              \_/                      U     

Output: true

Este es el código mini-golf, ¡la respuesta más corta en bytes gana!


1
Si su idioma tiene una buena matriz incorporada, puede convertir la entrada en una secuencia de operaciones ( \_/) con los siguientes pasos: dividir en una matriz de líneas, rotar, aplanar, eliminar espacios.
Cyoce

1
Esto es realmente más un mecanismo de vía fija que un campo de golf: P
Zach Gates

24
Me gusta que \/\/\/\/\/es un curso más eficiente que __________.
Ezrast

2
Eso es lo que estaba pensando, 4 abajo, 5 arriba, luego .5 debe ser promedio. Oh, plano es 1?
Leif Willerts

¿Cada línea en un curso siempre tendrá la misma longitud (con espacios finales llenando el final de las líneas más cortas)?
SnoringFrog

Respuestas:


17

Pyth, 27 bytes

.Am<sXsd"_\ /"[1_4Z5)Q._C.z

Demostración

Este código hace algo muy inteligente y nada seguro para escribir X. Compruébalo a continuación.

Explicación:

.Am<sXsd"_\ /"[1_4Z5)Q._C.z
                               Implicit: Z = 0, Q = eval(input())
                               Q is the initial power.
                         .z    Take all input, as a list of lines.
                        C      Transpose, giving all columns.
                      ._       Form all prefixes.
  m                            Map over the prefixes.
      sd                       Concatenate the prefix.
     X  "_\ /"[1_4Z5)          Change '_' to 1, '\' to -4, ' ' to 0, and '/' to 5.
                               In particular, 'U' is left unchanged.
    s                          Reduce on addition.
                               If all elements were numbers,
                               this results in the total change in power.
                               If there was a 'U', it results in a string.
   <                 Q         If the previous result was a number, this compares
                               it with the initial input to see if the ball is
                               still rolling.
                               If the previous result was a string, this slices off
                               the first Q characters, which always has a truthy
                               result.
.A                             Test whether all of the prefixes mapped to a thruthy
                               result.

Puede que me falte algo, pero ¿se detiene Q? Es decir, ¿el último ejemplo podría causar algunos problemas?
flindeberg

@flindeberg Así no es como funciona. El < ... Qfunciona como una comparación numérica hasta el agujero, no una rebanada. Después del agujero, todo lo que importa es que el resultado sea verdadero.
isaacg

14

Haskell, 111 109 bytes

import Data.List
g"_"=1
g"/"=5
g _= -4 
f n=all(>0).scanl(-)n.map g.fst.span(/="U").(>>=words).transpose.lines

Ejemplo de uso:

*Main> f 27 "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           "
True
*Main> f 26 "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           "
False

Cómo funciona:

                            lines  -- split into list of lines at nl
                       transpose   -- transpose
                  (>>=words)       -- turn each line into words (i.e. remove spaces)  
            fst.span(/="U")        -- take all words up to but excluding "U"
         map g                     -- turn each word into the speed modifier
    scanl(-)n                      -- build list of partial sums starting with n
                                   --   note: speed modifiers are negative so we
                                   --   use (-) with scanl to build sums 
all(>0)                            -- return true if all sums are greater than 0                                 

Editar: @ user81655 encontró 2 bytes para guardar. ¡Gracias!


7

Ruby, 104 87 caracteres

->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6}
s>0}

Ejecución de muestra:

2.1.5 :001 > track = '      ____       ____ _   
2.1.5 :002'>    __/    \     /    U \  
2.1.5 :003'> __/        \   /        \_
2.1.5 :004'>             \_/           
2.1.5 :005'> '
 => "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           \n" 

2.1.5 :006 > ->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6};s>0}[27, track]
 => true 

2.1.5 :007 > ->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6};s>0}[26, track]
 => false 

6

Japt, 38 bytes

Vz r"%s|U[^]*" ¬e@UµX¥'_?1:X¥'/?5:-4 ¬

Try it here!

¡Golpeando a CJam!

Explicación

Básicamente toma la entrada de la cadena, la gira 90 grados en el sentido de las agujas del reloj, elimina espacios y líneas nuevas, elimina el agujero y todo lo que está detrás, y se divide a lo largo de los caracteres. Luego verifica si la pelota llega a cero o menos usando la everyfunción.


Creo que `` debería ser positivo (la descripción parece incorrecta)
isaacg

No creo que eso funcione. Imagínese esto: una serie de pendientes eleva la velocidad de la pelota a -2, pero luego hay un +4 neto más adelante. La suma reflejaría +2, así que la pelota lo logró. En realidad, nunca llegaría a la sección positiva después de llegar a los negativos.
Cyoce

Creo que solucioné el problema.
Mama Fun Roll

Ese es un botón genial;)
J Atkin

¡Agradable! Entonces, jugar al golf ... La barra invertida doble es reemplazable por %, y >0puede ser reemplazada por ¬, ya que el sqrt de un número no positivo siempre es falso ( 0 -> 0, -1 -> NaN).
ETHproductions

6

CJam, 40 39 bytes

liqN/:.e>'U/0="\_/"[4W-5]er{1$+}/]:e<0>

La entrada tiene el poder en la primera línea y el curso comienza en la segunda línea. La salida es 0o 1.

Pruébalo aquí.

Explicación

li    e# Read power and convert to integer.
qN/   e# Read course and split into lines.
:.e>  e# Flatten course by folding maximum over columns.
'U/   e# Split around the hole.
0=    e# Keep the first chunk.
"\_/"[4W-5]er
      e# Replace \, _, / with 4, -1, 5, respectively.
{     e# For each of those costs...
  1$+ e#   Copy the previous power and add the cost.
}/    e# This leaves all partial sums on the stack.
]     e# Wrap them in an array.
:e<   e# Find the minimum.
0>    e# Check whether it's positive.

5

Retina, 82 81 77 74 68 67 68 bytes

+`(?<=(.)*) (?=.*¶(?<-1>.)*(.))
$2
\\
>>>>
+`>_|>{5}/|>¶

^>*U

Pruébalo en línea

  • La entrada se representa en una base unaria , como n >s, por ejemplo, 4 es >>>>\n. (¿Es esto legal?)
  • +`(?<=(.)*) (?=.*¶(?<-1>.)*(.)) $2 - aplanar el curso - reemplazar espacios con el personaje debajo de ellos.

    Después de esta etapa, los datos se verán así:

    >>>>>>>>>>>>>>>>>>>>>>>>>>
    __/__/____\\\_///____U_\\_
    __/__/    \\\_///    U \\_
    __/        \\_//        \_
                \_/           
    

    Podemos ignorar todo después del primero U, no llegaremos allí de todos modos.

  • > representan un paso que se nos permite dar, o la energía restante.
  • Reemplace cada uno \con cuatro >: una pendiente nos da energía adicional.
  • Bucle: eliminar polémicamente >_o >>>>>/hasta que no quede ninguno. _s y /s consumen energía.
  • Finalmente, intente hacer coincidir ^>*U: verifique si podemos alcanzar Ucon energía positiva (o sin energía).
    Esto generará 0o 1.

Otra opción de cierre con 91 79 bytes es:

+`(?<=¶(.)*) (?=.*¶(?<-1>.)*(.))
$2
^(>)+\n(?<-1>_|/(?<-1>){4}|\\(?<1>){5})+U

Pruébalo en línea

Este es el mismo enfoque pero con un grupo de equilibrio en lugar de un reemplazo contencioso.

Estoy seguro de que ambos pueden jugar más golf, por lo que cualquiera de ellos puede terminar más corto.


1
Sí, la entrada unaria es legítima (a menos que el desafío especifique "decimal"), aunque probablemente usaría 0o 1como el dígito si eso no incurre en bytes adicionales.
Martin Ender

1
También bienvenido a PPCG, ¡estoy muy contento de verte aquí! :) (Y usando Retina también.)
Martin Ender

¡Seguro! Estaba en la lista de preguntas calientes y parecía divertido. Pensé en probarlo :-)
Kobi

3

ES6, 117 bytes

(c,p)=>c.split`
`.map(s=>[...s.slice(0,c.match(/^.*U/m)[0].length-1)].map(c=>p+=c=='/'?-5:'    \\'.indexOf(c)))&&p>0

Sin golf:

function hole(course, power) {
    width = course.match(/^.*U/m)[0].length - 1; // calculate width to hole
    lines = course.split("\n");
    for (i = 0; i < lines.length; i++) {
        line = lines[i].slice(0, width); // ignore extraneous parts of the course
        for (j = 0; j < line.length; j++) {
            switch (line[j]) { // accumulate remaining power
            case '/': power -= 5; break;
            case '\\': power += 4; break;
            case ' ': break;
            default: power--; break;
            }
        }
    }
    return power > 0;
}

Editar: Guardado 4 bytes gracias a ՊՓԼՃՐՊՃՈԲՍԼ.


@ ՊՓԼՃՐՊՃՈԲՍԼ Gracias, sigo tratando de optimizar la velocidad ...
Neil

3

JavaScript (ES6), 108 107 106 bytes

Esta es la solución que se me ocurrió cuando creé el desafío.

(p,c)=>[...(l=c.split`
`)[w=0]].map((_,i)=>l.map(t=>(g=t[i])-1|p<=0?0:p-=g>"]"?1:g>"U"?-4:g>"/"?w=1:5))&&w

Explicación

Toma el poder como un número y el curso como una cadena. Devoluciones 1para trueo 0para false. El curso debe estar relleno de espacios.

(p,c)=>
  [...(l=c.split`
`)                          // l = array of lines
  [w=0]]                    // w = true if the ball has entered the hole
.map((_,i)=>                // for each index i
  l.map(t=>                 // for each line t
    (g=t[i])                // g = the character at the current index
    -1|p<=0?0:              // do nothing if g is a space or the ball has no speed left
    p-=
      g>"]"?1               // case _: subtract 1 from p
      :g>"U"?-4             // case \: add 4 to p
      :g>"/"?w=1            // case U: set w to true (it doesn't matter what happens to p)
      :5                    // case /: subtract 5 from p
  )
)
&&w                         // return w

Prueba

var solution = (p,c)=>[...(l=c.split`
`)[w=0]].map((_,i)=>l.map(t=>(g=t[i])-1|p<=0?0:p-=g>"]"?1:g>"U"?-4:g>"/"?w=1:5))&&w
Power = <input type="number" id="power" value="16" /><br />
<textarea id="course" rows="6" cols="50">_/\                                         _
   \      __       /\/\/\                  / 
    \    /  \     /      \                /  
     \__/    \   /        \____________ _/   
              \_/                      U     </textarea><br />
<button onclick="result.textContent=solution(+power.value,course.value)">Go</button>
<pre id="result"></pre>


3

Python (3.5) 169160 bytes

Una solución recursiva sin la función de transposición (zip)

def f(c,p):c=c.splitlines();l=len(c);f=lambda x,h,v:v if'U'==c[h][x]or v<1 else f(x+(h==l-1),(h+1)%l,v+{"_":-1,"\\":4,"/":-5," ":0}[c[h][x]]);return f(0,0,p)>0

Sin golf

c por supuesto, p para potencia, v para velocidad, h para altura

def f(c,p):
    c=c.splitlines()
    l=len(c)
    tmp = {"_":-1,"\\":4,"/":-5," ":0}
    f=lambda x,h,v:v if'U'==c[h][x]or v<1 else f(x+(h==l-1),(h+1)%l,v+tmp[c[h][x]])
    return f(0,0,p)>0

Uso

f(16,"_/\                                         _\n   \      __       /\/\/\                  / \n    \    /  \     /      \                /  \n     \__/    \   /        \____________ _/   \n              \_/                      U     ")
f(9,"/\/\/\/\/U")

2

Pyth, 35 bytes

VC.z=-Q@(1_4 5)x"_\\/"JrN6IqJ\U>Q_5

Explicación

                                    - Autoassign Q = eval(input())
                                    - Autoassign .z = rest of input
VC.z                                - For N in zip(*.z)
    =-Q                             - Q -= ...
                      JrN6          - Autoassign J to N.strip() (get rid of spaces)
       @(1_4 5)x"_\\/"              - {"_":1, "\\": -4, "/": 5, "U":5}[J] ("U" isn't defined but that's what it is according to how str.index works)
                          IqJ\U     - If J == "U"
                               >Q_5 - print Q > -5 ()

1

Ruby, 85 caracteres

->i,s{s.lines.map(&:bytes).transpose.any?{|o|(c=o.max)==85||i<0||!(i+=c*3%14-6)};i>0}

Respuesta de @ manatwork adaptada


1

JavaScript, 266 263 244 bytes

(s,a)=>{var f=(e,x)=>{for(var i=1;D=e[i][x],i<e.length;i++)if(D!=" ")return D},o=a.split(`
`),l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),b="";for(i=0;i<l;i)b+=f(o,i++);for(i=0;b[i]!="U"&&s>0;i++)s-=b[i]=="_"?1:b[i]=="/"?5:-4;return s>0}

Sin golf

(s,a)=>{
    var f=(e,x)=>{
        for(var i=1;D=e[i][x],i<e.length;i++)
            if(D!=" ")
                return D
    },
    o=a.split(`
`),
    l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),
    b="";
    for(i=0;i<l;)
        b+=f(o,i++);
    for(i=0;b[i]!="U"&&s>0;i++)
        s-=b[i]=="_"?1:b[i]=="/"?5:-4;
    return s>0
}

Uso

var o = (s,a)=>{var f=(e,x)=>{for(var i=1;D=e[i][x],i<e.length;i++)if(D!=" ")return D},o=a.split(`
`),l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),b="";for(i=0;i<l;)b+=f(o,i++);for(i=0;b[i]!="U"&&s>0;i++)s-=b[i]=="_"?1:b[i]=="/"?5:-4;return s>0}


o(27, `
      ____       ____ _   
   __/    \\     /    U \\  
__/        \\   /        \\_
            \\_/           `); // will return true

Mi error; Pensé que había copiado en el primer ejemplo con "27" como primer argumento. Corrigí esto. Gracias.
user49328

1

Java, 219 bytes

boolean p(int v,String c){int z=c.length(),f[]=new int[z],e,i,k;for(String r:c.split("\n"))for(i=-1;++i<r.length();)if((e=r.charAt(i))>32)f[i]=e;for(i=-1,e=0;++i<z&v>0;)v-=(k=f[i])>94?1:k>91?-4:k>84?(e=1):5;return 0<e;}
  • Acoplar el curso, porque la coordenada y no importa, desafortunadamente Java no tiene un recorte vertical. Tampoco tiene una transposición de cadena.

  • Iterar sobre el curso aplanado y realizar un seguimiento de la velocidad de la pelota.


1

Octava, 111 110 bytes

function g(v,s) A([95,47,92])=[1,5,-4];all(v>cumsum(A(m=max(cat(1,strsplit(s,'\n'){:}),[],1)))(1:find(m==85)))

Explicación:

  • Divida la entrada en nuevas líneas y convierta esa molesta matriz de celdas en una matriz
  • Acoplar la matriz al encontrar el maxpara cada columna
  • Asigna los caracteres '_/\'a [1, 5, -4](todos los demás caracteres menos de los que '_'están asignados 0)
  • Calcular la suma acumulativa de todos los elementos de la matriz asignada
  • Salida Truesi todas las sumas acumuladas desde el comienzo del curso hasta la taza son menores que la velocidad de inicio (de lo Falsecontrario).

Aquí hay un caso de prueba que ya había desarrollado similar al segundo propuesto por @Erwan y un par de resultados:

s9 =
   /\
  /  \
_/    \
       \
        \
         U

g(11,s9) %False
ans = 0
g(17,s9) %True
ans =  1

Y aquí está el primer caso de prueba:

s10 = 
  _
 / U\
/    \
      \
       \
        \
         \
          \_

>> g(11,s10)
ans = 0
>> g(12,s10)
ans =  1

Creo que si el curso es como "//_U\\\\\\\_el resultado es incorrecto, ya que no elimina el carácter después de las Umismas cosas si tiene un curso con un máximo local como_//\\\\\U
Erwan

@Erwan Pero no eliminan los caracteres después del U. Eso es lo que (1:find(m==85))hace; toma subarreglos desde el primer índice hasta la ubicación de U. Revisaré su caso de prueba con un par de velocidades iniciales y me pondré en contacto con usted.
vaso de precipitados

No pude ejecutar su solución (no tengo Octave) por eso solo pregunto ... y porque encuentro el issu con máximos locales en la otra solución de python :) finalmente su solución funciona con máximos locales ya que usa cumsum y no solo suma (no veo eso en la primera lectura)
Erwan

@Erwan He agregado los dos casos de prueba que sugirió. Eche un vistazo y vea si los resultados son los que espera. Si está intentando esto en MATLAB, entonces no podrá ejecutarlo porque usa una indexación que solo funciona en Octave. Tendría que asignar el resultado de cumsuma una variable intermedia y luego usarlo para la comparación final all(v>tmp(1:find(m==85))).
vaso de precipitados el

Su solución funciona bien, pierda muchas cosas en la primera lectura (solo pruebe en Matlab tantas variables intermedias para agregar)
Erwan

0

C, 629 bytes

#include <string.h>
#include <stdlib.h>
#include <string.h>

bool swing(char *c, unsigned int p)
{
    char *olc = calloc(strlen(c), 1);
    int x = 0;
    char *n = c;

    while(1) {
        if(*n == '\0')  break;
        else if(*n == ' ') x += 1;
        else if(*n == '\n') x = 0;
        else {
            olc[x] = *n;
            x += 1;
        }
        n++;
    }

    int hd = 0;
    for(char *i = olc; i != strchr(olc, 'U'); i++) {
        if(*i == '_') hd += 1;
        else if(*i == '/') hd += 5;
        else hd -= 4;
    }

    free(olc);
    if(hd < p) return 1;
    return 0;
}

Sin golf:

bool swing(char *course, unsigned int power)
{
    const size_t course_len = strlen(course);
    char *one_line_course = calloc(course_len, sizeof(char));
    assert(one_line_course);
    int x_pos = 0;
    char *next = course;

    //Convert to one line representation
    while(1) {
        if(*next == '\0') {
            break;
        }
        else if(*next == ' ') {
            x_pos += 1;
        }
        else if((*next == '\n') || (*next == '\r')) {
            x_pos = 0;
        }
        else {
            one_line_course[x_pos] = *next;
            x_pos += 1;
        }
        next++;
    }

    //Calculate power vs distance
    const char *hole_location = strchr(one_line_course, 'U');
    int hole_distance = 0;
    for(char *i = one_line_course; i != hole_location; i++) {
        if(*i == '_') {
            hole_distance += 1;
        }
        else if(*i == '/') {
            hole_distance += 5;
        }
        else {
            hole_distance -= 4;
        }
    }

    free(one_line_course);
    if(hole_distance < power) {
        return true;
    }
    else {
        return false;
    }
}

Básicamente, solo hago una pasada para convertir la cadena de entrada para que se ajuste a todo en una línea, luego


¡Bienvenido a Programming Puzzles & Code Golf! Puede (y debe) poder reducir el tamaño sustancialmente eliminando la mayoría de los espacios en blanco; puede reducir algunos de sus if/ elseeg x+=*n==' ')?1:*n=='\n'?-x:(olc[x]=*n,1. Otro consejo: en C, unsigned intse puede escribir unsigned, ahorrando 4 bytes de inmediato.
Toby Speight

0

Python, 212 201 188 143 bytes

Gran parte del crédito por esta iteración de este script es para @Erwan, quien me dio un enfoque completamente diferente para probar y algunos consejos que me ahorraron 55 bytes al final.

No es recursivo, por lo que debe ser sustancialmente diferente de la otra solución de Python.

def g(c,p):
 o=[''.join(x).split()[0] for x in zip(*c.split('\n'))]
 t={"_":1,"/":5,"\\":-4}
 for v in o:
    if v=="U" or p<1:return p>0
    p-=t[v]

Ungolfed un poco:

def g(course,power):
  course=course.split('\n') # split into lines
  course=zip(*course) 

  #transpose and flatten course, then remove spaces
  one_line_course=[''.join(x).split[0] for x in zip(*course)] 

  terrain_values={"_":1,"/":5,"\\":-4}
  for char in one_line_course:
    if char=="U" or power<1: 
      return power>0 # true when power remains, false otherwise
    power-=terrain_values[char]

Si desea una solución más corta, puede usar la punta Cyoce y la función incorporada de transposición. cosas como esas o=[''.join(x).split()[0] for x in zip(*c.split('\n'))]que ganan 40 bytes, creo
Erwan

también se puede sustituir breakpor return p>0y quitarif p...
Erwan

necesita agregar una condición if"U"==v or p<1 si hay un máximo local como_//\\\\\U
Erwan

@Erwan Su primer consejo no funciona si las líneas no tienen la misma longitud (las líneas cortas tienen espacios finales para que coincidan con las largas). Dado que la publicación decía "Los cursos se pueden rellenar opcionalmente con espacios" No estoy seguro de que podamos suponer que eso es cierto. He preguntado sobre eso en un comentario.
SnoringFrog

sí, supongo que todas las líneas tienen la misma longitud (egalized con espacios en blanco) tal vez estoy equivocado en este caso, creo que mi solución es mala
Erwan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.