Tuğla yapı sağlam mı?


24

Standart bir tuğla örgüyü şu şekilde temsil edelim: [__](ve üst kısmın açık olduğu gerçeğini görmezden gelin ). Bu tuğlalar istiflendiğinde diğer her katman tuğla yapımında olduğu gibi yarım tuğla ile dengelenir:

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

Böylece her tuğla en fazla altı komşuya sahiptir ve iki tuğlanın doğrudan dikey olarak sıralanması imkansızdır.

Kilit nokta, bu tuğlaların düzenlemelerinin harç değil , sadece yerçekimi tarafından bir arada tutulmasıdır. Bu nedenle, yapıdaki her tuğlanın sabit olması önemlidir, aksi takdirde bütün yapı kararsızdır.

Bir tuğlanın sabit kalmasının üç yolu vardır:

  1. Yerdeki tuğlalar (en alçak tuğla çizgisi) sabittir.
  2. Doğrudan altında iki tuğla bulunan herhangi bir tuğla sabittir:

      [__]   <- this brick is stable
    [__][__] <- because these bricks hold it up
    
  3. Aynı tarafta hem üstünde hem altında bir tuğla bulunan tuğlalar sabittir:

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

Bu kurallardan örneğin düzenlemeyi görebiliriz.

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

kararsızdır, çünkü sağ üst tuğla kararsızdır, tek gereken budur.

Bir tuğla yapısı ancak tüm tuğlaları sabit olduğunda sabittir.

Meydan okuma

Senin görevin bir tuğla yapı dizgisini alan ve yapı sabit olduğunda bir hakikat değeri ve dengesizse sahte bir değer döndüren bir işlev yazmaktır. ( truthy / falsy tanımı )

Giriş dizisi isteğe bağlı olarak büyük olabilir, ancak boşlukları doldurma alanları tuğla boşluklarıyla her zaman dikdörtgen bir karakter ızgarası olacaktır. Karakter ızgarasının genişliği 4 ile bölünebilir ancak yükseklik tek veya çift olabilir.

Tuğla ızgara her zaman sol alt tuğla pozisyonunun yukarısında ve sağında uzanır:

         .
         .
         .
  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?

Yapıya bağlı olarak, her biri BRK?bir tuğlayı ( [__]) veya boş bir alanı (4 boşluk) temsil eder .

Yarım tuğla boşluklarının karakter ızgarasının dikdörtgen olmasını sağlamak için boşluklarla doldurulduğuna dikkat edin.

puanlama

Bayt cinsinden en kısa kod kazanır.

notlar

  • İstenirse ., boş karakter yerine boşluk yerine kullanabilirsiniz .
  • Boş dize kararlı olarak kabul edilir.
  • Dilinizde işlev yoksa, giriş olarak adlandırılmış bir string değişkeni kullanabilir ve sonucu başka bir değişkene atayabilirsiniz.
  • Dilinizde dizeler yoksa, giriş için uygun olanı yapabilirsiniz.

Test Kılıfları

Boş satırlarla ayrılmış çeşitli test durumları. .Boşluklar için boşluk yerine açıklık kullanılır.

Kararlı:

[__]

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

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

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

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

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

Kararsız:

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

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

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

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

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

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

7
Kararlılık tanımınızın gerçeğe uymadığından eminim ;-)
John Dvorak

14
@JanDvorak Biliyorum ama kim bütün bir fizik motorunu golf
oynamak ister

........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(bu çizgileri zihinsel olarak üst üste istiflemeniz gerekir. Kurallarınızın, ağırlık merkezi yerle temas noktalarından çok uzak olan yapılara izin vermesi, kurallarınızın kurallara uygun olmasına izin verir. , eğer bir fizik motoruna ihtiyaç duymadan, eğer istersen.)
Nathaniel

2
Bununla birlikte, fizikteki kirlilik büyük bir solucan kutusudur. İstikrar sürtünme katsayısına ve / veya üstteki tuğlaların ağırlığına bağlı olduğu birçok basit durum ortaya çıkabilir.
COTO

10
"kararlı"… heh
wchargin

Yanıtlar:


12

80386 makine kodu, 98

Kod:

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

Kod ASCII resmini baştan sona tarar ve her seferinde 2 karakter atlar. Bu, gerekli kontrolleri iki kez yapar (4 karakter atlamak yeterlidir), ancak mantığı basitleştirir.

Kontrol etme, sondan sonraki karakter satırında başlar (son satırı kontrol etmenize gerek yoktur). Her satırda, sağdan 3 karakter başlar (sağdan çok fazla kontrol etmeye gerek yoktur). Her karakter için, 4 çevreleyen karakteri kontrol eder:

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

