La structure en brique est-elle stable?

24

Représentons une brique de maçonnerie standard comme [__](et ignorons le fait que le haut est ouvert). Lorsque ces briques sont empilées, toutes les autres couches sont compensées par une demi-brique, comme c'est généralement le cas dans la construction en briques:

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

Ainsi, chaque brique a au plus six voisins et il est impossible pour deux briques de s'aligner directement verticalement.

Le point clé est que les dispositions de ces briques ne sont pas mortier , mais simplement maintenues ensemble par gravité. Il est donc important que chaque brique de la structure soit stable, sinon la structure entière est instable.

Il existe trois façons dont une brique individuelle peut être stable:

  1. Toute brique au sol (la ligne de briques la plus basse) est stable.
  2. Toute brique qui a deux briques directement en dessous est stable:

      [__]   <- this brick is stable
    [__][__] <- because these bricks hold it up
    
  3. Toute brique qui a une brique au-dessus et en dessous du même côté est stable:

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

De ces règles, nous pouvons voir, par exemple, l'arrangement

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

est instable parce que la brique en haut à droite est instable, c'est tout ce qu'il faut.

Une structure en brique n'est stable que si toutes ses briques sont stables.

Défi

Votre tâche consiste à écrire une fonction qui prend une chaîne de structure en brique et retourne une valeur véridique si la structure est stable et une valeur fausse si elle est instable. ( définition véridique / fausse )

La chaîne d'entrée peut être arbitrairement grande mais ce sera toujours une grille rectangulaire de caractères, avec des espaces remplissant des zones vides de briques. La largeur de la grille de caractères sera divisible par 4 mais la hauteur peut être paire ou impaire.

La grille de briques s'étend toujours au-dessus et à droite de la position de brique inférieure gauche:

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

Selon la structure, chacun BRK?représente soit une brique ( [__]) soit un espace vide (4 espaces).

Notez que les cavités en demi-brique sont remplies d'espaces pour garantir que la grille de caractères est rectangulaire.

Notation

Le code le plus court en octets gagne.

Remarques

  • Si vous le souhaitez, vous pouvez utiliser à la .place de l'espace comme caractère d'espace vide.
  • La chaîne vide est considérée comme stable.
  • Si votre langue n'a pas de fonctions, vous pouvez utiliser une variable de chaîne nommée en entrée et affecter le résultat à une autre variable.
  • Si votre langue n'a pas de chaînes, vous pouvez faire tout ce qui semble approprié pour la saisie.

Cas de test

Différents cas de test, séparés par des lignes vides. Pour plus de clarté .est utilisé à la place de l'espace pour les espaces vides.

Stable:

[__]

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

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

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

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

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

Instable:

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

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

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

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

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

[__][__][__][__][__]
..[__][__][__][__]..
....[__][__][__]....
......[__][__]......
........[__]........
Loisirs de Calvin
la source
7
Je suis presque sûr que votre définition de la stabilité ne correspond pas à la réalité ;-)
John Dvorak
14
@JanDvorak Je sais mais qui voudrait jouer à un moteur de physique entier: P
Calvin's Hobbies
........[__].... ......[__][__].. ....[__][__].... ..[__][__]...... [__][__]........ ..[__]..........(vous devrez empiler mentalement ces lignes les unes sur les autres. Le fait étant que vos règles autorisent les structures dont le centre de gravité est loin de leur point de contact avec le sol. Il devrait être possible de les resserrer pour éviter cela , sans avoir besoin d'un moteur physique, si vous en aviez envie.)
Nathaniel
2
La vraisemblance dans la physique est cependant une énorme boîte de vers. On peut trouver de nombreux cas simples où la stabilité dépend du coefficient de frottement et / ou du poids des briques sur le dessus.
COTO
10
"stable"… heh
wchargin

Réponses:

12

80386 code machine, 98

Le code:

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

Le code scanne l'art ASCII de la fin au début, en sautant 2 caractères à la fois. Cela fait deux fois les vérifications nécessaires (il suffirait de sauter 4 caractères), mais simplifie la logique.

La vérification commence à l'avant-dernière ligne de caractères (pas besoin de vérifier la dernière ligne). A chaque ligne, il commence 3 caractères à partir de la droite (pas besoin de vérifier trop loin à droite). Pour chaque personnage, il vérifie 4 personnages environnants:

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

Il y a un tas de conditions logiques à vérifier:

  • Si A et C sont des caractères de brique, X est pris en charge
  • Si B et D sont des caractères de brique, X est pris en charge
  • Si C et D sont des caractères de brique, X est pris en charge
  • Si X est un caractère de brique, il doit être pris en charge; sinon la structure est instable

C'est une heureuse coïncidence que tous les personnages de briques [_]aient leur jeu LSB; tous les autres personnages l' .\nont clairement. En outre, le jeu d'instructions 80386 a ces « haut » à portée de main et les registres de « bas » ( ah, al, etc.), qui aide paralléliser les chèques un peu. Ainsi, tous les contrôles reviennent à un peu de tripotage obscur.

Je suis parti du code C suivant:

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

J'ai traduit le code en langage assembleur (c'est principalement un à un), y compris une implémentation golfée de strchret strlen. Le code source suivant est traduit par MS Visual Studio dans le code machine en haut de mon message.

