Objętości skrzynek ASCII


40

Wprowadzenie

W tym wyzwaniu otrzymujesz jako dane wejściowe reprezentację ASCII siatki (rozłożonej powierzchni) prostokątnego prostopadłościanu (ramka 3D). Format jest następujący:

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

Każda twarz prostopadłościanu jest prostokątem #s otoczonym +-|-znakami. Zewnętrzna część siatki jest wypełniona .s. Sieć zawsze będzie miała tę samą orientację: środkowa ściana otoczona jest czterema sąsiadującymi ścianami, a odpowiednik środkowej ściany znajduje się po prawej stronie wejścia. Dane wejściowe są wypełnione .s do kształtu prostokąta i nie będą zawierać dodatkowych wierszy ani kolumn .s.

Zadanie

Twoim zadaniem jest wziąć jako dane wejściowe diagram jak wyżej i obliczyć objętość prostopadłościanu, który reprezentuje, który jest tylko iloczynem jego wysokości, szerokości i głębokości. Możesz wziąć dane wejściowe jako ciąg rozdzielany znakiem nowej linii lub tablicę ciągów.

Długość każdej krawędzi to odległość między +znakami na dwóch końcach. Na przykład krawędź pozioma +--+ma długość 3, a krawędź pionowa

+
|
|
|
+

ma długość 4. Minimalna długość krawędzi wynosi 1. Przykładowy prostopadłościan powyżej ma objętość 2 * 3 * 4 = 24.

Zasady i punktacja

Możesz napisać pełny program lub funkcję, a wygrywa najniższa liczba bajtów.

Przypadki testowe

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

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

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

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

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

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

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

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

13
Naprawdę podoba mi się to wyzwanie. Ponieważ dane wejściowe mają tak zbędną strukturę, istnieje wiele możliwości odzyskania wymiarów.
xnor

Odpowiedzi:


25

Retina , 29 28 bajtów

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

¶\|
$`
y

Wypróbuj online!

Istnieje wiele sposobów podejścia do tego w Retinie, w zależności od tego, który obszar chcesz pomnożyć przez którą stronę, więc nie jestem pewien, jak optymalne jest to, ale w rzeczywistości jest już znacznie krótsze, niż się spodziewałem.

Obecnie mam dwa inne rozwiązania o tej samej liczbie bajtów, które wydają się nieco bardziej grywalne niż powyższe podejście:

\G\..+¶

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

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

Chociaż w każdym z nich mogę zapisać bajt, jeśli założę, że dane wejściowe kończą się końcowym podawaniem linii, ale wolałbym nie polegać na tym.

I jeszcze jeden, wciąż o 28 bajtach (ten w rzeczywistości mnoży trzy strony zamiast mnożenia jednego obszaru przez bok):

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

Wyjaśnienie

Główną ideą jest pomnożenie obszaru twarzy na górze przez długość pionowej strony, która dotyka granicy długości wejścia.

Jako przykład wykorzystam następujące dane wejściowe (ma długości boków 2, 3 i 4, czyli obszar 24):

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

Etap 1: Transliteracja

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

Wyrażenie regularne \G\..+¶dopasowuje linię rozpoczynającą się od .i bezpośrednio przylegającą do poprzedniej linii. To pasuje do wszystkich linii zawierających górną ścianę. Sama scena zamienia się .w xi wszystkie inne postacie (dowolne |+-#) w y. To daje nam następujący wynik:

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

Ma jeszcze jedną kolumnę, yniż potrzebujemy, aby przedstawić obszar górnej powierzchni. Naprawiamy to w następnym etapie.

Etap 2: Wymień

xy

Dopasowujemy więc ypoprzednik x(który jest dokładnie jednym z nich w wierszu) i usuwamy je oba z ciągu. Otrzymujemy to:

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

Mamy teraz obszar górnej powierzchni reprezentowany przez liczbę ys.

Etap 3: Wymień

¶\|
$`

