Volumes de boîtes ASCII

40

introduction

Dans ce défi, vous recevez en entrée la représentation ASCII du réseau (surface dépliée) d'un cuboïde rectangulaire (zone 3D). Le format est le suivant:

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

Chaque face du cuboïde est un rectangle de #s entouré de +-|caractères. L'extérieur du filet est rempli de .s. Le filet aura toujours la même orientation: il y a une face médiane entourée de ses quatre faces voisines et la contrepartie de la face médiane est située à la droite de l'entrée. L'entrée est complétée avec .s en une forme rectangulaire et ne contiendra pas de lignes ou de colonnes supplémentaires de .s.

La tâche

Votre tâche consiste à prendre en entrée un diagramme comme ci-dessus et à calculer le volume du cuboïde qu'il représente, qui est simplement le produit de sa hauteur, de sa largeur et de sa profondeur. Vous pouvez prendre l’entrée sous la forme d’une chaîne délimitée par une ligne ou d’un tableau de chaînes.

La longueur de chaque bord est la distance entre les +caractères à ses deux extrémités. Par exemple, le bord horizontal +--+a une longueur de 3 et le bord vertical

+
|
|
|
+

a une longueur de 4. La longueur minimale d’une arête est de 1. Le cuboïde exemple ci-dessus a un volume de 2 * 3 * 4 = 24.

Règles et notation

Vous pouvez écrire un programme complet ou une fonction, et le nombre d'octets le plus faible gagne.

Cas de test

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

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

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

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

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

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

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

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120
Zgarb
la source
13
J'aime vraiment ce défi. Étant donné que la structure de l'entrée est très redondante, les possibilités de récupération des dimensions sont nombreuses.
xnor

Réponses:

25

Rétine , 29 à 28 octets

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

¶\|
$`
y

Essayez-le en ligne!

Il y a beaucoup de façons d'aborder cela dans Retina, en fonction de la zone que vous voulez multiplier avec quel côté, alors je ne suis pas sûr que ce soit optimal, mais en réalité, il est déjà beaucoup plus court que je ne le pensais.

J'ai actuellement deux autres solutions au même nombre d'octets qui semblent un peu plus faciles à jouer que l'approche ci-dessus:

\G\..+¶

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

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

Bien que dans ceux-ci, je pourrais sauvegarder un octet chacun si je suppose que l'entrée se termine par un retour à la ligne final, mais je préfère ne pas avoir à me fier à cela.

Et un autre, toujours à 28 octets (celui-ci multiplie en réalité trois côtés au lieu de multiplier une zone par un côté):

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

Explication

L'idée principale est de multiplier la surface du visage par la longueur du côté vertical qui touche le bord de la longueur de l'entrée.

Je prendrai comme exemple l'entrée suivante (elle a les longueurs de côtés 2, 3 et 4, donc une surface de 24):

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

Étape 1: Translittérer

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

La regex \G\..+¶correspond à une ligne qui commence par .et est immédiatement adjacente à la ligne précédente. Donc, cela correspond à toutes les lignes qui contiennent la face supérieure. La scène elle-même se transforme .en xet tous les autres personnages (n'importe lequel |+-#) en y. Cela nous donne le résultat suivant:

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

Cela a une colonne de plus yque ce dont nous avons besoin pour représenter la zone de la face supérieure. Nous corrigeons cela à la prochaine étape.

Étape 2: remplacer

xy

Nous faisons donc correspondre un yqui est précédé d'un x(ce qui est exactement l'un d'entre eux par ligne) et les supprimons tous les deux de la chaîne. Nous obtenons ceci:

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

Nous avons maintenant la partie supérieure représentée par le nombre de ys.

Étape 3: remplacer

¶\|
$`

Notre objectif ici est de multiplier cette zone Apar la longueur de côté manquante, qui correspond au nombre situé |au début d'une ligne plus 1. Toutefois, il est en fait plus facile de multiplier par un nombre n+1car nous avons déjà une copie de Ala chaîne. . Si nous remplaçons les nchoses par A, nous nous retrouvons avec des n+1copies de A. Cela facilite beaucoup les choses pour nous.

