ASCII框的数量


40

介绍

在此挑战中,将为您提供矩形长方体(3D框)的(展开的表面)的ASCII表示作为输入。格式是这样的:

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

长方体的每个面都是#s 的矩形,由- +-|字符包围。网的外部充满.s。网络将始终具有相同的方向:有一个中间面被其四个相邻面围绕着,中间面的对应部分位于输入的右边界。输入用.s 填充为矩形,并且不会包含.s的额外行或列。

任务

您的任务是将上述图表作为输入,并计算它表示的长方体的体积,这只是其长,宽和深的乘积。您可以将输入作为换行符分隔的字符串或字符串数​​组。

每个边的长度是- +两端字符之间的距离。例如,水平边缘的+--+长度为3,垂直边缘的长度为3

+
|
|
|
+

的长度为4。边的最小长度为1。上面的示例长方体的体积为2 * 3 * 4 = 24。

规则和计分

您可以编写完整的程序或函数,最低的字节数为准。

测试用例

.++..
+++++
+++++
.++..
1

...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
3

..+-+....
..|#|....
+-+-+-+-+
|#|#|#|#|
|#|#|#|#|
+-+-+-+-+
..|#|....
..+-+....
12

.+---+.....
++---++---+
||###||###|
||###||###|
||###||###|
++---++---+
.+---+.....
16

....++.....
....||.....
....||.....
....||.....
+---++---++
|###||###||
|###||###||
|###||###||
+---++---++
....||.....
....||.....
....||.....
....++.....
16

...+--+......
...|##|......
...|##|......
+--+--+--+--+
|##|##|##|##|
+--+--+--+--+
...|##|......
...|##|......
...+--+......
18

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
24

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120

13
我真的很喜欢这个挑战。由于输入具有很多冗余结构,因此如何恢复尺寸有很多选择。
xnor

Answers:


25

视网膜29 28字节

T`.p`xy`\G\..+¶
xy

¶\|
$`
y

在线尝试!

在Retina中,有很多方法可以解决此问题,具体取决于您要与哪一侧相乘。因此,我不确定这是多么理想,但实际上已经比我想象的要短得多。

我目前有两个相同字节数的解决方案,它们比上述方法更具实用性:

\G\..+¶

¶\|
$'¶
G`\.
T`.|+

¶\||\+¶\.\D+
$'¶
G`\.
T`.|+

尽管在这些示例中,如果我假设输入以尾随换行符结尾,则可以节省一个字节,但是我宁可不必依赖于此。

还有一个仍然是28个字节(这实际上是将三边相乘而不是将一个区域乘以一边):

\G\.
x
-(?<=^.+)
$`
¶\|
$`
x

说明

主要思想是将顶面的面积乘以接触输入长度边框的垂直边的长度。

我将使用以下输入作为示例(它的边长为2、3和4,所以面积为24):

...+---+.......
...|###|.......
...|###|.......
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

阶段1:音译

T`.p`xy`\G\..+¶

正则表达式\G\..+¶匹配.以前一行开头并紧邻前一行的行。因此,这匹配了包含顶面的所有线条。舞台本身转向.x和所有其他字符(任何|+-#)进入y。这给我们以下结果:

xxxyyyyyxxxxxxx
xxxyyyyyxxxxxxx
xxxyyyyyxxxxxxx
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

y比我们要代表顶面的区域多一列。我们将在下一阶段修复此问题。

阶段2:更换

xy

因此,我们匹配一个以a y开头x的字符串(每行恰好是其中一个),并将它们都从字符串中删除。我们得到这个:

xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

因此,现在我们有了以ys 表示的顶面面积。

阶段3:更换

¶\|
$`

我们的目标是将这个区域乘以A缺少的边长,即行首的数字|加1。但是,实际上,乘以一个数字比较容易,n+1因为我们已经A在字符串中得到一个副本。如果我们用替换n事物A,则最终得到的n+1副本A。这对我们来说使事情变得容易得多。

因此,我们只需|在换行后立即将所有内容替换为比赛前的所有内容即可。这会使字符串杂乱无章,并使它比我们需要的大很多,但是ys 的数量最终是我们要寻找的结果:

xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

阶段4:比赛

y

剩下的就是计算ys 的数目,该数目最后显示为十进制数。


15

Python 2,57字节

lambda l:l[0].find('+')*~l[0].count('-')*~`l`.count("'|")

接受字符串列表的函数。

