The Golfista Adventure - Capítulo 1: El jarrón

13

La aventura del golfista

Este es el primer reto ! Habrá más desafíos más adelante que requerirán datos del desafío anterior :)

Capítulo 1: El florero

Imaginemos un minuto ... Eres un Dios poderoso, tus poderes son ilimitados pero requieren una cosa: Almas. Cada alma está aquí representada por un byte, cada byte que usas sacrifica un alma. Entonces, el objetivo es obviamente salvar a la mayor cantidad de personas mientras se sacrifica la menor cantidad de almas.

Su primer desafío es salvar un pequeño pueblo, el diablo está dispuesto a no destruir todo el pueblo si resuelve su desafío.

El reto :

Tienes un jarrón vertical que puede contener exactamente 10 cosas (aire incluido). Si pones una cosa en ese jarrón, la gravedad hará que esa cosa caiga al fondo. Si el jarrón ya está lleno (y siempre está lleno si lo considera "lleno de aire"), la entrada reemplazará el elemento en la parte superior del jarrón.

Aquí está el conjunto de cosas permitidas:

  • Aire 0 /
  • Una roca 1 / -
  • Una hoja 2 / ~
  • Una bomba 3 / x

Si hay una roca o una hoja encima de "A Bomb", explotará y destruirá la cosa que está encima.

La entrada es la lista de las cosas que pondrás en el florero cada turno.

Ejemplo: 11231 : Pondrás 2 rocas, luego una hoja, luego una bomba y finalmente una última roca.

Cuando el florero es estático, puede comenzar a contar con la siguiente regla:

  • Rock agrega 1 unidad al acumulador
  • Leaf multiplica el acumulador por 2
  • Bomba disminuye el acumulador en 1
  • El aire no hace nada

(Debe comenzar a contar desde la parte superior del florero)

Aquí está la simulación que obtenemos usando "11231" como entrada:

|-|  |-|  |~|  |x|  |-|  | |  | |  | |  | |  | |  | |
| |  |-|  |-|  |~|  |x|  |-|  | |  | |  | |  | |  | |
| |  | |  |-|  |-|  |~|  |x|  |-|  | |  | |  | |  | |
| |  | |  | |  |-|  |-|  |~|  |x|  |-|  | |  | |  | |
| |  | |  | |  | |  |-|  |-|  |~|  |x|  |-|  | |  | |
| |  | |  | |  | |  | |  |-|  |-|  |~|  |x|  |-|  | |
| |  | |  | |  | |  | |  | |  |-|  |-|  |~|  |x|  | |
| |  | |  | |  | |  | |  | |  | |  |-|  |-|  |~|  |~|
| |  | |  | |  | |  | |  | |  | |  | |  |-|  |-|  |-|
| |  | |  | |  | |  | |  | |  | |  | |  | |  |-|  |-|

Y el resultado será 2 (calculado como ((0 x 2) + 1) + 1) ¡No es necesario imprimir todos los estados del florero!

El programa base (Python3)

Puede ejecutarlo para comprender cómo funciona.

def printVase(vase):
  for i in vase:
    if i == 1:
      print("|-|")
    elif i == 2:
      print("|~|")
    elif i == 3:
      print("|x|")
    else:
      print("| |")

def updateVase(vase):
  changed = False
  for i in range(len(vase), -1, -1):
    if i < len(vase) - 1:
      if vase[i+1] == 3 and vase[i] in [1,2]:
        vase[i], vase[i+1] = 0, 0
        changed = True
      if not vase[i+1] and vase[i] in [1, 2, 3]:
        vase[i], vase[i+1] = vase[i+1], vase[i]
        changed = True
  return changed

userInput = input("Vase : ")
vase = [0 for i in range(0, 10)]
oldVase = vase
while updateVase(vase) or userInput != "":
  if userInput != "":
    vase[0] = int(userInput[0])
  userInput = userInput[1::]
  printVase(vase)
  input()

accumulator = 0
for i in vase:
  if i == 1:
    accumulator += 1
  if i == 2:
    accumulator *= 2
  if i == 3:
    accumulator -= 1
print(accumulator)

Versión de golf (Python3, sin pantalla de florero): 360 bytes = 360 puntos

def u(v):
  c=0
  for i in range(len(v),-1,-1):
    if i<len(v)-1:
      if v[i+1]==3 and v[i]in[1,2]:v[i],v[i+1],c=0,0,1
      if not v[i+1]and v[i]in[1,2,3]:v[i],v[i+1],c=v[i+1],v[i],1
  return c
