벽돌 구조는 안정적입니까?


24

표준 벽돌 벽돌 을 표현해 봅시다 [__](그리고 꼭대기가 열려 있다는 사실을 무시하십시오). 이 벽돌이 쌓이면 벽돌 구성에서 평소와 같이 다른 모든 층이 벽돌 반으로 오프셋됩니다.

  [__][__][__][__]
[__][__][__][__]  
  [__][__][__][__]
[__][__][__][__]  

따라서 각 벽돌에는 최대 6 개의 이웃이 있으며 두 개의 벽돌을 세로로 직접 정렬하는 것은 불가능합니다.

요점은이 벽돌의 배열은 모르타르 가 아니라 중력에 의해 함께 유지된다는 것입니다. 따라서 구조물의 각 벽돌이 안정적이어야하며, 그렇지 않으면 전체 구조물이 불안정합니다.

개별 벽돌이 안정 될 수있는 세 가지 방법이 있습니다.

  1. 바닥에있는 벽돌 (가장 낮은 벽돌)은 안정적입니다.
  2. 바로 아래에 두 개의 벽돌이있는 벽돌은 안정적입니다.

      [__]   <- this brick is stable
    [__][__] <- because these bricks hold it up
    
  3. 같은 측면에 벽돌이 위와 아래에있는 벽돌은 안정적입니다.

      [__]  [__]
    [__]      [__] <- these middle bricks are stable
      [__]  [__]      because the upper and lower bricks clamp them in
    
    [__]          [__]
      [__]      [__]   <- these middle bricks are NOT stable
        [__]  [__]
    

이러한 규칙에서 우리는 예를 들어

  [__][__][__][__]
[__][__][__][__]  
  [__][__][__][__]
[__][__][__][__]  

오른쪽 상단 벽돌이 불안정하기 때문에 불안정합니다.

벽돌 구조는 모든 벽돌이 안정적인 경우에만 안정적입니다.

도전

당신의 임무는 벽돌 구조 문자열을 받아 구조가 안정적인 경우 진실한 값을 반환하고 불안정하면 거짓 값을 반환하는 함수를 작성하는 것입니다. ( 진실 / 거짓 정의 )

입력 문자열은 임의로 클 수 있지만 항상 벽돌이없는 영역을 채우는 공간이있는 직사각형 문자 그리드입니다. 문자 그리드 너비는 4로 나눌 수 있지만 높이는 홀수이거나 짝수 일 수 있습니다.

브릭 그리드는 항상 왼쪽 하단 브릭 위치의 위와 오른쪽으로 확장됩니다.

         .
         .
         .
  BRK?BRK?BRK?BRK?  
BRK?BRK?BRK?BRK?BRK?
  BRK?BRK?BRK?BRK?  
BRK?BRK?BRK?BRK?BRK? . . .
  BRK?BRK?BRK?BRK?  
BRK?BRK?BRK?BRK?BRK?

구조에 따라 각각 BRK?벽돌을 나타냅니다 ([__] ) 또는 빈 공간 (4 칸)을 나타냅니다.

하프 브릭 캐비티는 문자 그리드가 직사각형이되도록 공백으로 채워져 있습니다.

채점

바이트 단위 의 가장 짧은 코드 이깁니다.

노트

  • 원하는 경우 사용할 수 있습니다 . 공백 대신 공백 대신 문자를 .
  • 빈 문자열은 안정적인 것으로 간주됩니다.
  • 언어에 함수가 없으면 명명 된 문자열 변수를 입력으로 사용하고 결과를 다른 변수에 할당 할 수 있습니다.
  • 언어에 문자열이 없으면 입력에 적합한 것으로 보일 수 있습니다.

테스트 사례

빈 줄로 구분 된 다양한 테스트 사례. .빈 공간을위한 공간 대신 명확성 을 위해 사용됩니다.

안정된:

[__]

..[__]..
[__][__]

........[__]........
......[__][__]......
........[__]........

..[__][__]..
[__][__][__]
..[__][__]..
[__]....[__]

............[__]..
..[__][__][__][__]
[__][__][__][__]..
..[__][__][__][__]
[__][__][__][__]..

..[__]........[__]..
[__][__][__][__][__]
..[__][__][__][__]..
....[__][__][__]....
......[__][__]......
........[__]........

