La struttura in mattoni è stabile?


24

Rappresentiamo un mattone in muratura standard come [__](e ignoriamo il fatto che la parte superiore è aperta). Quando questi mattoni vengono impilati, ogni altro strato viene spostato di mezzo mattone, come al solito nella costruzione di mattoni:

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

Quindi ogni mattone ha al massimo sei vicini ed è impossibile che due mattoni si allineino direttamente in verticale.

Il punto chiave è che le disposizioni di questi mattoni non sono mortali , ma semplicemente tenute insieme dalla gravità. Quindi è importante che ogni mattone nella struttura sia stabile, altrimenti l'intera struttura è instabile.

Esistono tre modi in cui un singolo mattone può essere stabile:

  1. Qualsiasi mattone sul terreno (la linea più bassa di mattoni) è stabile.
  2. Qualsiasi mattone che ha due mattoni direttamente sotto di esso è stabile:

      [__]   <- this brick is stable
    [__][__] <- because these bricks hold it up
    
  3. Qualsiasi mattone che ha un mattone sia sopra che sotto sullo stesso lato è stabile:

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

Da queste regole possiamo vedere, ad esempio, la disposizione

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

è instabile perché il mattone in alto a destra è instabile, il che è tutto ciò che serve.

Una struttura in mattoni è stabile solo se tutti i suoi mattoni sono stabili.

Sfida

Il tuo compito è scrivere una funzione che accetta una stringa di struttura in mattoni e restituisce un valore di verità se la struttura è stabile e un valore di falsa se instabile. ( definizione di verità / falsa )

La stringa di input può essere arbitrariamente grande ma sarà sempre una griglia rettangolare di caratteri, con spazi che riempiono le aree prive di mattoni. La larghezza della griglia del personaggio sarà divisibile per 4 ma l'altezza può essere pari o dispari.

La griglia del mattone si estende sempre sopra e a destra della posizione del mattone in basso a sinistra:

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

A seconda della struttura, ognuno BRK?rappresenta uno [__]spazio in mattoni ( ) o vuoto (4 spazi).

Si noti che le cavità del mezzo mattone sono riempite di spazi per garantire che la griglia del personaggio sia rettangolare.

punteggio

Vince il codice più breve in byte .

Gli appunti

  • Se lo si desidera è possibile utilizzare . posto dello spazio come carattere spazio vuoto.
  • La stringa vuota è considerata stabile.
  • Se la tua lingua non ha funzioni, puoi utilizzare una variabile stringa denominata come input e assegnare il risultato a un'altra variabile.
  • Se la tua lingua non ha stringhe, puoi fare tutto ciò che sembra appropriato per l'input.

Casi test

Vari casi di test, separati da righe vuote. Per chiarezza .viene utilizzato al posto dello spazio per gli spazi vuoti.

Stabile:

[__]

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

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

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

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

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

Instabile:

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

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

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

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

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

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

7
Sono abbastanza sicuro che la tua definizione di stabilità non corrisponda alla realtà ;-)
John Dvorak,

14
@JanDvorak Lo so, ma chi vorrebbe giocare a golf con un intero motore fisico: P
Calvin's Hobbies,

........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(Dovrai impilare mentalmente le linee una sopra l'altra. Il punto è che le tue regole consentono alle strutture il cui baricentro è lontano dal punto di contatto con il terreno. Dovrebbe essere possibile restringerle per evitare questo , senza aver bisogno di un motore fisico, se ne hai avuto voglia.)
Nathaniel,

2
La verosimiglianza in fisica è tuttavia un'enorme lattina di vermi. Si possono trovare molti casi semplici in cui la stabilità dipende dal coefficiente di attrito e / o dal peso dei mattoni in cima.
COTO

10
"stabile" ... heh
wchargin,

Risposte:


12

80386 codice macchina, 98

Il codice:

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

Il codice analizza l'arte ASCII dalla fine all'inizio, saltando 2 caratteri alla volta. Questo fa il doppio dei controlli necessari (sarebbe sufficiente saltare 4 caratteri), ma semplifica la logica.

Il controllo inizia dall'ultima riga di caratteri (non è necessario controllare l'ultima riga). Ad ogni riga, inizia 3 caratteri da destra (non è necessario controllare troppo a destra). Per ogni personaggio, controlla 4 personaggi circostanti:

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

