Чи можете ви порахувати кількість прямокутників?


21

Одне з моїх улюблених математичних занять - намалювати прямокутну сітку, а потім знайти всі прямокутники, які видно в цій сітці. Ось візьміть це запитання і ризикніть для себе!

Чи можете ви порахувати кількість прямокутників?

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

Загальна кількість прямокутників для цієї міні-шахи 4 х 4 рівно

100

Ви мали рацію?

Супутня математика: Скільки прямокутників є на контрольній дошці 8 × 8?

Змагання

Напишіть найкоротшу функцію / програму, яка підраховує загальну кількість видимих ​​прямокутників на нетороїдальній сітці / зображенні .

Пов'язані завдання: Порахуйте унікальні прямокутники! , Знайдіть кількість прямокутників у двовимірному байтовому масиві .

Формат введення

Ваша функція або програма можуть вибрати роботу з текстовим введенням або з графічним введенням.

Введення тексту на основі тексту

Сітка буде m -by- n ( m рядків, n стовпців) ASCII сітка, що складається з таких символів:

  • пробіли,
  • - для частин відрізка горизонтальної лінії,
  • | для частин сегмента вертикальної лінії та
  • + для куточків.

Ви можете представити цю сітку ASCII як вхід / аргумент до вашої програми / функції у вигляді

  • один рядок, розмежований перервами рядків,
  • рядок без нових рядків, але з одним або двома цілими числами, що кодують розміри сітки, або
  • масив рядків.

Примітка . Текстовий вхід містить принаймні 1 рядок і принаймні 1 стовпець.

Графічне введення

Крім того, сітки кодуються як чорно-білі зображення PNG шириною 5 * n пікселів і висотою 5 * м . Кожне зображення складається з 5 px * 5 px блоків, які відповідають входу ASCII:

  • Проміжки перетворюються на білі блоки. Ці блоки називаються блоками пробілів .
  • Сегменти та кути рядків перетворюються на блоки, що не містять простору. Центральний піксель таких блоків - чорний.
  • Редагувати: Якщо два кути (на вході ASCII) з'єднані лінійним відрізком, відповідні блоки блоків (у графічному вході) повинні бути також з’єднані чорною лінією.

Це означає, що кожен блок можна було вибрати лише Будь ласка, ігноруйте сині межі. (Клацніть тут для збільшення зображення) .

Примітка . Сині межі призначені лише для ілюстрації. Графічний вхід має принаймні 5 пікс. Ширини та 5 пікс. Ви можете перетворити графічний вхід у будь-яке монохромне зображення, можливо, в інші формати файлів зображень). Якщо ви вирішили конвертувати, вкажіть у відповіді. Штраф за конверсію не передбачений.

Формат виводу

Якщо ви пишете програму, вона повинна відображати негативне число із зазначенням загальної кількості прямокутників на вході.

Якщо ви пишете функцію, вона також повинна повернути невід'ємне число із зазначенням загальної кількості прямокутників на вході.

Приклади справ

Випадок 1, графічний: Випадок 1( 30 px * 30 px), ASCII: ( 6 рядків, 6 col)

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

Очікуваний вихід: 3

Випадок 2, графічний: Випадок 2( 20 px * 20 px), ASCII: ( 4 рядки, 4 col)

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

Очікуваний вихід: 6

Випадок 3, Графіка: Випадок 3( 55 px * 40 px), ASCII: ( 8 рядків, 11 cols)

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

Очікуваний вихід: 9

Випадок 4, графічний: Випадок 4( 120 px * 65 px), ASCII: ( 13 рядків, 24 cols)

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

Очікуваний вихід: 243

Випадок 5, Graphic: Справа 5( 5 точок * 5 . Точок Так, це є!), ASCII: Просто один пробіл.

Очікуваний вихід: 0

Випадок 6, графічний: Справа 6( 35 px * 20 px), ASCII: ( 4 рядки, 7 col)

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

Очікуваний вихід: 5

Припущення

Щоб полегшити життя, ви гарантуєте, що:

  • Будучи нетороїдальною , сітка не згортається ні горизонтально, ні вертикально.
  • Немає вільних кінців, наприклад, +--- або +- -+. Усі відрізки рядків мають два кінці.
  • Дві лінії, що зустрічаються в, +повинні перетинатися одна з одною в цій точці.
  • Вам не доведеться турбуватися про недійсні введення.

Діють правила щодо стандартних лазів. Будь ласка, розглядайте квадрати як прямокутники. За бажанням, ви можете видалити пробіли в кожному рядку сітки.

Це , тому зробіть свій запис якомога коротшим. Текстові та графічні рішення змагатимуться разом.

Таблиця лідерів


Чи дозволена однотонна растрова карта?
користувач202729

@ user202729 Так. Якщо ви вирішили працювати з зображеннями, що не належать до PNG, вкажіть це у відповіді.
Frenzy Li