불안정한:

..[__]..
........

..[__]..
[__]....

..[__]..
....[__]

..[__][__]..
[__]....[__]
..[__][__]..
[__]....[__]

..[__][__][__][__]
[__][__][__][__]..
..[__][__][__][__]
[__][__][__][__]..

[__][__][__][__][__]
..[__][__][__][__]..
....[__][__][__]....
......[__][__]......
........[__]........

7
나는 꽤 현실 ;-) 일치하지 않는 안정성의 당신의 정의를 확신
존 드보락

14
@JanDvorak 알고 있지만 누가 물리 엔진 전체를 골프로 만들고 싶을까요? : P
Calvin 's Hobbies

........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(정신적으로 그 선들을 서로 위에 쌓아야합니다. 요점은 규칙에 따라 무게 중심이지면과의 접촉점으로부터 멀리 떨어져있는 구조물을 허용한다는 것입니다. 이것을 피하기 위해 조일 수 있어야합니다 , 물리 엔진이 필요하지 않은 경우, 느낌이
Nathaniel

2
그러나 물리학의 Verisimilitude는 거대한 웜 캔입니다. 안정성은 마찰 계수 및 / 또는 상단의 벽돌 무게에 의존하는 많은 간단한 경우를 생각해 낼 수 있습니다.
COTO

10
"안정된"… heh
wchargin

답변:


12

80386 기계 코드, 98

코드:

60 8b f1 8b f9 b0 0a f2 ae 8b ef 2b ee b0 00 f2
ae 2b fe 83 ef 02 2b fd 72 41 03 f7 2b f5 33 c9
8a 7c 6e fc 8a 1c 6e b1 02 33 d2 8b c7 f7 f5 83
fa 02 75 03 b7 00 41 8a 66 fc 8a 06 3b fd 7d 02
33 c0 23 c3 0a c4 22 df 0b c3 f6 44 2e fe 01 74
04 d1 e8 73 06 2b f1 2b f9 73 c5 61 d1 d0 83 e0
01 c3

이 코드는 ASCII 아트를 처음부터 끝까지 스캔하여 한 번에 2 자씩 점프합니다. 이것은 필요한 검사의 두 배를 수행하지만 (4 자 점프하기에 충분) 논리를 단순화합니다.

확인은 문자의 마지막 행부터 시작합니다 (마지막 행을 확인할 필요가 없습니다). 각 줄에서 오른쪽에서 3 자로 시작합니다 (오른쪽으로 너무 멀리 확인할 필요가 없음). 각 문자마다 4 개의 주변 문자를 확인합니다.

A...B
..X..
C...D

확인해야 할 논리 조건이 많이 있습니다.

  • A와 C가 벽돌 문자이면 X가 지원됩니다
  • B와 D가 벽돌 문자이면 X가 지원됩니다
  • C와 D가 벽돌 문자이면 X가 지원됩니다
  • X가 벽돌 문자이면 지원되어야합니다. 그렇지 않으면 구조가 불안정하다

모든 브릭 캐릭터에 [_]LSB가 설정되어 있다는 것은 운이 좋은 우연입니다 . 다른 모든 문자 .\n는 명확합니다. 또한, 80386 명령어 세트는 (이 편리한 "높음"및 "낮음"의 레지스터를 갖고 ah,al 도움말 검사를 조금 병렬화 등). 따라서 모든 검사는 약간의 불분명 한 비트 조정에 해당합니다.

다음 C 코드에서 시작했습니다.

int check(const char* ptr)
{
    int width, result = 0, pos;

    width = strchr(ptr, '\n') - ptr + 1;
    pos = strlen(ptr) - 1 - width; // pos points to the B character
    ptr += pos - width;

    while (pos >= 0)
    {
        int a = ptr[-4];
        int c = ptr[-4 + 2 * width];
        int b = ptr[0];
        int d = ptr[0 + 2 * width];
        int ab = a << 8 | b;
        int cd = c << 8 | d;
        if (pos < width)
            ab = 0; // A and B don't exist; set them to 0
        int jump = 2; // distance to next brick
        if (pos % width == 2) // leftmost brick?
        {
            cd &= 0xff; // C doesn't exist; set it to 0
            ++jump;
        }
        int support_v = ab & cd;
        support_v = support_v | support_v >> 8; // data in LSB
        int support_h = cd & cd >> 8; // data in LSB
        int support = (support_v | support_h) & 1;
        if (!support & ptr[-2 + width])
            goto UNSTABLE;
        ptr -= jump;
        pos -= jump;
    }
    return 1;
UNSTABLE:
    return 0;
}

strchrand 의 골프 구현을 포함하여 코드를 어셈블리 언어 (대부분 일대일)로 변환했습니다 strlen. 다음 소스 코드는 MS Visual Studio에서 내 게시물 상단의 기계 코드로 변환됩니다.

__declspec(naked) int __fastcall check(const char* ptr) // MS Visual Studio syntax
{
    _asm
    {
        pushad;

        // ecx = ptr
        mov esi, ecx; // esi = ptr
        mov edi, ecx
        mov al, 10;
        repne scasb;
        mov ebp, edi;
        sub ebp, esi; // ebp = width

        mov al, 0;
        repne scasb;
        sub edi, esi;
        sub edi, 2;
        sub edi, ebp; // edi = pos
        jc DONE;

        add esi, edi;
        sub esi, ebp;

        xor ecx, ecx; // ecx = jump

    LOOP1:
        mov bh, [esi - 4 + 2 * ebp]; // bh = C
        mov bl, [esi + 2 * ebp]; // bl = D
        // bx = CD
        mov cl, 2;
        xor edx, edx
        mov eax, edi
        div ebp;
        cmp edx, 2;
        jne LABEL2;
        mov bh, 0
        inc ecx;
    LABEL2:

        mov ah, [esi - 4]; // ah = A
        mov al, [esi]; // al = B
        // ax = AB
        cmp edi, ebp;
        jge LABEL3;
        xor eax, eax;
    LABEL3:

        and eax, ebx; // ax = support_v
        or al, ah; // al = support_v
        and bl, bh; // bl = support_h
        or eax, ebx; // eax = support
        test byte ptr[esi - 2 + ebp], 1;
        jz LABEL4; // not a brick character - nothing to check
        shr eax, 1; // shift the LSB into the carry flag
        jnc DONE;
    LABEL4:
        sub esi, ecx;
        sub edi, ecx;
        jnc LOOP1;

    DONE:
        // here, the result is in the carry flag; copy it to eax
        popad;
        rcl eax, 1;
        and eax, 1;
        ret;
    }
}

7

MATLAB-119 바이트

축소 :

function c=S(B),f=@(m)conv2([(0&B(1,:))+46;B]+3,m,'valid');M=[2 0;-1 -1;0 2];c=isempty(B)||all(all(f(M)&f(fliplr(M))));

넓히는:

function c = isstable( B )

f = @(m) conv2( [(0&B(1,:))+46; B] + 3, m, 'valid' );
M = [2 0;-1 -1;0 2];
c = isempty( B ) || all(all( f( M ) & f(fliplr( M )) ));

샘플 사용법 :

S4 = [  '..[__][__]..'; ...
        '[__][__][__]'; ...
        '..[__][__]..'; ...
        '[__]....[__]'];

fprintf( 'S4: %d\n', isstable( S4 ) );

S4: 1

U4 = [  '..[__][__]..'; ...
        '[__]....[__]'; ...
        '..[__][__]..'; ...
        '[__]....[__]'];

fprintf( 'U4: %d\n', isstable( U4 ) );

U4: 0

세부

루틴 .은 입력 행렬의 맨 위에 행을 추가 한 다음 ASCII 문자 코드에 3을 추가하여 숫자 행렬로 변환합니다. 이 변환이 주어지면 커널과 2D 컨볼 루션

 2  0
-1 -1
 0  2

0문자 패턴 이 있는 위치에 행렬을 생성합니다.

 . *
 _ _
 * .

*"모든 문자" 를 나타내는 것으로 표시됩니다. 커널이 구성 되었기 때문에 이것은 유효한 문자 패턴입니다 0.

커널의 왼쪽-오른쪽 뒤집힌 버전으로 동일한 컨볼 루션이 수행됩니다.

 * .
 _ _
 . *

입력이 i ) 비어 있거나 ii ) 회선에 0이 표시되지 않으면 입력이 안정적 입니다.

