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 !


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


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



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.


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


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.