分别确定3个维度:

l[0].find('+')
+第一行中第一行 的索引。

-~l[0].count('-')
-第一行中 的标志数。

~`l`.count("'|")
|符号开始的行数,通过列表的字符串表示形式进行,该列表前面带有引号。


62个字节:

def f(l):a=l[0].find('+');print(len(l[0])/2-a)*(len(l)-a+~a)*a

接收字符串列表并输出结果的函数。

在第一行中找到一个维度a作为的索引+。从中可以推断出其他两个维度以及输入矩形的宽度和高度。

63字节的替代方案,单独查找尺寸:

lambda l:l[0].find('+')*~l[0].count('-')*~zip(*l)[0].count('|')

11

Bash + coreutils, 83,77字节

编辑:

  • 通过使用“ Here String”并优化正则表达式节省了6个字节

打高尔夫球

bc<<<`sed -rn '1{s/(.+)[^\.]*\1/(0\1)*(0/
s/\./+1/gp;a)*(-1
}
/^[+|]/a+1
'`\)

讲解

sed转换:

....+--+....... => (0+1+1+1+1)*(0+1+1+1 )*(-2 +1
. =>()
. =>()
. =>()
. =>()
+ => +1
| => +1
+ => +1
. =>()
. =>()
. =>()
. =>()

使用反引号消除换行符,附加)

=> (0+1+1+1+1)*(0+1+1+1 )*(-2 +1 +1 +1 +1)

将结果表达式送入BC

=> 24

测试

./box <<EOF
.++..
+++++
+++++
.++..
EOF

1

./box <<EOF
...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
EOF

3

./box <<EOF
....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
EOF

24

在线尝试! (使用bash算术扩展而不是 bc,因为后者不可用)


10

蜗牛,19字节

AM
=~d^.+\+.+l.+^.2

在线尝试。

这个想法是,我们从网中最右边的某个地方开始,然后再到最底面的某个地方。边缘的长度和脸部的面积乘以计数所有匹配路径的机制。

AM   ,, A -> count all matching paths
     ,, M -> first char matched is the one in the current direction
     ,,      from the starting location, rather than directly on it
=~          ,, check that we are on the right edge of the grid
d ^.+ \+    ,, go down, matching one or more non-'.' characters, then a '+'
.+          ,, go down one or more times
l .+        ,, go left one or more times
^. 2        ,, match two further characters which aren't '.' to the left

4

JavaScript(ES6),67 91

s=>(a=~-s.search`
`/2-(b=s.indexOf`+`))*b*(s.split`
`.length-1-2*b)

测试

F=
s=>(a=~-s.search`
`/2-(b=s.indexOf`+`))*b*(s.split`
`.length-1-2*b)

out=x=>O.textContent+=x+'\n\n'

;`.++..
+++++
+++++
.++..
1

...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
3

..+-+....
..|#|....
+-+-+-+-+
|#|#|#|#|
|#|#|#|#|
+-+-+-+-+
..|#|....
..+-+....
12

.+---+.....
++---++---+
||###||###|
||###||###|
||###||###|
++---++---+
.+---+.....
16

....++.....
....||.....
....||.....
....||.....
+---++---++
|###||###||
|###||###||
|###||###||
+---++---++
....||.....
....||.....
....||.....
....++.....
16

...+--+......
...|##|......
...|##|......
+--+--+--+--+
|##|##|##|##|
+--+--+--+--+
...|##|......
...|##|......
...+--+......
18

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
24

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120`
.split('\n\n').forEach(t=>{
  t=t.split('\n')
  k=+t.pop()
  t=t.join('\n')
  v=F(t)
  out(v+' '+k +' '+(v==k?'OK':'KO')+'\n'+t)
})
<pre id=O></pre>


3

Ruby,44岁

类似的原理,以其他答案作品:找到的第一个+找的深度,找到下一个.+找宽度和计数的数量|在行尾加1找到的高度。

