Dibujando un cubo en arte ASCII

32

Descripción de la tarea:

Dibuje un cubo en el arte ASCII en aproximadamente una proyección de gabinete.

Monospaced fontsa menudo tienen caracteres que son aproximadamente dos veces más altos que anchos. Dado que la entrada es la longitud de las líneas verticales (excluyendo las esquinas), las líneas horizontales se dibujan con el doble de caracteres para que la imagen resultante sea realmente aproximadamente un cubo. Las líneas que retroceden se dibujan a la mitad de la longitud según lo ordenado por una proyección de gabinete.

Las esquinas del cubo están representadas por +, líneas horizontales por -, líneas verticales por |y diagonales /.

Resumiendo: deje que la entrada sea n , luego

  • Se dibuja un borde horizontal del cubo -y consta de 2  n caracteres.
  • Se dibuja un borde vertical del cubo |y consta de n caracteres.
  • Se dibuja un borde diagonal del cubo /y consta de n / 2 caracteres.
  • Se dibujan las esquinas del cubo +. Las esquinas no se cuentan para la longitud de un borde como se detalla anteriormente (ver ejemplos a continuación también).

Entrada:

La entrada, dada en la entrada estándar, es un solo número positivo, par n (2 ≤ n ≤ 30) que da la longitud de las líneas verticales del cubo. Es seguido por un solo salto de línea.

Salida:

La salida es un cubo en la salida estándar siguiendo las reglas anteriores. Se ignora el espacio en blanco al final de las líneas.

Entrada de muestra 1:

2

Salida de muestra 1:

  +----+
 /    /|
+----+ |
|    | +
|    |/
+----+

Entrada de muestra 2:

4

Salida de muestra 2:

   +--------+
  /        /|
 /        / |
+--------+  |
|        |  |
|        |  +
|        | /
|        |/
+--------+

ETA: ahora acepté la solución más corta. Actualizaré la respuesta aceptada cuando aparezca una más corta.

Como algunas personas preguntaron por cuánto tiempo fueron las entradas de nuestros concursantes:

227 - Python
240 - Perl
310 - C
315 - C
326 - VB.NET
459 - C

Además de nuestras propias soluciones (no clasificadas con las demás):

140 - Golfscript
172 - Ruby
183 - PowerShell

Joey
fuente
¿Puedes contarnos un poco sobre las mejores soluciones que tienes? ¿Cuántos caracteres tenía el más pequeño?
Juan
@Juan: Se agregó la información solicitada
Joey
1
Curiosamente, C ++ puede usar dibujos similares como "literales analógicos": hostilefork.com/2009/08/29/tweakinganalog-literals-humor
Dr. Rebmu
@Hostile: Sí, ese fue agradable, aunque un poco malvado ;-)
Joey

Respuestas:

10

Golfscript - 96 caracteres

~:<2/:$){' '*}:s~'++'<'--'**:^n$,{.$\-s'//'2s<*:&*@s'|':|n}%^$[$s|n|&|]*$s'+'n$,{n'/'@s|&|}%-1%^

La mayor parte de la compacidad proviene del almacenamiento agresivo de casi todo en una variable (a menos que incluya estar escrito en golfscript).

<    n
$    n/2
s    {' '*}     # top of the stack becomes a string of that many spaces
^    '+------+'
&    '      '   # 2n spaces, i.e. 2s<* or <s2*
|    '|'

Un par de otros pequeños trucos aquí.

  1. 'LR''str'*-> 'LstrR'.
  2. Como necesitamos invertir el orden de las líneas en la última matriz, optamos por hacer esto después de generar el texto en lugar de antes. Esto nos permite guardar un carácter porque los espacios antes del '/'único deben pasar dos elementos de la pila ( @) en lugar de 3 ( @ .. \).
Nabb
fuente
16

Python - 248 243 230 227 191

Ligeramente desordenado, pero básicamente imprime el cubo línea por línea (usando un búfer de cadena).

