ASCIIボックスのボリューム


40

前書き

この課題では、長方形の直方体(3Dボックス)のネット(展開された表面)のASCII表現が入力として与えられます。形式は次のとおりです。

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

直方体の各面は、-文字で#囲まれたsの長方形です+-|。ネットの外側は.s で満たされています。ネットは常に同じ向きになります。4つの隣接する面に囲まれた中央の面があり、中央の面の対応物は入力の右境界にあります。入力は.sで長方形にパディングされ、sの余分な行または列は含まれません.

タスク

あなたのタスクは、上記の図を入力として取得し、それが表す直方体の体積を計算することです。直方体は、その高さ、幅、深さの積にすぎません。入力は、改行区切りの文字列または文字列の配列として取得できます。

各エッジの長さは、+両端の文字間の距離です。たとえば、水平エッジの+--+長さは3、垂直エッジの長さは

+
|
|
|
+

エッジの最小長は1です。上の例の直方体のボリュームは2 * 3 * 4 = 24です。

ルールとスコアリング

あなたは完全なプログラムまたは関数を書くことができ、最も低いバイト数が勝ちます。

テストケース

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

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

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

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

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

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

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

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

13
私はこの挑戦が本当に好きです。入力には非常に多くの冗長な構造があるため、ディメンションを復元する方法には多くの選択肢があります。
XNOR

回答:


25

網膜29 28バイト

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

¶\|
$`
y

オンラインでお試しください!

Retinaでこれにアプローチする方法はたくさんあります。どの領域をどの側に掛けるかによって異なります。これがどれほど最適かはわかりませんが、実際にはすでに思ったよりもずっと短くなっています。

私は現在、同じバイト数で他の2つのソリューションを持っていますが、これは上記のアプローチよりも少しゴルフに適しているようです:

\G\..+¶

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

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

これらでは、入力が末尾の改行で終わると仮定すると、1バイトずつ保存できますが、それに頼る必要はありません。

そして、まだ28バイトです(これは実際に1つの領域に1辺を乗算する代わりに3辺を乗算します)。

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

説明

主なアイデアは、上部の顔の面積に、入力の長さの境界に接する垂直辺の長さを掛けることです。

例として次の入力を使用します(辺の長さは2、3、および4なので、面積は24です)。

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

ステージ1:文字変換

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

正規表現は、前の行\G\..+¶で始まり.、直前の行に隣接する行と一致します。したがって、これは上面を含むすべての行に一致します。ステージ自体が.xなり、他のすべてのキャラクター(のいずれか|+-#)がになりyます。これにより、次の結果が得られます。

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

これにはy、上面の領域を表すのに必要な列がもう1つあります。これを次の段階で修正します。

ステージ2:交換

xy

そのためy、前にが付いたa x(行ごとに正確に1つです)に一致し、両方を文字列から削除します。これを取得します。

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

これで、ys の数で表される上面の領域が得られました。

ステージ3:交換

¶\|
$`

ここでの目標は、この領域に行の先頭のA数に|1を加えた行方不明の辺の長さを掛けることです。ただし、文字列にn+1は既に1つのコピーがあるため、実際には数字を掛ける方が簡単です。Anものを置き換えるとA、のn+1コピーになりAます。これにより、作業が非常に簡単になります。

そのため|、ラインフィードの直後にあるすべてのものを、試合の前にあるすべてのものに置き換えるだけです。これにより、文字列がかなり大きくなり、必要なサイズよりかなり大きくなりますが、ys の数が最終的に求めている結果になります。

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

ステージ4:試合

y

あとは、ys の数を数えるだけです。これは、最後に10進数として出力されます。


15

Python 2、57バイト

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

文字列のリストを受け取る関数。

3次元を個別に決定します。

l[0].find('+')
+最初の行の 最初のインデックス。

-~l[0].count('-')
-最初の行の記号 の数。

~`l`.count("'|")
|symbolで 始まる行の数。その前に引用記号があるリストの文字列表現を使用します。


62バイト:

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

文字列のリストを取り込んで結果を出力する関数。

最初の行のaインデックスとして1つのディメンションを検索し+ます。他の2つの次元は、それと入力長方形の幅と高さから推測されます。

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

オンラインでお試しください! (後者は使用できないため、 bcではなくbash算術展開を使用します)


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

ルビー、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バイト

させるWおよびH入力の幅と高さ-ボックスではありません。次に、ボックスの寸法ABおよびC次のルールに従います。

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

次の図に示すものをABおよびCエッジの名前の観点から、以下のとおりです。

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

したがって、上記の式。このプログラムを計算はA、値の導出するBC、最終的に彼らの積を計算します。

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 の数、最初の行のの数+-s-1、および|+ 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がラインを下っている場合、垂直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]、2番目の次元が得られd2ます。
  3. 同様|に、最初の行のの数を数えることができ1 + length['|' | '|':_ <- r]、3番目の次元も数えられd3ます。

2.と3.のリストの内包表記はに短縮することが可能1+sum[1|'-'<-x]1+sum[1|'|':_<-r]「|」または「 - 」の各発生のためのもののリストを構築することにより、そして合計を取ります。さらにto とto をyield およびに1+追加することにより、アウターをリスト内包に含めることができます。これで、両方の述語を同じ内包に入れることで両方のリスト内包を組み合わせることができます:便利なことに、リストと次のリスト内包はデカルト積であるため、これは2つの次元の積を正確に計算します。-x"|"rsum[1|'-'<-'-':x]sum[1|'|':_<-"|":r]sum[1|'|':_<-"|":r,'-'<-'-':x]FGF 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
ズガルブ16

@Zgarbありがとう、これはいくつかのバイトを節約します。
ライコニ16

1

Java 8、185 129バイト

-56バイトのZgarbに感謝

ゴルフ:

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

ここでaおよびbは、ベースの寸法で hあり、高さです。で始まるh最初のh行を数えることで見つけることができます.


入力は配列または文字列として受け取ることができるため、手動で分割する必要はありません。
ズガルブ16

oops thx、それを修正...
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の答えから得た良い説明:

させるWおよびH入力の幅と高さ-ボックスではありません。次に、ボックスの寸法ABおよびC次のルールに従います。

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

0

Wolfram言語(Mathematica)、64バイト

(2(x=#@"
")-(y=#@"|")-9)((9-5x+y)^2-9#@".")/54&@*CharacterCounts

オンラインでお試しください!

番号を使用して.|し、\n入力中の文字は、ボリュームのために解決します。の代わりに実際の新しい行があるので、それは愚かに見え\nます。

もしAB、およびC、その後、両側あり. = 2C(A+2C)| = 5B+4C-9\n = B+2C、私たちは、ボリュームのために解決することができABC、これらの3つの文字カウントの観点から。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.