두 가지 좌절은

  1. MATLAB의 기본 컨볼 루션은 피연산자 행렬의 가장자리를지나 실행되므로 0두 컨볼 루션의 반대쪽 구석에 오류가 발생하여 컨볼 루션이 유효한 영역으로 출력을 제한 ,'valid'하기 위해 (8 바이트)를 추가해야 conv2합니다.

  2. 빈 문자열을 처리하면 12 바이트가 추가됩니다.


6

자바 스크립트 (E6) 131261

F=a=>
  [...a].every((e,p)=>
    !(d={']':-3,'[':3}[e])
     |a[p-r]=='_'&(x=a[p+r]!=' ')
     |a[p-r+d]=='_'&(y=a[p+r+d]!=' ')
     |x&y
  ,r=a.search(/\n/)+1)

FireFox / FireBug 콘솔에서 테스트

;['[__]', '  [__]  \n[__][__]', '        [__]        \n      [__][__]      \n        [__]        ',
 '  [__][__]  \n[__][__][__]\n  [__][__]  \n[__]    [__]',
 '            [__]  \n  [__][__][__][__]\n[__][__][__][__]  \n  [__][__][__][__]\n[__][__][__][__]  ',
 '  [__]        [__]  \n[__][__][__][__][__]\n  [__][__][__][__]  \n    [__][__][__]    \n      [__][__]      \n        [__]        ']