t=v=h=input()/2
s,p,b,f,n=" +|/\n"
l=p+"-"*t*4+p;S=s*4*t;k=s*h;K=b+S+b
r=s*t+s+l+n
while t:r+=s*t+f+S+f+s*(h-t)+b+n;t-=1
r+=l+k+b+n+(K+k+b+n)*(v-1)+K+k+p+n
while v:v-=1;r+=K+s*v+f+n
print r+l

Gracias a @marcog, por señalar la primera línea, a @ThomasO por señalar la segunda línea y a @Juan por hacerme darme cuenta de que puedo combinar líneas.

JPvdMerwe
fuente
44
Para ahorrar más espacio, cambie s=" ";p="+";b="|";f="/";n="\n"a s,p,b,f,n=" +|/\n".
Thomas O
1
Un voto no es suficiente. Me has empujado a mejorar mi solución a límites que pensé imposibles, gracias: D
Juan
:) ahora para ver si es posible mejor.
JPvdMerwe
10

Python - 179

h=input()*2
j=d=h/4
q,e,u,p,k="| \n+/"
w=e*d
s=p+'-'*h+p
i=''
o=e+w+s+u
v=q+e*h+q
while j:o+=e*j+k+e*h+k+e*(d-j)+q+u;j-=1;i+=v+e*j+k+u
print o+s+w+q+u+(v+w+q+u)*(d-1)+v+w+p+u+i+s

Me gustaría tener en cuenta que tomé algunas ideas de JPvdMerwe (usar una cadena para imprimir una vez, y la frase que no sabía era la sintaxis correcta en Python).

Juan
fuente
A la línea 3 le falta un 2 al final, lo que, desafortunadamente, eleva el conteo a 256.
JPvdMerwe
@JPvdMerwe oops, ¡gracias por entender eso!
Juan
1
¿Quizás puede intentar almacenar en caché los resultados en una cadena como lo hice y solo imprimir una vez?
JPvdMerwe
1
@Juan Creo que deberíamos evitar mantener copias antiguas en la publicación, a menos que las dos versiones sean muy diferentes. Se pueden ver en el historial de edición si alguien quiere leerlo.
marcog
2
En cuanto a las preguntas frecuentes: a menudo incluyo un historial de duración en mis publicaciones (  sin embargo, aquí hay un ejemplo que es demasiado largo para incluir). No sé si tal cosa es útil, pero puede ayudar a otros a descubrir qué trucos se usaron para mantenerlo breve. Aunque también tengo un historial SVN para eso también.
Joey
8

fortran 77 - 484 caracteres

      program z
      read(*,*) i
      g=f('+- ',i/2+1,i,0)
      do k=1,i/2
         g=f('/ |',i/2-k+1,i,k-1)
      end do
      g=f('+-|',0,i,i/2)
      do k=1,i/2-1
         g=f('| |',0,i,i/2)
      end do
      g=f('| +',0,i,i/2)
      do k=1,i/2
         g=f('| /',0,i,i/2-k)
      end do
      g=f('+- ',0,i,0)
      stop
      end
      real function f(c,l,m,n)
      character c(3)
      write(*,*)(' ',j=1,l),c(1),(c(2),j=1,2*m),c(1),(' ',j=1,n),c(3)
      return
      end

No tiene sentido proporcionar una versión "sin obstáculos". Y tenga en cuenta que el descuento no se lleva bien con los requisitos de sangría.

Intenté fortran debido a los bucles en línea proporcionados por la writedeclaración. Obviamente ayudan, pero no suman lo suficiente como para matar el verbo del lenguaje. Podría reducirse mediante el uso de entrada de forma libre.

Validación:

 $ wc cube_func_array.f
 22  41 484 cube_func_array.f
 $ gfortran cube_func_array.f
 $ echo 2 | ./a.out
   +----+ 
  /    /|
 +----+ |
 |    | +
 |    |/
 +----+ 
 $ echo 4 | ./a.out
    +--------+ 
   /        /|
  /        / |
 +--------+  |
 |        |  |
 |        |  +
 |        | /
 |        |/
 +--------+ 

