황천의 차 원문 탐지


53

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

흑요석이 세로 평면에 빈 사각형의 외곽선을 형성하면 황천 포털 을 만들 수 있습니다. 빈 직사각형은 폭이 2 단위, 높이가 3 단위, 너비가 22 단위, 높이가 22 단위 일 수 있습니다. 직사각형의 모서리는 흑요석으로 경계를 둘 필요가 없으며 측면 만 있습니다.

예를 들어 X흑요석이고 .공허하다고 가정합니다 . (숫자는 식별 목적으로 만 사용되며 비어 있습니다.)

...................................
..XXXX....XXXX....XXXXXXXXX........
..X..X...X....X..X.........X..XXXX.
..X.1X...X.2..X..X...3...X.X..X....
..X..X...X....XXXX.........X..X.6X.
..XXXX....XXXX...XXXXXXXXXXX..X..X.
.............X.4.X....X.5.X...XXXX.
.............X...X....X...X........
..............XXX......XXX.........
...................................

이 그리드에는 3 개의 유효한 포털이 있습니다.

  • Portal 1은 2 x 3 단위이며 완전히 비어 있으며 흑요석으로 경계를 이룹니다. 따라서 유효합니다.
  • Portal 2는 4 x 3이며 완전히 비어 있으며 흑요석에 접해 있습니다. 따라서 유효합니다.
  • 포털 3이 완전히 비어 있지 않습니다. 따라서 유효하지 않습니다.
  • Portal 4는 3 x 3이며 완전히 비어 있으며 흑요석으로 둘러싸여 있습니다. 따라서 유효합니다.
  • Portal 5는 3 x 2 단위로 너무 작습니다. 따라서 유효하지 않습니다.
  • Portal 6에 테두리의 일부가 없습니다. 따라서 유효하지 않습니다.

도전

흑요석과 공허의 격자를이 문자열로 표현하고 유효한 네더 포털의 수를 인쇄하거나 반환하는 프로그램이나 함수를 작성하십시오.

  • stdin 또는 파일 또는 함수 인수에서 입력 할 수 있습니다.
  • 입력이 항상 올바르게 구성되어 있다고 가정 할 수 있습니다. 즉, 너비가 1 자 이상인 완벽하게 직사각형 인 텍스트 격자와가 포함 X되어 .있습니다. 선택적으로 마지막 행 다음에 줄 바꿈 문자가 있다고 가정 할 수 있습니다.

  • 원하는 경우 및 대신 두 개의 인쇄 가능한 ASCII 문자를 사용할 수 있습니다 .X.

  • 흑요석이 그리드의 경계에있을 수 있습니다. 경계를 넘어서는 것은 비어있는 것으로 간주됩니다.

입력 예-출력은 다음 4과 같아야합니다 .

................................................................
...................................XXXXXXXXXXXXXXXXXXXXXXXXX....
..XXXX....XXXX....XXXXXXXXX........X.......................X....
..X..X...X....X..X.........X..XXXX.X.......................X....
..X..X...X....X..X.......X.X..X....X.......................X....
..X..X...X....XXXX.........X..X..X..XXXXXXXXXXXXXXXXXXXXXXXX....
..XXXX....XXXX...XXXXXXXXXXX..X..X.X......................X..XXX
.............X...X....X...X...XXXX.X......................X..X..
.............X...X....X...X........X......................X..X..
..............XXX......XXX........XXXXXXXXXXXXXXXXXXXXXXXX...X..
..................................XX.........................XXX

채점

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


줄 바꿈 대신 다른 ASCII 문자를 사용할 수 있습니까?
Zgarb

@ Zgarb 아니요, 여전히 입력이 그리드처럼 보이기를 원합니다.
Calvin 's Hobbies

4
네더 포털의 크기는 언제 정적 2x3에서 더 큰 옵션 크기로 변경 되었습니까?
Sparr

5
@Sparr SInce 1.7.2 ( 업데이트 기록 참조 ). 그들이 콘솔 에디션에서 이것을 할 수 있는지 확실하지 않습니다.
Calvin 's Hobbies

4
마인 크래프트 때문에 확실히 +1.
Alex A.

답변:


24

펄, 81 86

둘 이상의 정규 표현식을 사용합니다.

