Простий симулятор Redstone


27

Redstone - це матеріал у грі Minecraft, і його використовують для багатьох складних випадків. Для цієї програми вам знадобиться лише імітувати три елементи: дріт з червоного каменю (відмічено з R), факел з червоного каменю (відмічено з T) та блок (відмічено з B).

Ось перелік основних правил щодо функціонування redstone:

A redstone torch sends power to any adjacent redstone wire.
TRRRR
 ^This redstone wire is powered.

Redstone wire can only hold power for 15 blocks.
TRRRRRRRRRRRRRRRR
                ^This last wire is unpowered, because the torch is >15 blocks away.

A block is said to be powered if a powered redstone wire is found adjacent to it.
TRRRB
    ^This block is powered.

If a block next to a redstone torch is powered, then the torch stops emitting power.
T
R
R
R
B <This block is powered.
T <This redstone torch does not emit power because of the block next to it.
R <This redstone is unpowered because the torch is not providing power.
R

Введення буде надано у двовимірних масивах розміром до 64х64, таким чином:

TRRR
   B
TBRTRR
R
RRRRRRRRR
        R
   RRRRRR

Гарантується, що на вході не буде жодних "годинників" або червоного каменю, що живиться від факела, що вказує на блок, на якому горить. У кожному вході буде лише одна схема червоного каменю.

Ваша програма повинна змінити кожен символ на 1 або 0, 1, вказуючи, чи цей елемент живиться / випромінює потужність, і 0, якщо він не працює / не випромінює живлення.

Цей вхід повинен мати такий вихід:

1111
   1
100000
1
111111111
        1
   001111

Це кодовий гольф, тому найкоротший код виграє, як завжди.


1
Якого результату ви очікуєте для таких ситуацій "TRR\nB B\nRRT"?
Говард

111\n0 1\n000- вихід; здається, це звучить у межах правил. Я поставлю обмеження на введення, кажучи, що у вас не може виникнути ситуацій, наприклад TRR B R RRR, коли воно блимає повторно.
beary605

1
Чи можемо ми припустити, що кожен вхідний масив буде містити лише одну повну ланцюг, що працює зверху вниз, як у вашому прикладі, або нам доведеться кодувати декілька окремих схем, починаючи з будь-якого місця в масиві?
Грем

@Graham: Буде лише одна схема червоного каменю для кожного входу.
beary605

1
Знаючи гру Minecraft, я думаю, що у вашому прикладі даний блок на лінії 2 не заважає сусідньому факелу подавати владу (червоний камінь насправді не підключається до блоку). Це помилка чи спрощене спрощення?
tomsmeding

Відповіді:


4

Хаскелл, 400

import Data.Char
import Data.List
f x=[(++[x]).tail,(x:).init]
h(' ':_)=' '
h('T':s)=if elem 'b's then 'T'else 't'
h('t':s)=h$'T':s
h('B':s)=if any(`elem`s)['e'..'s']then 'b'else 'B'
h('b':s)=h$'B':s
h(_:s)=max 'd'$chr$ord(maximum s)-1
o ' '=' '
o c|elem c"dTB"='0'
o _='1'
a=(map.map)o.(!!(64^2+16)).iterate(map(map h.transpose).transpose.(\l->[g l|g<-id:f(map(const ' ')$head l)++map map (f ' ')]))

map(map h.transpose).transpose.(\l->[g l|g<-id:f(map(const ' ')$head l)++map map (f ' ')])замінює кожну плитку списком із самим собою, за яким йдуть чотири сусіди, а потім картами, що через h. h говорить про кожну плитку як вона реагує на сусідів: Факели вимикаються ('T', а не 't'), коли поблизу є блок живлення ('b'), дроти ('d' для мертвих через 's') недосконало копіюють їхній найпотужніший сусід (хоча не може стати гіршим, ніж мертвий) тощо.

iterateПовторює цей крок, (!!(64^2+16))вириває ітерацію, при якій ациклічні схеми робляться конвергенційними, і я повністю написав це так, щоб дати інтуїтивно зрозумілий зв'язок, а не приземлятися на 400.


4

Пітон, 699

