Volúmenes de cajas ASCII

40

Introducción

En este desafío, se le da como entrada la representación ASCII de la red (superficie desplegada) de un cuboide rectangular (cuadro 3D). El formato es este:

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

Cada cara del cuboide es un rectángulo de #s rodeado de +-|caracteres. El exterior de la red está lleno de .s. La red siempre tendrá la misma orientación: hay una cara central rodeada por sus cuatro caras vecinas, y la contraparte de la cara central está en el borde derecho de la entrada. La entrada se rellena con .s en forma rectangular y no contendrá filas o columnas adicionales de .s.

La tarea

Su tarea es tomar como entrada un diagrama como el anterior, y calcular el volumen del cuboide que representa, que es solo el producto de su altura, ancho y profundidad. Puede tomar la entrada como una cadena delimitada por una nueva línea o una matriz de cadenas.

La longitud de cada borde es la distancia entre los +caracteres en sus dos extremos. Por ejemplo, el borde horizontal +--+tiene una longitud 3 y el borde vertical

+
|
|
|
+

tiene una longitud 4. La longitud mínima de un borde es 1. El ejemplo del cuboide anterior tiene un volumen 2 * 3 * 4 = 24.

Reglas y puntaje

Puede escribir un programa completo o una función, y gana el conteo de bytes más bajo.

Casos de prueba

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

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

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

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

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

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

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

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120
Zgarb
fuente
13
Realmente me gusta este desafío. Debido a que la entrada tiene tanta estructura redundante, hay muchas opciones sobre cómo recuperar las dimensiones.
xnor

Respuestas:

25

Retina , 29 28 bytes

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

¶\|
$`
y

Pruébalo en línea!

Hay muchas formas de abordar esto en Retina, dependiendo de qué área quieres multiplicar con qué lado, por lo que no estoy seguro de cuán óptimo es esto, pero en realidad ya es mucho más corto de lo que pensé que sería.

Actualmente tengo otras dos soluciones en el mismo número de bytes que parecen un poco más golfables que el enfoque anterior:

\G\..+¶

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

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

Aunque en estos podría guardar un byte cada uno si supongo que la entrada termina con un salto de línea final, pero prefiero no tener que depender de eso.

Y otro, aún a 28 bytes (este en realidad multiplica tres lados en lugar de multiplicar un área por un lado):

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

Explicación

La idea principal es multiplicar el área de la cara en la parte superior por la longitud del lado vertical que toca el borde de longitud de la entrada.

Usaré la siguiente entrada como ejemplo (tiene longitudes laterales 2, 3 y 4, por lo que un área de 24):

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

Etapa 1: transliterar

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

La expresión regular \G\..+¶coincide con una línea que comienza con .y es inmediatamente adyacente a la línea anterior. Entonces esto coincide con todas las líneas que contienen la cara superior. El escenario en sí se convierte .en xy todos los demás personajes (cualquiera de |+-#) en y. Esto nos da el siguiente resultado:

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

Esto tiene una columna más de la yque necesitamos para representar el área de la cara superior. Arreglamos esto con la siguiente etapa.

Etapa 2: reemplazar

xy

Entonces, hacemos coincidir un yprecedido por un x(que es exactamente uno de ellos por línea) y los eliminamos a ambos de la cadena. Obtenemos esto:

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

Entonces ahora tenemos el área de la cara superior representada por el número de ys.

Etapa 3: reemplazar

¶\|
$`

Nuestro objetivo aquí es multiplicar esta área Apor la longitud del lado faltante, que es el número |al principio de una línea más 1. Sin embargo, en realidad es más fácil multiplicar por un número n+1porque ya tenemos una copia de Ala cadena . Si reemplazamos las ncosas con A, terminamos con n+1copias de A. Esto nos facilita mucho las cosas.

Por lo tanto, simplemente reemplazamos cualquier |inmediatamente después de un salto de línea con todo en frente del partido. Esto destroza la cadena bastante y la hace un poco más grande de lo que necesitamos, pero el número de ys termina siendo el resultado que estamos buscando:

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

Etapa 4: partido

y

Todo lo que queda es contar el número de ys, que se imprime como un número decimal al final.

Martin Ender
fuente
15

Python 2, 57 bytes

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

Una función que toma una lista de cadenas.

Determina las 3 dimensiones por separado:

l[0].find('+')
El índice del primero +en la primera fila.

-~l[0].count('-')
El número de -signos en la primera fila.

~`l`.count("'|")
El número de filas que comienzan con el |símbolo, a través de la representación de cadena de la lista que tiene un símbolo de comillas antes.


62 bytes:

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

Una función que toma una lista de cadenas e imprime el resultado.

Encuentra una dimensión acomo índice de +en la primera fila. Las otras dos dimensiones se infieren de él y del ancho y alto del rectángulo de entrada.

Una alternativa de 63 bytes, que encuentra las dimensiones por separado:

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

Bash + coreutils, 83, 77 bytes

EDICIONES:

  • Guardado 6 bytes, usando "Here String" y optimizando un poco la expresión regular

Golfed

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

Explicado

Transformar con sed :

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

Deshágase de las nuevas líneas usando backticks, anexe)

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

Alimentar la expresión resultante a bc

=> 24

Prueba

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

1

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

3

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

24

Pruébalo en línea! (usa expansión aritmética bash, en lugar de bc , ya que esta última no está disponible)

zepelín
fuente
10

Caracoles , 19 bytes

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

Pruébalo en línea.

