The Golfer Adventure - Rozdział 1: Wazon

13

Przygoda Golferów

To pierwsze wyzwanie! Później będzie więcej wyzwań, które będą wymagały danych z poprzedniego wyzwania :)

Rozdział 1: Wazon

Wyobraźmy sobie chwilę .. Jesteś potężnym Bogiem, twoje moce są nieograniczone, ale wymagają jednej rzeczy: Duszy. Każda dusza jest tutaj reprezentowana przez bajt, każdy używany bajt poświęca duszę. Zatem celem jest oczywiście uratowanie jak największej liczby ludzi przy jednoczesnym poświęceniu jak najmniejszej liczby dusz.

Twoim pierwszym wyzwaniem jest uratowanie małej wioski, diabeł chce nie zniszczyć całej wioski, jeśli rozwiążesz jego wyzwanie.

Wyzwanie :

Masz pionowy wazon, który może zawierać dokładnie 10 rzeczy (w tym powietrze). Jeśli umieścisz coś w wazonie, grawitacja sprawi, że spadnie on na dno. Jeśli wazon jest już pełny (i zawsze jest pełny, jeśli uważasz go za „pełen powietrza”), dane wejściowe zastąpią element na górze wazy.

Oto zestaw dozwolonych rzeczy:

  • Powietrze 0 /
  • Skała 1 / -
  • Liść 2 / ~
  • Bomba 3 / x

Jeśli na szczycie „Bomby” znajduje się kamień lub liść, eksploduje i zniszczy przedmiot na nim.

Dane wejściowe to lista rzeczy, które umieszczasz w wazonie za każdym razem.

Przykład: 11231 : Umieścisz 2 skały, potem liść, potem bombę i wreszcie ostatnią skałę.

Gdy wazon jest statyczny, możesz zacząć liczyć zgodnie z następującą zasadą:

  • Rock dodaje 1 jednostkę do akumulatora
  • Liść mnoży akumulator przez 2
  • Bomba obniża akumulator o 1
  • Powietrze nic nie robi

(Musisz zacząć liczyć od góry wazy)

Oto symulację, którą otrzymujemy, używając „11231” jako danych wejściowych:

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

Wyjście wyniesie 2 (obliczone jako ((0 x 2) + 1) + 1) Nie trzeba drukować wszystkich stanów wazonu!

Program podstawowy (Python3)

Możesz go wykonać, aby zrozumieć, jak to działa.

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)

Wersja golfowa (Python3, bez wyświetlacza wazowego): 360 bajtów = 360 punktów

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)

Jeśli chcesz sprawdzić, czy Twój program działa poprawnie, możesz przetestować to wejście: 12122111131

Prawidłowa odpowiedź to 43 :) (Dzięki Emigna)

Teraz punkty:

  • (x) punkty, w których: x jest liczbą bajtów potrzebną do napisania programu. Jeśli odpowiesz po opublikowaniu następnego wyzwania, punkty za to wyzwanie nie zostaną dodane do całkowitej liczby punktów.

Celem jest zachowanie minimalnej liczby punktów podczas całego wyzwania :) Jeśli pominiesz jedną z części wyzwania, domyślnie otrzymasz (wx + 1) punkty za pominiętą część (gdzie wx to najgorszy wynik dla tego wyzwania).

Dane, które będą wymagane do następnego wyzwania:

Wyjście, gdy wejście = 10100000200310310113030200221013111213110130332101

Obecny mistrz: Emigna

Powodzenia wszystkim !

Sygmei
źródło
2
Co oznacza „może zawierać dokładnie 10 rzeczy”? Czy „powietrze” ma znaczenie? Czy wkład jest gwarantowany w taki sposób, że wazon będzie zawierał tylko 10 rzeczy (nie widzę, żeby można go było znaleźć w referencyjnej implementacji)? Wydaje się, że również dane wejściowe, które generują dane do następnego wyzwania, zawierają więcej niż 10 rzeczy (nawet jeśli powietrze jest niczym i bomby wysadzają kolejną rzecz na powietrzu, myślę, że będzie 14 rzeczy).
Jonathan Allan
1
Dane wejściowe 333konstruują wazon [0, 0, 0, 0, 0, 0, 0, 3, 3, 3]w algorytmie golfowym, a więc wynik -3, ale czy nie powinien to być [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]wynik -1zgodny ze specyfikacją?
Laikoni
2
@Laikoni Zapomniałem sprecyzować, że bomby nie wybuchają, gdy bomba znajduje się na innej, dzięki!
Sygmei
1
Wyjście dla 10100000200310310113030200221013111213110130332101 wydaje się być 22, prawda?
Erik the Outgolfer
2
Dobrym pomysłem może być dodanie trudnej skrzynki testowej, takiej jak 12122111131 .
Emigna

