Terra Mystica: poder de ciclismo


28

El juego de mesa Terra Mystica tiene algunas mecánicas muy interesantes para uno de los principales recursos, el poder. En lugar de obtener y gastar unidades de poder de un banco, cada jugador comienza el juego con exactamente 12 unidades de poder que se distribuyen en tres "cuencos", que están etiquetados como I, II y III. Ganar y gastar poder simplemente cambia el poder entre estos cuencos:

  • Para gastar una unidad de poder, muévala del tazón III al tazón I (siempre que tenga una unidad en el tazón III).
  • Cuando ganes una unidad de poder, si hay una unidad en el tazón I, muévela al tazón II. Si no hay unidades en el recipiente I, pero hay una unidad en el recipiente II, muévala al recipiente III. Si todas las unidades ya están en el recipiente III, no pasa nada.
  • Cuando gana o gasta varias unidades a la vez, se procesan una unidad a la vez.

Aquí hay un ejemplo. Digamos, un jugador comienza con la siguiente distribución de poder (dada en orden I | II | III):

5 | 7 | 0

Su poder cambia de la siguiente manera si ganan y gastan poder varias veces:

               5 |  7 |  0
Gain  3  ==>   2 | 10 |  0
Gain  6  ==>   0 |  8 |  4   (move 2 power from I to II, 
                              then the remaining 4 from II to III)
Gain  7  ==>   0 |  1 | 11
Spend 4  ==>   4 |  1 |  7
Gain  1  ==>   3 |  2 |  7
Spend 7  ==>  10 |  2 |  0
Gain 12  ==>   0 | 10 |  2   (move 10 power from I to II,
                              then the remaining 2 from II to III)
Gain 12  ==>   0 |  0 | 12   (the two excess units go to waste)

Su tarea es calcular el resultado de uno de esos eventos de ganancia o gasto.

El reto

Te dan cuatro enteros como entrada. Los tres primeros, I, II, III, representan la cantidad de energía en cada uno de los tres tazones. No serán negativos y sumarán 12. El cuarto número, Pes la cantidad de poder ganado o gastado, y estará en el rango inclusivo [-III, 24](por lo que puede suponer que el jugador nunca intentará gastar más poder). de lo que pueden actualmente, pero podrían estar ganando más poder del que necesitan para mover todo el poder al bol III).

Puede tomar estos números en cualquier orden consistente, como argumentos separados, como una lista de enteros o como una cadena que contiene estos enteros. También se puede tomar Pcomo un argumento, como I, II, IIIcomo un argumento lista separada.

Usted debe de salida tres enteros I', II', III'que representan la cantidad de energía en cada plato después de P unidades se adquirieron o se gastan, siguiendo las reglas explicadas anteriormente.

Puede escribir un programa o una función y utilizar cualquiera de nuestros métodos estándar para recibir entradas y proporcionar salidas.

Puede usar cualquier lenguaje de programación , pero tenga en cuenta que estas lagunas están prohibidas por defecto.

Este es el , por lo que gana la respuesta válida más corta, medida en bytes .

Casos de prueba

I II III P => I' II' III'
5 7 0 3    => 2 10 0
2 10 0 6   => 0 8 4
0 8 4 7    => 0 1 11
0 1 11 -4  => 4 1 7
4 1 7 0    => 4 1 7
4 1 7 1    => 3 2 7
3 2 7 -7   => 10 2 0
10 2 0 12  => 0 10 2
0 10 2 12  => 0 0 12

1
Recomiendo eliminar los pronombres específicos de género y reemplazarlos por otros de género neutro (o reestructurar oraciones): los jugadores no tienen que ser hombres.
Greg Martin

1
@ GregMartin Por supuesto. ¿Los atrapé a todos?
Martin Ender

2
Mira eso; gracias por pensarlo! Además, ¿Terra Mystica es tan increíble como he escuchado?
Greg Martin

44
@GregMartin sí. :)
Martin Ender

55
¿No hay quemaduras de energía del tazón 2? Esto se siente tan incompleto.
moreON

Respuestas:


6

Mathematica, 52 bytes