__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;
    }
}
anatolyg
la source
7

MATLAB - 119 octets

Minifié:

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

Étendu:

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

Exemple d'utilisation:

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

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

S4: 1

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

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

U4: 0

Détails

La routine ajoute une ligne de .en haut de la matrice d'entrée, puis convertit en une matrice numérique en ajoutant 3 aux codes de caractères ASCII. Compte tenu de cette conversion, une convolution 2D avec le noyau

 2  0
-1 -1
 0  2

donne une matrice 0aux endroits où le motif de caractères

 . *
 _ _
 * .

est présent, *représentant "n'importe quel caractère". En raison de la construction du noyau, c'est le seul modèle de caractère valide qui produira a 0.

Une convolution identique est effectuée avec la version inversée gauche-droite du noyau pour détecter

 * .
 _ _
 . *

Une entrée est stable si i ) elle est vide ou ii ) aucun zéro n'apparaît dans l'une ou l'autre convolution.

Deux frustrations sont

  1. La convolution par défaut de MATLAB passe le long des bords de la matrice d'opérande, produisant des 0s erronés dans les coins opposés pour les deux convolutions, nécessitant ,'valid'(8 octets) d'être ajouté pour conv2appeler afin de limiter la sortie à la zone où la convolution est valide.

  2. La gestion du cas de chaîne vide ajoute 12 octets.

COTO
la source
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)

Test dans la 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)))

Sortie

    [__]
true

  [__]  
[__][__]
true

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

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

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

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

  [__]  
false

  [__]  
[__]    
false

  [__]  
    [__]
false

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

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

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

Non golfé

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] != '.'
    )  
  )
)
edc65
la source
Que [...a]faire, si cela ne vous dérange pas que je demande? Je sais que ES6 permet ...argcomme dernier argument d'une fonction de capturer des variadics, mais je ne l'ai jamais vu utilisé de cette façon.
COTO
@COTO codegolf.stackexchange.com/a/37723/21348 , cas d'utilisation 2 (c'est très courant, je l'utilise dans peut-être 80% de mes réponses)
edc65
Sunofagun. Tout comme {:}dans MATLAB. Ça va être très utile. Merci. :)
COTO
1

Python 279

Je pense que je suis assez mauvais dans les défis de golf de code et peut-être que j'utilise les mauvais langages pour cela: D Mais j'aime le code qui peut être facilement lu :) Btw Je voudrais voir un code python qui utilise moins d'octets!

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

Exemples possibles:

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

B = "..[__]........[__]..\n\
[__][__][__][__][__]\n\
..[__][__][__][__]..\n\
....[__][__][__]....\n\
......[__][__]......\n\
........[__]........"
print t(B) #True
Wikunia
la source
Je n'utilise pas les points à l'intérieur de mon code, en fait, votre entrée peut utiliser n'importe quel caractère, mais pas _et [
Wikunia
1
Généralement, au lieu d'utiliser <>, vous utiliseriez !=.
Ethan Bierlein
@EthanBierlein n'était pas sûr, mais oui, !=c'est la voie préférée de
Tge
1

JavaScript 2 (ES6) - 148 151 octets

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

Attend une chaîne de lignes de briques séparées par des sauts de ligne (remarque: si nous pouvions utiliser un caractère de séparation différent comme "|" pour séparer les lignes, cela pourrait être raccourci d'un octet).

Testez dans la console Firefox avec:

F('..[__]......\n[__][__][__]\n..[__][__]..\n[__]....[__]'); // false
F('..[__][__]..\n[__][__][__]\n..[__][__]..\n[__]....[__]'); // true
moi et mon chat
la source
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=="["])

Tests:

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]

Sortie:

[True, True, True, True, True, True, False, False, False, False, False, False]
legionixtiwo
la source