Vị trí ngực Minecraft


20

Trò chơi video Minecraft là tất cả về việc đặt và loại bỏ các loại khối khác nhau trong mạng số nguyên 3D tạo nên thế giới ảo. Mỗi điểm mạng có thể chứa chính xác một khối hoặc trống (một khối " không khí " chính thức). Trong thử thách này, chúng ta sẽ chỉ quan tâm đến một mặt phẳng 2D ngang của thế giới 3D và một loại khối: rương .

Rương cho người chơi lưu trữ vật phẩm. Khi hai rương kề nhau trực giao trong cùng một mặt phẳng nằm ngang, kết cấu của chúng liên kết với nhau và một rương đôi với hai lần công suất. Không có gì lớn hơn một đôi ngực có thể được thực hiện; không có ba rương cũng không phải bốn rương.

Một khối ngực chỉ có thể được đặt trong một điểm mạng trống nếu bốn điểm liền kề trực giao của nó đều trống hoặc nếu chính xác một khối chứa một khối ngực không phải là một phần của ngực kép. Các quy tắc vị trí này đảm bảo rằng không bao giờ có bất kỳ sự mơ hồ nào về việc khối ngực nào liên kết để tạo thành rương đôi.

Ví dụ: giả sử .là không gian trống và Clà một rương: (Các số cũng là không gian trống và chỉ dành cho mục đích nhận dạng.)

.......C..
.1.C2.C3..
........5C
.CC4..CC..
..........
  • Một cái rương có thể được đặt ở vị trí 1 vì 4 hàng xóm của nó trống rỗng.
  • Một rương có thể được đặt ở vị trí 2 vì rương lân cận không phải là một phần của rương đôi.
  • Một chiếc rương không thể được đặt ở vị trí 3 vì sẽ có sự mơ hồ về cách hình thành của chiếc rương đôi.
  • Một rương không thể được đặt ở vị trí 4 vì rương lân cận đã là một phần của rương đôi.
  • Một rương có thể được đặt ở vị trí 5. Ngực đôi lân cận chéo không ảnh hưởng gì.

Giả sử khu vực bên ngoài lưới trống, thay đổi mọi thứ .trong lưới thành *nếu có thể đặt rương ở đó sẽ dẫn đến kết quả này:

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

Tất nhiên, không phải tất cả các *không gian đều có thể chứa các rương cùng một lúc, nhưng nếu bạn chỉ có một rương, nó có thể được đặt trong bất kỳ rương nào.

Thử thách

Viết một chương trình hoặc chức năng mà mất trong một .Clưới điện, và thay đổi mỗi .một *nếu một ngực có thể được đặt ở đó, in hoặc trả lại lưới kết quả.

  • Đầu vào có thể từ stdin hoặc tệp hoặc dưới dạng đối số chuỗi cho hàm.

  • Bạn có thể giả sử đầu vào được hình thành tốt - tức là một lưới văn bản hình chữ nhật hoàn hảo, rộng ít nhất 1 ký tự, chỉ chứa .Cbạn có thể tùy ý giả sử có một dòng mới sau hàng cuối cùng (và có thể có một trong đầu ra ).

  • Bạn có thể cho rằng việc sắp xếp các rương trong đầu vào phù hợp với các quy tắc ở trên. Sẽ không bao giờ có sự mơ hồ về việc rương nào tạo thành rương đôi.

  • Nếu muốn, bạn có thể sử dụng bất kỳ ba biệt ASCII in ký tự thay ., C*. Bạn không thể sử dụng cái gì khác thay cho dòng mới.

  • Tất cả các rương đều là rương bình thường. Không bị mắc kẹt rương hoặc rương ender .

Chấm điểm

Việc gửi với ít byte nhất sẽ thắng.

Đối với một thử thách liên quan đến Minecraft khó khăn hơn một chút, hãy thử Phát hiện Cổng thông tin Nether .


5
Từ quan điểm Minecrafting, tôi thấy trò chơi này khá khó chịu. Điều tốt là có những cái rương bị mắc kẹt: P
Sp3000 15/2/2015

Khi lấy đầu vào lưới từ stdin hoặc một đối số chuỗi đơn, có thể chấp nhận lấy kích thước lưới làm đầu vào bổ sung không? hoặc nó phải được suy ra từ dòng mới và độ dài chuỗi?
Cấp sông St

@steveverrill Nó phải được suy ra.
Sở thích của Calvin

Vì tò mò, tại sao mọi câu trả lời bao gồm cả câu trả lời của riêng tôi đều có một downvote? Tôi chỉ có thể cho rằng đó là cùng một người, họ sẽ quan tâm để giải thích?
Cấp sông St

Đối với một thử thách thêm, người ta có thể viết một chương trình để tìm vị trí tối ưu cho các rương; nghĩa là tìm một cấu hình cho phép đặt số lượng rương bổ sung tối đa mà không vi phạm các quy tắc ngay cả giữa các rương mới.
AJMansfield

Câu trả lời:


11

CJam, 82 76 66 62 58 54 byte

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

Định dạng đầu vào mong đợi 0cho tế bào không khí và 8cho một tế bào ngực. Đầu ra chứa 1cho tất cả các ô có thể được đặt bằng Rương.

CẬP NHẬT : Đã sửa lỗi. Tăng thêm 3 byte :( chơi gôn hơn :). 4 byte được lưu nhờ @ Sp3000

Ví dụ đầu vào:

0000000800
0008008000
0000000008
0880008808
0000000000

Đầu ra:

1111110811
1110018010
1008800108
0880088008
1008800110

Tôi nghĩ bây giờ tôi đã chơi golf xong ...

Giải trình

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";

Dùng thử trực tuyến tại đây


8