Nous remplaçons donc simplement tout |immédiatement après un saut de ligne par tout ce qui se trouve devant le match. Cela altère beaucoup la chaîne et la rend un peu plus large que nécessaire, mais le nombre de ys finit par être le résultat recherché:

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

Étape 4: match

y

Il ne reste plus qu'à compter le nombre de ys, qui est imprimé sous forme de nombre décimal à la fin.

Martin Ender
la source
15

Python 2, 57 octets

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

Une fonction qui prend une liste de chaînes.

Détermine les 3 dimensions séparément:

l[0].find('+')
L'index du premier +dans la première ligne.

-~l[0].count('-')
Le nombre de -signes dans la première rangée.

~`l`.count("'|")
Le nombre de lignes commençant par |symbole, via la représentation sous forme de chaîne de la liste précédée d'un symbole de citation.


62 octets:

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

Une fonction qui prend une liste de chaînes et imprime le résultat.

Trouve une dimension en atant qu'index de +dans la première ligne. On en déduit les deux autres dimensions et la largeur et la hauteur du rectangle en entrée.

Une alternative de 63 octets, trouvant les dimensions séparément:

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

Bash + coreutils, 83, 77 octets

EDITS:

  • Sauvegardé 6 octets, en utilisant "Here String" et en optimisant un peu l'expression rationnelle

Golfé

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

A expliqué

Transformer avec sed :

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

Débarrassez-vous des newlines en utilisant des backticks, ajoutez)

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

Transmettre l'expression résultante à bc

=> 24

Tester

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

1

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

3

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

24