Odpowiedzi:

5

Python 2 - 208 191 185 180 172 164 156 bajtów

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

Podział polega na tym, że usuwa powietrze i bomby, jeśli są na stosie, wtedy się liczy.

EDYCJA: Zamieniłem na Python 2, aby zapisać bajt, ale teraz dane wejściowe należy umieścić w nawiasach klamrowych, takich jak „3312123”

EDIT2: Jestem także trochę dumny z liczby akumulatorów

EDIT3: Dziękuję za wszystkie sugestie, których nigdy bym nie pomyślał, że mogę to osiągnąć tak nisko

Pâris Douady
źródło
Ładna pierwsza odpowiedź! Myślałem również o Pythonie, ale dzisiaj brakuje mi czasu. Myślisz, że i tak pokonasz moje podejście.
ElPedro
Dzięki za miły komentarz :) Po raz pierwszy uprawiam golfa kodowego i muszę powiedzieć, że to niezła zabawa.
Pâris Douady
Użyj t[:10][::-1]zamiast, reverse()aby zapisać 4 bajty, a także może użyć Python 2, aby zapisać nawias w print? Przychodzi jeszcze 5 dusz dla mnie uratowanych :)
ElPedro
Nie ma dla mnie Python2, ponieważ musiałbym użyć metody input (), aby str zadziałało, zabijając jeszcze 5 dusz. Niezły haczyk na [:: - 1]
Pâris Douady
btw, nie widziałem nic w pytaniu, które mówi, że dane wejściowe można zawrzeć w cudzysłów. Po prostu mówi „Dane wejściowe to lista rzeczy”. Działa w Python 2 :)
ElPedro
4

05AB1E , 28 36 bajtów

05AB1E wykorzystuje kodowanie CP-1252 .

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

Wypróbuj online!

Emigna
źródło
1
Imponujące jak zawsze: D Trudno będzie to pokonać
Sygmei
2
T£ÀRS ->Łzy ->płaczę w porządku ...
steenbergh
3

Python 2, 150 146 bajtów

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

Dzięki Pâris Douady za formułę punktów i za zaoszczędzenie 4 bajtów.

TFeld
źródło
Czy wziąłeś moją formułę do liczenia punktów? Tak czy inaczej fajne rozwiązanie, pokonałeś mnie i jest znacznie czystszy. możesz także zaoszczędzić trochę bajtów, wykonując for c in input()bezpośrednio
Pâris Douady,
2

JavaScript, 267 264 249 dusz poświęconych

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}

Wersja edytowana, ponieważ poprzednia była niepoprawna dla większych danych wejściowych. Grał w golfa nieco dalej, przekształcając się string.prototype.replace()w wywołanie funkcji dostępne w tablicy. Wyjaśnienie:

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');zwraca 2. Wypróbuj online

Steenbergh
źródło
10100000200310310113030200221013111213110130332101 nie zwraca dobrego wyniku :) Mimo wszystko jesteś blisko :)
Sygmei
@Sygmei Wiem i debugowałem z tego badziewia, ale nie wiem, dlaczego. Czy widzisz mnie na czacie?
steenbergh
1

Haskell, 221 202 181 177 166 bajtów dusz

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

Wypróbuj na ideone . Pobiera pozycje jako listę liczb całkowitych.

Stosowanie:

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

(Edytuj: stary) Objaśnienie:

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
źródło
Dobra robota :) ! Jakie są ostatnie trzy "?
Sygmei,
@Sygmei to dwa ciągi f "0000000000" "", po prostu nie potrzebujesz spacji między nimi. Dodałem wyjaśnienie do kodu.
Laikoni,
Miło, łatwiej zrozumieć teraz :)
Sygmei,