Naszym celem jest pomnożenie tego obszaru Aprzez brakującą długość boku, czyli liczbę |na początku wiersza plus 1. Jednak w rzeczywistości łatwiej jest pomnożyć przez liczbę, n+1ponieważ mamy już jedną kopię Aciągu . Jeśli zastąpimy nrzeczy A, otrzymamy n+1kopie A. To nam znacznie ułatwia.

Więc po prostu zastępujemy dowolne |bezpośrednio po wysunięciu linii wszystkim przed meczem. Spowoduje to, że struna dość mocno i sprawia, że ​​jest ona nieco większa niż potrzebujemy, ale liczba ys kończy się wynikiem, którego szukamy:

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

Etap 4: Mecz

y

Pozostało tylko policzyć liczbę ys, która jest drukowana jako liczba dziesiętna na końcu.


15

Python 2, 57 bajtów

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

Funkcja, która przyjmuje listę ciągów.

Określa 3 wymiary osobno:

l[0].find('+')
Indeks pierwszego +w pierwszym rzędzie.

-~l[0].count('-')
Liczba -znaków w pierwszym rzędzie.

~`l`.count("'|")
Liczba wierszy rozpoczynających się od |symbolu, poprzez ciąg znaków reprezentujący listę z symbolem cytatu przed nią.


62 bajty:

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

Funkcja, która pobiera listę ciągów i wypisuje wynik.

Znajduje jeden wymiar ajako indeks +w pierwszym wierszu. Pozostałe dwa wymiary są z niego wywnioskowane oraz szerokość i wysokość prostokąta wejściowego.

63-bajtowa alternatywa polegająca na oddzielnym określaniu wymiarów:

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

11

Bash + coreutils, 83, 77 bajtów

EDYCJE:

  • Zapisano 6 bajtów, używając „Here String” i nieco optymalizując wyrażenie regularne

Grał w golfa

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

Wyjaśniono

Przekształć za pomocą sed :

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

Pozbądź się nowych linii, używając backticków, dołącz)

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

Wprowadź wynikowe wyrażenie do bc

=> 24

Test

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

1

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

3

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

24

Wypróbuj online! (używa rozszerzenia arytmetycznego bash zamiast bc , ponieważ ten ostatni nie jest dostępny)


10

Ślimaki , 19 bajtów

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

Wypróbuj online.

Chodzi o to, że zaczynamy gdzieś na skraju prawej krawędzi w sieci, a następnie udajemy się gdzieś w dolną ścianę. Długość krawędzi i powierzchnia twarzy są mnożone przez mechanizm zliczania wszystkich pasujących ścieżek.

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)

Test

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

Działa na zasadzie podobnej do innych odpowiedzi: znajdź pierwszą, +aby znaleźć głębokość, znajdź następną .po, +aby znaleźć szerokość i policz liczbę |na końcu linii i dodaj 1, aby znaleźć wysokość.

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

nie wziął udziału w programie testowym

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 bajtów

Niech Wi Hbędzie odpowiednio szerokością i wysokością danych wejściowych - nie pudełkiem. Następnie, wymiary skrzyni A, Ba Cwedług poniższych zasad:

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

Poniższy rysunek pokazuje co A, Bi Csą, w zakresie nazw brzegowych:

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

Stąd powyższe formuły. Ten program Oblicza A, dedukuje wartości Bi Cwreszcie oblicza swój produkt.

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

Wypróbuj online!

Poprzednia wersja - Inne podejście - 26 bajtów

|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 bajtów

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

Wypróbuj online!

Wyjaśnienie:

Objętość pudełka można obliczyć mnożąc liczbę .sekund na pierwszej linii przed wszelkimi innymi postaciami, przez liczbę +i -s na pierwszej linii - 1, oraz liczbę wierszy, które zaczynają się od |+ 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

Musiałem przesunąć IP w górę, zamiast w dół, aby użyć pionu, jeśli w 3. linii. Jeśli adres IP spadał w dół, pionowe if zmusiłoby górę stosu do 1, gdy trafi w następujący poziomo if, wysyłając go w złym kierunku.