Afortunadamente, la especificación no dice qué tamaño debería verse:

 $ echo 1 | ./a.out
  +--+ 
 +--+|
 |  |+
 +--+ 

pero otros tamaños impares son razonables:

 $ echo 3 | ./a.out
   +------+ 
  /      /|
 +------+ |
 |      | +
 |      |/
 +------+ 
dmckee
fuente
Interesante elección de idioma :-). Bueno, el tamaño 1 no se ve tan mal. Mi solución arroja un bucle sin fin. Los diferentes comportamientos de redondeo fueron la razón para arrojar tamaños impares, si no recuerdo mal (y el límite superior de 30 para ajustar en 80 caracteres de ancho).
Joey
1
@joey: De vez en cuando hago fortran, y estoy feliz si tengo menos de 10 veces más que el ganador.
dmckee
4

Mi propia solución, ya que Python ya la ha matado a golpes:

Windows PowerShell, 183

$t=($w=($s=' ')*($o=($n="$input")/2))*4
$r="|$t|"
$s*($a=$o+1)+($q='+'+'--'*$n+'+')
$o..1|%{$s*--$a+"/$t/$($s*$b++)|"}
"$q$w|"
for(;$o-++$x){"$r$w|"}"$r$w+"
--$b..0|%{$r+$s*$_+'/'}
$q
Joey
fuente
Ah ... idiomas que le permiten "múltiples" cadenas por una ayuda escalar para esto ...
dmckee
Bueno, todavía está muy por detrás de Ruby o Golfscript de Ventero, como siempre;)
Joey
4

PostScript, 237