Kontrol etmek için bir sürü mantıksal koşul var:

  • A ve C tuğla karakterleri ise, X desteklenir
  • B ve D tuğla karakterleri ise, X desteklenir
  • C ve D tuğla karakterleri ise, X desteklenir
  • X bir tuğla karakteri ise, desteklenmesi gerekir; Aksi takdirde yapı kararsız

Tüm tuğla karakterlerin [_]LSB setlerine sahip olması şanslı bir tesadüf ; diğer tüm karakterlerde .\nnet. Buna ek olarak, 80.386 komut kümesi bu kullanışlı "en yüksek" ve "düşük" register (vardır ah, alyardım çekleri biraz parallelize, vs). Bu yüzden tüm kontroller biraz gizli bir işe yaramazlığa işaret ediyor.

Aşağıdaki C kodundan başladım:

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

Ben golfed uygulanması da dahil olmak üzere (bu bire bir çoğunlukla var) derleme dile kod tercüme strchrve strlen. Aşağıdaki kaynak kod MS Visual Studio tarafından yazımın en üstündeki makine koduna çevrilmiş.

__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 bayt

minified:

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

Expanded:

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

Örnek Kullanım:

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

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

S4: 1

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

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

U4: 0

ayrıntılar

Rutin ., giriş matrisinin en üstüne bir satır ekler , ardından ASCII karakter kodlarına 3 ekleyerek sayısal bir matrise dönüştürür. Bu dönüşüm göz önüne alındığında, çekirdekli bir 2D evrişimi

 2  0
-1 -1
 0  2

0karakter deseninin bulunduğu yerlerde bir matris verir

 . *
 _ _
 * .

ile, mevcut olan *"herhangi bir karakter" temsil eder. Çekirdeğin yapısından dolayı, bu a'yı üretecek tek geçerli karakter kalıbıdır 0.

Aynı çekirdeğin saptanması için çekirdeğin sol-sağ çevrilmiş versiyonu ile gerçekleştirilir.

 * .
 _ _
 . *

Bir giriş ya i ) boşsa ya da ii ) her iki evrişimde de sıfır görünmüyorsa sabittir .

İki hayal kırıklığı

  1. MATLAB'ın varsayılan konvolüsyonu operand matrisinin kenarlarından geçerek 0her iki konvolüsyon için karşıt köşelerde hatalı s üreterek , çıktının geçerli olduğu alana sınırlandırmak ,'valid'için conv2çağrılması için (8 bayt) eklenmesini gerektirmiştir .

  2. Boş dize harfini kullanmak, 12 bayt ekler.


6

JavaScript (E6) 131 261

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 konsolunda test edin

;['[__]', '  [__]  \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)))

Çıktı

    [__]
true

  [__]  
[__][__]
true

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

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

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

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

  [__]  
false

  [__]  
[__]    
false

  [__]  
    [__]
false

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

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

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

Ungolfed

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]Benim sormamda sakınca yoksa ne yapar ? ES6'nın, ...argdeğişkenleri yakalama işlevinin son argümanı olarak izin verdiğini biliyorum , ancak bu şekilde kullanıldığını hiç görmedim.
COTO

@COTO codegolf.stackexchange.com/a/37723/21348 , vaka 2'yi kullanın (çok yaygındır, cevaplarımın% 80'inde kullanırım)
edc65

Sunofagun. Tıpkı {:}MATLAB'daki gibi . Bu çok faydalı olacak. Teşekkürler. :)
COTO

1

Python 279

Kod golf zorluklarında oldukça kötüyüm ve belki bunun için yanlış dilleri kullanıyorum: D Ama kolayca okunabilen kodu seviyorum :) Btw Daha az byte kullanan bir python kodu görmek istiyorum!

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

Muhtemel örnekler:

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

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

_[
Kodumun

1
Genellikle kullanmak yerine <>kullanırsınız !=.
Ethan Bierlein,

@EthanBierlein emin değildi, ama evet !=tge tercih edilen bir yol
Wikunia

1

JavaScript 2 (ES6) - 148 151 bayt

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

Bir satır newline ayrılmış tuğla satırları bekler (not: satırları ayırmak için "|" gibi farklı bir ayırıcı karakter kullanabilirsek bu 1 bayt daha kısa yapılabilir).

Firefox konsolunda aşağıdakilerle test edin:

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=="["])

Testler:

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]

Çıktı:

[True, True, True, True, True, True, False, False, False, False, False, False]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.