¿Puedes contar la cantidad de rectángulos?


21

Uno de mis pasatiempos matemáticos favoritos es dibujar una cuadrícula rectangular y luego encontrar todos los rectángulos visibles en esa cuadrícula. ¡Toma esta pregunta y aventúrate por ti mismo!

¿Puedes contar la cantidad de rectángulos?

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

El número total de rectángulos para este tablero de 4 x 4 minichess es exactamente

100

¿Estabas en lo correcto?

Matemáticas relacionadas: ¿Cuántos rectángulos hay en un tablero de ajedrez de 8 × 8?

El reto

Escriba la función / programa más corto que cuente el número total de rectángulos visibles en una cuadrícula / imagen no toroidal .

Desafíos relacionados: ¡ Cuenta los rectángulos únicos! , Encuentra el número de rectángulos en una matriz de bytes 2D .

Formato de entrada

Su función o programa puede elegir trabajar con entrada basada en texto o entrada gráfica.

Entrada basada en texto

La cuadrícula será una cuadrícula ASCII m -by- n ( m filas, n columnas) que consta de los siguientes caracteres:

  • espacios,
  • - para partes de un segmento de línea horizontal,
  • | para partes de un segmento de línea vertical, y
  • + para esquinas

Puede introducir esta cuadrícula ASCII como la entrada / argumento de su programa / función en forma de

  • una sola cadena delimitada por saltos de línea,
  • una cadena sin líneas nuevas pero con uno o dos enteros que codifican las dimensiones de la cuadrícula, o
  • Un conjunto de cuerdas.

Nota: La entrada basada en texto contiene al menos 1 fila y al menos 1 columna.

Entrada gráfica

Alternativamente, las cuadrículas se codifican como imágenes PNG en blanco y negro de 5 * n píxeles de ancho y 5 * m píxeles de alto. Cada imagen consta de bloques de 5 px * 5 px que corresponden a la entrada ASCII por:

  • Los espacios se convierten en bloques blancos. Estos bloques se denominan bloques de espacios en blanco .
  • Los segmentos de línea y las esquinas se convierten en bloques que no son espacios en blanco. El píxel central de tales bloques es negro.
  • Editar: si dos esquinas (en la entrada ASCII) están conectadas por un segmento de línea, los centros de bloque correspondientes (en la entrada gráfica) también deberían estar conectados por una línea negra.

Esto significa que cada bloque solo se puede elegir Por favor ignore los límites azules. (haga clic aquí para ampliar la imagen) .

Nota: Los límites azules son solo para fines ilustrativos. La entrada gráfica tiene al menos 5 px de ancho y 5 px de alto. Puede convertir la entrada gráfica a cualquier imagen monocroma, potencialmente a otros formatos de archivo de imagen). Si elige convertir, especifique en la respuesta. No hay penalidad para la conversión.

Formato de salida

Si está escribiendo un programa, debe mostrar un número no negativo que indique el número total de rectángulos en la entrada.

Si está escribiendo una función, también debería devolver un número no negativo que indica el número total de rectángulos en la entrada.

Casos de ejemplo

Caso 1, Gráfico: Caso 1( 30 px * 30 px), ASCII: ( 6 filas, 6 cols)

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

Rendimiento esperado: 3

Caso 2, Gráfico: Caso 2( 20 px * 20 px), ASCII: ( 4 filas, 4 cols)

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

Rendimiento esperado: 6

Caso 3, Gráfico: Caso 3( 55 px * 40 px), ASCII: ( 8 filas, 11 cols)

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

Rendimiento esperado: 9

Caso 4, Gráfico: Caso 4( 120 px * 65 px), ASCII: ( 13 filas, 24 cols)

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

Rendimiento esperado: 243

Caso 5, Gráfico: Caso 5( 5 px * 5 px. ¡Sí, está ahí!), ASCII: Solo un espacio.

Rendimiento esperado: 0

Caso 6, Gráfico: Caso 6( 35 px * 20 px), ASCII: ( 4 filas, 7 cols)

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

Rendimiento esperado: 5

Supuestos

Para facilitarle la vida, tiene la garantía de que:

  • Al ser no toroidal , la cuadrícula no se ajusta horizontal ni verticalmente.
  • No hay cabos sueltos, por ejemplo, +--- o +- -+. Todos los segmentos de línea tienen dos extremos.
  • Dos líneas que se encuentran en +deben cruzarse en ese punto.
  • No tiene que preocuparse por entradas no válidas.

Se aplican las reglas contra las lagunas estándar. Por favor trate los cuadrados como rectángulos. Opcionalmente, puede eliminar los espacios finales en cada fila de la cuadrícula.

Este es el , así que haga su entrada lo más corta posible. Las soluciones gráficas y basadas en texto competirán juntas.

Tabla de clasificación


¿Está permitido el mapa de bits monocromo?
user202729

@ user202729 Sí. Si elige trabajar con imágenes que no sean PNG, especifíquelo en la respuesta.
Frenesí Li

¿Es esta una entrada válida? (La esquina del rectángulo toca el borde del rectángulo más grande). Si es así, considere agregarlo como un caso de prueba.
Zgarb

