A aventura do jogador de golfe - Capítulo 1: O vaso

13

The Golffer Adventure

Este é o primeiro desafio ! Mais tarde haverá mais desafios que exigirão dados do desafio anterior :)

Capítulo 1: O Vaso

Vamos imaginar um minuto. Você é um Deus poderoso, seus poderes são ilimitados, mas exigem uma coisa: Almas. Cada alma é aqui representada por um byte, cada byte que você usa sacrifica uma alma. Portanto, o objetivo é obviamente salvar a maior quantidade de pessoas, sacrificando a menor quantidade de almas.

Seu primeiro desafio é salvar uma pequena vila, o diabo está disposto a não destruir a vila inteira se você resolver o desafio dele.

O desafio :

Você tem um vaso vertical que pode conter exatamente 10 itens (incluindo ar). Se você colocar uma coisa nesse vaso, a gravidade fará com que ela caia no fundo. Se o vaso já estiver cheio (e sempre cheio, se você o considerar como "cheio de ar"), a entrada substituirá o elemento na parte superior do vaso.

Aqui está o conjunto de coisas permitidas:

  • Ar 0 /
  • Uma pedra 1 / -
  • Uma folha 2 / ~
  • Uma bomba 3 / x

Se houver uma pedra ou uma folha em cima de "A Bomb", ela explodirá e destruirá a coisa em cima dela.

A entrada é a lista das coisas que você colocará no vaso a cada turno.

Exemplo: 11231: Você colocará 2 pedras, depois uma folha, depois uma bomba e finalmente uma última pedra.

Quando o vaso é estático, você pode começar a contar com a seguinte regra:

  • Rock adiciona 1 unidade ao acumulador
  • Folha multiplica o acumulador por 2
  • Bomba decrementa o acumulador em 1
  • O ar não faz nada

(Você precisa começar a contar a partir do topo do vaso)

Aqui está a simulação que obtemos usando "11231" como entrada:

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

E a saída será 2 (calculada como ((0 x 2) + 1) + 1) Não há necessidade de imprimir todos os estados do vaso!

O programa base (Python3)

Você pode executá-lo para entender como 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)

Versão em golfe (Python3, sem exibição de vaso): 360 bytes = 360 pontos

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)

Se você deseja testar se o seu programa funciona corretamente, você pode testar esta entrada: 12122111131

A resposta correta é 43 :) (Obrigado Emigna)

Agora, para os pontos:

  • (x) pontos em que: x é a quantidade de bytes necessários para escrever seu programa. Se você responder após o lançamento do próximo desafio, os pontos desse desafio não serão adicionados à sua quantidade total de pontos.

O objetivo é manter uma quantidade mínima de pontos durante todo o desafio :) Se você pular uma parte do desafio, terá (wx + 1) pontos por padrão para a parte ignorada (onde wx é a pior pontuação para esse desafio).

Dados que serão necessários para o próximo desafio:

Saída quando entrada = 10100000200310310113030200221013111213110130332101

Campeão atual: Emigna

Boa sorte a todos !

Sygmei
fonte
2
O que há com o "pode ​​conter exatamente 10 coisas"? "Air" conta como uma coisa? A entrada é garantida para ser tal que o vaso contenha apenas 10 coisas (não a vejo atendida na implementação de referência)? Além disso, a entrada que produz os dados para o próximo desafio parece ter mais de 10 coisas (mesmo que o ar seja como nada e as bombas explodam a próxima coisa em cima do ar, haverá 14 coisas, eu acho).
Jonathan Allan
1
Uma entrada 333constrói um vaso [0, 0, 0, 0, 0, 0, 0, 3, 3, 3]no seu algoritmo de golfe e, portanto, uma pontuação de -3, mas não deveria ser [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]e então uma pontuação de -1acordo com sua especificação?
Laikoni
2
@Laikoni Eu esqueci de especificar que as bombas não explodem quando uma bomba está em cima de outra, obrigado!
Sygmei
1
A saída para 10100000200310310113030200221013111213110130332101 parece ser 22, certo?
Erik the Outgolfer
2
Adicionar um caso de teste complicado como 12122111131 pode ser uma boa ideia.
Emigna

Respostas:

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

O problema é que ele remove o ar e as bombas, se estiverem na pilha, contam.

EDIT: Eu troquei para Python 2 para salvar um byte, mas agora a entrada deve ser colocada entre chaves como '3312123'

EDIT2: Também estou orgulhoso da contagem do acumulador

EDIT3: Obrigado por todas as suas sugestões, eu nunca teria pensado que poderia obtê-lo tão baixo

Pâris Douady
fonte
Boa primeira resposta! Eu estava pensando com Python também, mas com pouco tempo hoje. Acho que você teria derrotado minha abordagem de qualquer maneira.
ElPedro
Obrigado pelo gentil comentário :) Na primeira vez que estou fazendo um código de golfe, devo dizer que é bem divertido.
Pâris Douady 24/11
Use em t[:10][::-1]vez de reverse()salvar 4 bytes e talvez também use Python 2 para salvar um colchete no print? Trata de mais 5 almas salvas para mim :)
ElPedro
Nenhum Python2 para mim, pois eu teria que lançar input () para str para que ele funcionasse, matando mais 5 almas. Boa captura no [:: - 1]
Pâris Douady 24/11
Aliás, eu não vi nada na pergunta que diz que a entrada pode 'ser colocada entre aspas. Apenas diz "A entrada é a lista das coisas". Obras em Python 2 :)
ElPedro
4

05AB1E , 28 36 bytes

05AB1E usa a codificação CP-1252 .

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

Experimente online!

Emigna
fonte
1
Impressionante como sempre: D Vai ser difícil de bater que
Sygmei
2
T£ÀRS ->Lágrimas ->, estou chorando ...
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

Obrigado a Pâris Douady pela fórmula de pontos e por salvar 4 bytes.

TFeld
fonte
Você tomou minha fórmula para a contagem do ponto? De qualquer maneira, uma solução agradável, você me vence e é muito mais limpo. também você pode economizar alguns bytes fazendo for c in input()diretamente
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}

Versão editada, porque a anterior estava incorreta para entradas maiores. Jogou um pouco mais longe ao fazer string.prototype.replace()uma chamada de função acessada por matriz. Explicação:

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');retorna 2. Experimente online

steenbergh
fonte
10100000200310310113030200221013111213110130332101 não retorna o resultado bom :) Você está perto embora :)
Sygmei
@ Sygmei eu sei, e venho depurando tudo isso, mas não consigo descobrir o porquê. Você pode me ver no chat?
steenbergh
1

Haskell, 221 202 181 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])%)

Experimente em ideone . Leva itens como lista inteira.

Uso:

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

(Edit: Old) Explicação:

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
fonte
Bom trabalho :) ! Quais são os três últimos "?
Sygmei 25/11
@ Sygmei são duas strings f "0000000000" "", você simplesmente não precisa de espaços entre elas. Eu adicionei uma explicação para o código.
Laikoni
Agradável, mais fácil de entender agora :)
Sygmei