#!perl -p0
$_=map{/.
/;$n="@-"-++$.;/(?=X{$.}..{$n}(X\.{$.}X.{$n}){3,22}.X{$.})/gs}($_)x21

포털의 특정 너비에 대한 정규 표현식은 일반적인 너비 보다 훨씬 간단합니다. X{$m}..{$n}(X\.{$m}X.{$n}){3,22}.X{$m}여기서 m포털의 너비 ntotal width - 1 - m입니다. (?=...)일치하는 항목이 겹칠 수 있으므로 정규 표현식을 너비가 0 인 어설 션에 넣어야합니다 . 그런 다음이 정규 표현식 설정 $n과에서 21 번 반복합니다 $.. "@-"/.\n/총 너비-1 인 마지막 일치 ( ) 의 시작 위치로 평가됩니다 . 와 함께 사용될 때 $.초기화 될 1때 다른 변수로 사용됩니다 -p0.


2
.빈 셀 과 다른 문자를 사용하면 바이트를 저장할 수 있으므로 이스케이프 할 필요가 없습니다.
Martin Ender 2019

62

정규식 (.NET 맛) 182 181 145 132 126 114 104 100 98 97 96 바이트

2D ASCII 아트 패턴 인식? 정규식에 대한 직업처럼 들립니다! (그렇지 않습니다.)

나는 이것이 정규식 제출이 유효한 프로그램인지 아닌지에 대해 끊임없는 토론을 다시 시작할 것이라는 것을 알고 있지만, 어쨌든 이것이 APL 또는 CJam을 이길 것이라고 의심하므로 아무런 해가 보이지 않습니다. (밝혔다되는 것을 그들은 어떻게 우리의 다이 하드 시험에 합격 "어떻게 프로그래밍 언어를?" .)

일치하는 문자열로 입력을 받고 결과는 찾은 일치 수입니다. 후자를 탈출해야하기 때문에 _대신 대신 사용합니다 .. 또한 후행 줄 바꿈이 필요합니다.

(X(X){1,21})(?=\D+((?>(?<-2>_)+)_))(?=.((?!\7)(.)*
.*(X\3X|()\1.)(?=(?<-5>.)*(?(5)!)
)){4,23}\7)

RegexHero 또는 RegexStorm 에서 실시간으로 테스트 할 수 있습니다 ). 경기는 포털의 최고 흑요석 행이됩니다. 실패한 테스트 사례를 찾으면 알려주십시오!

이 마법은 무엇입니까?

다음 설명은 .NET의 밸런싱 그룹에 대한 기본적인 이해를 가정합니다 . 요점은 캡처가 .NET 정규 표현식의 스택이라는 것입니다. 같은 이름의 모든 새로운 캡처는 스택으로 푸시되지만 해당 스택에서 다시 캡처를 캡처하는 구문과 하나의 스택에서 팝업을 캡처하는 구문 및 푸시 캡처도 있습니다 동시에 다른 사람에게. 더 완전한 그림을 보려면 모든 세부 사항을 다루는 스택 오버플로에 대한 내 대답을 볼 수 있습니다 .

기본 아이디어는 다음과 같은 패턴을 일치시키는 것입니다.

 X{n}..{m}
X_{n}X.{m} |
X_{n}X.{m} |  3 to 22 times
X_{n}X.{m} |
 X{n}..{m} 

어디는 n2 사이와 22 (포함)입니다. 까다로운 것은 모든 ns와 모든 ms를 동일하게 만드는 것입니다 . 실제 문자는 같지 않으므로 역 참조를 사용할 수 없습니다.

정규식에는 줄 바꿈이 포함 \n되어 있어야하며 다음과 같이 작성합니다.

