마인 크래프트 상자 배치


20

비디오 게임 Minecraft 는 가상 세계를 구성하는 3D 정수 격자 에 다른 유형의 블록을 배치하고 제거하는 것에 관한 것 입니다. 각 격자 점은 정확히 하나의 블록을 포함하거나 비어있을 수 있습니다 ( 공식적으로 " 공기 "블록). 이 도전에서 우리는 3D 세계의 하나의 수평 2D 평면과 하나의 블록 유형 인 가슴 에만 관심을 가질 것 입니다.

상자는 플레이어가 아이템을 저장할 수있게합니다. 두 개의 가슴이 동일한 수평면에 직교로 인접 해 있으면 두 개의 가슴이 연결되고 두 배의 용량이있는 두 개의 가슴이 연결됩니다. 이중 상자보다 큰 것은 만들 수 없습니다. 트리플 상자 나 쿼드 상자가 없습니다.

가슴 블록은 네 개의 직교 인접 점이 모두 비어 있거나 정확히 하나에 이미 이중 가슴의 일부가 아닌 가슴 블록이있는 경우 빈 격자 점에만 배치 할 수 있습니다. 이 배치 규칙은 어떤 가슴 블록이 이중 가슴을 형성하기 위해 연결되어 있는지에 대한 모호성을 절대로 보장하지 않습니다.

예를 들어, .빈 공간이고 C가슴 이라고 가정합니다 (숫자는 빈 공간이며 식별 목적으로 만 사용됩니다).

.......C..
.1.C2.C3..
........5C
.CC4..CC..
..........
  • 네 개의 이웃이 비어 있기 때문에 가슴을 지점 1에 놓을 수 있습니다.
  • 인접한 가슴이 (아직) 이중 가슴의 일부가 아니므로 가슴을 스팟 2에 놓을 수 있습니다.
  • 이중 가슴이 어떻게 형성되는지 모호하기 때문에 가슴을 3 자리에 넣을 수 없습니다.
  • 인접한 상자가 이미 이중 상자의 일부이므로 상자를 지점 4에 배치 할 수 없습니다.
  • 가슴은 자리 5에 놓을 수 있습니다. 대각선으로 인접한 이중 상자는 아무 영향을 미치지 않습니다.

그리드 너머의 영역이 비어 있다고 가정하면 그리드의 모든 것을 가슴을 배치 할 수 .있는 *경우로 변경 하면 다음과 같은 결과가 발생합니다.

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

물론 모든 *공간이 동시에 가슴으로 채워질 수는 없지만 가슴이 하나만 있으면 어느 공간 에나 둘 수 있습니다.

도전

.C그리드 를받는 프로그램 또는 함수를 작성하고 가슴을 배치하거나 결과 그리드를 인쇄하거나 반환 할 수 .있는 *경우 마다 로 변경 합니다.

  • 입력은 stdin 또는 파일 또는 함수에 대한 문자열 인수 일 수 있습니다.

  • , 텍스트의 예를 완벽하게 직사각형 그리드, 적어도 1 개 문자 너비와 높이 만 포함 - 당신은 입력이 잘 형성되어 가정 할 수 .C선택적으로 마지막 행 다음에 후행 줄 바꿈이 있다고 가정 할 수있다 (그리고 출력에 하나있을 수 있습니다 ).

  • 입력에서 가슴의 배열이 위의 규칙과 일치한다고 가정 할 수 있습니다. 어떤 상자가 이중 상자를 형성하는지 모호성이 없을 것입니다.

  • 원하는 경우, 당신은 어떤 세 가지 사용할 수 있습니다 인쇄 가능한 ASCII 대신에 문자를 ., C하고 *. 줄 바꿈 대신 다른 것을 사용할 수 없습니다.

  • 모든 가슴은 정상적인 가슴입니다. 가슴 이나 엔더 가슴이 갇히지 않았습니다 .

채점

가장 적은 바이트를 가진 제출이 이깁니다.

좀 더 어려운 마인 크래프트 관련 챌린지는 Nether Portal Detection을 사용해보십시오 .


5
Minecrafting 관점에서 게임 에서이 성가신 것을 발견했습니다. 가슴이 갇혀있는 것이 좋습니다 : P
Sp3000

stdin 또는 단일 문자열 인수에서 그리드 입력을 가져올 때 그리드 치수를 추가 입력으로 받아 들일 수 있습니까? 또는 줄 바꿈과 문자열 길이에서 추론해야합니까?
Level River St

@steveverrill 그것은 유추되어야한다.
Calvin 's Hobbies

호기심 때문에 내 자신을 포함한 모든 답변에 하나의 공감대가 있습니까? 나는 그것이 같은 사람이라고 생각할 수 있습니다.
Level River St

추가적인 도전을 위해 가슴에 가장 적합한 위치를 찾는 프로그램을 작성할 수 있습니다. 즉, 새 가슴 사이에서도 규칙을 위반하지 않고 최대 수의 추가 가슴을 배치 할 수있는 구성을 찾으십시오.
AJMansfield

답변:


11

CJam, 82 76 66 62 58 54 바이트

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

입력 형식 0은 에어 셀과 8가슴 셀에 필요합니다. 1상자에 배치 할 수있는 모든 셀에 대한 출력이 포함 됩니다.