l,v=input(),[0 for i in range(0, 10)]
while u(v)or l!="":
  if l!="":v[0],l=int(l[0]),l[1::]
a=0
for i in v:
  if i==1:a+=1
  if i==2:a*=2
  if i==3:a-=1
print(a)

Si desea probar si su programa funciona correctamente, puede probar esta entrada: 12122111131

La respuesta correcta es 43 :) (Gracias Emigna)

Ahora para los puntos:

  • (x) puntos donde: x es la cantidad de bytes necesarios para escribir su programa. Si responde después de que se publique el próximo desafío, los puntos para este desafío no se agregarán a su cantidad total de puntos.

El objetivo es mantener una cantidad mínima de puntos durante todo el desafío :) Si omite una parte de la parte del desafío, tendrá (wx + 1) puntos por defecto para la parte omitida (donde wx es la peor puntuación) para ese desafío).

Datos que serán necesarios para el próximo desafío:

Salida cuando entrada = 10100000200310310113030200221013111213110130332101

Campeón actual: Emigna

Buena suerte a todos !

Sygmei
fuente
2
¿Qué pasa con el "puede contener exactamente 10 cosas"? ¿"Aire" cuenta como una cosa? ¿Se garantiza que la entrada sea tal que el jarrón solo contendrá 10 cosas (no veo que se atienda en la implementación de referencia)? Además, la entrada que produce los datos para el próximo desafío parece tener más de 10 cosas (incluso si el aire no se parece a nada y las bombas explotan la próxima cosa encima del aire, creo que habrá 14 cosas).
Jonathan Allan
1
Una entrada 333construye un jarrón [0, 0, 0, 0, 0, 0, 0, 3, 3, 3]en su algoritmo de golf y, por lo tanto, una puntuación de -3, pero ¿no debería ser [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]y luego una puntuación de -1acuerdo con su especificación?
Laikoni
2
@Laikoni Olvidé especificar que las bombas no explotan cuando una bomba está encima de otra, ¡gracias!
Sygmei
1
La salida para 10100000200310310113030200221013111213110130332101 parece ser 22, ¿verdad?
Erik the Outgolfer
2
Agregar un caso de prueba complicado como 12122111131 podría ser una buena idea.
Emigna

Respuestas:

5

Python 2 - 208 191 185 180 172 164 156 bytes

t=filter(bool,map(int,input()))
i=a=0
n=len(t)
while 0<n-1>i<11:
 if(t[i]>=3>t[i+1]):del t[i:i+2];i,n=0,n-2
 i+=1
for x in t[9::-1]:a+=a+x%2*(2-x-a)
print a

El desglose es que elimina el aire y las bombas si están en la pila cuentan.

EDITAR: Cambié a Python 2 para guardar un byte, pero ahora la entrada debe ponerse entre llaves como '3312123'

EDIT2: también estoy un poco orgulloso del conteo de acumuladores

EDITAR3: Gracias por todas sus sugerencias, nunca hubiera pensado que podría llegar tan bajo

Pâris Douady
fuente
Buena primera respuesta! Estaba pensando con Python también, pero hoy tengo poco tiempo. Creo que habrías superado mi enfoque de todos modos.
ElPedro
Gracias por el amable comentario :) La primera vez que estoy haciendo un código de golf y tengo que decir que es bastante divertido.
Pâris Douady
Use en t[:10][::-1]lugar de reverse()guardar 4 bytes y también puede usar Python 2 para guardar un soporte en el print? Viene a 5 almas más guardadas para mí :)
ElPedro
No tengo Python2 para mí, ya que tendría que lanzar input () para que funcione, matando a 5 almas más. Buena captura en el [:: - 1]
Pâris Douady
por cierto, no vi nada en la pregunta que diga que la entrada puede 'estar entre comillas. Simplemente dice "La entrada es la lista de las cosas". Funciona en Python 2 :)
ElPedro
4

05AB1E , 28 36 bytes

05AB1E utiliza la codificación CP-1252 .