(                     # Open capturing group 1. This will contain the top of a portal, which
                      # I can reuse later to match the bottom (being of the same length).
  X                   # Match a single X.
  (X){1,21}           # Match 1 to 21 X's, and push each separately on the <2> stack. Let's
                      # Call the number of X's captured N-1 (so N is the inner width of the
                      # portal).
)                     # End of group 1. This now contains N X's.
(?=                   # Start a lookahead. The purpose of this lookahead is to capture a 
                      # string of N underscores in group 2, so I can easily use this to match 
                      # the inside rows of the portal later on. I can be sure that such a 
                      # string can always be found for a valid portal (since it cannot have 0 
                      # inner height).
  \D+                 # Skip past a bunch of non-digits - i.e. *any* of the vaild characters
                      # of the input (_, X, \n). This to make sure I search for my N 
                      # underscores anywhere in the remainder of the input.
  (                   # Open capturing group 3. This will contain a portal row.
    (?>               # This is an atomic group. Once the engine hass successfully matched the
                      # contents of this group, it will not go back into the group and try to
                      # backtrack other possible matches for the subpattern.
      (?<-2>_)+       # Match underscores while popping from the <2> stack. This will match as
                      # many underscores as possible (but not more than N-1).
    )                 # End of the atomic group. There are two possible reasons for the
                      # subpattern stopping to match: either the <2> stack is empty, and we've
                      # matched N-1 underscores; or we've run out of underscores, in which 
                      # case we don't know how many underscores we matched (which is not 
                      # good).
    _                 # We simply try to match one more underscore. This ensures that we 
                      # stopped because the <2> stack was empty and that group 3 will contain
                      # exactly N underscores.
  )                   # End of group 3.
)                     # End of the lookahead. We've got what we want in group 2 now, but the
                      # regex engine's "cursor" is still at the end of the portal's top.
(?=                   # Start another lookahead. This ensures that there's actually a valid
                      # portal beneath the top. In theory, this doesn't need to be a 
                      # lookahead - I could just match the entire portal (including the lines
                      # it covers). But matches cannot overlap, so if there were multiple
                      # portals next to each other, this wouldn't return all of them. By 
                      # putting the remainder of the check in a lookahead the actual matches
                      # won't overlap (because the top cannot be shared by two portals).
  .                   # Match either _ or X. This is the character above the portal side.

  (                   # This group (4) is where the real magic happens. It's purpose is to to
                      # count the length of the rest of the current line. Then find a portal
                      # row in the next line, and ensure that it's the same distance from the
                      # end of the line. Rinse and repeat. The tricky thing is that this is a
                      # single loop which matches both inner portal rows, as well as the 
                      # bottom, while making sure that the bottom pattern comes last.

    (?!\7)            # We didn't have a group 7 yet... group 7 is further down the pattern.
                      # It will capture an empty string once the bottom row has been matched.
                      # While the bottom row has not been matched, and nothing has been
                      # captured, the backreference will fail, so the negative lookahead will
                      # pass. But once we have found the bottom row, the backreference will
                      # always match (since it's just an empty string) and so the lookahead
                      # will fail. This means, we cannot repeat group 4 any more after the
                      # bottom has been matched.
    (.)*              # Match all characters until the end of the line, and push each onto
                      # stack <5>.
    \n                # Match a newline to go to the next line.
    .*                # Match as many characters as necessary to search for the next portal
                      # row. This conditions afterwards will ensure that this backtracks to
                      # the right position (if one exists).
    (                 # This group (6) will match either an inner portal row, or the bottom
                      # of the portal.
      X\3X            # Match X, then N underscores, then X - a valid inner portal row.
    |                 # OR
      ()              # Capture an empty string into group 7 to prevent matching further rows.
      \1.             # Use the captured top to match the bottom and another character.
    )
    (?=               # This lookahead makes sure that the row was found at the same 
                      # horizontal position as the top, by checking that the remaining line
                      # is the same length.
      (?<-5>.)*       # Match characters while popping from the <5> stack.
      (?(5)!)\n       # Make sure we've hit end of the line, *and* the <5> stack is empty.
    )
  ){4,23}             # Repeat this 4 to 23 times, to ensure an admissible portal height.
                      # Note that this is one more than the allowed inner height, to account
                      # for the bottom row.
  \7                  # Now in the above repetition there is nothing requiring that we have
                      # actually matched any bottom row - it just ensured we didn't continue
                      # if we had found one. This backreference takes care of that. If no
                      # bottom row was found, nothing was captured into group 7 and this
                      # backreference fails. Otherwise, this backreference contains an empty
                      # string which always matches.
)

C #, 185 바이트

다음은 완전한 C # 함수입니다. 유효한 항목입니다. .NET 정규식에 대한 명령 줄 "인터프리터"를 작성해야합니다.