@ Zgarb Es una entrada válida. También editaré la publicación.
Frenesí Li

¿Hay alguna razón para poner los resultados esperados en spoilers? Parece que solo hace que verificar tu código sea un poco más molesto.
FryAmTheEggman

Respuestas:


4

Grime , 31 28 bytes

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

Pruébalo en línea!

Toma entrada en formato ASCII.

Explicación

La sintaxis de Grime está muy cerca de las expresiones regulares. Cada línea define un patrón que puede coincidir o no con un rectángulo de caracteres. Tcoincide con un rectángulo cuya fila superior y columna izquierda parecen válidas.

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

La segunda fila es el "programa principal".

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

6

JavaScript (ES6), 176 171 bytes

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>

Toma la entrada como una matriz de cadenas de igual longitud. Explicación: Crea una serie de expresiones regulares que coinciden con rectángulos de todos los anchos y alturas posibles (y algunos anchos y alturas imposibles, pero ese es el código de golf para usted) y cuenta cuántas coincidencias producen todos. Debido a que hay un grupo de captura en la expresión regular, splitregresa 2n+1para las ncoincidencias, por lo que me desplazo a la derecha en 1 para obtener el número de coincidencias, ya que eso ahorra un byte sobre hacer que el grupo no se capture.


Hmm, el fragmento de código no funciona para mí [Firefox 54.0.1 (32 bits) o Chrome 60.0.3112.90 (64 bits), ambos en Windows (64 bits)].
Jonathan Allan

El fragmento tampoco funciona en Safari [Mac (64 bits)].
Sr. Xcoder

2
Parece que tenemos que pegar cosas en el área de texto. Se requiere el mismo número de caracteres por línea.
Frenesí Li

Ah ya veo, buen lugar @FrenzyLi!
Jonathan Allan

4

J , 103 95 86 80 76 70 bytes

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

Pruébalo en línea!

Toma la entrada como una matriz de cadenas con espacios finales (para que cada cadena sea del mismo tamaño). Utiliza el operador de submatriz completo;._3 para iterar sobre cada tamaño de submatriz posible mayor que 2 x 2, y cuenta las submatrices que son rectángulos válidos. Completa todos los casos de prueba casi al instante.


1
@FrenzyLi Gracias. La función está recibiendo la entrada como una matriz de cadenas, pero codifiqué cada una de ellas como una cadena plana reformada en una matriz antes de almacenarlas en cada variable para usarlas como argumento para la función.
millas

Ahh ... Gracias por tu explicación.
Frenesí Li

@miles agradable. cuando dice entrada como conjunto de cadenas, ¿cada línea de la entrada 1 pica?
Jonás

@Jonah Las cadenas en J son solo matrices de caracteres, por lo que la entrada es en realidad una matriz 2D de caracteres.
millas

3

Mathematica, 136 134 132 bytes

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}]&

Uso: (para la versión antigua de 136 bytes, pero la nueva versión es básicamente idéntica)

_ _

Nota:

  • Esto se ejecuta en el tiempo O (m 2 n 2 max (m, n)), por lo que solo use entradas pequeñas.
  • Aunque se supone que esto funciona con imágenes binarias, aparentemente puede funcionar con imágenes no binarias. (pero el negro debe ser idénticamente cero)
  • Los gráficos no necesariamente se construyen con bloques de 5x5, los bloques pueden ser más pequeños.
  • @*es nuevo en la versión 10. En versiones anteriores, use en Tr~Composition~Flattenlugar de Tr@*Flatten.

¿En qué versión de MMA está esto? En 9.0, responde con"Tr@" cannot be followed by "*Flatten".
Frenzy Li

1
@FrenzyLi 10.0. Sí, @*(abreviatura de Composition) es nuevo en la versión 10.
user202729

1
¿Por qué no lo usas RectangleCount[]?
MCMastery

2
@MCMastery Mathematica es famoso por tener muchas funciones integradas, pero no esta.
user202729

@ user202729 lol sí, soy jk
MCMastery

2

Jalea ,  60 53 52 51  50 bytes

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

Un programa completo que acepta una lista de cadenas (filas de igual longitud) e imprime el recuento.

Pruébalo en línea!
... o para facilitar la entrada de copiar y pegar, use este programa completo (con un byte adicional para dividir líneas)
. Sin embargo, tenga en cuenta que las líneas deben contener espacios finales para que el programa funcione correctamente.

¿Cómo?

Ñ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

2

Slip , 32 29 bytes

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

Pruébalo en línea!

27 bytes de código + 2 bytes para las banderas ny o. Toma información en el mismo formato provisto en la pregunta (es decir, bloque de líneas delimitado por nueva línea).


2

Haskell, 180 167 166 bytes

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]

Pruébalo en línea!

Revise todas las posiciones de esquina posibles con cuatro bucles anidados y verifique si todos los caracteres en las líneas entre ellos consisten en +-(horizontal) o +|(vertical).


1

Jalea , 41 39 34 33 bytes

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

Pruébalo en línea! o Ver todos los casos.

Basado en mi respuesta en J.

Explicación

,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

Ahora finalmente está comenzando a sentirse competitivamente corto en 34 bytes.
millas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.