โครงสร้างอิฐมีความเสถียรหรือไม่?


24

ให้เป็นตัวแทนของอิฐก่ออิฐมาตรฐานเป็น[__](และไม่สนใจความจริงที่ว่าด้านบนเปิด) เมื่อก้อนอิฐเหล่านี้ถูกซ้อนทับกันชั้นอื่น ๆ จะถูกชดเชยครึ่งอิฐเหมือนปกติในการก่อสร้างอิฐ:

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

ดังนั้นอิฐแต่ละก้อนมีเพื่อนบ้านได้มากที่สุดหกคนและเป็นไปไม่ได้ที่อิฐสองก้อนจะเรียงตัวในแนวตั้งได้โดยตรง

จุดสำคัญคือการจัดเรียงของอิฐเหล่านี้ไม่ได้ถูกทำให้ตายแต่มีเพียงแรงโน้มถ่วง ดังนั้นสิ่งสำคัญคืออิฐแต่ละก้อนในโครงสร้างมีความเสถียรไม่เช่นนั้นโครงสร้างทั้งหมดจะไม่เสถียร

อิฐมีความเป็นไปได้สามทาง:

  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
ฉันค่อนข้างมั่นใจว่าคำจำกัดความความมั่นคงของคุณไม่ตรงกับความเป็นจริง ;-)
John Dvorak

14
@JanDvorak ฉันรู้ แต่ผู้ที่ต้องการกอล์ฟเป็นเครื่องมือฟิสิกส์ทั้งหมด: P
Calvin's Hobbies

........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(คุณจะต้องเรียงซ้อนเส้นใจเหล่านั้นไว้ด้านบนจุดที่กฎของคุณอนุญาตให้โครงสร้างที่จุดศูนย์กลางของแรงโน้มถ่วงอยู่ห่างไกลจากจุดที่สัมผัสกับพื้นดินมากเกินไป โดยไม่จำเป็นต้องใช้เครื่องมือฟิสิกส์ถ้าคุณรู้สึกว่ามัน)
นาธาเนียล

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 art ตั้งแต่ต้นจนจบเริ่มต้นกระโดดครั้งละ 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;
}

ฉันแปลรหัสเพื่อประกอบภาษา (เป็นส่วนใหญ่แบบหนึ่งต่อหนึ่ง) รวมทั้งการดำเนินงานของแข็งแรงเล่นกอล์ฟและ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 ไบต์

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

ขยาย:

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

รายละเอียด

รูทีนจะผนวกแถวของ.ถึงด้านบนสุดของเมทริกซ์อินพุตจากนั้นแปลงเป็นเมทริกซ์ตัวเลขโดยเพิ่ม 3 ลงในรหัสอักขระ ASCII รับการแปลงนี้ convolution 2D กับเคอร์เนล

 2  0
-1 -1
 0  2

ให้เมทริกซ์กับ0ที่ตำแหน่งที่รูปแบบอักขระ

 . *
 _ _
 * .

มีอยู่โดย*แสดง "อักขระใด ๆ " เนื่องจากการสร้างเคอร์เนลนี่เป็นรูปแบบอักขระที่ถูกต้องเท่านั้นที่จะให้0เนื่องจากการก่อสร้างของเคอร์เนลนี้เป็นเพียงรูปแบบอักขระที่ถูกต้องที่จะให้ผลผลิต

การบิดที่เหมือนกันจะดำเนินการกับเคอร์เนลเวอร์ชันพลิกด้านซ้ายขวาเพื่อตรวจจับ

 * .
 _ _
 . *

อินพุตมีความเสถียรถ้าi ) มันว่างเปล่าหรือii ) ไม่มีศูนย์ปรากฏในการบิด

สองผิดหวังคือ

  1. การแปลงค่าเริ่มต้นของ MATLAB จะวิ่งผ่านขอบของตัวถูกดำเนินการทำให้เกิดข้อผิดพลาด0ในมุมตรงข้ามสำหรับทั้งคู่ซึ่งต้องเพิ่ม,'valid'(8 ไบต์) เพื่อconv2เรียกใช้เพื่อ จำกัด เอาต์พุตในพื้นที่ที่การแปลงนั้นถูกต้อง

  2. การจัดการกรณีสตริงว่างเพิ่ม 12 ไบต์


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

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

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]ทำถ้าคุณไม่คิดขอให้ฉันได้อย่างไร ฉันรู้ว่า ES6 อนุญาตให้...argเป็นอาร์กิวเมนต์สุดท้ายของฟังก์ชั่นในการจับภาพตัวแปร แต่ฉันไม่เคยเห็นมันใช้วิธีนี้
COTO

@COTO codegolf.stackexchange.com/a/37723/21348ใช้ case 2 (เป็นเรื่องธรรมดามากฉันใช้มันใน 80% ของคำตอบของฉัน)
edc65

Sunofagun เหมือน{:}ใน MATLAB มันจะมีประโยชน์มาก ขอบคุณ :)
COTO

1

Python 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 ไม่แน่ใจ แต่ใช่!=เป็นวิธีที่ต้องการ
tge

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.