.NET Regex ( Retina ), 434 416 310 + 1 = 311 byte

Sau thử thách cuối cùng mà tôi đã trả lời trong regex (Thử thách Cổng thông tin Nether được liên kết trong thử thách này), cuối cùng tôi đã bắt đầu viết một công cụ dòng lệnh, hoạt động như một trình thông dịch cho các biểu thức chính quy theo kiểu .NET, vì vậy tôi có thể trả lời các câu hỏi với regex mà không bị thách thức rằng chúng không phải là ngôn ngữ độc lập. Tôi đã đặt tên cho nó là Retina.

Bây giờ, thử thách này không cho vay rất tốt khi nộp regex, nhưng tôi phải sử dụng Retina ngay bây giờ. ;) (Plus, Sp3000 đã thách tôi làm như vậy trong trò chuyện.) Vì vậy, đây là:

Tập tin Regex

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)!)

Tập tin thay thế

*

Tệp regex chủ yếu chỉ là regex, ngoại trừ `cho phép bạn đặt một vài tùy chọn trong tệp, trong trường hợp này chỉ đơn giản là chế độ đa dòng. Khi được cung cấp hai tệp, Retina sẽ tự động giả định chế độ thay thế tất cả. Hai tệp này xác định chương trình đọc đầu vào từ STDIN và in kết quả sang STDOUT.

Bạn cũng có thể kiểm tra nó trên RegexHeroRegexStorm . Regex hoạt động cả có và không có dòng mới, và sử dụng _thay thế .. (Rõ ràng, đôi khi RegexStorm có vấn đề nếu không có dòng mới, nhưng RegexHero dường như xử lý tốt cả hai trường hợp.)

Có một số lượng trùng lặp khủng khiếp trong regex và tôi có một vài ý tưởng để rút ngắn đáng kể ... Tôi sẽ thử lại sau và sau đó thêm một lời giải thích. Trong lúc này, hãy cho tôi biết nếu bạn có thể tìm thấy bất kỳ đầu vào nào dẫn đến kết quả sai.


7

J, 75 73 byte

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

Sử dụng định dạng trong câu hỏi, sử dụng ./ */ Ccho không gian / không gian có thể sử dụng / rương, tương ứng.

Chỉnh sửa: sửa một lỗi nhỏ (Tôi vô tình sử dụng hình xuyến thay vì coi đúng xung quanh là khoảng trống).

Giải trình

## 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

2 dòng mới không rõ ràng cho rõ ràng. Các thay đổi liên quan đến mã không được mã hóa bao gồm: các ký tự dưới dạng mã ascii thay vì ký tự; sắp xếp lại v = 0, strlen và strchr để lưu các ký tự (strchr là xấu nhất, vì điều đó có nghĩa là một phép tính chỉ được thực hiện một lần duy nhất, được thực hiện 5 lần trên mỗi ô!)

Các hàm C không chấp nhận các chuỗi làm đối số hoặc trả về chúng dưới dạng các giá trị, vì vậy điều tốt nhất tôi có thể làm là như sau: qlà một con trỏ tới chuỗi đầu vào. Hàm sửa đổi chuỗi và khi hàm trả về đầu ra được tìm thấy trong chuỗi gốc.

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;}

Để tóm tắt các quy tắc:

một hình vuông trống (không chứa C hoặc dòng mới) có thể được chuyển đổi nếu nó có tối đa 1 hàng xóm với C

... VÀ người hàng xóm đó không có hàng xóm với C.

Hàm g chứa hàm f đệ quy từ độ sâu 1 xuống độ sâu 0. Chỉ với 2 mức đệ quy, một f(r,0)lệnh gọi đệ quy đơn giản sẽ thực hiện, không cần f(r,d-1)!

Mã bị lỗi trong chương trình thử nghiệm

Chuỗi kiểm tra đầu vào được mã hóa cứng. getsscanfsẽ không chấp nhận một chuỗi đầu vào có dòng mới trong đó; họ cắt nó thành từng mảnh ở mỗi dòng mới.

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);
}

Đầu ra dựa trên ví dụ câu hỏi

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

1

JavaScript (ES6) 124 129

Sử dụng các ký tự 0 (*), 6 (C), 7 (.)

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('')

Ung dung và giải thích

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
}

Kiểm tra trong bảng điều khiển Firefox / FireBug

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

console.log(F(a))

Đầu ra

0000007600
0006006700
0770007706
7667076670
0770007700

1

Perl, 66

Cuộc xung đột ngực phù hợp regrec đã kết thúc ở phía dài, vì vậy không có cạnh tranh với CJam lần này.

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

Sử dụng 0 và 2 cho khoảng trống và khoảng trống trên đầu vào, 1 để đánh dấu các điểm trên đầu ra.

Hãy thử nó ở đây .


0

Python 2 - 281 byte

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=''

(Dòng 8 và 9 được dành cho một ký tự tab duy nhất, SE chuyển đổi thành 4 khoảng trắng. Mỗi dòng trong chương trình này có 0 hoặc 1 byte khoảng trắng hàng đầu.)

Đầu vào: 0không có ngực, 2đối với ngực
Ouput: 0không có ngực, 2đối với ngực hiện tại, 1đối với ngực mới có thể


Chúa ơi, điều này thật kinh khủng. Tôi phải nghiêm túc ra khỏi thực hành. Tôi đã ném mọi mánh mà tôi biết về nó và nó xuất hiện ... ừm, nó xuất hiện dưới dạng 281 byte, thua mọi câu trả lời trừ câu trong regex , haha. Tôi thực sự cảm thấy như tôi đã chơi golf tốt, vì vậy tôi đoán rằng thuật toán của tôi chỉ kém lý tưởng.

Ung dung:

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=''
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.