업데이트 : 버그가 수정되었습니다. 3 바이트 증가 :( 골프 더 :). @ Sp3000 덕분에 4 바이트 절약

입력 예 :

0000000800
0008008000
0000000008
0880008808
0000000000

산출:

1111110811
1110018010
1008800108
0880088008
1008800110

나는 지금 골프를 끝냈다 고 생각한다.

설명

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

여기에서 온라인으로 사용해보십시오


8

.NET 정규식 ( 망막 ) 434 416 310 + 1 = 311 바이트

정규식 (이 도전과 관련된 황천 포털 도전)에서 마지막으로 도전 한 후에 마침내 .NET 스타일 정규 표현식의 해석기 역할을하는 명령 줄 도구를 작성했습니다. 정규식이 아닌 독립형 언어가 아닌 도전을받지 않고 나는 그것을 Retina라고 명명했습니다.

이제이 과제는 정규식 제출에 적합하지 않지만 지금은 Retina를 사용해야했습니다. ;) (또한 Sp3000은 채팅에서 그렇게하도록 요청했습니다.) 따라서 다음과 같습니다.

정규식 파일

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

교체 파일

*

정규 표현식 파일은 파일 `에 몇 가지 옵션을 넣을 수 있다는 점을 제외하고는 대부분 정규 표현식 입니다. 두 개의 파일이 주어지면 Retina는 자동으로 대체 모드를 가정합니다. 이 두 파일은 STDIN에서 입력을 읽고 결과를 STDOUT에 인쇄하는 프로그램을 정의합니다.

RegexHeroRegexStorm 에서 테스트 할 수도 있습니다 . 정규식은 후행 줄 바꿈과 함께 또는없이 작동하며 _대신에 사용 됩니다 .. (마지막으로 줄 바꿈이 없으면 RegexStorm에 문제가있는 경우가 있지만 RegexHero는 두 경우 모두 잘 처리하는 것으로 보입니다.)

정규식에는 끔찍한 중복이 있으며 크게 단축 할 수있는 몇 가지 아이디어가 있습니다 ... 나중에 시도하고 설명을 추가 할 것입니다. 그 동안 잘못된 결과가 나오는 입력을 찾을 수 있는지 알려주십시오.


7

J, 75 73 바이트

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

공간 / 사용 가능한 공간 / 가슴에 각각 ./ */ C를 사용하여 질문의 형식을 사용합니다 .

편집 : 작은 버그 수정 (우연히 주변을 빈 공간으로 올바르게 처리하는 대신 원환 체를 사용했습니다).

설명

## 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 개의 불필요한 개행. ungolfed 코드와 관련된 변경 사항은 다음과 같습니다. 문자 리터럴 대신 ASCII 코드로 문자; 문자를 저장하기 위해 v = 0, strlen 및 strchr의 재 배열

C 함수는 문자열을 인수로 허용하지 않거나 값으로 반환하지 않으므로 최선을 다할 수있는 것은 다음과 같습니다 q. 입력 문자열에 대한 포인터입니다. 이 함수는 문자열을 수정하고 함수가 리턴 할 때 출력이 원래 문자열에서 발견됩니다.

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

규칙을 요약하려면 다음을 수행하십시오.

빈 사각형 (C 또는 개행 문자를 포함하지 않음)은 C와 이웃이 최대 1 인 경우 변환 할 수 있습니다.

... 그리고 그 이웃은 C와 이웃이 없습니다.

함수 g에는 깊이 1에서 깊이 0까지 재귀하는 함수 f가 포함되어 있습니다. 재귀 수준이 2 단계 인 경우 간단한 f(r,0)재귀 호출 만 수행하면됩니다 f(r,d-1)!

테스트 프로그램의 언 골프 코드

입력 테스트 문자열이 하드 코드되었습니다. gets그리고 scanf거기에 줄 바꿈으로 입력 문자열을 수락하지 않습니다; 그들은 개행마다 그것을 조각으로 자른다.

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

질문 예에 따른 출력

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

1

자바 스크립트 (ES6) 124 129

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

언 골프 및 설명

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 콘솔에서 테스트

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

console.log(F(a))

산출

0000007600
0006006700
0770007706
7667076670
0770007700

1

펄, 66

정규식 일치하는 가슴 충돌은 결국 끝났으므로 이번에는 CJam과 경쟁하지 않습니다.

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

입력의 빈 공간과 가슴 공간에 0과 2를 사용하고 출력에 점을 표시하려면 1을 사용합니다.

여기에서 시도 하십시오 .


0

파이썬 2-281 바이트

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

(8 행과 9 행은 단일 탭 문자를 사용하여 SE는 4 개의 공백으로 변환됩니다.이 프로그램의 모든 행에는 0 또는 1 바이트의 선행 공백이 있습니다.)

입력 : 0가슴 없음, 2가슴
출력 : 0가슴 없음, 2기존 가슴, 1새 가슴 가능


세상에, 이것은 끔찍하다. 나는 연습이 심각해야합니다. 나는 내가 알고있는 모든 트릭을 던졌고 나왔다 ... 음, 그것은 281 바이트로 나왔고, 정규 표현식 haha를 제외한 모든 대답을 잃었습니다 . 솔직히 골프를 쳤다는 느낌이 들기 때문에 알고리즘이 이상적이지 않다고 생각합니다.

언 골프 드 :

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=''
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.