2

Haskell, 64 56 bajtów

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

Wypróbuj online!

Wyjaśnienie

Dane wejściowe powinny być listą ciągów dla każdej linii, więc w fparametrze xjest pierwszy wiersz i rlista pozostałych wierszy.

  1. fst(span(>'+')x)zwraca .prefiks pierwszej linii jako ciąg znaków, podobnie length(fst(span(>'+')x))jak pierwszy wymiar d1.
  2. Zrozumienie listy może działać jak filtr, np. ['-' | '-' <- x]Zwraca ciąg wszystkiego -w pierwszym wierszu, a więc 1 + length['-' | '-' <- x]zwraca drugi wymiar d2.
  3. Analogicznie |można policzyć liczbę w pierwszym rzędzie, podobnie 1 + length['|' | '|':_ <- r]jak trzeci wymiar d3.

Zrozumienie listy w punktach 2. i 3. można skrócić do 1+sum[1|'-'<-x]i 1+sum[1|'|':_<-r]budując listę takich dla każdego wystąpienia „-” lub „|” a następnie biorąc sumę. Możemy dodatkowo umieścić zewnętrznej 1+do listy pojmowania przez dołączenie -do xi "|"do rotrzymując sum[1|'-'<-'-':x]a sum[1|'|':_<-"|":r]. Teraz możemy połączyć oba zestawienia listowe, umieszczając oba predykaty w tym samym rozumieniu: sum[1|'|':_<-"|":r,'-'<-'-':x]Dogodnie oblicza to dokładnie iloczyn dwóch wymiarów, ponieważ dla list Fi Gponiższym zestawieniem list jest produkt kartezjański F x G =[(a,b)|a<-F,b<-G].

Wreszcie, zamiast mnożenia 1. przez kombinację 2. i 3. możemy skorzystać z >>operatora na listach: F>>Gpowtarza G length Fczasy i łączy wynik. fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]Powtarza więc listę d2*d3tych d1czasów, dając listę d1*d2*d3tych, które są następnie sumowane w celu uzyskania objętości.


Możesz wziąć dane wejściowe jako listę ciągów, eliminując potrzebę lines.
Zgarb

@Zgarb Dzięki, to oszczędza niektóre bajty.
Laikoni,

1

Java 8, 185 129 bajtów

dzięki Zgarbowi za -56 bajtów

grał w golfa:

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;}

bez golfa:

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;
}

Wyjaśnienie

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

gdzie ai bsą wymiary podstawy i hjest wysokość. Możesz znaleźć h, licząc pierwsze hlinie, od których zaczynasz od ..


Możesz wziąć dane wejściowe jako tablicę lub ciągi, więc nie musisz ręcznie ich dzielić.
Zgarb

Ups, dzięki, naprawiam ...
Bobas_Pett,

1

Java, 112 bajtów

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);}

Rozszerzony:

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 bajtów

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

Uwaga: "$args"|% i*f + jest skrótem do"$args".indexOf('+')

Wyjaśnienie

Dobre wyjaśnienie pochodzi z odpowiedzi Osable :

Niech Wi Hbędzie odpowiednio szerokością i wysokością danych wejściowych - nie pudełkiem. Następnie, wymiary skrzyni A, Ba Cwedług poniższych zasad:

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

Poniższy rysunek pokazuje co A, Bi Csą, w zakresie nazw brzegowych:

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

I Cjest pozycją pierwszego +w pierwszym wierszu wejścia.

Skrypt testowy:

$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"
}

Wynik:

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

0

Wolfram Language (Mathematica) , 64 bajty

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

Wypróbuj online!

Wykorzystuje szereg ., |i \nznaki na wejściu do rozwiązania dla objętości. Wygląda to głupio, ponieważ zamiast niego pojawiła się nowa linia \n.

Jeśli A, Bi Csą stronami, to . = 2C(A+2C), | = 5B+4C-9i \n = B+2C, więc możemy rozwiązać problem z objętością ABCpod względem tych trzech liczb znaków.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.