Minecraft Göğüs Yerleşimi


20

Minecraft video oyunu tamamen sanal dünyayı oluşturan 3D tamsayı kafese farklı blok türlerini yerleştirmek ve kaldırmakla ilgilidir . Her kafes noktası tam olarak bir blok içerebilir veya boş olabilir ( resmi olarak bir " hava " bloğu). Bu meydan okumada, 3D dünyasının sadece bir yatay 2D düzlemi ve bir tür blokla ilgileneceğiz: sandıklar .

Sandıklar oyuncuların eşyaları saklamasına izin verir. İki göğüs aynı yatay düzlemde dik olarak bitişik olduğunda, dokuları birbirine bağlanır ve iki kat kapasite formlu bir çift göğüs. Çift göğüsten daha büyük bir şey yapılamaz; üçlü sandık veya dörtlü sandık yoktur.

Bir göğüs bloğu, ancak dikey olarak bitişik dört noktasının tümü boşsa veya tam olarak biri zaten bir çift göğsün parçası olmayan bir göğüs bloğu içeriyorsa boş bir kafes noktasına yerleştirilebilir. Bu yerleştirme kuralları, hangi göğüs bloklarının çift sandık oluşturmak üzere bağlandığı konusunda hiçbir belirsizlik olmamasını sağlar.

Örneğin ., boş alan ve Cbir sandık olduğunu varsayalım : (Sayılar da boş alan ve sadece tanımlama amaçlıdır.)

.......C..
.1.C2.C3..
........5C
.CC4..CC..
..........
  • Bir komşu boş olduğu için 1. noktaya bir göğüs yerleştirilebilir.
  • Komşu göğüs bir çift göğsün (henüz) bir parçası olmadığı için 2. noktaya bir göğüs yerleştirilebilir.
  • Bir göğüs nokta 3'e konulamaz, çünkü çift göğsün nasıl oluştuğuna dair bir belirsizlik olacaktır.
  • Komşu göğüs zaten bir çift göğsün parçası olduğu için 4. noktaya bir göğüs yerleştirilemez.
  • 5. noktaya bir göğüs yerleştirilebilir. Çapraz olarak komşu çift göğüs hiçbir şeyi etkilemez.

Izgara ötesindeki alanın boş olduğu varsayılarak, bir göğüs yerleştirilebiliyorsa .ızgaradaki her birinin bir olarak değiştirilmesi *, bununla sonuçlanır:

******.C**
***C**C.**
*..***..*C
.CC.*.CC.*
*..***..**

Tüm *alanlar aynı anda sandıklarla dolu olmayabilir, ancak sadece bir göğsünüz varsa, bunlardan herhangi birine yerleştirilebilir.

Meydan okuma

Bir de götüren bir program veya fonksiyon yazın .ve Cızgara ve her değiştirir .a *bir göğüs baskı ya çıkan ızgara dönen, orada yerleştirilebilir eğer.

  • Girdi stdin'den veya bir dosyadan veya bir işleve dize bağımsız değişkeni olarak olabilir.

  • Girdinin iyi biçimlendirildiğini varsayabilirsiniz - yani en az 1 karakter genişliğinde ve uzunluğunda, sadece dikdörtgen bir metin ızgarası, yalnızca içeren .ve Cİsteğe bağlı olarak son satırdan sonra bir satırsonu olduğunu varsayabilirsiniz (ve çıktıda bir satır olabilir) ).

  • Girdi içindeki sandıkların düzeninin yukarıdaki kurallara uygun olduğunu varsayabilirsiniz. Hangi sandıkların çift sandık oluşturduğu konusunda hiçbir zaman belirsizlikler olmayacaktır.

  • İstenirse, herhangi üç farklı kullanabilir yazdırılabilir ASCII yerine karakterler ., Cve *. Yeni satırların yerine başka bir şey kullanamazsınız.

  • Bütün sandıklar normal sandıklardır. Değil sandıkları sıkışıp veya ender sandıkları .

puanlama

En az bayt içeren gönderim kazanır.