->s{(s=~/\+/)*($'=~/\./)*s.split("|
").size}

在测试程序中取消

f=->s{(s=~/\+/)*    # index of first match of /\+/ in s
($'=~/\./)*         # $' is a special variable, contains string to right of last match. index of /\./ in $' 
s.split("|
").size}            # split the string at |\n to form an array and count the members

puts f[".++..
+++++
+++++
.++.."]

puts f["...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++...."]

#etc.

3

05AB1E,21个字节

WH分别为输入的宽度和高度-而不是盒子。然后,选择框尺寸ABC遵循以下规则:

W = 2(A+C)+1
H = B+2C+1

下图显示了什么AB并且C是在边缘的名称而言:

....AAAA.......
....|##|.......
....|##|.......
....|##|.......
B---+--CCCCC--+
B###|##|###|##|
B---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

因此,上述公式。这个程序计算A,推导出的值B,并C最终计算出自己的产品。

S'.ÊO<D¹g<;-(D·|g-()P

S'.Ê                  From each character of the first line, yield 0 if it is '.' or 1 otherwise. The result is stored in an array
    O<D               A = sum(array) - 1
       ¹g<;-(D        C = (W-1)/2 - A
              ·|g-(   B = H-1-2*C
                   )  Yield [A,C,B]
                    P Take the product and implicitly display it

在线尝试!

旧版本-不同的方法-26字节

|vyS'.Ê})¬O<sø¬O<s€O¬Ê1k)P

|                          Take the input as an array of lines (strings)
 vy                        For each line
   S'.Ê                    For each character in the line, yield 0 if it is '.' or 1 otherwise
       }                   End For
        )                  Wrap the results as an array
         ¬O<               A = sum(first_line) - 1
            sø             Transpose the box pattern
              ¬O<          B = sum(first_line) - 1 ; since the pattern is transposed, it corresponds to the first column
                 s€O       Sum every line from the transposed pattern
                    ¬Ê1k   C = index of the first line that has a different sum from the first line
                        )  Yield [A, B, C]
                         P Take the product A*B*C and implicitly display it

2

Befunge 93,56个字节

~2%#^_1+
  @.*+<
`"z"~<|:`~0+
5*\`#^_\1>*\~7
%2~\<\+1_^#

在线尝试!

说明:

箱的容积可以通过的数量乘以计算.上之前的任何其他字符的第一行S,由数量+-1,以及与启动的行数- S于第一行|+ 1。

~2%#^_1+         Uses the ASCII value % 2 of a character to count the .s

%2~\<\+1_^#      IP wraps around to the bottom. Counts the non . chars
                 Works because ("+" % 2) == ("-" % 2) == 1

5*\`#^_\1>*\~7   Multiplies the previous 2 results and cycles through
                 characters until it hits a newline or EOF

`"z"~<|:`~0+     Adds 1 to the 3rd dimension if the following char is a "|"
                 Also checks for EOF; If there is more input, goes back to
                 previous line. Otherwise, goes to the last line

  @.*+<          Adds 1 to the 3rd dimension, multiplies it to the rest,
                 prints the volume, and ends the program

如果要在第3行中使用垂直,我必须向上移动IP而不是向下移动IP。如果IP沿线下降,则垂直if将在碰到后面的水平if时将堆栈的顶部强制为1,从而以错误的方向发送它。


2

Haskell,64 56字节

f(x:r)=sum$fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]

在线尝试!

说明

输入应该是每一行的字符串列表,因此f参数x中的第一行r是其余行的列表。

  1. fst(span(>'+')x).以字符串形式返回第一行的-prefix,第length(fst(span(>'+')x))一个维度也是如此d1
  2. 列表推导可以充当过滤器,例如,在第一行中['-' | '-' <- x]返回所有字符串-,因此1 + length['-' | '-' <- x]产生第二维d2
  3. 类似地,|可以计算第一行中的数量,因此也可以计算1 + length['|' | '|':_ <- r]第三维d3

2.和3.列表内涵可以缩短到1+sum[1|'-'<-x]1+sum[1|'|':_<-r]通过构建者的列表的每次出现“ - ”或“|” 然后取总和。我们可以进一步把外1+通过添加到列表中理解-x,并"|"r产生sum[1|'-'<-'-':x]sum[1|'|':_<-"|":r]。现在,我们可以通过将两个谓词置于相同的理解中来组合这两个列表理解:sum[1|'|':_<-"|":r,'-'<-'-':x]方便地,这将精确地计算这两个维度的乘积,因为对于列表而言FG以下列表理解是笛卡尔乘积F x G =[(a,b)|a<-F,b<-G]

最后,我们可以使用>>列表上的运算符来代替将1.与2和3的组合相乘:F>>G重复G length F次数并连接结果。因此,fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]重复的名单d2*d3那些d1时间,产生的名单d1*d2*d3那些然后将其总结了取得的体积。


您可以将输入作为字符串列表,而无需输入lines
Zgarb

@Zgarb谢谢,这节省了一些字节。
Laikoni '16

1

Java的8,185个 129字节

感谢Zgarb提供-56字节

打高尔夫球:

int g(String[]i){int h=0;for(String k:i){if(k.charAt(0)=='.')h++;else break;}return((i[0].length()-2*h-1)/2)*(i.length-2*h-1)*h;}

松散:

int g(String[] i) {
    int h = 0;
    for (String k : i) {
        if (k.charAt(0) == '.') h++;
        else break;
    }
    return ((i[0].length()-2*h-1)/2)*(i.length-2*h-1)*h;
}

说明

a*b*h = ((length_of_line-2*h-1)/2)*(number_of_lines-2*h-1)*h

其中ab是底座的尺寸, h是高度。您可以h通过对以h开头的第一行进行计数来查找.


您可以将输入作为数组或字符串,因此无需手动拆分。
Zgarb

糟糕,修复...
Bobas_Pett

1

Java,112字节

int v(String[]s){int a=s[0].lastIndexOf('+')-s[0].indexOf('+'),b=s[0].length()/2-a;return a*b*(s.length-2*b-1);}

展开:

int v(String[] s)
{
  // length of the edge in the first line
  int a = s[0].lastIndexOf('+') - s[0].indexOf('+');
  // length of the second edge
  // int b = s[0].length() - 2 * a - 1; <-- multiplied by 2
  int b = s[0].length()/2 - a; // <-- hack, length is always odd
  // length of the third edge in ()
  // volume
  return a * b * (s.length - 2 * b - 1);
} // end method v

1

Powershell,68 67字节

($c="$args"|% i*f +)*($args[0].Length/2-.5-$c)*($args.Count-1-2*$c)

注:"$args"|% i*f + 在快捷方式"$args".indexOf('+')

说明

很好的解释来自于Osable的回答

WH分别为输入的宽度和高度-而不是盒子。然后,选择框尺寸ABC遵循以下规则:

W = 2(A+C)+1
H = B+2C+1

下图显示了什么AB并且C是在边缘的名称而言:

CCCCAAAA.......
....|##|.......
....|##|.......
....|##|.......
B---+--+---+--+
B###|##|###|##|
B---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

并且C+输入的第一行中第一行的位置。

测试脚本:

$f = {

($c="$args"|% i*f +)*($args[0].Length/2-.5-$c)*($args.Count-1-2*$c)

}

@(

,(1, ".++..",
     "+++++",
     "+++++",
     ".++..")

,(3,"...++....",
    "...||....",
    "...||....",
    "+--++--++",
    "+--++--++",
    "...||....",
    "...||....",
    "...++....")

,(12,"..+-+....",
     "..|#|....",
     "+-+-+-+-+",
     "|#|#|#|#|",
     "|#|#|#|#|",
     "+-+-+-+-+",
     "..|#|....",
     "..+-+....")

,(16,".+---+.....",
     "++---++---+",
     "||###||###|",
     "||###||###|",
     "||###||###|",
     "++---++---+",
     ".+---+.....")

,(16,"....++.....",
     "....||.....",
     "....||.....",
     "....||.....",
     "+---++---++",
     "|###||###||",
     "|###||###||",
     "|###||###||",
     "+---++---++",
     "....||.....",
     "....||.....",
     "....||.....",
     "....++.....")

,(18,"...+--+......",
     "...|##|......",
     "...|##|......",
     "+--+--+--+--+",
     "|##|##|##|##|",
     "+--+--+--+--+",
     "...|##|......",
     "...|##|......",
     "...+--+......")


,(24,"....+--+.......",
     "....|##|.......",
     "....|##|.......",
     "....|##|.......",
     "+---+--+---+--+",
     "|###|##|###|##|",
     "+---+--+---+--+",
     "....|##|.......",
     "....|##|.......",
     "....|##|.......",
     "....+--+.......")

,(120,"....+-----+..........",
      "....|#####|..........",
      "....|#####|..........",
      "....|#####|..........",
      "+---+-----+---+-----+",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "+---+-----+---+-----+",
      "....|#####|..........",
      "....|#####|..........",
      "....|#####|..........",
      "....+-----+..........")

) | % {
    $expected,$s = $_
    $result = &$f @s
    "$($result-eq$expected): $result"
}

输出:

True: 1
True: 3
True: 12
True: 16
True: 16
True: 18
True: 24
True: 120

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.