¡Juguemos a Mölkky!


32

Mölkky

Mölkky es un juego de lanzamiento finlandés. Los jugadores usan un alfiler de madera (también llamado "mölkky") para intentar derribar alfileres de madera de dimensiones casi similares con el alfiler, marcado con números del 1 al 12. La posición inicial de los alfileres es la siguiente:

   (07)(09)(08)
 (05)(11)(12)(06)
   (03)(10)(04)
     (01)(02)

Esta descripción y las siguientes reglas se basan en Wikipedia .

Reglas simplificadas de Mölkky

  1. Derribar un pin puntúa el número de puntos marcados en el pin.

  2. Golpear 2 o más pines puntúa el número de pines derribados (por ejemplo, derribar 3 pines obtiene 3 puntos).

  3. El objetivo del juego es alcanzar exactamente 50 puntos. Anotar más de 50 se penaliza al volver a marcar 25 puntos.

  4. Para el propósito de este desafío, asumiremos que los pines siempre están en el orden exacto descrito anteriormente. (En un juego real, los pines se ponen de pie nuevamente después de cada lanzamiento en el lugar donde aterrizaron).

Todas las demás reglas de Mölkky se ignoran y solo se considera un jugador.

Entrada

Una lista no vacía de listas de 12 booleanos. Cada lista de booleanos describe el resultado de un lanzamiento: 1 si el pin fue derribado y 0 en caso contrario. Los booleanos se dan en el orden exacto de los pines, de arriba a la izquierda a la derecha: 7 , 9 , 8 , 5 , 11 , 12 , 6 , 3 , 10 , 4 , 1 , 2 .

Salida

El puntaje después de todos los lanzamientos descritos en la entrada, calculado aplicando las reglas 1 , 2 y 3 .

Ejemplo detallado

Consideremos la siguiente entrada:

