レンガの構造は安定していますか?


24

標準的な石積みのレンガをとして表現しましょう[__](上部が開いているという事実を無視します)。これらのレンガを積み重ねると、レンガの構造では通常のように、他のすべてのレイヤーがレンガの半分だけオフセットされます。

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

したがって、各ブリックには最大で6つの隣接があり、2つのブリックが直接垂直に並ぶことは不可能です。

重要な点は、これらのレンガの配置は迫撃砲ではなく、単に重力によって一緒に保持されることです。したがって、構造内の各ブリックが安定していることが重要です。そうでなければ、構造全体が不安定になります。

個々のブリックが安定する可能性がある3つの方法があります。

  1. 地面のレンガ(レンガの一番下のライン)は安定しています。
  2. 直下に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年

14
私が知っている@JanDvorak誰がゴルフに全体の物理エンジンを望む:P
カルバンの趣味

........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(これらの線を精神的に積み重ねる必要があります。ポイントは、ルールが重心が地面との接触点からはるかにオフセットしている構造を許可するという点です。これを避けるためにそれらを締めることが可能です、物理エンジンを必要とせずに、あなたがそれを感じた場合。)
ナサニエル14年

2
しかし、物理学の真正性は巨大なワームの缶です。安定性が摩擦係数および/または上部のレンガの重量に依存する多くの単純なケースを思い付くことができます。
COTO

10
「安定した」... あわや
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文字ずつジャンプします。これは必要なチェックの2倍を行います(4文字をジャンプするのに十分でしょう)が、ロジックを簡素化します。

チェックは、文字の最後から2番目の行から始まります(最後の行をチェックする必要はありません)。各行で、右から3文字で始まります(右に余計にチェックする必要はありません)。各文字について、周囲の4文字をチェックします。

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

確認する論理条件は多数あります。

  • AとCがブリック文字の場合、Xがサポートされます
  • BとDがブリック文字の場合、Xがサポートされます
  • CとDがブリック文字の場合、Xがサポートされます
  • Xがブリックキャラクターの場合、サポートする必要があります。そうでなければ、構造は不安定です

すべてのブリックキャラクターに[_]LSBセットがあるのは幸運な偶然です。他のすべてのキャラクター.\nは明確です。また、80386の命令セットは、これらの便利な「高」と「低」のレジスタ(持つahalヘルプはチェックを少し並列化、など)。そのため、すべてのチェックは不明瞭なビットのいじりになります。

私は次の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;
}

私はのgolfed実装を含む、(それは主に1対1だ)アセンブリ言語にコードを翻訳strchrして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)畳み込みにゼロが表示されない場合、入力は安定しています。

2つのフラストレーションは

  1. MATLABの既定の畳み込みは、オペランドマトリックスのエッジを超えて実行さ0れ、両方の畳み込みの反対側のコーナーに誤ったsを生成します。畳み込みが有効な領域に出力を制限するには、呼び出しに,'valid'(8バイト)を追加する必要conv2があります

  2. 空の文字列のケースを処理すると、12バイトが追加されます。


6

JavaScript(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が...arg関数の最後の引数としてバリアドをキャプチャすることを許可していることは知っていますが、この方法でES6が使用されるのを見たことはありません。
COTO

@COTOのcodegolf.stackexchange.com/a/37723/21348、ユースケース2(それは非常に一般的ですが、私は私の答えの多分80%でそれを使用)
edc65

スノファガン。{:}MATLABと同じです。これは非常に便利です。ありがとう。:)
COTO 14年

1

Python 279

私はコードゴルフの挑戦がかなり下手だと思うし、そのために間違った言語を使うかもしれません:Dしかし、私は簡単に読むことができるコードが大好きです:)ところで私はより少ないバイトを使用するPythonコードを見たいです!

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
通常、使用する代わりに<>、を使用します!=
イーサンビアライン14年

@EthanBierleinは確かではありませんでしたが、はい!=はtgeが望ましい方法です
Wikunia 14年

1

JavaScript 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

Python、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.