Essayez-le en ligne! (utilise le développement arithmétique bash au lieu de bc , ce dernier n'étant pas disponible)

Zeppelin
la source
10

Escargots , 19 octets

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

Essayez-le en ligne.

L'idée est que nous commençons quelque part sur le bord droit du filet, puis que nous allions quelque part dans le bas de la face. La longueur du bord et la surface de la face sont multipliées par le mécanisme de comptage de tous les chemins correspondants.

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
feersum
la source
4

JavaScript (ES6), 67 91

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

Tester

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>

edc65
la source
3

Ruby, 44 ans

Fonctionne sur le même principe que d'autres réponses: trouver le premier +pour trouver la profondeur, trouver le suivant .après le +pour trouver la largeur, compter le nombre de |en bout de ligne et ajouter 1 pour trouver la hauteur.

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

programme non testé

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.
Level River St
la source
3

05AB1E , 21 octets

Laisser Wet Hêtre respectivement la largeur et la hauteur de l'entrée - pas la boîte. Ensuite, les dimensions de la boîte A, Bet Crespecter les règles suivantes:

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

Le montre la figure de ce qui suit A, Bet Csont, en termes de noms de bord:

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

D'où les formules ci-dessus. Ce programme calcule de A, les valeurs de déduit Bet Cet enfin calcule leur produit.

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

Essayez-le en ligne!

Version précédente - Approche différente - 26 octets

|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
Osable
la source
2

Befunge 93 , 56 octets

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

Essayez-le en ligne!

Explication:

Le volume de la boîte peut être calculé en multipliant le nombre de . s sur la première ligne avant tout autre caractère, le nombre de +et -s sur la première ligne - 1, et le nombre de lignes commençant par a |+ 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

Je devais déplacer les lignes IP vers le haut plutôt que vers le bas pour utiliser la verticale si dans la 3ème ligne. Si l'adresse IP descendait, la verticale if forcerait le haut de la pile à 1 lorsque vous frappez l'horizontale suivante, en l'envoyant dans la mauvaise direction.

MildlyMilquetoast
la source
2

Haskell, 64 56 octets

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

Essayez-le en ligne!

Explication

L'entrée doit être une liste de chaînes pour chaque ligne. Par conséquent, la première ligne fdu paramètre xet rune liste des lignes restantes figurent dans le paramètre .

  1. fst(span(>'+')x)renvoie le .préfixe de la première ligne sous forme de chaîne, de même que length(fst(span(>'+')x))la première dimensiond1 .
  2. Une compréhension de liste peut agir en tant que filtre, par exemple ['-' | '-' <- x]renvoie une chaîne de tout -dans la première ligne, 1 + length['-' | '-' <- x]générant ainsi la deuxième dimensiond2 .
  3. De manière analogue, le nombre de |dans la première ligne peut être compté, de même que 1 + length['|' | '|':_ <- r]la troisième dimension d3.

Les listes de compréhension de 2. et 3. peuvent être réduites à 1+sum[1|'-'<-x]et1+sum[1|'|':_<-r] en construisant une liste de celles pour chaque occurrence de '-' ou '|' et ensuite prendre la somme. Nous pouvons continuer à mettre l'extérieur 1+en annexant dans la compréhension de la liste -à xet "|"à rcéder sum[1|'-'<-'-':x]et sum[1|'|':_<-"|":r]. Nous pouvons maintenant combiner les deux types de compréhension de liste en les mettant dans la même compréhension: De manière sum[1|'|':_<-"|":r,'-'<-'-':x]pratique, le produit des deux dimensions est calculé car, pour les listes Fet Gla liste suivante, la compréhension est le produit cartésien F x G =[(a,b)|a<-F,b<-G].

Enfin, au lieu de multiplier 1. avec la combinaison de 2. et 3., nous pouvons utiliser l' >>opérateur sur les listes:F>>G répète les G length Ftemps et concatène le résultat. Donc , fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]répète la liste des d2*d3ones d1fois, ce qui donne une liste de d1*d2*d3ceux qui sont ensuite additionnés pour obtenir le volume.

Laikoni
la source
Vous pouvez prendre l'entrée comme une liste de chaînes, éliminant ainsi la nécessité de lines.
Zgarb
@Zgarb Merci, cela économise quelques octets.
Laikoni
1

Java 8, 185 129 octets

merci à Zgarb pour -56 octets

joué au golf:

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

ungolfed:

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

Explication

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

aet bsont les dimensions de la base et hest la hauteur. Vous pouvez trouver hen comptant les premières hlignes où vous commencez par un ..

Bobas_Pett
la source
Vous pouvez prendre l’entrée sous forme de tableau ou de chaînes, il n’est donc pas nécessaire de la séparer manuellement.
Zgarb
oups merci, réparer ...
Bobas_Pett
1

Java, 112 octets

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

Étendu:

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
Andrey
la source
1

Powershell, 68 à 67 octets

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

Note: "$args"|% i*f + est un raccourci pour"$args".indexOf('+')

Explication

Bonne explication tirée de la réponse d'Osable :

Laisser Wet Hêtre respectivement la largeur et la hauteur de l'entrée - pas la boîte. Ensuite, les dimensions de la boîte A, Bet Crespecter les règles suivantes:

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

Le montre la figure de ce qui suit A, Bet Csont, en termes de noms de bord:

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

Et Cest la position du premier +dans la première ligne de l'entrée.

Script de test:

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

Sortie:

True: 1
True: 3
True: 12
True: 16
True: 16
True: 18
True: 24
True: 120
mazzy
la source
0

Wolfram Language (Mathematica) , 64 octets

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

Essayez-le en ligne!

Utilise le nombre de ., |et \ncaractères dans l’entrée à résoudre pour le volume. Cela semble stupide car il y a une nouvelle ligne à la place de\n .

Si A, Bet Csont les côtés, alors . = 2C(A+2C), | = 5B+4C-9et \n = B+2C, afin que nous puissions résoudre le volume ABCen termes de ces trois nombres de caractères.

Misha Lavrov
la source