Î0KDvT¹g‚£`sTØõ:žwõ:ì}ÁT£ÀRS"<>·"è.V

Pruébalo en línea!

Emigna
fuente
1
Impresionante como siempre: D Será difícil superar eso
Sygmei
2
T£ÀRS ->Lágrimas ->, estoy llorando bien ...
steenbergh
3

Python 2, 150 146 bytes

v=[]
s=0
for c in input():
 v=v[:9]
 if'0'==c:1
 elif 3 in v[-1:]and c in'21':v=v[:-1]
 else:v+=[int(c)]
for x in v[::-1]:s+=s+x%2*(2-x-s)
print s

Gracias a Pâris Douady por la fórmula de puntos y por guardar 4 bytes.

TFeld
fuente
¿Tomaste mi fórmula para contar los puntos? De cualquier manera, es una buena solución, me ganaste y es mucho más limpio. También puede guardar algunos bytes haciendo for c in input()directamente
Pâris Douady
2

Javascript, 267 264 249 almas sacrificadas

r='replace'
f=t=>{t=t[r](/0/g,'');while(/3[12]/.test(t.substring(0,10)))t=t[r](/3[12]/,'');
a=t.length-1;x=(t.substring(0,9)+(a>8?t[a]:'')).split('').reverse().join('');
c='c=0'+x[r](/1/g,'+1')[r](/2/g,';c*=2;c=c')[r](/3/g,'-1');eval(c);return c}

Versión editada, porque la anterior era incorrecta para entradas más grandes. Lo jugué un poco más al convertirlo string.prototype.replace()en una llamada de función a la que se accede a una matriz. Explicación:

f=t=>{                                  Function declaration, input t
t=t.replace(/0/g,'');                   Remove air
while(/3[12]/.test(t.substring(0,10)))  Look for bombs; not double bombs, and only in the first 10 chars
    t=t.replace(/3[12]/,'');            Detonate bombs. If this makes a new bomb fall into the vase, or
                                        a double bomb is now a single bomb, it'll detonate that bomb too.
x=(t.substring(0,9)+                    Fill the vase, take the first 9 items
    (t.length>9?t[t.length-1]:''))      If we have more than 9 items, then add the last one
    .split('').reverse().join('');      Flip the instruction string.
c='c=0'+x.replace(/1/g,'+1')            Replace each item with the proper instruction to the ACC
         .replace(/2/g,';c*=2;c=c')
         .replace(/3/g,'-1');
eval(c);return c}                       Eval to get the value of ACC and return it.

f('11231');vuelve 2. Pruébalo en línea

Steenbergh
fuente
10100000200310310113030200221013111213110130332101 no devuelve el buen resultado :) Sin embargo, estás cerca :)
Sygmei
@Sygmei Lo sé, y he estado depurando la basura, pero no puedo descubrir por qué. ¿Puedes verme en el chat?
steenbergh el
1

Haskell, 221 202181 177 166 almas bytes

g(0:r)=r++[0]
g(3:x:r)|0<x,x<3=0:0:g r|1<3=3:g(x:r)
g(x:r)=x:g r
g r=r
v%(x:r)=g(init v++[x])%r
v%[]|v==g v=foldr([id,(+)1,(*)2,(-)1]!!)0v|1<3=g v%[]
(([0..9]>>[0])%)

Pruébalo con ideone . Toma elementos como lista entera.

Uso:

*Prelude> (([0..9]>>[0])%) [1,2,1,2,2,1,1,1,1,3,1]
43

(Editar: antiguo) Explicación:

g [] = []                             -- g simulates gravity in the vase
g ('0':r) = r ++ "0"                  -- the first 0 from the bottom is removed
g ('3':x:r) | elem x "12" = "00"++g r -- if a 1 or 2 is on a bomb, explode 
            | True = '3' : g(x:r)     -- else continue
g (x:r) = x : g r                     -- no air and no bomb, so check next item

c x = [id,(+)1,(*)2,(-)1]!!(read[x])  -- map 0, 1, 2, 3 to their score functions

f v w (x:r) =                         -- v is the current vase state, w the previous one
               init v++[x]            -- replace last vase element with input
             g(init v++[x])           -- simulate one gravity step
           f(g(init v++[x]))v r       -- repeat, w becomes v
f v w[] | v==w =                      -- if the input is empty and vase reached a fixpoint
                 foldr c 0 v          -- then compute score 
        | True = f (g v) v []         -- else simulate another gravity step


vase input = f "0000000000" "" input  -- call f with empty vase, previous vase state and
                                      -- the input as string of numbers
Laikoni
fuente
Buen trabajo :) ! ¿Cuáles son los últimos tres "?
Sygmei
@Sygmei son dos cadenas f "0000000000" "", simplemente no necesitas espacios entre ellas. Agregué una explicación al código.
Laikoni
Agradable, más fácil de entender ahora :)
Sygmei