// 07 09 08 05 11 12 06 03 10 04 01 02
[ [ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 5 (rule #1)
  [ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 2 (rule #2), total: 7
  [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 ],  // scores 7, total: 14
  [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ],  // scores 12, total: 26
  [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ],  // scores 12, total: 38
  [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],  // scores 11, total: 49
  [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 7, total: 56 -> 25 (rule #3)
  [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ] // scores 2, total: 27

La salida esperada es 27 .

Reglas de desafío

  • Puede tomar información en cualquier formato razonable. En lugar de listas de booleanos, puede usar números enteros donde el bit más significativo es el pin # 7 y el bit menos significativo es el pin # 2. En este formato, el ejemplo anterior se pasaría como [ 256, 2304, 127, 64, 64, 128, 2048, 3072 ].
  • La lista de entrada puede contener tiros en los que no se derriba ningún pin, en cuyo caso el puntaje no se modifica.
  • No tiene nada especial que hacer cuando el puntaje alcanza exactamente 50 puntos. Pero puede suponer que no seguirá otro lanzamiento cuando suceda.
  • Este es el , por lo que gana la respuesta más corta en bytes.

Casos de prueba

Usando listas de enteros como entrada:

[ 0 ] --> 0
[ 528 ] --> 2
[ 4095 ] --> 12
[ 64, 0, 3208 ] --> 16
[ 16, 1907, 2048 ] --> 18
[ 2023, 2010, 1, 8 ] --> 29
[ 1726, 128, 35, 3136, 1024 ] --> 34
[ 32, 32, 2924, 2, 256, 16 ] --> 28
[ 64, 64, 2434, 1904, 3251, 32, 256 ] --> 25
[ 3659, 2777, 2211, 3957, 64, 2208, 492, 2815 ] --> 25
[ 2047, 1402, 2, 2599, 4, 1024, 2048, 3266 ] --> 50
[ 256, 2304, 127, 64, 64, 128, 2048, 3072 ] --> 27
[ 16, 8, 128, 1, 2048, 1, 2048, 513, 8, 3206 ] --> 30

Puede seguir este enlace para obtener estos casos de prueba en formato booleano.


55
Genial desafío, y también un gran juego para jugar en verano para aquellos de ustedes que no lo han probado, funciona muy bien junto con una parrilla.
Nit

2
@Nit Gracias. :) Tengo que confesar que no conocía este juego hasta hoy. Vi gente jugando mientras caminaba en un parque esta tarde. Ahora, me gustaría intentarlo.
Arnauld

Respuestas:


7

Python 2 , 126111108104 bytes

-3 bytes gracias a Jonathan Allan

-4 bytes gracias a Kaya!

f=lambda A,t=0:t>50and f(A,25)or A and f(A[1:],t-~(sum(A[0])-1or 762447093078/12**A[0].index(1)%12))or t

Pruébalo en línea!

Define una función recursiva que toma una matriz 2D de 1s y 0s y devuelve un valor entero. Nada demasiado especial en la construcción, y estoy seguro de que hay una solución más simple.

Explicación:

f=lambda A,t=0:    #Define the function, initialising t to 0 on the first iteration
               t>50and f(A,25)      #If t>50 then iterate again with t=25
                              or    #Else
               A and                #If A exists
                     f(A[1:],       #Iterate again without the first list of A
                        t-~         #And add to t, either
                           (sum(A[0])-1   #The sum of all elements if that's not 1
                                         or
                           762447093078/12**A[0].index(1)%12   #Else the appropriate pin value (black magic!)
               or t       #Finally, if A is finished, just return t

(0x103925BA4786>>4*A[0].index(1))%16ahorra 1 personaje versusord('GIHEKLFCJDAB'[A[0].index(1)])-65
Kaya

1
Un poco más óptimo:762447093078/12**A[0].index(1)%12
Kaya

¡Eso me parece magia negra! Gracias @Kaya!
Jo King

1
Eso es solo codificación con base 12
enedil

6

Jalea , 25 bytes

“ñ€bḷ’œ?TLḢṖ?µ€+25¹>?50ɗ/

Un enlace monádico que acepta una lista de listas de unos y ceros (cada uno de longitud 12) que devuelve un número entero.

Pruébalo en línea! O vea el conjunto de pruebas (usando los valores enteros dados en el OP)

¿Cómo?

Esta solución hace uso de, œ? , que, dado un número, n, y una lista encuentra la enésima permutación lexicográfica de la lista donde la lista define el orden de clasificación. Primero tenemos que resolver esto n:

 index:  1  2  3  4  5  6  7  8  9 10 11 12
 value:  7  9  8  5 11 12  6  3 10  4  1  2   (as defined by the question)
     P: 11 12  8 10  4  7  1  3  2  9  5  6   (our permutation lookup array)

... es decir, Pal índice ise establece en el índice original del valor i.
Esto Ptiene un índice lexicográfico de 438,337,469 (es decir, si tomara las 12 permutaciones de los números del 1 al 12 y las clasificara lexicográficamente, el 438,337,469 th sería P).
Esto se puede encontrar usando el Œ¿átomo de Jelly .
Ambos pasos se pueden realizar de una vez usando el programa JellyĠŒ¿

“ñ€bḷ’œ?TLḢṖ?µ€+25¹>?50ɗ/ - Link: list of lists of zeros and ones
             µ€           - perform the monadic chain to the left for €ach list:
“ñ€bḷ’                    -   base 250 number = 438337469
      œ?                  -   nth permutation (reorder the 1s and 0s to their pin values)
        T                 -   truthy indices (get the pin values of the 1s)
            ?             -   if...
           Ṗ              -   ...condition: pop (length greater than 1 ?)
         L                -   ...then: length (the number of pins)
          Ḣ               -   ...else: head (the first (& only) pin value)
                        / - reduce the resulting list of integers with:
                       ɗ  -   last three links as a dyad:
               +          -     addition (add the two values together)
                     50   -     literal fifty
                    ?     -     if...
                   >      -     ...condition: greater than (sum greater than 50 ?)
                25        -     ...then: literal twenty-five
                  ¹       -     ...else: identity (do nothing - just yield the sum)

Creo que su explicación sobre cómo encontrar el índice lexicográfico apropiado entre todas las permutaciones valdría la pena agregar como una sugerencia de Jelly . (La última vez que tuvo que hacer eso, hice una búsqueda dicotómica manual, que no es que mucho tiempo para secuencias cortas pero ... un poco tediosas ^^.)
Arnauld

Jajaja Tenía exactamente la misma solución, excepto por dos bytes diferentes: -> , µ-> Ʋ. Jelly realmente se beneficiaría de aceptar un enlace niládico como ¡'s <link>(primer argumento), excepto que, si desde el inicio del programa, mantiene el comportamiento de carcasa especial.
Erik the Outgolfer

... y casi uso los dos!
Jonathan Allan


4

Pyth, 51 48 38 bytes

VQI>=+Z?qJsN1@.PC"îO&"S12xN1J50=Z25;Z

Ahorró 10 bytes gracias a Jonathan Allan Toma entradas como una lista de listas de booleanos.
Pruébalo aquí

Explicación

VQI>=+Z?qJsN1@.PC"îO&"S12xN1J50=Z25;Z
VQ                                  ;     For each input...
    =+Z                                   ... add to the total...
       ?q sN1                             ... if one pin is down...
             @.PC"îO&"S12xN1              ... the score of that pin.
         J                    J           ... otherwise, the count.
  I>                           50         If we pass 50...
                                 =Z25     ... reset to 25.
                                     Z    Output the total.

No estoy seguro de cómo ingresarlo exactamente en el programa, pero debería ahorrar 6 o 7 bytes si puede ... 7tT8h4hT12h5h2T4h02-> .PC"îO&"S12- usa indexación de permutación lexicográfica como mi respuesta de Jelly. (El código tiene un byte no imprimible de 0x0F al comienzo de la cadena).
Jonathan Allan

))puede ser;
Jonathan Allan

4

05AB1E , 29 28 bytes

v•CÞŸαLć•13вyOΘmyÏOO25‚¬50›è

Pruébalo en línea!

Explicación

v                              # for each boolean list in input
 •CÞŸαLć•                      # push 13875514324986
         13в                   # convert to a list of base-13 numbers
            yO                 # push the sum of y
              Θm               # truthify and raise the pin-list to this number (0 or 1)
                yÏ             # keep those which are true in the current list
                  OO           # sum the list and the stack
                    25‚        # pair with 25
                       ¬50›    # check if the first number is larger than 50
                           è   # index into the pair with this result

4

Perl 5 , 74 70 bytes

$\+=y/1//-1||/1/g&&(0,6,8,7,4,10,11,5,2,9,3,0,1)[pos];$\=25if++$\>50}{

Pruébalo en línea!

Toma datos como una serie de cadenas de bits separadas por una nueva línea.


3

Haskell , 96 bytes

foldl(\s a->([s..50]++e)!!sum(last$zipWith(*)[7,9,8,5,11,12,6,3,10,4,1,2]a:[a|sum a>1]))0
e=25:e

Pruébalo en línea!

El ajuste es inteligente: esencialmente indexo en la posición s+sum(…)en la lista ([0..50]++cycle[25]). Sin embargo, una forma más corta de escribir es indexar en la posición sum(…)y comenzar la lista en s.


3

Java 10, 131 130 129 bytes

m->{int r=0,i,s,t;for(var a:m){for(i=s=t=0;i<12;s+=a[i++])t=a[i]>0?"    \n".charAt(i):t;r+=s<2?t:s;r=r>50?25:r;}return r;}

Contiene 10 no imprimibles.
Entrada como matriz entera de ceros y unos.

-1 byte gracias a @JonathanFrech , cambiando \ta una pestaña real (funciona en TIO, no funciona en mi IDE local).

Pruébalo en línea.

Explicación:

m->{                // Method with integer-matrix parameter and integer return-type
  int r=0,          //  Result-integer, starting at 0
      i,s,t;        //  Temp integers
  for(var a:m){     //  Loop over the integer-arrays of the input
    for(i=s=t=0;    //   Reset `i`, `s` and `t` to 0
        i<12;       //   Loop `i` in the range [0,12)
        s+=a[i++])  //    Increase `s` by the current value (0 or 1)
      t=a[i]>0?     //    If the current value is 1:
         "  \n".charAt(i)
                    //     Set `t` to the score at this position
        :t;         //    Else: Leave `t` the same
    r+=s<2?         //   If only a single pin was hit:
        t           //    Add its score `t` to the result
       :            //   Else:
        s;          //    Add the amount of pins `s` to the result
    r=r>50?         //   If the result is now above 50
       25           //    Penalize it back to 25
      :r;}          //   If not, it stays the same
  return r;}        //  Return the result

Creo que puede guardar un byte utilizando un carácter de tabulación real en "\t\n".
Jonathan Frech

@JonathanFrech Hmm, de hecho parece funcionar en TIO. No funciona localmente en mi IDE, pero a quién le importa eso, supongo ...;)
Kevin Cruijssen

Cuando hay una implementación funcional en alguna parte, está permitido. : @
Jonathan Frech

2

Carbón , 43 bytes

≔⁰ηFθ«≧⁺⎇⊖ΣιΣι⌕᧔$|#z⁸Ug⊗”⌕ι¹η¿›η⁵⁰≔²⁵η»Iη

Pruébalo en línea! El enlace es a la versión detallada del código. Toma la entrada como una matriz booleana. Explicación:

≔⁰η

Establece el puntaje en 0.

Fθ«

Recorre los lanzamientos.

⎇⊖Σι

¿Es el número de pines 1?

Σι

De lo contrario, tome el número de pines.

⌕᧔$|#z⁸Ug⊗”⌕ι¹

De lo contrario, traduzca la posición del pin a un valor.

≧⁺...η

Añádelo a la partitura.

¿›η⁵⁰≔²⁵η

Si el puntaje excede 50, vuelva a establecerlo en 25.

»Iη

Imprime el resultado final después de todos los lanzamientos.


2

Haskell , 110 bytes

m s|sum s==1=sum$zipWith(*)[7,9,8,5,11,12,6,3,10,4,1,2]s|1>0=sum s
f l=foldl(\b->c.(b+).m)0l
c a|a>50=25|1>0=a

Misma longitud: en f l=foldl(\b a->last$b+m a:[25|b+m a>50])0llugar de fyc

Pruébalo en línea!


Suelta el argumento l en f por 3 bytes. f=foldl(\b->c.(b+).m)0
aoemica

2

Casco , 47 35 bytes

-12 bytes gracias a H.PWiz (mejor forma de generar los puntos de codificación de la lista)!

F₅0
S?25>50+?←Lε`f`+Nm+3d4652893071

Pruébalo en línea!

Explicación

F₅0  -- input is a list of boolean lists
F    -- left fold by
 ₅   -- | the function flipped (overflowing label) on line 1
  0  -- | with initial value 0

S?25>50+?←Lε`f`+Nm+3d4652893071  -- example inputs: [0,0,0,1,0,0,0,0,0,0,0,0] 0
                     4652893071  -- integer literal: 4652893071
                    d            -- digits: [4,6,5,2,8,9,3,0,7,1]
                 m+3             -- map (+3): [7,9,8,5,11,12,6,3,10,4]
              `+N                -- append natural numbers: [7,9,8,5,11,12,6,3,10,4,1,2,3,...
            `f                   -- filter this list by argument: [5]
        ?  ε                     -- if it's of length 1
         ←                       -- | take first
          L                      -- | else the length
                                 -- : 5
       +                         -- add to argument: 5
 ?  >50                          -- if the value is > 50
  25                             -- | then 25
S                                -- | else the value
                                 -- : 5

¿Qué tal m+3d4652893071?
H.PWiz

1

Rojo , 189 172 bytes

func[b][s: 0 foreach c b[d: 0 foreach e c[if e = 1[d: d + 1]]i: find c 1
n: either i[pick[7 9 8 5 11 12 6 3 10 4 1 2]index? i][0]if 50 < s: s + either 1 < d[d][n][s: 25]]s]

Pruébalo en línea!

Explicación del código no golfizado:

f: func[b][                                            ; a block of blocks of booleans
    s: 0                                               ; sets sum to 0
    foreach c b[                                       ; for each row of booleans 
        d: 0 foreach e c[if e = 1[d: d + 1]            ; count the number of 1s         
        i: find c 1                                    ; the index of the first 1
        n: either i[pick [7 9 8 5 11 12 6 3 10 4 1 2]  ; if there is 1, pick the number
                    index? i][0]                       ; at the index of 1
                                                       ; otherwise 0  
        if 50 < s: s + either 1 < d[d][n][s: 25]       ; if there is only one 1, add 
                                                       ; the number to the sum, otherwise
                                                       ; the number of 1s 
                                                       ; if the sum > 50, reset it to 25 
    ]
    s                                                  ; return the sum 
]

1

JavaScript (ES6), 98 bytes

a=>a.map(b=>b.map((m,i)=>(c+=m,d+=m*('0x'+'7985bc63a412'[i])),c=d=0)|(t+=c>1?c:d)>50?t=25:0,t=0)|t

Casos de prueba:


Mismo tamaño que (y muy similar a) mi implementación de referencia . :)
Arnauld

Ah, guay. Estoy feliz cada vez que puedo coincidir con el tamaño de tu código. Solo una vez en una luna azul puedo vencerlo :)
Rick Hitchcock

0

Stax , 37 bytes

├T<↓"♥←~;▌6»≥øF←î5░U╚_π○Q▒<│∟└ù║pε♀▀æ

Ejecutar y depurarlo

Pruébalo en línea!

Explicación

F:1"=EA5MQ9-I1%)"!s@c%1={h+}{%+}?c50>{d25}{}?    # Full program, unpacked

F                                                # Loop through every element
 :1                                              # Get indices of truthy elements
   "=EA5MQ9-I1%)"!                               # Push encoded [7,9,8,5,11,12,6,3,10,4,1,2]
                 s@                              # Swap the top 2 elements of stack and get elements at indexes
                   c%1=                          # Copy the top element, get length of array, compare to length of 1
                       {h+}{%+}?                 # If it has length of 1, add the element, otherwise add the length of the array to total
                                 c50>            # Compare total to 50, 
                                     {d25}{}?    # If it is greater, pop it off and push 25 to reset counter, otherwise do nothing

No es mi mejor trabajo, pero funciona. Estoy seguro de que hay algo que me falta para hacerlo un poco más corto.


0

Python 2 , 109 105 103 bytes

c=0
for l in input():a=sum(l);c+=int('7985bc63a412'[l.index(1)],16)if a==1else a;c=(25,c)[c<51]
print c

Pruébalo en línea!

Alternativa sin una función recursiva.

-2 con agradecimiento a @Jo King


Puede quitar los corchetes alrededor del literal de la cadena
Jo King,
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.