Simulateur de redstone simple

27

Redstone est un matériau du jeu Minecraft, et il est utilisé pour de nombreux engins complexes. Pour ce programme, vous n'aurez qu'à simuler trois éléments: le fil de redstone (noté avec R), la torche de redstone (noté avec T) et le bloc (noté avec B).

Voici une liste de règles de base sur le fonctionnement de 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

L'entrée sera donnée dans des tableaux bidimensionnels jusqu'à une taille de 64x64, comme ceci:

TRRR
   B
TBRTRR
R
RRRRRRRRR
        R
   RRRRRR

Il est garanti que l'entrée n'aura aucune "horloge" ou redstone alimentée par une torche pointant vers le bloc sur lequel la torche est allumée. Il n'y aura qu'un seul circuit redstone dans chaque entrée.

Votre programme doit changer chaque caractère en 1 ou en 0, 1 indiquant si cet élément est alimenté / émettant de la puissance, et 0 s'il n'est pas alimenté / n'émettant pas de puissance.

Cette entrée doit avoir cette sortie:

1111
   1
100000
1
111111111
        1
   001111

C'est un code-golf, donc le code le plus court gagne, comme toujours.

beary605
la source
1
Quelle sortie attendez-vous pour des situations comme "TRR\nB B\nRRT"?
Howard
111\n0 1\n000est la sortie; cela semble être conforme aux règles. Je mettrai une restriction d'entrée disant que vous ne pouvez pas avoir de situations comme TRR B R RRR, où il clignote à plusieurs reprises.
beary605
1
Pouvons-nous supposer que chaque tableau d'entrée ne contiendra qu'un seul circuit complet allant de haut en bas comme dans votre exemple ou devons-nous coder pour plusieurs circuits séparés commençant n'importe où dans le tableau?
Graham
@Graham: Il n'y aura qu'un seul circuit redstone pour chaque entrée.
beary605
1
Connaissant le jeu Minecraft, je pense que dans votre exemple, le bloc de la ligne 2 n'empêche pas la torche adjacente de donner du pouvoir (la redstone ne se connecte pas réellement au bloc). Est-ce une erreur ou une simplification voulue?
tomsmeding

Réponses:

4

Haskell, 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 ' ')])remplace chaque tuile par une liste d'elle-même suivie de ses quatre voisins, puis la transforme en h. h indique pour chaque tuile comment il réagit aux voisins: les torches s'éteignent ('T' plutôt que 't') quand il y a un bloc d'alimentation ('b') à proximité, les fils ('d' pour dead through 's') copient imparfaitement leur voisin le plus puissant (bien qu'il ne puisse pas être pire que mort), etc.

iteraterépète cette étape, (!!(64^2+16))arrache une itération à laquelle les circuits acycliques se font converger, et je l'ai totalement écrit comme ça pour donner une limite intuitive, pas pour atterrir à 400.

Gurkenglas
la source
4

Python, 699

Ceci est juste un passage rapide (a manqué de temps pour l'instant). Il peut probablement utiliser beaucoup plus de golf.

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))
ESultanik
la source
Oui, par exemple, vous pouvez utiliser f=setet créer un fichier l=lambda x:zip(x,[0]*len(x)). Eh bien, vous auriez encore plus de 700 caractères. De plus, vous avez laissé un espace inutile à ... or not (a,z)in o.
Morwenn
Avez-vous besoin d'espace après votre relevé d'impression?
Zacharý
@ZacharyT Vous avez raison. Merci!
ESultanik
Cela a déjà été dit, mais f=setcela raserait quelques caractères, et vous avez un autre personnage inutile @not (a,z)in o
Zacharý
Utilisez des tabulations ET des espaces pour réaliser des économies d'indentation.
mbomb007
4

Python 2, 556 octets

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'

Voyez-le en action

  • Suppose que chaque ligne en entrée se termine par une nouvelle ligne
  • Sorties via print()
  • Chaque ligne de sortie se termine par de nombreux espaces et une nouvelle ligne

  • Beaucoup d'octets enregistrés grâce à @ mbomb007 (# 34718)
  • 1 octet enregistré grâce à @ZacharyT (# 55550)
Quelklef
la source
Vous n'êtes pas obligé d'avoir une entrée et une sortie via des fichiers. Vous pouvez utiliser stdin et stdout, avec input()et print. En outre, str(int(bool(j[1:]!=u)))c'est la même chose que `int(j[1:]!=u)`.
mbomb007
@ mbomb007 Eh bien, pas tout à fait, j'ai toujours besoin du str(, mais bon point à propos bool(.
Quelklef
`x`(en utilisant des raccourcis, c'est un alias pour repr) est identique à str(x)(pour les petits entiers, au moins. C'est différent pour certains objets, longs, générateurs, etc.). Un autre golf: if g!=0est le même que if g. Vous pouvez également avoirk=lambda h,l,z:max(...
mbomb007
@ mbomb007 Les backticks ne sont pas pour Py3 , et je n'en ai pas 2 sur ce pc. Si je l'installe ou que je change d'ordinateurs, j'ajouterai cela, merci.
Quelklef
1
Avez-vous besoin d'espace ici? print ''? Serait-ce possible print''?
Zacharý