La idea es que comencemos en algún lugar del borde más a la derecha de la red, y luego viajemos a algún lugar en la cara más inferior. La longitud del borde y el área de la cara se multiplican por el mecanismo de contar todas las rutas coincidentes.

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
fuente
4

JavaScript (ES6), 67 91

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

Prueba

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
fuente
3

Rubí, 44

Funciona según un principio similar a otras respuestas: encuentre el primero +para encontrar la profundidad, encuentre el siguiente .después +del ancho, y cuente el número |al final de la línea y agregue 1 para encontrar la altura.

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

sin golf en el programa de prueba

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
fuente
3

05AB1E , 21 bytes

Sea Wy Hsea, respectivamente, el ancho y el alto de la entrada, no el cuadro. Luego, las dimensiones de la caja A, By Csiga estas reglas:

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

La siguiente figura muestra lo que A, By Cson, en términos de nombres de borde:

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

De ahí las fórmulas anteriores. Este programa calcula A, deduce los valores de By Cy, finalmente, calcula su producto.

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

Pruébalo en línea!

Versión anterior - Enfoque diferente - 26 bytes

|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
fuente
2

Befunge 93 , 56 bytes

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

Pruébalo en línea!

Explicación:

El volumen de la caja se puede calcular multiplicando el número de .s en la primera línea antes de cualquier otro carácter, por el número de +e -s en la primera línea - 1, y el número de líneas que comienzan con un |+ 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

Tuve que mover las líneas IP hacia arriba en lugar de hacia abajo para usar la vertical si estaba en la tercera línea. Si la IP bajaba por las líneas, el vertical if forzaría a la parte superior de la pila a ser 1 al golpear el siguiente horizontal si, enviándolo en la dirección incorrecta.

Levemente Milquetoast
fuente
2

Haskell, 64 56 bytes

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

Pruébalo en línea!

Explicación

Se espera que la entrada sea una lista de cadenas para cada línea, por lo que en fel parámetro se xencuentra la primera línea y runa lista de las líneas restantes.

  1. fst(span(>'+')x)devuelve el .prefijo de la primera línea como una cadena, por lo que length(fst(span(>'+')x))es la primera dimensión d1.
  2. Una comprensión de la lista puede actuar como filtro, por ejemplo, ['-' | '-' <- x]devuelve una cadena de todos -en la primera línea, por lo que 1 + length['-' | '-' <- x]produce la segunda dimensión d2.
  3. Análogamente, |se puede contar el número de en la primera fila, también lo 1 + length['|' | '|':_ <- r]es la tercera dimensión d3.

Las comprensiones de la lista de 2. y 3. se pueden acortar 1+sum[1|'-'<-x]y 1+sum[1|'|':_<-r]crear una lista de las mismas para cada aparición de '-' o '|' y luego tomando la suma. Podemos poner aún más el exterior 1+en la lista por comprensión añadiendo -a xy "|"a rceder sum[1|'-'<-'-':x]y sum[1|'|':_<-"|":r]. Ahora podemos combinar ambas comprensiones de listas poniendo ambos predicados en la misma comprensión: sum[1|'|':_<-"|":r,'-'<-'-':x]convenientemente, esto calcula exactamente el producto de las dos dimensiones porque para las listas Fy Gla siguiente comprensión de listas es el producto cartesiano F x G =[(a,b)|a<-F,b<-G].

Finalmente, en lugar de multiplicar 1. con la combinación de 2. y 3. podemos usar el >>operador en las listas: F>>Grepite los G length Ftiempos y concatena el resultado. Por lo tanto, fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]repite la lista de d2*d3los d1tiempos, produciendo una lista de d1*d2*d3los que luego se resumen para obtener el volumen.

Laikoni
fuente
Puede tomar la entrada como una lista de cadenas, eliminando la necesidad de lines.
Zgarb
@ Zgarb Gracias, esto ahorra algunos bytes.
Laikoni
1

Java 8, 185 129 bytes

gracias a Zgarb por -56 bytes

golfizado:

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

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

Explicación

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

donde ay bson las dimensiones de la base y hes la altura. Puede encontrar hcontando las primeras hlíneas donde comienza con a ..

Bobas_Pett
fuente
Puede tomar la entrada como una matriz o cadenas, por lo que no es necesario dividirla manualmente.
Zgarb
Uy, gracias, arreglándolo ...
Bobas_Pett
1

Java, 112 bytes

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

Expandido:

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
fuente
1

Powershell, 68 67 bytes

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

Nota: "$args"|% i*f + es un atajo para"$args".indexOf('+')

Explicación

Buena explicación tomada de la respuesta de Osable :

Sea Wy Hsea, respectivamente, el ancho y el alto de la entrada, no el cuadro. Luego, las dimensiones de la caja A, By Csiga estas reglas:

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

La siguiente figura muestra lo que A, By Cson, en términos de nombres de borde:

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

Y Ces la posición del primero +en la primera línea de la entrada.

Script de prueba:

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

Salida:

True: 1
True: 3
True: 12
True: 16
True: 16
True: 18
True: 24
True: 120
mazzy
fuente
0

Wolfram Language (Mathematica) , 64 bytes

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

Pruébalo en línea!

Utiliza el número de ., |y \npersonajes de la entrada a resolver para el volumen. Parece estúpido porque hay una nueva línea real en lugar de\n .

Si A, By Cson los lados, entonces . = 2C(A+2C), | = 5B+4C-9y \n = B+2C, entonces podemos resolver el volumen ABCen términos de estos tres recuentos de caracteres.

Misha Lavrov
fuente