Пригода гольфіста - Глава 1: Ваза


13

Пригода гольфіста

Це перший виклик! Пізніше буде більше викликів, які потребуватимуть даних попереднього виклику :)

Глава 1: Ваза

Давайте уявимо хвилинку .. Ви - потужний Бог, ваші сили безмежні, але потребуєте одного: Душі. Кожна душа тут представлена ​​байтом, кожен байт, який ви використовуєте, приносить в жертву душу. Отже, мета, очевидно, врятувати найбільшу кількість людей, при цьому жертвуючи найменшою кількістю душ.

Ваше перше завдання - врятувати маленьке село, чорт готовий не знищити все село, якщо ви вирішите його виклик.

Змагання :

У вас є вертикальна ваза, яка може містити рівно 10 речей (включено повітря). Якщо ви покладете річ у цю вазу, гравітація змусить цю річ впасти на дно. Якщо ваза вже заповнена (і вона завжди повна, якщо ви вважаєте її "повною повітря"), введення замінить елемент у верхній частині вази.

Ось набір дозволених речей:

  • Повітря 0 /
  • Скеля 1 / -
  • Листок 2 / ~
  • Бомба 3 / x

Якщо на вершині "Бомби" є скеля або лист, вона вибухне і знищить річ на її вершині.

Вхід - це список речей, які ви будете ставити у вазу щоразу.

Приклад: 11231: Ви покладете 2 скелі, потім листок, потім бомбу і нарешті останню скелю.

Коли ваза статична, ви можете почати рахувати за наступним правилом:

  • Рок додає 1 одиницю до акумулятора
  • Лист помножує акумулятор на 2
  • Зниження бомби акумулятора на 1
  • Повітря нічого не робить

(Почати рахувати потрібно з верхньої частини вази)

Ось моделювання, яке ми отримуємо, використовуючи "11231" як вхід:

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

А вихід буде 2 (розраховано як ((0 x 2) + 1) + 1) Не потрібно друкувати всі стани вази!

Базова програма (Python3)

Ви можете виконати його, щоб зрозуміти, як це працює.

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)

Версія для гольфу (Python3, без відображення вази): 360 байт = 360 балів

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)

Якщо ви хочете перевірити, чи правильно працює ваша програма, ви можете перевірити цей вхід: 12122111131

Правильна відповідь - 43 :) (Спасибі Емінья)

Тепер для балів:

  • (x) точки, де: x - кількість байтів, необхідних для написання вашої програми. Якщо ви відповісте після наступного виклику, бали за цей виклик не додаватимуться до вашої загальної суми балів.

Мета - зберегти мінімальну кількість балів протягом усього виклику :) Якщо ви пропустите одну з частин виклику, у вас буде (wx + 1) балів за промовчанням за пропущену частину (де wx - найгірший бал для цього виклику).

Дані, необхідні для наступного виклику:

Вихід при вході = 10100000200310310113030200221013111213110130332101

Поточний чемпіон: Емінья

Успіхів усім!


2
Що з "може містити рівно 10 речей"? Чи вважає "Повітря" річ? Чи гарантовано вхід такий, що ваза буде містити лише 10 речей (я не бачу, щоб це було задоволено у посиланні)? Крім того, на вході, який видає дані для наступного виклику, здається, є більше ніж 10 речей (навіть якщо повітря не схоже ні на що, а бомби підірвуть наступну річ, то, думаю, буде 14 речей).
Джонатан Аллан

1
Вхід 333будує вазу [0, 0, 0, 0, 0, 0, 0, 3, 3, 3]в алгоритмі гольфу і, отже, бал -3, але чи не повинен бути, [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]а потім оцінка -1відповідно до вашої специфікації?
Лайконі

2
@Laikoni Я забув вказати, що бомби не вибухають, коли бомба поверх іншої, дякую!
Сигмей

1
Виробник для 10100000200310310113030200221013111213110130332101 здається 22, правда?
Ерік Атголфер

2
Додавання складної тестової справи на зразок 12122111131 може бути хорошою ідеєю.
Емінья

Відповіді:


5

Пітон 2 - 208 191 185 180 172 164 156 байт

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

Поломка полягає в тому, що вона видаляє повітря, а бомби, якщо вони знаходяться на стеці, тоді враховуються.

EDIT: я помінявся на Python 2, щоб зберегти байт, але тепер введення потрібно поставити в дужки типу "3312123"

EDIT2: Я також якось пишаюся кількістю акумуляторів

EDIT3: Дякую за всі ваші пропозиції, я б ніколи не думав, що можу це зробити так низько


Приємна перша відповідь! Я думав і з Python, але сьогодні не вистачає часу. Думаю, ти все одно побив би мій підхід.
ElPedro

Дякую за добрий коментар :) Вперше я роблю гольф з кодом, і я можу сказати, що це дуже весело.
Pâris Douady

Використовуйте t[:10][::-1]замість того, reverse()щоб зберегти 4 байти, а також, можливо, використовуйте Python 2, щоб зберегти дужку на print? Приходить до 5 врятованих для мене душ :)
ElPedro

Немає Python2 для мене, оскільки мені доведеться подати input () на str, щоб він працював, вбиваючи ще 5 душ. Гарний вилов на [:: - 1]
Парі Дуді

btw, я нічого не бачив у запитанні, яке говорить про те, що введення можна «загорнути в лапки. Просто сказано "Вхід - це список речей". Працює в Python 2 :)
ElPedro



3

Python 2, 150 146 байт

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

Дякуємо Парісу Дуаді за формулу очок та за економію 4 байтів.


Ви взяли мою формулу для підрахунку пункту? У будь-якому випадку приємне рішення, ви побили мене, і це набагато чистіше. також ви можете зберегти кілька байтів, зробивши for c in input()безпосередньо
Pâris Douady

2

Javascript, принесено в жертву 267 264 249 душ

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}

Відредагована версія, оскільки попередня версія була невірною для великих входів. Полезний у гольф трохи далі, здійснюючи string.prototype.replace()виклик функції з масивом. Пояснення:

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');повертає 2. Спробуйте в Інтернеті


10100000200310310113030200221013111213110130332101 не повертає хорошого результату :) Хоча ти близький :)
Сигмей

@Sygmei Я знаю, і я налагоджував лайно з цього, але не можу дізнатися чому. Ви можете бачити мене в чаті?
steenbergh

1

Haskell, 221 202 181 177 166 душ байтів

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

Спробуйте це на ideone . Приймає елементи як цілий список.

Використання:

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

(Редагувати: Старе) Пояснення:

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

Хороша робота :) ! Які останні три "?
Sygmei

@Sygmei це два рядки f "0000000000" "", просто не потрібно між ними пробілів. Я додав пояснення до коду.
Лайконі

Приємно, простіше зрозуміти зараз :)
Sygmei
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.