Це просто швидкий пропуск (зараз не вистачає часу). Можливо, це може використовувати набагато більше гольфу.

import sys
m=[list(x)for x in sys.stdin.read().split('\n')]
e=enumerate
S=set
s=lambda x:S([(r,c)for r,i in e(m)for c,j in e(i)if j==x])
q=S()
t=s('T')
b=s('B')
n=s('R')
def d(o,r,c,i,h,q):
 if i<0:return 0
 o[(r,c)]=1
 for p in[(r+1,c),(r-1,c),(r,c+1),(r,c-1)]:
  if p in q or(p in b and not(r,c)in n):continue
  if(r,c)in b and p in t-q:
   x=S([p])
   q|=x
   o[p]=0
   return 1
  if p in h or not p in o:continue
  h|=S([p])
  if not d(o,p[0],p[1],i-1,h,q):return 1
g=1
while g:
 o=dict(zip(b,[0]*len(b))+zip(n,[0]*len(n))+zip(q,[0]*len(q)))
 g=0
 for x,y in t:
  if not(x,y)in q and d(o,x,y,15,S(),q):g=1
for p in o.keys():m[p[0]][p[1]]=o[p]
print"\n".join(map(lambda x:"".join(map(str,x)),m))

Так, наприклад, ви можете використовувати f=setта створювати l=lambda x:zip(x,[0]*len(x)). Що ж, у вас все одно буде понад 700 символів. Крім того, ви залишили марний простір у ... or not (a,z)in o.
Морвен

Вам потрібен простір після вашої друкованої заяви?
Zacharý

@ZacharyT Ти маєш рацію. Спасибі!
ESultanik

Про це вже було сказано, але ви f=setхочете поголити кілька символів, і у вас є ще один марний персонаж @not (a,z)in o
Zacharý

Використовуйте вкладки І пробіли для економії відступу.
mbomb007

4

Python 2, 556 байт

c=' 0';L=len;M=map;q=list;r='B';s='16';t='T';u='0';E=enumerate
b=[q(M(lambda x:x+[u,s][x==t],q(w[:-1])))+[c]*(64-L(w))for w in open('redstone.txt')]
k=lambda h,l,z:max(q(M(lambda x:[int((x or c)[1:]),0][l^((x or c)[0]==h)],z)))
def v(d=0):
 for e,f in E(b):
    for g,G in E(f):z=[e!=0and b[e-1][g],g<L(f)-1and f[g+1],e<L(b)-1and b[e+1][g],g and f[g-1]];j=G;i=j[0]+str([[s,u][k(r,1,z)>0],4,4,k(t,0,z),0,max(1,k(r,0,z))-1][ord(j[0])%7]);b[e][g]=i;d=d|(i!=j)
 return d
while v():0
for f in b:print''.join(M(lambda j:[' ',`int(j[1:]!=u)`][j[0]!=' '],f))+'\n'

Побачити це в дії

  • Передбачає, що кожен рядок у вхідних кінцях закінчується новим рядком
  • Виходи через print()
  • Кожен рядок виводу закінчується великою кількістю пробілів та новим рядком

  • Збережено багато байтів завдяки @ mbomb007 (# 34718)
  • Збережено 1 байт завдяки @ZacharyT (# 55550)

Вам не потрібно мати введення та виведення файлів. Ви можете використовувати stdin та stdout, за допомогою input()та print. Також, str(int(bool(j[1:]!=u)))те саме, що `int(j[1:]!=u)`.
mbomb007

@ mbomb007 Ну, не зовсім, я все ще потребую str(, але хороший момент про bool(.
Quelklef

`x`(з використанням зворотних посилань, це псевдонім для repr) - це те саме, що str(x)(принаймні для малих цілих чисел. Це різне для певних об'єктів, довжин, генераторів тощо). Ще один гольф: if g!=0те саме, що if g. Ви також можете матиk=lambda h,l,z:max(...
mbomb007

@ mbomb007 Backticks не для Py3 , і у мене немає 2 на цьому ПК. Якщо я встановлю його або переключую комп’ютери, додам це, дякую.
Quelklef

1
Вам потрібен простір тут? print ''? Чи може бути print''?
Zacharý
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.