Є чи це дійсний увійти в систему? (Кут прямокутника стосується межі великого прямокутника.) Якщо так, розгляньте додавання його як тестовий випадок.
Згарб

@ Zgarb Це правильний ввід. Я також відредагую публікацію.
Frenzy Li

Чи є причина, що ви ставите очікувані результати в спойлери? Здається, що це просто робить перевірку вашого коду дещо більш дратівливою.
FryAmTheEggman

Відповіді:


4

Grime , 31 28 байт

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

Спробуйте в Інтернеті!

Здійснює введення у форматі ASCII.

Пояснення

Синтаксис Grime дуже близький до регулярних виразів. Кожен рядок визначає візерунок, який може або не відповідає прямокутнику символів. Tвідповідає прямокутнику, верхній рядок і лівий стовпець виглядають дійсними.

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

Другий ряд - це «основна програма».

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 байт

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>

Приймає введення як масив рядків однакової довжини. Пояснення: Створює серію регулярних виразів, які відповідають прямокутникам усіх можливих ширини та висоти (а також деякі неможливі ширини та висоти, але це код для гольфу для вас) та підраховує кількість збігів, які вони створюють. Оскільки в регулярному вираженні є група захоплення, splitповертається 2n+1для nзбігів, тому я праворуч зміщую на 1, щоб отримати кількість збігів, оскільки це економить байт над тим, щоб група не захоплювала.


Гм, фрагмент коду для мене не працює [Firefox 54.0.1 (32bit) або Chrome 60.0.3112.90 (64bit) у Windows (64bit)].
Джонатан Аллан

Фрагмент Не працює і на Safari [Mac (64bit)].
Містер Xcoder

2
Здається, що нам потрібно вставити речі в область тексту. Потрібно однакова кількість символів на рядок.
Frenzy Li

Ах бачу, добре місце @FrenzyLi!
Джонатан Аллан

4

J , 103 95 86 80 76 70 байт

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

Спробуйте в Інтернеті!

Приймає вхід як масив рядків з пробілами (таким чином, щоб кожен рядок був однакового розміру). Використовує повний оператор підрядного масиву ;._3для ітерації над кожним можливим розміром підмасива, більшим за 2 х 2, і підраховує підриси, які є дійсними прямокутниками. Завершує всі тестові справи майже миттєво.


1
@FrenzyLi Дякую Функція отримує вхід як масив рядків, але я кодував кожен кожен масив у вигляді плоскої рядки, переробленої в масив, перш ніж зберігати їх у кожній змінній, щоб використовуватись як аргумент для функції.
милі

А-а-а ... дякую за ваше пояснення.
Шалений Лі

@miles приємно. коли ви кажете введення як масив рядків, чи є кожен рядок введення 1 строк?
Іона

@Jonah Strings в J - це лише масиви символів, тож вхід - це фактично 2d масив символів.
миль

3

Математика, 136 134 132 байт

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

Використання: (для старої 136-байтної версії, але нова версія в основному однакова)

_

Примітка:

  • Це працює в часі O (m 2 n 2 max (m, n)), тому використовуйте лише невеликі входи.
  • Хоча це має працювати з бінарними зображеннями, очевидно, це може працювати з небінарними зображеннями. (але чорний має бути однаково нульовим)
  • Графіка не обов'язково повинна бути побудована з 5x5 блоків, блоки можуть бути меншими.
  • @*є новою у версії 10. У старих версіях використовуйте Tr~Composition~Flattenзамість Tr@*Flatten.

У якій версії MMA це? У 9.0 він відповідає"Tr@" cannot be followed by "*Flatten".
Frenzy Li

1
@FrenzyLi 10.0. Так, @*скорочення для Compositionнової у версії 10.
user202729

1
Чому ви просто не використовуєте RectangleCount[]?
MCMastery

2
@MCMastery Mathematica відомий тим, що має багато вбудованих, але не цей.
користувач202729

@ user202729 lol yep, im jk
MCMastery

2

Желе ,  60 53 52 51  50 байт

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

Повна програма, що приймає список рядків (рядки однакової довжини) та друкує кількість.

Спробуйте в Інтернеті!
... або для зручності копіювання та вставлення вводу використовуйте цю повну програму (з додатковим байтом для розділених ліній)
- зауважте, що рядки повинні містити пробіли, щоб програма працювала правильно.

Як?

Ñ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

Haskell, 180 167 166 байт

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]

Спробуйте в Інтернеті!

Пройдіть усі можливі кутові положення з чотирма вкладеними петлями і перевірте, чи всі символи на лініях між ними складаються +-(горизонтальні) або +|(вертикальні).


1

Желе , 41 39 34 33 байт

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

Спробуйте в Інтернеті! або Переглянути всі справи.

Спираючись на мою відповідь Дж.

Пояснення

,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

Тепер він нарешті починає відчувати себе конкурентоспроможним у 34 байтах.
миль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.