Minecraft ile ilgili biraz daha zorlayıcı bir meydan okuma için Nether Portal Detection'ı deneyin .


5
Minecrafting açısından, bu oldukça sinir bozucu oyunda buldum. İyi bir şey sıkışmış sandıklar var: P
Sp3000

Stdin'den veya tek bir dize bağımsız değişkeninden ızgara girişi alırken, ızgara boyutlarını ek bir girdi olarak almak kabul edilebilir mi? veya yeni satırlardan ve dize uzunluğundan çıkarılması mı gerekiyor?
Level River St

@steveverrill Çıkarılmalıdır.
Calvin'in Hobileri

Sadece merakımdan, neden benim dahil her cevabın bir aşağı oyu var? Sadece aynı kişi olduğunu varsayabilirim, açıklamak ister mi?
Level River St

Ekstra bir meydan okuma için, sandıklar için en uygun yerleşimi bulmak için bir program yazılabilir; yani, yeni sandıklar arasında bile kuralları ihlal etmeden maksimum sayıda ek sandığın yerleştirilmesine izin veren bir yapılandırma bulun.
AJMansfield

Yanıtlar:


11

CJam, 82 76 66 62 58 54 bayt

qN/::~4{[8_]f/[9_]f*z{[{1$8-g)+}*]W%}%}*{_8<\2<8?}f%N*

Girdi formatı 0hava hücresi ve 8bir göğüs hücresi bekler . Çıktı, 1Göğüs ile yerleştirilebilen tüm hücreleri içerir .

GÜNCELLEME : Bir hata düzeltildi. 3 bayt artırıldı :( daha fazla golf :). @ Sp3000 sayesinde 4 bayt kaydedildi

Örnek girdi:

0000000800
0008008000
0000000008
0880008808
0000000000

Çıktı:

1111110811
1110018010
1008800108
0880088008
1008800110

Sanırım şimdilik golf yaptım ...

açıklama

qN/::~                   "This part converts the input into array of integer array";
qN/                      "Split input on new line";
   ::~                   "Parse each character in each row as integer";

4{[8_]f/[9_]f*z{[{1$8-g)+}*]W%}%}*

4{   ...z{       W%}%}*  "Run the logic 4 times, first, columns in correct order, then,";
                         "columns in reverse order, then for rows";
  [8_]f/[9_]f*           "Convert adjacent chests represented by two 8 into two 9";
                         "This happens for all the rows in the columns iterations and";
                         "for all the columns in the rows iterations";
  {               }%     "For each row/column";
   [{        }*]         "Reduce and wrap it back in the array";
     :I8-                "Store the second number in I, remove 8 from it";
         g               "Do signum. Now we have -1 for < 8 number, 0 for 8 and 1 for > 8";
          )+I            "Increment to get 0, 1 & 2. Add it to first number and put I back";

{_8<\2<8?}f%N*           "This part converts the output from previous iterations";
                         "to 3 character based final output and prints it";
{        }f%             "Map each row using the code block";
 _8<   8?                "If the value is greater than 7, make it 8, else:";
    \2<                  "If the value is greater than 1, make it 0, else 1";
            N*           "Join the arrays using new line";

Buradan çevrimiçi deneyin


8

.NET Normal İfade ( Retina ), 434 416 310 + 1 = 311 bayt

Regex'te cevapladığım son meydan okumadan sonra (bu meydan okumaya bağlı Nether Portal Challenge), sonunda .NET tarzı düzenli ifadeler için bir tercüman olarak görev yapan bir komut satırı aracı yazmaya başladım, böylece soruları cevaplayabilirim tek başına bir dil olmadıklarına meydan okunmadan normal ifadeyle. Retina adını verdim.

Şimdi, bu meydan okuma normal ifade gönderimi için çok iyi borç vermiyor, ama şimdi Retina'yı kullanmak zorunda kaldım. ;) (Artı, Sp3000 sohbet etmem için beni zorladı.) İşte burada:

Normal ifade dosyası

