Pouvez-vous compter le nombre de rectangles?

21

Un de mes passe-temps mathématiques préférés est de dessiner une grille rectangulaire, puis de trouver tous les rectangles visibles dans cette grille. Ici, prenez cette question et aventurez-vous par vous-même!

Pouvez-vous compter le nombre de rectangles?

+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |     |
+-----+-----+-----+-----+

Le nombre total de rectangles pour cette planche minichess 4 x 4 est exactement

100

Aviez-vous raison?

Mathématiques connexes: Combien de rectangles y a-t-il sur un damier 8 × 8?

Le défi

Écrivez la fonction / le programme le plus court qui compte le nombre total de rectangles visibles sur une grille / image non toroïdale .

Défis connexes: comptez les rectangles uniques! , Trouver le nombre de rectangles dans un tableau d'octets 2D .

Format d'entrée

Votre fonction ou programme peut choisir de fonctionner avec une entrée textuelle ou une entrée graphique.

Saisie basée sur du texte

La grille sera une grille ASCII m- par- n ( m lignes, n colonnes) composée des caractères suivants:

  • les espaces,
  • - pour les parties d'un segment de ligne horizontale,
  • | pour les parties d'un segment de ligne verticale, et
  • + pour les coins.

Vous pouvez introduire cette grille ASCII comme entrée / argument dans votre programme / fonction sous la forme de

  • une seule chaîne délimitée par des sauts de ligne,
  • une chaîne sans retour à la ligne mais avec un ou deux entiers codant les dimensions de la grille, ou
  • un tableau de chaînes.

Remarque: L'entrée textuelle contient au moins 1 ligne et au moins 1 colonne.

Entrée graphique

Alternativement, les grilles sont codées en noir et blanc images PNG de 5 * n pixels de large et 5 * m pixels de haut. Chaque image se compose de blocs de 5 px * 5 px qui correspondent à l'entrée ASCII par:

  • Les espaces sont convertis en blocs blancs. Ces blocs sont appelés blocs d' espaces .
  • Les segments de ligne et les coins sont convertis en blocs non blancs. Le pixel central de ces blocs est noir.
  • Modifier: si deux coins (dans l'entrée ASCII) sont connectés par un segment de ligne, les centres de blocs correspondants (dans l'entrée graphique) doivent également être connectés par une ligne noire.