[/n(%stdin)(r)file token()/p{print}/r{repeat}([){{( )p}r}/N{n 2 mul}(]){n 2 idiv}/l{N(+)p{(-)p}r(+)p}/I{(|)p}/X{][p}>>begin
( )X l()=]-1 1{dup[(/)p N[(/)p]exch sub[(|)=}for
l(|
)X]1 sub{I N[I(|
)X}r
I N[I(+
)X]-1 1{I N[I 1 sub[(/)=}for
l

Historia:

  • 2011-03-01 01:54 (427) Primer intento.
  • 2011-03-01 02:01 (342) def editó algunas cosas más que aparecían a menudo.
  • 2011-03-01 02:24 (283) Aún más defs.
  • 2011-03-01 02:42 (281) Aa y otro defque ahorra dos bytes más.
  • 2011-03-01 03:01 (260) [ y ]tienen buenas propiedades cuando se usan como variables :-). Gracias a KirarinSnow .
  • 2011-03-01 03:12 (246) Saltos de línea en línea, usando un dict en lugar de numerosos defs. Thansk otra vez :-).
  • 2011-03-01 03:26 (237) Más gracias a KirarinSnow .
Joey
fuente
3

Ruby 1.9, 172 165 162 caracteres

w=(s=?\s)*o=(n=gets.to_i)/2;r=(z=?|)+w*4+z
puts s*(o+1)+q=?++?-*2*n+?+,(l=0...o).map{|u|[s*(o-u),w*4,s*u+z]*?/},q+w+z,[r+w+z]*o-=1,r+w+?+,l.map{|u|r+s*(o-u)+?/},q
Ventero
fuente
1

Ruby - 423 caracteres

Realmente no quiero compartir esto ya que es un recuento tan horrible, pero desde que lo he escrito también podría hacerlo.

n=$<.read.to_i
a=(q=Array).new(n+n/2+3){q.new(2*n+n/2+3,' ')<<"\n"}
a[n+1][2*n+n/2+2]=a[0][n/2+1]=a[0][2*n+n/2+1]=a[n/2+1][0]=a[n/2+1][2*n]=a[n+n/2+2][0]=a[n+n/2+2][2*n]=:+
a[0][n/2+2,n*2-1]=a[n/2+1][1,n*2-1]=a[n+n/2+2][1,n*2-1]=[:-]*2*n
a[n/2+2,n].each{|b|b[0]=b[2*n+1]=:|}
a[1,n].each{|b|b[2*n+n/2+2]=:|}
c=n/2
a[1,n/2].each{|b|b[c]=b[2+2*n+c-=1]=:/}
c=n/2
a[n+2,n/2].each{|b|b[2+2*n+c-=1]=:/}
a.flatten.each{|g|print g}

Probablemente podría reducirse bastante, pero dudo que este enfoque de fuerza bruta se acerque a un número decente de personajes, por lo que no puedo molestarme.

Nemo157
fuente
1

PHP, 401 392 382 363 caracteres:

<? $h=fgets(STDIN);$s="str_repeat";$w=$h*2;$d=$h/2;$b=$h;$c=" ";echo$s($c,$h/2+1)."+".$s("-",$w)."+\n";for($i=1;$i<=$d;$i++,$a=--$b){echo$s($c,($h/2+1)-$i)."/".$s($c,$w)."/".$s($c,$i-1)."|\n";}echo"+".$s("-",$w)."+".$s($c,$d)."|\n";for($i=1;$i<=$h;$i++){echo"|".$s($c,$w)."|";echo $a-->0?$s($c,$b).($a>0?"|":"+")."\n":$s($c,$h-$i)."/\n";}echo"+".$s("-",$w)."+\n";

Originalmente hice esto para ver qué tan corto podía lograr hacer esto en PHP, ya que sabía que sería bastante largo. Estoy seguro de que podría reducirse, pero no considerando mucho que PHP no tiene muchos atajos.

Validación:
http://codepad.viper-7.com/ftYYz9.php53

Versión Ungolfed: http://codepad.viper-7.com/4D3kIA

Kevin Brown
fuente
Solo lo modifiqué para leerlo desde stdin, lo perdí en la pregunta. Ya no necesita la función por eso.
Kevin Brown
Modificó el código para que se lea correctamente desde stdin. También lo jugué un poco más para reducir el tamaño.
Kevin Brown
La línea diagonal inferior derecha no está allí y en su lugar aparece una línea vertical desplazada. Sin embargo, a menos que esté haciendo algo mal al invocarlo.
Joey
1

Perl, 163

$d=<>/2;$s=$"x$d;$H=$s x4;$f="|$H|";$t.=$"
x$d--."/$H/".$"x$_."|\n",$m.="$f$s|\n",$b
=$f.$"x$_."/\n$b"for 0..$d-1;$_="+$H+";
y/ /-/;say" $s$_\n$t$_$s|\n$m$f$s+\n$b$_"

Perl 5.10 o posterior, ejecuta con perl -E '<code here>'

Versión separada:

$d = <> / 2;
$s = $" x $d;
$H = $s x 4;
$f = "|$H|";

$t .= $" x $d-- . "/$H/" . $"x$_ . "|\n",
$m .= "$f$s|\n",
$b = $f . $" x $_ . "/\n$b"
  for 0 .. $d-1;

$_ = "+$H+";
y/ /-/;
say " $s$_\n$t$_$s|\n$m$f$s+\n$b$_"
JB
fuente
1

Perl, 269 ​​269 262 256 245 244 237 226 228 224 217 caracteres

sub p {y / xS / + \ //; print; y / + \ // xS /} $ b = / 2; $ a = $ b; $ _ = "xx \ n"; s / x / x- --- / while ($ a -); hasta (/ ^ S /) {p; s / [xS] / S / g; s / -x / S | /; y / - / /} s / ( ? = * S) / - / g; y / S / x /; p; y / -x / | /; p while (- $ b); s /.$/ x /; while (/ \ | / ) {p; s /..$/ S /} y / | S / ++ - /; p

La idea básica es hacer todo con sustituciones de expresiones regulares. Debido a que dos de los caracteres utilizados (+ y /) son caracteres especiales y aparecen mucho en las expresiones regulares, vale la pena usar otros caracteres y sustituirlos para imprimir.

Versión ligeramente más legible:

# Subrutina para sustituir, imprimir y no sustituir como se describe anteriormente
sub p {y / xS / + \ //; print; y / + \ // xS /}
# Leer de stdin y configurar la línea inicial
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# Imprime la cara superior
hasta (/ ^ S /) {
  pags;
  s / [xS] / S / g; # Primera ronda: izquierda + -> /; tiempos posteriores mover / izquierda
  s / -x / S | /; # Solo relevante la primera vez en el ciclo
  y / - / / # Solo relevante la primera vez en el ciclo
}
# Prepare e imprima la línea que contiene la segunda línea horizontal
s / (? = * S) / - / g;
y / S / x /;
pags;
# Ahora imprime (n-1) / 2 líneas idénticas
y / -x / | /;
p while (- $ b);
# Trae el borde derecho adentro
s /.$/ x /;
mientras que (/ \ | /)
{
  pags;
  s /..$/ S /
}
# Línea final
y / | S / ++ - /;
pags

En cierto sentido, estoy haciendo trampa usando $ b como contador en el bucle intermedio; en su lugar, podría agregar espacios en blanco en el bucle sobre $ ay luego usar regex reemplaza para ese bucle también, pero voy a permitir esa ligera desviación de una solución de regex puro.

Sin duda alguna persona aterradora puede convertir esto en un script sed mucho más corto.

Peter Taylor
fuente
"Versión ligeramente más legible": me encanta que Perl solo se vuelva un poco más legible cuando se incluyen líneas nuevas y espacios en blanco. :)
Steve
@ Steve, incluso con los comentarios tienes que saber un poco de Perl para entenderlo. Usar yfor trno es obvio, y en cuanto a la forma en que "while" puede ir antes o después ...
Peter Taylor
1

LUA, 294 302 292 bytes

Golfizado:

n=(...)p="+"d=2*n s=" "S=s:rep(d)h=n/2 T=s:rep(h)L="\n"o="/"v="|"a=p..("-"):rep(d)..p r=T..s..a..L for i=0,h-1 do r=r..s:rep(h-i)..o..S..o..s:rep(i)..v..L end r=r..a..T..v for i=1,h do r=r..L..v..S..v..T..(i==h and p or v) end for i=h-1,0,-1 do r=r..L..v..S..v..s:rep(i)..o end print(r..L..a)

Sin golf:

n        = n or io.read() or 6
plus     = "+"
doubled  = 2*n
space    = " "
Space    = space:rep(doubled)
halved   = n/2
T        = space:rep(halved)
Line     = "\n"
or_sign  = "/"
vertical = "|"
a        = plus..("-"):rep(doubled)..plus
result   = T..space..a..Line

for i=0,halved-1 do
    result = result .. space:rep(halved-i) .. or_sign .. Space .. or_sign .. space:rep(i) .. vertical .. Line
end

result = result..a..T..vertical

for i=1,halved do
    result = result .. Line .. vertical .. Space .. vertical .. T .. (i==halved and plus or vertical)
end

for i=halved-1,0,-1 do
    result = result .. Line .. vertical .. Space .. vertical .. space:rep(i) .. or_sign
end

print(result .. Line .. a)
Monja permeable
fuente
La entrada se proporciona en la secuencia de entrada estándar. Esto no parece funcionar aquí.
Joey
También puede omitir or 6después de la read()llamada, lo que ahorra cuatro bytes :-)
Joey
Hm, ahora con el (...)ya no funciona para mí en Lua 5.1.4.
Joey
1

Lienzo , 63 bytes.

╴»
±╵⁷/╋╴«3+⁷
-×+×║⌐1╴├╋;⁷├⁷±╋2⁷⁸⁸├⁷/╋12╴«├2⁷5×3+⁷±╵⁰2n{┤╴|*+∔╋

Pruébalo aquí!

dzaima
fuente