.forEach(x => console.log(x+'\n'+F(x)))

;['  [__]  \n        ', '  [__]  \n[__]    ' ,'  [__]  \n    [__]',
 '  [__][__]  \n[__]    [__]\n  [__][__]  \n[__]    [__]',
 '  [__][__][__][__]\n[__][__][__][__]  \n  [__][__][__][__]\n[__][__][__][__]  ',
 '[__][__][__][__][__]\n  [__][__][__][__]  \n    [__][__][__]    \n      [__][__]      \n        [__]        ']
.forEach(x => console.log(x+'\n'+F(x)))

산출

    [__]
true

  [__]  
[__][__]
true

        [__]        
      [__][__]      
        [__]        
true

  [__][__]  
[__][__][__]
  [__][__]  
[__]    [__]
true

            [__]  
  [__][__][__][__]
[__][__][__][__]  
  [__][__][__][__]
[__][__][__][__]  
true

  [__]        [__]  
[__][__][__][__][__]
  [__][__][__][__]  
    [__][__][__]    
      [__][__]      
        [__]        
true

  [__]  
false

  [__]  
[__]    
false

  [__]  
    [__]
false

  [__][__]  
[__]    [__]
  [__][__]  
[__]    [__]
false

  [__][__][__][__]
[__][__][__][__]  
  [__][__][__][__]
[__][__][__][__]  
false

[__][__][__][__][__]
  [__][__][__][__]  
    [__][__][__]    
      [__][__]      
        [__]        
false

언 골프

F=a=>(
  a=a.replace(/__/g,'').replace(/  /g,'.'),
  r=a.search(/\n/)+1,
  [...a].every((e,p)=>
    e < '0' ||
    (e ==']'
    ? // stable right side
     a[p-r]=='[' & a[p+r]!='.' 
     |
     a[p-r-1]==']' & a[p+r-1]!='.' 
     |
     a[p+r]!='.' & a[p+r-1] != '.'
    : // stable left side
     a[p-r]==']' & a[p+r]!='.' 
     |
     a[p-r+1]=='[' & a[p+r+1]!='.' 
     |
     a[p+r]!='.' & a[p+r+1] != '.'
    )  
  )
)

무엇 않습니다 [...a]당신이 내 물어 마음을하지 않는 경우, 어떻게? 나는 ES6이 ...argvariadics를 캡처하는 함수의 마지막 인수로 허용 한다는 것을 알고 있지만, 이런 식으로 사용되는 것을 본 적이 없습니다.
COTO

@COTO codegolf.stackexchange.com/a/37723/21348 , 유스 케이스 2 (매우 일반적이며, 아마도 내 답변의 80 %에서 사용합니다)
edc65