static int f(string p){return System.Text.RegularExpressions.Regex.Matches(p,@"(X(X){1,21})(?=\D+((?>(?<-2>_)+)_))(?=.((?!\7)(.)*
.*(X\3X|()\1.)(?=(?<-5>.)*(?(5)!)
)){4,23}\7)").Count;}

5
흠, 내가 순수한 정규식 답변에 대해 어떻게 생각하는지 모르겠습니다. 상단을 일치시키는 것은 숫자를 인쇄하는 것과 다릅니다. 물론 프로그램에서 정규식을 사용하고 일치하는 수를 인쇄하는 것이 좋습니다. 아직도, 당신이 말했듯이, 아마 구타 될 것이므로 너무 걱정됩니다.
Calvin 's Hobbies

1
^(또는 사용하지 않은 문자)를 사용할 수 있습니다 (?!).
jimmy23013

@ user23013 오, 좋은 지적입니다. 감사합니다.
Martin Ender 2019


@ user23013 난과 (114)를 가지고 단지 이름이 그룹을 사용하지만, 하지 하나에 선 검사를 결합.
Martin Ender

11

파이썬, 219 바이트

def f(s):s=s.split();L=len;R=range;return L([r for r in R(L(s))for a in R(L(s[0]))for w in R(2,23)for h in R(3,min(L(s)+~r,23))if(s[r][a:a+w]==s[r-~h][a:a+w]==w*"X")*all(s[r-~k][a-1:a+w+1]=="X"+"."*w+"X"for k in R(h))])

Java보다 낫지 만 5 중 중첩 루프가 아프다. 는 for/in사용하여 약간 압축 할 수 있습니다 %s대체를하지만, 많은 저장되지 않습니다.

넓히는:

def f(s):
  s=s.split()
  L=len
  R=range
  return L([r for r in R(L(s))
              for a in R(L(s[0]))
              for w in R(2,23)
              for h in R(3,min(L(s)+~r,23))
              if(s[r][a:a+w]==s[r-~h][a:a+w]==w*"X")* 
                 all(s[r-~k][a-1:a+w+1]=="X"+"."*w+"X"for k in R(h))])

1
내 본능은 itertools 중첩 루프 생성 마법사를 시도하는 것입니다.
imallett

7

자바, 304 바이트

이것은 정규 표현식보다 훨씬 깁니다. 입력에서 가능한 모든 사각형을 반복합니다. 유효한 포털 인 경우 카운터를 1 씩 증가시킵니다. 그런 다음 카운터를 반환합니다. 이것은 아마도 훨씬 더 골프를 칠 수 있습니다. 어떤 제안이라도 환영합니다.

int a(String...a){a=a[0].split("\n");int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();for(;c<j;c++)for(d=0;d<i;d++)for(e=c+2;++e<j&e<c+24;)a:for(f=d+3;++f<i&f<d+24;){for(g=c;g<=e;g++)for(h=d;h<=f;h++){if(g==c|g==e&&h==d|h==f)continue;if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)continue a;}b++;}return b;}

들여 쓰기 :

int a(String...a){
    a=a[0].split("\n");
    int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();
    for(;c<j;c++)
        for(d=0;d<i;d++)
            for(e=c+2;++e<j&e<c+24;)
                a:for(f=d+3;++f<i&f<d+24;){
                    for(g=c;g<=e;g++)
                        for(h=d;h<=f;h++){
                            if(g==c|g==e&&h==d|h==f)
                                continue;
                            if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)
                                continue a;
                        }
                    b++;
                }
    return b;
}

전체 프로그램 :

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class B {

    public static void main(String[] args) throws FileNotFoundException {
        String blocks = new BufferedReader(new FileReader(args[0])).lines().reduce((a,b)->a+"\n"+b).get();
        System.out.println(new B().a(blocks));
    }

    int a(String...a){
        a=a[0].split("\n");
        int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();
        for(;c<j;c++)
            for(d=0;d<i;d++)
                for(e=c+2;++e<j&e<c+24;)
                    a:for(f=d+3;++f<i&f<d+24;){
                        for(g=c;g<=e;g++)
                            for(h=d;h<=f;h++){
                                if(g==c|g==e&&h==d|h==f)
                                    continue;
                                if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)
                                    continue a;
                            }
                        b++;
                    }
        return b;
    }

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