{x=#-#4~Min~#,y=Max[#2+#-Abs[#4~Max~0-#],0],12-x-y}&

Esta es una función sin nombre que toma una lista {I, II, III, P}como entrada y devuelve una lista {I', II', III'}.

Una solución de forma cerrada. Realmente no se siente óptimo todavía ...


Pensé que podría acortar, pero {##,12-+##}&[#-#4~Min~#,Max[#2+#-Abs[#4~Max~0-#],0]]&es un byte más largo. Aunque me gusta 12-+##.
Greg Martin

1
@ GregMartin Intenté lo mismo :)
Martin Ender

6

C, 97 94 bytes

f(i,j,k,n){for(;n;n-=n/abs(n))n<0?k?++i+--k:0:i?++j+--i:j?++k+--j:0;printf("%d %d %d",i,j,k);}

En forma no golfista:

f(i, j, k, n) {
    while (n) {
        if (n < 0) {
            if (k) {
                ++i; --k;
            }
            ++n;
        } else {
            if (i) {
                ++j; --i;
            }
            else if (j) {
                ++k; --j;
            }
            --n;
        }
    }
    printf("%d %d %d", i, j, k);
}

5

Python 2, 104 bytes

def f(i,d,t,g):
 x=min(i,g);i-=x;q=g>0;g-=x
 if q:d+=x;x=min(d,g);g-=x;d-=x;t+=x
 else:t+=x
 print i,d,t

Pruébalo en línea

Sin golf:

def f(i,d,t,g):
 if g>0:
    x=min(i,g)
    g-=x
    i-=x
    d+=x    
    x=min(d,g)
    g-=x
    d-=x
    t+=x
 else:
    x=min(i,g)
    g-=x
    i-=x
    t+=x
 print(i,d,t)

5

Haskell, 58 bytes

f(a,b,c)d|m<-min a d,z<-min(c+d-max 0 m)12=(a-m,b+c+m-z,z)

El valor intermedio mdenota la cantidad de energía que va desde (o hacia, si es negativo) el primer tazón, zdenota la cantidad de energía en el tercer tazón después de la acción. Una optimización de un byte de último minuto cambió la antigua expresión para el segundo tazón de 12-a+m-zusar la identidad a+b+c=12.

El tipo de resultado natural es un triple para los tazones, por lo que la entrada también toma los tazones como un triple y el cambio de potencia como un segundo argumento. Esto permite manejar todos los casos de prueba con una aplicación de scanl:

*Main> scanl f (5,7,0) [3,6,7,-4,0,1,-7,12,12]
[(5,7,0),(2,10,0),(0,8,4),(0,1,11),(4,1,7),(4,1,7),(3,2,7),(10,2,0),(0,10,2),(0,0,12)]

5

Röda , 100 94 bytes

f a,b,c,p{{c+=p;a-=p}if[p<0]else{{a--;b++;p--}while[p*a>0];{b--;c++;p--}while[p*b>0]};[a,b,c]}

Sin golf:

f a,b,c,p {
    if [ p < 0 ] do
        c += p
        a -= p
    else
        { a-=1; b+=1; p-=1 } while [ p > 0 and a > 0 ]
        { b-=1; c+=1; p-=1 } while [ p > 0 and b > 0 ]
    done
    return a, b, c
}

¿Röda no tiene los operadores ++y --?
Kritixi Lithos

@KritixiLithos ¡Gracias! Si lo hace
fergusq


3

GNU sed , 66 bytes

Incluye +1 para -r

/-/!{:
s/1,(.* )1/,1\1/
t}
s/(.*)(1+) -\2/\2\1/
s/(,,1{12}).*/\1/

Utiliza unario (ver este consenso ).

Pruébalo en línea!

/-/!{                  # If there is not a '-'
  :                    # start loop
  s/1,(.* )1/,1\1/     # move a 1 from before a ',' to after the ',' for every 1 after the space
                       # sed reads left to right, so this takes everything from the first bowl before starting on the second
  t                    # loop if something changed
}                      # end if
s/(.*)(1+) -\2/\2\1/   # take all of the 1s from after a '-' and move them to the begining.
                       # at the same time, remove that many 1s from the 3rd bowl
s/(,,1{12}).*/\1/      # remove everything after 12 1s in the third bowl

3

Retina ,  46  41 39 38 bytes

Gracias a Martin Ender por múltiples sugerencias útiles!

+`1,(.*¶)1
,1$1
(.*)(1+)¶-\2$
$2$1
G`,

Toma entrada en unario. La primera línea contiene las cantidades de energía en los tres cuencos, separados por comas, la segunda línea la cantidad de energía para ciclar.

Banco de pruebas : toma todas las entradas en una sola línea y convierte de decimal a unario y viceversa para mayor comodidad de uso.

Explicación

+`1,(.*¶)1
,1$1

Caso positivo: eliminamos repetidamente el inicio 1de la segunda línea, y movemos un 1del primer tazón no vacío al siguiente, siempre que esta operación sea posible (es decir, el número de potencia para el ciclo no es cero y no todos el poder está en el tercer tazón). El smodificador significa single-line, lo .que permite coincidir también con la nueva línea.

(.*)(1+)¶-\2$
$2$1

Caso negativo: hecho todo en un solo paso, moviendo la cantidad de energía indicada por la última entrada desde el tercer al primer tazón. Esto también eliminará la línea que contiene la cantidad negativa de potencia para moverse.

G`,

Mantenga (grep) solo líneas que contengan una coma. Esto eliminará los eventuales restos de la primera línea.



2

Lote, 87 bytes

@set/a"i=%4-%1,j=%4*(-%4>>5)-%2-2*i*(-i>>5),i*=i>>5,j*=j>>5,k=12-i-j
@echo %i% %j% %k%

Use las siguientes fórmulas:

I' = min(I - P, 0)
II' = min(II + min(P, 0) - 2 * min(P - I, 0), 0)
III' = 12 - I' - II'

Como Batch no tiene un operador menor que, calculo i = min(-i, 0)usando i*=i>>5.


2

Perl 6 , 99 bytes

->\a,\b,\c,\d{d>0??[»+»] (a,b,c),|(|((-1,1,0)xx a),|((0,-1,1)xx a+b),|(0 xx*))[^d]!!(a- d,b,c+d)}

Sea a, by csea ​​el número de fichas iniciales en los tazones I, II y III, respectivamente. Luego, para el caso de poder adicional, se crea una lista que contiene acopias del triplete (-1, 1, 0), seguidas de a + bcopias del triplete (0, -1, 1), seguidas de infinitas copias de 0. Los primeros delementos de esta lista, que dson la cantidad de energía que se agrega, se agregan en forma de elementos a la distribución de energía inicial.

Para restar potencia (negativo d), se utiliza una forma cerrada simple: (a - d, b, c + d).


2

tinylisp , 134 bytes

(d f(q((x y z p)(i p(i(l p 0)(f(s x p)y(a z p)0)(i x(f(s x 1)(a y 1)z(s p 1))(i y(f x(s y 1)(a z 1)(s p 1))(f x y z 0))))(c x(c y(c z(

Define una función fque toma cuatro argumentos, los tres tazones ( x y z) y la cantidad de energía que se transmite ( p), y devuelve una lista de los tres tazones después de la transacción. Aquí hay una versión correctamente espaciada con todos los casos de prueba: ¡ Pruébelo en línea!

(d f                         Define f to be
 (q(                          a quoted two-item list (which acts as a function):
  (x y z p)                    Arglist: the three bowls x y z and power p
  (i p                         If p is nonzero
   (i (l p 0)                   then if p is negative (spending power)
    (f(s x p)y(a z p)0)          then take -p from z, add -p to x, and recurse with p=0
    (i x                         else (gaining power), if x is nonzero
     (f(s x 1)(a y 1)z(s p 1))    then take 1 from x, add to y, decrement p and recurse
     (i y                         else if y is nonzero
      (f x(s y 1)(a z 1)(s p 1))   then take 1 from y, add to z, decrement p and recurse
      (f x y z 0))))               else no moves possible; recurse with p=0
   (c x(c y(c z())))))))        else (p=0), cons x y z into a list and return it
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.