수노 파군. {:}MATLAB에서 와 마찬가지로 . 매우 유용 할 것입니다. 감사. :)
COTO

1

파이썬 279

나는 코드 골프 도전에 꽤 나쁘고 어쩌면 나는 그것에 대해 잘못된 언어를 사용한다고 생각한다 : D 그러나 나는 쉽게 읽을 수있는 코드를 좋아한다 :) Btw 적은 바이트를 사용하는 파이썬 코드를보고 싶다!

def t(b):
    r=b.split()
    l=len(r[0])
    r=['.'*l]+r
    for i in range(len(r)-2,0,-1):
        r[i]+='...'
        for j in range(l):
            if(r[i][j]=='['):
                if(r[i+1][j]<>'_'or(r[i+1][j+3]<>'_'and r[i-1][j]<>'_'))and(r[i+1][j+3]<>'_'or r[i-1][j+3]<>'_'):
                    return False
    return True

가능한 예 :

A = "..[__][__][__][__]\n\
[__][__][__][__]..\n\
..[__][__][__][__]\n\
[__][__][__][__].."
print t(A) #False

B = "..[__]........[__]..\n\
[__][__][__][__][__]\n\
..[__][__][__][__]..\n\
....[__][__][__]....\n\
......[__][__]......\n\
........[__]........"
print t(B) #True

나는 실제로 입력 캔은 어떤 문자를 사용하지만, 내 코드 내부의 점을 사용하지 않는 _[
Wikunia

1
일반적으로을 사용하는 대신을 사용 <>합니다 !=.
Ethan Bierlein

@EthanBierlein은 확실하지 않지만 예 !=는 선호되는 방법입니다
Wikunia

1

자바 스크립트 2 (ES6) - 148 151 바이트

F=s=>s.split(/\n/).every((b,i,a)=>(r=1,b.replace(/]/g,(m,o)=>(T=z=>(a[i-1+(z&2)]||[])[o-z%2*3]=='_',r&=i>a.length-2?1:T(2)?T(3)|T(0):T(3)&T(1))),r))

줄 바꿈으로 분리 된 벽돌 행의 문자열을 예상합니다 (참고 : 행을 구분하기 위해 "|"와 같은 다른 구분 문자를 사용할 수 있으면 1 바이트 더 짧아 질 수 있습니다).

Firefox 콘솔에서 다음을 사용하여 테스트하십시오.

F('..[__]......\n[__][__][__]\n..[__][__]..\n[__]....[__]'); // false
F('..[__][__]..\n[__][__][__]\n..[__][__]..\n[__]....[__]'); // true

0

파이썬, 209

def s(b):
 c=b.split("\n");s="".join(c);l=len(c[0]);t=" "*l+s+"]]"*l;a=lambda x,y,z:t[x+l*y+z]=="]"
 return all([(a(i,1,1)&a(i,1,5))or(a(i,-1,1)&a(i,1,1))or(a(i,-1,5)&a(i,1,5))for i,x in enumerate(t)if x=="["])

테스트 :

towers=(
"[__]",

"..[__]..\n"
"[__][__]",

"........[__]........\n"
"......[__][__]......\n"
"........[__]........",

"..[__][__]..\n"
"[__][__][__]\n"
"..[__][__]..\n"
"[__]....[__]",

"............[__]..\n"
"..[__][__][__][__]\n"
"[__][__][__][__]..\n"
"..[__][__][__][__]\n"
"[__][__][__][__]..",

"..[__]........[__]..\n"
"[__][__][__][__][__]\n"
"..[__][__][__][__]..\n"
"....[__][__][__]....\n"
"......[__][__]......\n"
"........[__]........",

"..[__]..\n"
"........",

"..[__]..\n"
"[__]....",

"..[__]..\n"
"....[__]",

"..[__][__]..\n"
"[__]....[__]\n"
"..[__][__]..\n"
"[__]....[__]",

"..[__][__][__][__]\n"
"[__][__][__][__]..\n"
"..[__][__][__][__]\n"
"[__][__][__][__]..",

"[__][__][__][__][__]\n"
"..[__][__][__][__]..\n"
"....[__][__][__]....\n"
"......[__][__]......\n"
"........[__]........",
)
[s(x) for x in towers]

산출:

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