Cela signifie que chaque bloc ne peut être choisi que parmi Veuillez ignorer les limites bleues. (Cliquez ici pour agrandir l'image) .

Remarque: Les limites bleues sont uniquement à des fins d'illustration. L'entrée graphique mesure au moins 5 px de large et 5 px de haut. Vous pouvez convertir l'entrée graphique en n'importe quelle image monochrome, potentiellement d'autres formats de fichier image). Si vous choisissez de convertir, veuillez préciser dans la réponse. Il n'y a aucune pénalité à la conversion.

Format de sortie

Si vous écrivez un programme, il doit afficher un nombre non négatif indiquant le nombre total de rectangles dans l'entrée.

Si vous écrivez une fonction, elle doit également renvoyer un nombre non négatif indiquant le nombre total de rectangles dans l'entrée.

Exemples de cas

Cas 1, graphique: Cas 1( 30 px * 30 px), ASCII: ( 6 lignes, 6 cols)

+--+  
|  |  
| ++-+
+-++ |
  |  |
  +--+

Production attendue: 3

Cas 2, graphique: Cas 2( 20 px * 20 px), ASCII: ( 4 lignes, 4 cols)

++-+
|+++
+++|
+-++

Production attendue: 6

Cas 3, graphique: Cas 3( 55 px * 40 px), ASCII: ( 8 lignes, 11 colonnes )

  +++--+   
+-+++  |   
|  |  ++--+
+--+--++ ++
      |  ||
      |  ||
++    +--++
++         

Production attendue: 9

Cas 4, graphique: Cas 4( 120 px * 65 px), ASCII: ( 13 lignes, 24 cols)

+--+--+ +--+  +--+  +--+
|  |  | |  |  |  |  |  |
+--+--+ |  |  |  |  |  |
|  |  | +--+--+--+--+--+
+--+--+    |  |  |  |   
           |  |  |  | ++
+-+-+-+-+  +--+  +--+ ++
| | | | |
+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+

Production attendue: 243

Cas 5, graphique: Cas 5( 5 px * 5 px. Oui, il est là!), ASCII: un seul espace.

Production attendue: 0

Cas 6, graphique: Cas 6( 35 px * 20 px), ASCII: ( 4 lignes, 7 colonnes )

+--+--+
|++|++|
|++|++|
+--+--+

Production attendue: 5

Hypothèses

Pour vous faciliter la vie, vous avez la garantie que:

  • En étant non toroïdal , la grille ne s'enroule ni horizontalement ni verticalement.
  • Il n'y a aucune extrémité libre, par exemple +--- ou +- -+. Tous les segments de ligne ont deux extrémités.
  • Deux lignes qui se rencontrent à +doivent se croiser à ce point.
  • Vous n'avez pas à vous soucier des entrées invalides.

Les règles contre les failles standard s'appliquent. Veuillez traiter les carrés comme des rectangles. Vous pouvez éventuellement supprimer les espaces de fin sur chaque ligne de la grille.

Il s'agit de , alors faites votre entrée aussi courte que possible. Les solutions textuelles et graphiques seront en concurrence.

Classement

Frenzy Li
la source
Le bitmap monochrome est-il autorisé?
user202729
@ user202729 Oui. Si vous choisissez de travailler avec des images non PNG, veuillez le préciser dans la réponse.
Frenzy Li
Est- ce une entrée valide? (Le coin rectangle touche la bordure d'un rectangle plus grand.) Si c'est le cas, envisagez de l'ajouter comme cas de test.
Zgarb
@Zgarb Il s'agit d'une entrée valide. Je vais également modifier le message.
Frenzy Li
Y a-t-il une raison pour laquelle vous mettez les sorties attendues dans les spoilers? Il semble que cela rend la vérification de votre code un peu plus ennuyeuse.
FryAmTheEggman

Réponses:

4

Grime , 31 28 octets

T=\+[+\-]*\+/[+|]/+$
n`T&To2

Essayez-le en ligne!

Prend l'entrée au format ASCII.

Explication

La syntaxe de Grime est très proche des expressions régulières. Chaque ligne définit un motif qui peut correspondre ou non à un rectangle de caractères. Tcorrespond à un rectangle dont la ligne supérieure et la colonne de gauche semblent valides.

T=\+[+\-]*\+/[+|]/+$
T=                    Define T as
  \+[+\-]*\+          a row that matches this regex
            /         and below that
             [+|]/+   a column of + or |
                   $  with anything to its right.

La deuxième ligne est le "programme principal".

n`T&To2
n`       Print number of rectangles that match
  T      the pattern T
   &     and
    To2  T rotated 180 degrees.
Zgarb
la source
6

JavaScript (ES6), 176 171 octets

g=a=>Math.max(...b=a.map(a=>a.length))-Math.min(...b)?``:f(a);f=
a=>a.map((b,i)=>[...b].map((_,j)=>n+=a.join`
`.split(eval(`/\\+(?=[-+]{${j}}\\+[^]{${l=b.length+~j}}([|+].{${j}}[|+][^]{${l}}){${i}}\\+[-+]{${j}}\\+)/`)).length>>1),n=0)|n
<textarea rows=8 cols=8 oninput=o.textContent=g(this.value.split`\n`)></textarea><pre id=o>

Prend l'entrée comme un tableau de chaînes de longueur égale. Explication: crée une série d'expressions régulières qui correspondent à des rectangles de toutes les largeurs et hauteurs possibles (et certaines largeurs et hauteurs impossibles, mais c'est le code golf pour vous) et compte le nombre de correspondances qu'ils produisent tous. Parce qu'il y a un groupe de capture dans l'expression régulière, splitretourne 2n+1pour les ncorrespondances, donc je décale vers la droite de 1 pour obtenir le nombre de correspondances, car cela économise un octet par rapport à la non-capture du groupe.

Neil
la source
Hmm, l'extrait de code ne fonctionne pas pour moi [Firefox 54.0.1 (32 bits) ou Chrome 60.0.3112.90 (64 bits) tous les deux sur Windows (64 bits)].
Jonathan Allan
L'extrait Il ne fonctionne pas non plus sur Safari [Mac (64 bits)].
M. Xcoder
2
Il semble que nous devons coller des éléments dans la zone de texte. Le même nombre de caractères par ligne est requis.
Frenzy Li
Ah je vois, bon endroit @FrenzyLi!
Jonathan Allan
4

J , 103 95 86 80 76 70 octets

[:+/@,]*/@('-|++'*/@(e.,&'+')~&>]({.,{:)&.>@;|:;{.;{:);._3"$~2+$#:i.@$

Essayez-le en ligne!

Prend l'entrée comme un tableau de chaînes avec des espaces de fin (de sorte que chaque chaîne ait la même taille). Utilise l' opérateur de sous-tableau complet;._3 pour itérer sur toutes les tailles de sous-tableau possibles supérieures à 2 x 2 et compte les sous-tableaux qui sont des rectangles valides. Complète tous les cas de test presque instantanément.

miles
la source
1
@FrenzyLi Merci. La fonction reçoit l'entrée sous la forme d'un tableau de chaînes, mais j'ai codé chaque tableau sous la forme d'une chaîne plate remodelée dans un tableau avant de les stocker dans chaque variable à utiliser comme argument pour la fonction.
miles
Ahh ... Merci pour votre explication.
Frenzy Li
@miles nice. lorsque vous dites entrée sous forme de tableau de chaînes, chaque ligne de l'entrée 1 est-elle une piqûre?
Jonah
@Jonah Strings en J ne sont que des tableaux de caractères, donc l'entrée est en fait un tableau 2D de caractères.
miles
3

Mathematica, 136 134 132 octets

S=Tr@*Flatten;S@Table[1-Sign@S@{d[[{i,j},k;;l]],d[[i;;j,{k,l}]]},{i,($=Length)[d=ImageData@#]},{j,i+1,$@d},{k,w=$@#&@@d},{l,k+1,w}]&

Utilisation: (pour l'ancienne version de 136 octets, mais la nouvelle version est fondamentalement identique)

_

Remarque:

  • Cela fonctionne dans le temps O (m 2 n 2 max (m, n)), donc n'utilisez que de petites entrées.
  • Bien que cela soit censé fonctionner avec des images binaires, il peut apparemment fonctionner avec des images non binaires. (mais le noir doit être identique à zéro)
  • Les graphiques ne sont pas nécessairement construits avec des blocs 5x5, les blocs peuvent être plus petits.
  • @*est nouveau dans la version 10. Dans les anciennes versions, utilisez Tr~Composition~Flattenplutôt que Tr@*Flatten.
user202729
la source
Dans quelle version de MMA est-ce? En 9.0, il répond avec"Tr@" cannot be followed by "*Flatten".
Frenzy Li
1
@FrenzyLi 10.0. Oui, @*(raccourci pour Composition) est nouveau dans la version 10.
user202729
1
Pourquoi n'utilisez-vous pas simplement RectangleCount[]?
MCMastery
2
@MCMastery Mathematica est célèbre pour avoir beaucoup de fonctions intégrées, mais pas celle-ci.
user202729
@ user202729 lol yep, im jk
MCMastery
2

Gelée ,  60 53 52 51  50 octets

ÑFQe⁹ṚẆ;W¤
Ḣ,Ṫ
=”+ÇÇ€Ạȧ1ŀ
Zç⁾+-ȧç⁾+|$
Ẇ;"/€Ẇ€Ç€€FS

Un programme complet acceptant une liste de chaînes (lignes de longueur égale) et imprimant le nombre.

Essayez-le en ligne!
... ou pour faciliter la copie et le collage, utilisez ce programme complet (avec un octet supplémentaire pour séparer les lignes)
- notez que les lignes doivent contenir des espaces de fin pour que le programme fonctionne correctement.

Comment?

ÑFQe⁹ṚẆ;W¤   - Link 1, sidesAreValid?: list of lists, area; list allowedSideCharacters
Ñ            - call the next link (2) as a monad (get the sides in question
             -   note: these sides do not include the corners since the area was modified
             -   to not include the other sides by the first call to link 2 inside link 3.
 F           - flatten into a single list
  Q          - de-duplicate (unique characters)
         ¤   - nilad followed by link(s) as a nilad:
    ⁹        -   right argument (either "+-"                or "+|"               )
     Ṛ       -   reverse        (either "-+"                or "|+"               )
      Ẇ      -   all sublists   (either ["-","+","-+"]      or ["|","+","|+"]     )
        W    -   wrap           (either ["+-"]              or ["+|"]             )
       ;     -   concatenate    (either ["-","+","-+","+-"] or ["|","+","|+","+|"])
   e         - exists in?

Ḣ,Ṫ          - Link 2, topAndTail helper: list
Ḣ            - head (get the first element and modify the list)
  Ṫ          - tail (get the last element and modify the list)
 ,           - pair (the elements together)

=”+ÇÇ€Ạȧ1ŀ   - Link 3, isPartlyValid?: list of lists, area; list allowedSideCharacters
=”+          - equal to '+'? (vectorises across the whole area, 1 if so, 0 otherwise)
   Ç         - call the last link (2) as a monad (gets the values for two edges)
    Ç€       - call the last link (2) as a monad for €ach (...values for the four corners)
      Ạ      - all? (all corners are '+' 1 if so, 0 if not)
        1ŀ   - call link number 1 as a dyad with sideCharacters as the right argument
             -    ...and the modified area on the left
       ȧ     - logical and (both all corners are '+' and the sides in question look right)

Zç⁾+-ȧç⁾+|$  - Link 4, isValidSquare?: list of lists, area
Z            - transpose
 ç⁾+-        - call the last link (3) as a dyad with right argument "+-"
          $  - last two links as a monad:
      ç⁾+|   -   call the last link (3) as a dyad with right argument "+|"
     ȧ       - logical and (1 if so 0 otherwise)

Ẇ;"/€Ẇ€Ç€€FS - Main Link: list of lists of characters, rows
Ẇ            - all sublists (= all non-zero length runs of rows)
   /€        - reduce €ach by:
  "          -   zip with:
 ;           -     concatenation (= all non-zero length vertical edges)
     Ẇ€      - all sublists for €ach (= all possible areas)
       Ç€€   - call the last link (4) as a monad for €ach for €ach (for each area)
          F  - flatten
           S - sum
Jonathan Allan
la source
2

Slip , 32 29 octets

$a([+`-]*`+>[+`|]*`+>){2}$A

Essayez-le en ligne!

27 octets de code + 2 octets pour les drapeaux net o. Prend la saisie dans le même format que celui fourni dans la question (c.-à-d. Bloc de lignes délimité par des sauts de ligne).

notjagan
la source
2

Haskell, 180 167 166 octets

l=length
a%b=[a..b-1]
h c a g b=all(`elem`c)$g<$>[a..b]
f s|(#)<-(!!).(s!!)=sum[1|y<-1%l s,x<-1%l(s!!0),i<-0%y,j<-0%x,h"+|"i(#x)y,h"+-"j(y#)x,h"+|"i(#j)y,h"+-"j(i#)x]

Essayez-le en ligne!

Parcourez toutes les positions de coin possibles avec quatre boucles imbriquées et vérifiez si tous les caractères sur les lignes entre eux sont constitués de +-(horizontal) ou +|(vertical).

nimi
la source
1

Gelée , 41 39 34 33 octets

,Z;.ị$⁺€ḟ€"⁾-|Fḟ”+
ẆḊÐfZ€µ⁺€ẎÇÐḟL

Essayez-le en ligne! ou Voir tous les cas.

D'après ma réponse dans J.

Explication

,Z;.ị$⁺€ḟ€"⁾-|Fḟ”+  Helper. Input: 2d array of characters
 Z                  Transpose
,                   Pair
  ;                   Concatenate with
     $                The tail and head
   .ị                   Select at index 0.5 -> Select at index 0 and 1
                        Jelly uses 1-based modular indexing, so
                        0 means to select the tail
      ⁺€              Repeat on each - This selects the last and first rows,
                      last and first columns, and the 4 corners
           ⁾-|       The string array ['-', '|']
          "          Vectorize
        ḟ€             Filter each
              F      Flatten
                ”+   The character '+'
               ḟ

ẆḊÐfZ€µ⁺€ẎÇÐḟL  Main. Input: 2d array of characters
      µ         Combine into a monad
Ẇ                 Generate all sublists
  Ðf              Filter for the values that are truthy (non-empty)
 Ḋ                  Dequeue
    Z€            Transpose each
       ⁺€       Repeat on each
         Ẏ      Tighten, join all lists on the next depth
          ÇÐḟ   Discard the values where executing the helper returns truthy
             L  Length
miles
la source
Maintenant, il commence enfin à se sentir compétitif à 34 octets.
miles