你能算出矩形的数量吗?


21

我最喜欢的数学消遣之一是绘制一个矩形网格,然后找到该网格中所有可见的矩形。在这里,提出这个问题,为自己冒险!

你能算出矩形的数量吗?

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

4 x 4 微型基板的矩形总数正好是

100

你说得对吗?

相关数学: 8×8棋盘上有几个矩形?

挑战

编写最短的函数/程序,计算非环形网格/图像上可见矩形的总数。

相关挑战: 计算独特的矩形!在2D字节数组中查找矩形的数量

输入格式

您的函数或程序可以选择使用基于文本的输入或图形输入。

基于文本的输入

网格将是一个m × nm行,n列)的ASCII网格,由以下字符组成:

  • 空格,
  • - 对于水平线段的部分,
  • | 对于垂直线段的部分,以及
  • + 对于角落。

您可以将ASCII网格作为程序/函数的输入/参数引入,格式为

  • 由换行符分隔的单个字符串,
  • 一个没有换行符,但具有一个或两个整数的字符串,用于编码网格的尺寸,或者
  • 字符串数组。

注意: 基于文本的输入至少包含1行和至少1列。

图形输入

或者,将网格编码为宽5 * n像素和高5 * m像素的黑白PNG图像。每个图像由5 px * 5 px的块组成,这些块对应于ASCII输入,方法是:

  • 空格将转换为白色块。这些块称为空白块。
  • 线段和角将转换为非空白块。这种块的中心像素是黑色的。
  • 编辑:如果两个角(在ASCII输入中)通过线段连接,则相应的块中心(在图形输入中)也应通过黑线连接。

这意味着只能从中选择每个块请忽略蓝色边界。 (单击此处查看大图)

注意: 蓝色边界仅用于说明目的。图形输入至少5像素宽,5像素像素高。您可以将图形输入转换为任何单色图像(可能是其他图像文件格式)。如果您选择转换,请在答案中指定。转换不会受到任何惩罚。

输出格式

如果要编写程序,则它必须显示一个非负数,表示输入中矩形的总数。

如果要编写函数,它还应返回一个非负数,表示输入中矩形的总数。

案例案例

情况1,图形:情况130像素* 30像素),ASCII:(6行,6列)

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

预期产量: 3

情况2中,图示:情况二20像素* 20像素),ASCII:(4行,4个 COLS)

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

预期产量: 6

情况3,图形:情况355 px * 40 px),ASCII:(8行,11列)

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

预期产量: 9

情况4,图形:案例4120 px * 65 px),ASCII:(13行,24列)

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

预期产量: 243

案例5,图解:案例55 PX * 5。PX是的,这那里!),ASCII:仅一个空格。

预期产量: 0

情况下如图6所示,图形:案例635像素* 20像素),ASCII:(4行,7个 COLS)

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

预期产量: 5

假设条件

为了让生活更轻松,我们保证:

  • 通过非环形,网格不会水平或垂直缠绕。
  • 没有松散的末端,例如 +---+- -+。所有线段都有两个末端。
  • 此时+相交的两条线必须相交。
  • 您不必担心输入无效。

应对标准漏洞的规则适用。请将正方形视为矩形。(可选)您可以删除网格每行上的尾随空格。

这是,因此请使输入尽可能短。基于文本和图形的解决方案将相互竞争。

排行榜


是否允许单色位图?
user202729

@ user202729是的。如果您选择使用非PNG图片,请在答案中进行指定。
疯狂李

这个有效的输入?(矩形角接触到较大矩形的边界。)如果是这样,请考虑将其添加为测试用例。
Zgarb

@Zgarb是有效输入。我也会编辑帖子。
疯狂的李

您将预期的输出放入扰流板是有原因的吗?似乎只是使您的代码验证变得有些烦人。
FryAmTheEggman

Answers:


4

污垢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+1n比赛,所以我右移1移来获得匹配的数量,作为在制作组非捕获保存一个字节。


嗯,该代码段对我不起作用[在Windows(64位)上均为Firefox 54.0.1(32位)或Chrome 60.0.3112.90(64位))。
乔纳森·艾伦

摘录[Mac(64bit)]也无法在Safari上运行。
Xcoder先生17年

2
看来我们必须将内容粘贴到文本区域中。每行需要相同数量的字符。
疯狂的李

我知道了,@ FrenzyLi好地方!
乔纳森·艾伦,

4

J103 95 86 80 76 70字节

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

在线尝试!

将输入作为带有尾随空格的字符串数组(以使每个字符串的大小相同)。使用完整的子数组运算符;._3迭代每个大于2 x 2的可能子数组大小,并对有效矩形的子数组进行计数。几乎立即完成所有测试用例。


1
@FrenzyLi谢谢。该函数以字符串数组形式接收输入,但是在将它们存储在每个变量中用作函数的参数之前,我将每个数组编码为扁平字符串,然后重整为数组。
英里

啊...谢谢您的解释。
疯狂的李

@miles很好。当您说输入为字符串数组时,输入的每一行是否为1?
约拿(Jonah)

@Jonah J中的字符串只是chars数组,因此输入实际上是2d chars数组。
英里

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 '17

2
@MCMastery Mathematica以内置很多功能而闻名,但是没有内置功能。
user202729

@ user202729大声笑是的,即时通讯
MCMastery '17

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

单据32 29字节

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

在线尝试!

27个字节的代码+ 2个字节的no标志。以问题中提供的相同格式进行输入(即以换行符分隔的行块)。


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

在线尝试!查看所有案例。

根据我在J中的回答

说明

,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个字节。
英里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.