m`(?<=(?=.(.)*).*)(?<=((?<=(?<2>C|C(?(1)!)(\n|(?<-1>.))*)?)C(?=(?<2>C|(\n|(?<-1>.))*(?(1)!)C)?)(()(?(6)!)|(?<=^(?(7)!)(?<-7>.)*C).*\n(.)*()(?(8)!)))?){2}_(?=(?<2>((?(10)!)()|(?(11)!)()(.)*\n.*(?=C(?<-12>.)*(?(12)!)$))(?<=(?<2>C|C(?(1)!)(\n|(?<-1>.))*)?)C(?=(?<2>C|(\n|(?<-1>.))*(?(1)!)C)?))?){2}(?<-2>)?(?(2)!)

Değiştirme dosyası

*

Normal ifade dosyası çoğunlukla normal ifadedir, ancak `dosyaya birkaç seçenek eklemenize izin verir, bu durumda çok satırlı mod. İki dosya verildiğinde, Retina otomatik olarak tümünü değiştir modunu alır. Bu iki dosya STDIN'den girişi okuyan ve sonucu STDOUT'a yazdıran bir program tanımlar.

Ayrıca RegexHero ve RegexStorm üzerinde de test edebilirsiniz . Normal ifade, sondaki satırsonu ile veya satır çizgisi olmadan çalışır ve _yerine. . (Görünüşe göre, takip eden yeni satır yoksa RegexStorm zaman zaman sorun yaşar, ancak RegexHero her iki durumun da üstesinden gelebilir.)

Normal ifadede korkunç miktarda çoğaltma var ve bunu önemli ölçüde kısaltmak için birkaç fikrim var ... Bunu daha sonra deneyeceğim ve sonra bir açıklama ekleyeceğim. Bu arada, yanlış sonuç veren herhangi bir girdi bulup bulamayacağınızı bildirin.


7

J, 75 73 bayt

