L'aventure du golfeur - Chapitre 1: Le vase

13

L'aventure du golfeur

C'est le premier défi! Il y aura plus de défis plus tard qui nécessiteront des données du défi précédent :)

Chapitre 1: Le vase

Imaginons une minute .. Vous êtes un Dieu puissant, vos pouvoirs sont illimités mais nécessitent une chose: les âmes. Chaque âme est ici représentée par un octet, chaque octet que vous utilisez sacrifie une âme. Le but est donc évidemment de sauver le plus de monde possible tout en sacrifiant le moins d'âmes.

Votre premier défi est de sauver un petit village, le diable est prêt à ne pas détruire tout le village si vous résolvez son défi.

Le défi :

Vous avez un vase vertical qui peut contenir exactement 10 choses (Air inclus). Si vous mettez quelque chose dans ce vase, la gravité fera tomber cette chose au fond. Si le vase est déjà plein (et il est toujours plein si vous le considérez comme "plein d'air"), l'entrée remplacera l'élément en haut du vase.

Voici l'ensemble des choses autorisées:

  • Air 0 /
  • Un rocher 1 / -
  • Une feuille 2 / ~
  • Une bombe 3 / x

S'il y a un rocher ou une feuille au-dessus de "A Bomb", il explosera et détruira la chose au-dessus.

L'entrée est la liste des choses que vous mettrez dans le vase à chaque tour.

Exemple : 11231: Vous mettrez 2 pierres, puis une feuille, puis une bombe et enfin une dernière pierre.

Lorsque le vase est statique, vous pouvez commencer à compter avec la règle suivante:

  • Rock ajoute 1 unité à l'accumulateur
  • Leaf multiplie l'accumulateur par 2
  • Bombe décrémenter l'accumulateur de 1
  • L'air ne fait rien

(Vous devez commencer à compter à partir du haut du vase)

Voici la simulation que nous obtenons en utilisant "11231" en entrée:

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

Et la sortie sera 2 (calculée comme ((0 x 2) + 1) + 1) Pas besoin d'imprimer tous les états du vase!

Le programme de base (Python3)

Vous pouvez l'exécuter pour comprendre comment cela fonctionne.

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)

Version golfée (Python3, pas d'affichage Vase): 360 octets = 360 points

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 vous voulez tester si votre programme fonctionne correctement, vous pouvez tester cette entrée: 12122111131

La bonne réponse est 43 :) (Merci Emigna)

Maintenant pour les points:

  • (x) indique où: x est la quantité d'octets nécessaires pour écrire votre programme. Si vous répondez après la publication du prochain défi, les points de ce défi ne seront pas ajoutés à votre total de points.

Le but est de garder un minimum de points pendant tout le défi :) Si vous sautez l'une des parties du défi, vous aurez (wx + 1) points par défaut pour la partie sautée (où wx est le pire score) pour ce défi).

Données qui seront nécessaires pour le prochain défi:

Sortie lorsque entrée = 10100000200310310113030200221013111213110130332101

Champion actuel: Emigna

Bonne chance à tous !

Sygmei
la source
2
Quel est le "peut contenir exactement 10 choses"? "Air" compte-t-il comme une chose? L'entrée est-elle garantie d'être telle que le vase ne contiendra que 10 choses (je ne vois pas qu'il soit pris en compte dans la mise en œuvre de référence)? De plus, l'entrée qui produit les données pour le prochain défi semble avoir plus de 10 choses (même si l'air ne ressemble à rien et que les bombes explosent la chose suivante au-dessus de l'air, il y aura 14 choses, je pense).
Jonathan Allan
1
Une entrée 333construit un vase [0, 0, 0, 0, 0, 0, 0, 3, 3, 3]dans votre algorithme de golf et donc un score de -3, mais ne devrait-il pas en être [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]ainsi un score de -1selon vos spécifications?
Laikoni
2
@Laikoni J'ai oublié de préciser que les bombes n'explosent pas lorsqu'une bombe est au dessus d'une autre, merci!
Sygmei
1
La sortie pour 10100000200310310113030200221013111213110130332101 semble être de 22, non?
Erik the Outgolfer
2
Ajouter un cas de test délicat comme 12122111131 pourrait être une bonne idée.
Emigna

Réponses:

5

Python 2 - 208 191 185 180 172 164 156 octets

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

La panne est qu'il enlève de l'air et les bombes si elles sont sur la pile comptent alors.

EDIT: je suis passé à Python 2 pour enregistrer un octet, mais maintenant l'entrée doit être mise entre accolades comme '3312123'

EDIT2: Je suis également un peu fier du nombre d'accumulateurs

EDIT3: Merci pour toutes vos suggestions, je n'aurais jamais pensé que je pourrais l'obtenir si bas

Pâris Douady
la source
Belle première réponse! Je pensais aussi à Python mais à court de temps aujourd'hui. Je pense que tu aurais battu mon approche de toute façon.
ElPedro
Merci pour le gentil commentaire :) La première fois que je fais un golf de code et je dois dire que c'est assez amusant.
Pâris Douady
Utilisez t[:10][::-1]au lieu de reverse()pour enregistrer 4 octets et utilisez peut-être Python 2 pour enregistrer un support sur le print? Vient à 5 âmes de plus sauvées pour moi :)
ElPedro
Pas de Python2 pour moi car je devrais lancer input () pour que cela fonctionne, tuant 5 âmes de plus. Belle prise sur le [:: - 1]
Pâris Douady
btw, je n'ai rien vu dans la question qui dit que l'entrée peut «être entourée de guillemets. Dit simplement "L'entrée est la liste des choses". Fonctionne en Python 2 :)
ElPedro
4

05AB1E , 28 36 octets

05AB1E utilise le codage CP-1252 .

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

Essayez-le en ligne!

Emigna
la source
1
Impressionnant comme toujours: D Ce sera difficile à battre
Sygmei
2
T£ÀRS ->Des larmes ->je pleure 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

Merci à Pâris Douady pour la formule des points et pour avoir économisé 4 octets.

TFeld
la source
Avez-vous pris ma formule pour le comptage du point? Quoi qu'il en soit, belle solution, vous me battez et c'est beaucoup plus propre. vous pouvez également économiser quelques octets en faisant for c in input()directement
Pâris Douady
2

Javascript, 267 264 249 âmes sacrifiées

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}

Version modifiée, car la précédente était incorrecte pour les entrées plus importantes. Il a joué un peu plus loin en faisant string.prototype.replace()un appel de fonction accessible par la baie. Explication:

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');retourne 2. Essayez-le en ligne

steenbergh
la source
10100000200310310113030200221013111213110130332101 ne renvoie pas le bon résultat :) Vous êtes tout de même proche :)
Sygmei
@Sygmei Je sais, et j'en ai débogué la merde, mais je ne peux pas savoir pourquoi. Pouvez-vous me voir dans le chat?
steenbergh
1

Haskell, 221 202 181 177 177 166 octets d' âmes

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])%)

Essayez-le sur ideone . Prend les éléments sous forme de liste entière.

Usage:

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

(Édition: ancienne) Explication:

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
la source
Bon travail :) ! Quels sont les trois derniers "?
Sygmei
@Sygmei c'est deux chaînes f "0000000000" "", vous n'avez juste pas besoin d'espace entre elles. J'ai ajouté une explication au code.
Laikoni
Sympa, plus facile à comprendre maintenant :)
Sygmei