Esistono molte condizioni logiche da verificare:

  • Se A e C sono caratteri in mattoni, X è supportato
  • Se B e D sono caratteri in mattoni, X è supportato
  • Se C e D sono caratteri in mattoni, X è supportato
  • Se X è un personaggio brick, deve essere supportato; altrimenti la struttura è instabile

È una coincidenza fortunata che tutti i personaggi di mattoni [_]abbiano il loro set LSB; tutti gli altri personaggi .\nhanno chiaro. Inoltre, il set di istruzioni 80386 ha questi a portata di mano "alta" e registri "bassi" ( ah, al, ecc), che aiutano parallelizzare i controlli un po '. Quindi tutto il controllo equivale a un po 'oscuro che armeggia.

Ho iniziato dal seguente codice 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;
}

Ho tradotto il codice in linguaggio assembly (è principalmente uno a uno), inclusa un'implementazione golfizzata di strchre strlen. Il seguente codice sorgente è tradotto da MS Visual Studio nel codice macchina nella parte superiore del mio post.

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

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

Allargato:

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

Esempio di utilizzo:

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

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

S4: 1

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

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

U4: 0

Dettagli

La routine aggiunge una riga .all'inizio della matrice di input, quindi si converte in una matrice numerica aggiungendo 3 ai codici di caratteri ASCII. Data questa conversione, una convoluzione 2D con il kernel

 2  0
-1 -1
 0  2

produce una matrice con 0nelle posizioni in cui il modello di carattere

 . *
 _ _
 * .

è presente, con la *rappresentazione di "qualsiasi personaggio". A causa della costruzione del kernel, questo è l'unico modello di carattere valido che produrrà a 0.

Una convoluzione identica viene eseguita con la versione capovolta sinistra-destra del kernel per rilevare

 * .
 _ _
 . *

Un input è stabile se i ) è vuoto, oppure ii ) nessuno zeri appare in nessuna convoluzione.

Sono due frustrazioni

  1. La convoluzione predefinita di MATLAB supera i bordi della matrice dell'operando, producendo 0s errati in angoli opposti per entrambe le convoluzioni, richiedendo ,'valid'di aggiungere (8 byte) per conv2chiamare per limitare l'output nell'area in cui la convoluzione è valida.

  2. La gestione del caso stringa vuota aggiunge 12 byte.


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)

Test nella console 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)))

Produzione

    [__]
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] != '.'
    )  
  )
)

Cosa fa [...a], se non ti dispiace che io ti chieda? So che ES6 consente ...argcome ultimo argomento di una funzione di acquisire variabili, ma non l'ho mai visto usato in questo modo.
COTO

@COTO codegolf.stackexchange.com/a/37723/21348 , utilizzare il caso 2 (è molto comune, lo uso forse nell'80% delle mie risposte)
edc65,

Sunofagun. Proprio come {:}in MATLAB. Sarà molto utile. Grazie. :)
COTO

1

Python 279

Penso di essere abbastanza cattivo nelle sfide del code golf e forse uso le lingue sbagliate per questo: D Ma adoro il codice che può essere letto facilmente :) Btw Mi piacerebbe vedere un codice Python che utilizza meno byte!

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

Possibili esempi:

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

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

Non uso i punti all'interno del mio codice, in realtà il tuo input può usare qualsiasi carattere ma non _e [
Wikunia,

1
Generalmente invece di usare <>, useresti !=.
Ethan Bierlein,

@EthanBierlein non era sicuro, ma sì !=è il modo preferito per
tge

1

JavaScript 2 (ES6) - 148 151 byte

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

Espone una stringa di righe di mattoni separate newline (nota: se potessimo usare un carattere di separazione diverso come "|" per separare le righe, questo potrebbe essere ridotto di 1 byte).

Test nella console di Firefox con:

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

test:

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]

Produzione:

[True, True, True, True, True, True, False, False, False, False, False, False]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.