((,.|.)0 _1 0 1)(+:@](LF,@:,.~'*.C'{~>.)(2=f)+.[f]*f=.[:+/|.!.0)'C'&=;._2

Sırada ./ */ Ciçin kullanılabilir alan / kullanılabilir alan / sandık kullanarak sorudaki biçimi kullanır .

Düzenleme: küçük bir hatayı düzeltir (yanlışlıkla çevreyi boş alan olarak işlemek yerine bir torus kullandım).

açıklama

## Preparation
              'C'&=;._2  NB. Map ./C to 0/1, turn into matrix
((,.|.)0 _1 0 1)         NB. Compute offsets to shift into each direction
                         NB. (i.e. [[_1 0], [1 0], [0 _1], [0 1]] in any order)


## "Part B"
(2=f)+.[f]*f=.[:+/|.!.0  NB. This part computes a matrix that is 1 for cells that
                         NB. cannot contain a chest:
              [:+/|.!.0  NB. Sum of shifts: shift in each of the four cardinal
                         NB. directions (using the array above) and then sum up.
           f=.           NB. Define this function as `f`; we'll use it some more.
         ]*              NB. Multiply by the "is chest" matrix: this isolates
                         NB. double-chests.
       [f                NB. Sum of shifts--1 for double-chest neighbours.
(2=f)                    NB. Isolate cells with two neighbouring chest.
     +.                  NB. Boolean or--either two neighbouring chests or next
                         NB. to a double-chest.

## Wrap up the result
(+:@] (fmt >.) PartB)    NB. Maximum of the array from the above and twice the "is
 +:@]      >.  PartB     NB. chest" matrix--this is 0,1,2 for '*', '.' or chest,
                         NB. respectively.

## Output formatting
LF,@:,.~'*.C'{~          NB. Format output...
        '*.C'{~          NB. Map 0,1,2 to '*.C' by using the value as index
LF   ,.~                 NB. Append line feed at end of each line
  ,@:                    NB. Ravel into one line

4

Cı, 193

Açıklık için 2 gereksiz satırsonu. Yasadışı kod ile ilgili değişiklikler şunları içerir: karakter değişmez değerleri yerine ascii kodları olarak karakterler; karakterleri kaydetmek için v = 0, strlen ve strchr öğelerinin yeniden düzenlenmesi (strchr en çirkindir, aksi takdirde yalnızca bir kez gerçekleştirilecek bir hesaplama hücre başına 5 kez yapılır!)

C işlevleri, dizeleri bağımsız değişken olarak kabul etmez veya değer olarak döndürmez, bu yüzden yapabileceğim en iyi şey şudur: q giriş dizesinin bir göstergesidir. İşlev dizeyi değiştirir ve işlev döndüğünde çıktı orijinal dizgide bulunur.

g(char*q){int v,j,w,l;
int f(p,d){int s=0,i=w=strchr(q,10)-q+1,r;for(;w/i;i-=i-1?w-1:2)r=p+i,r>-1&r<l&&q[r]==67&&++s&&d&&f(r,0);v|=s>d;}
for(j=l=strlen(q);j--;f(j,1),46-q[j]||v||(q[j]=42))v=0;}

Kuralları özetlemek gerekirse:

C ile yeni satır içermeyen boş bir kare (C veya satırsonu içermeyen) dönüştürülebilir

... VE o komşunun C ile komşusu yok.

G işlevi, derinlik 1'den derinlik 0'a geri dönen bir işlev f içerir. Yalnızca 2 düzey yineleme ile basit bir f(r,0)özyinelemeli çağrı yapılır, buna gerek yoktur.f(r,d-1) !

Test programında kodlanmamış kod

Giriş test dizesi sabit kodlanmıştır. getsve scanfiçinde yeni satır bulunan bir giriş dizesi kabul etmez; her satırda parçalara ayırırlar.

char n[]=".......C..\n...C..C...\n.........C\n.CC...CC..\n..........";

g(char*q){

  int v,j,w,l;

  int f(p,d){                    //p=cell to be checked,d=recursion depth
    int s=0,i=w,r;               //sum of C's found so far=0, i=width
    for(;w/i;i-=i-1?w-1:2)       //For i in   w,1,-1,-w   = down,right,left,up
      r=p+i,                     //r=cell adjacent to p
      r>-1&r<l&&q[r]=='C'&&++s   //If r not out of bounds and equal to C, increment s...
        &&d&&f(r,0);             //...and if recursion depth not yet at zero, try again one level deeper. 
    v|=s>d;                      //If the local s exceeds d, set global v to true to indicate invalid.
  }

  w=strchr(q,10)-q+1;            //width equals index of first newline + 1                   
  l=strlen(q);                   //length of whole string;
  for(j=l;j--;)                  //for l-1 .. 0 
    v=0,                         //clear v
    f(j,1),                      //and scan to see if it should be set
    '.'-q[j]||v||(q[j]='*');     //if the character is a '.' and v is not invalid, change to '*'
}

main(){
  g(n);
  puts(n);
}

Soru örneğine dayalı çıktı

******.C**
***C**C.**
*..***..*C
.CC.*.CC.*
*..***..**

1

JavaScript (ES6) 124 129

0 (*), 6 (C), 7 (.) Karakterlerini kullanma

F=s=>[for(c of(d=[o=~s.search('\n'),-o,1,i=-1],s))
   d.map(j=>t-=s[i+j]==6&&~d.some(k=>s[i+j+k]==6),t=i++)|c<7|t>i&&c
].join('')

Açık ve açık

F=s=>
{
  o=~s.search('\n') // offset to prev row (~ is shorter than +1 and sign does not matter)
  d=[o,-o,1,-1] // array of offset to 4 neighbors
  i=-1
  result = '' // in golfed code, use array comprehension to build the result into an array, then join it
  for (c of s) // scan each char
  {
    t = i++ // set a starting value in t and increment current position in i
    d.forEach(j => // for each near cell, offset in j
    {         
      if (s[i+j]==6) // if cell contains a Chest, must increment t
      {  
        // In golfed code "~some(...)" will be -1(false) or -2(true), using decrement instead of increment
        if (d.some(k=>s[i+j+k]==6)) // look for another Cheast in the neighbor's neighbors
        {
          // more than one chest, position invalid
          t += 2
        }
        else
        {
          t += 1
        }
      }
    })
    if (c < 7 // current cell is not blank
        || t > i) // or t incremented more than once, position invalid
    {
       result += c // curent cell value, unchanged
    }
    else
    {
       result += 0 // mark a valid position 
    }
  }
  return result
}

Firefox / FireBug konsolunda test et

a='\
7777777677\n\
7776776777\n\
7777777776\n\
7667776677\n\
7777777777\n';

console.log(F(a))

Çıktı

0000007600
0006006700
0770007706
7667076670
0770007700

1

Perl, 66

Normal ifadeyle eşleşen göğüs çatışmaları uzun tarafta sona erdi, bu yüzden CJam ile bu sefer rekabet etmiyor.

#!perl -p0
/.
/;$"=".{@-}";s%0%s/\G0/2/r!~/2((.$")?2(.$")?|2$"|$"2)2/s*1%eg

Girişteki boş ve göğüs boşlukları için 0 ve 2, çıkıştaki noktaları işaretlemek için 1 kullanır.

Burada deneyin .


0

Python 2-281 bayt

f=lambda x,y:sum(m[y][x-1:x+2])+m[y-1][x]+m[y+1][x]
m=[];o=''
try:
 while 1:m+=[map(int,'0%s0'%raw_input())]
except:a=len(m[0]);l=len(m);m+=[[0]*a]
for y in range(l*2):
 for x in range(1,a-1):
    if y<l:m[y][x]*=f(x,y)
    else:o+=`2if m[y-l][x]else +(f(x,y-l)<5)`
 if y>=l:print o;o=''

(Satır 8 ve 9, SE'nin 4 boşluğa dönüştürdüğü tek bir sekme karakteriyle tasarlanmıştır. Bu programdaki her satırda 0 veya 1 bayt önde gelen boşluk vardır.)

Girdi: göğsüz 0, 2göğüs için
Çıkış: göğsüz 0, 2mevcut göğüs 1için, olası yeni göğüs için


Tanrım, bu korkunç. Ciddi bir şekilde pratik dışı kalmalıyım. Bildiğim her numarayı attım ve çıktı ... iyi, 281 bayt olarak çıktı, regex dışındaki her cevaba kaybettim , haha. Dürüst olmak gerekirse biraz golf gibi hissediyorum, bu yüzden algoritma ideal daha az olduğunu tahmin ediyorum.

Ungolfed:

def f(x,y):
    """Given x,y coords of the board, return the sum of that point and all
    adjacent points.
    """
    return (sum(board[y][x-1:x+2]) # (x-1,y) + (x,y) + (x+1,y)
            + board[y-1][x]
            + board[y+1][x])
board=[]
output=''
try:
    while True:
        row = '0%s0' % raw_input() # line from stdin with a leading and trailing 0
        board.append(map(int, row)) # convert to list of ints
except:
    pass # exception is thrown when stdin is empty

board_width = len(board[0])
board_height = len(board)

board.append([0]*board_width) # new row of all 0s

for y in xrange(board_height*2):
    # board_height multiplied by 2 so we can use this loop to simulate two
    for x in xrange(1,board_width-1):
        if y < board_height: # "first loop"
            board[y][x] *= f(x,y) # multiply everything on the board by itself + sum
                                  # of neighbours
                                  # empty cells (0) stay 0 no matter what
                                  # lone chests (2 surrounded by 0) become 2*2==4
                                  # double chests (2 touching another 2) are weird:
                                  # - one chest becomes 2*(2+2)==8
                                  # - the other chest becomes 2*(2+8)==20
        else: # "second loop"
            if board[y - board_height][x] != 0:
                output += '2' # anything not equal to 0 is an existing chest
            else:
                valid = f(x, y - board_height) < 5 # if the sum of neighbours > 4, the
                                                   # current cell is either beside a
                                                   # double chest or more than one
                                                   # single chest
                output += '01'[valid]
    if y >= board_height: # only print during the "second loop"
        print output
        output=''
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.