Rysowanie sześcianu w sztuce ASCII

32

Opis zadania:

Narysuj sześcian w sztuce ASCII w przybliżeniu w rzucie szafki.

Monospaced fontsczęsto mają postacie, które są około dwa razy wyższe niż są szerokie. Ponieważ wejściem jest długość linii pionowych (z wyłączeniem narożników), linie poziome są rysowane z dwukrotnie większą liczbą znaków, dzięki czemu powstały obraz jest w przybliżeniu sześcianem. Cofające się linie są narysowane w połowie długości, jak nakazuje to rzut szafki.

Narożniki sześcianu są reprezentowane przez +linie poziome, linie -pionowe i linie |ukośne /.

Podsumowując: Niech będzie wejście n , a następnie

  • Rysowana jest pozioma krawędź sześcianu -i składa się z 2  n znaków.
  • Rysowana jest pionowa krawędź sześcianu |i składa się z n znaków.
  • Rysowana jest ukośna krawędź sześcianu /i składa się z n / 2 znaków.
  • Rysowane są rogi sześcianu +. Narożniki nie są liczone dla długości krawędzi, jak wyszczególniono powyżej (patrz również przykłady poniżej).

Wkład:

Dane wejściowe podane na standardowym danych wejściowych to pojedyncza dodatnia, parzysta liczba n (2 ≤ n ≤ 30), która podaje długość pionowych linii sześcianu. Następnie następuje przerwa pojedynczej linii.

Wydajność:

Dane wyjściowe to sześcian na standardowym wyjściu zgodnie z powyższymi zasadami. Końcowe białe znaki w liniach są ignorowane.

Przykładowe wejście 1:

2

Przykładowy wynik 1:

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

Przykładowe wejście 2:

4

Przykładowe wyjście 2:

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

ETA: Teraz zaakceptowałem najkrótsze rozwiązanie. Zaktualizuję przyjętą odpowiedź, gdy pojawi się krótsza.

Ponieważ niektóre osoby pytały, jak długo trwały zgłoszenia naszych uczestników:

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

Jak również nasze własne rozwiązania (niesklasyfikowane według innych):

140 - Golfscript
172 - Ruby
183 - PowerShell

Joey
źródło
czy możesz powiedzieć trochę o najlepszych rozwiązaniach, które miałeś? Ile znaków ma najmniejszy?
Juan
@Juan: Dodano wymagane informacje
Joey
1
Co zabawne, C ++ może używać podobnych rysunków jak „literały analogowe”: hostilefork.com/2009/08/08/29/tweakinganalog-literals-humor
Dr. Rebmu
@Hostile: Tak, ten był miły, choć trochę zły ;-)
Joey

Odpowiedzi:

10

Golfscript - 96 znaków

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

Większość zwartości pochodzi z agresywnego przechowywania prawie wszystkiego do zmiennej (chyba że uwzględnisz zapisywanie w golfa).

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

Kilka innych małych sztuczek tutaj.

  1. 'LR''str'*-> 'LstrR'.
  2. Ponieważ musimy odwrócić kolejność wierszy w ostatniej tablicy, zdecydowaliśmy się to zrobić po wygenerowaniu tekstu zamiast wcześniej. To pozwala nam zapisać jedną postać, ponieważ spacje przed '/'jedynymi muszą przejść obok dwóch elementów stosu ( @) zamiast 3 ( @ .. \).
Nabb
źródło
16

Python - 248 243 230 227 191

Nieco niechlujny, ale w zasadzie drukuje sześcian linia po linii (używając bufora łańcuchów).

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

Dzięki @marcog za wskazanie pierwszej linii, @ThomasO za ​​wskazanie drugiej linii i @Juan za uświadomienie mi, że mogę łączyć linie.

JPvdMerwe
źródło
4
Aby zaoszczędzić trochę miejsca zmień s=" ";p="+";b="|";f="/";n="\n"na s,p,b,f,n=" +|/\n".
Thomas O
1
Jeden głos nie wystarczy. Popychasz mnie do ulepszenia mojego rozwiązania do granic, które uważałem za niemożliwe, dzięki: D
Juan
:) teraz, aby zobaczyć, czy lepiej jest możliwe.
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

Chciałbym zauważyć, że wziąłem kilka pomysłów z JPvdMerwe (użycie jednego ciągu do wydrukowania raz, a jeden wiersz dla tego, czego nie wiedziałem, był poprawną składnią w Pythonie).

Juan
źródło
W wierszu 3 brakuje 2 na końcu, co niestety podnosi liczbę do 256.
JPvdMerwe
@JPvdMerwe ups, dzięki za złapanie tego!
Juan
1
Może możesz spróbować zapisać wyniki w pamięci podręcznej tak jak ja i wydrukować tylko raz?
JPvdMerwe,
1
@Juan Myślę, że powinniśmy unikać przechowywania starych kopii w poście, chyba że obie wersje są zasadniczo różne. Są widoczne w historii edycji, jeśli ktoś chce ją przeczytać.
marcog
2
Co do FAQ: często umieszczam długą historię w moich postach (  tutaj był jednak przykład, który był zbyt długi, aby go uwzględnić). Nie wiem, czy coś takiego jest pomocne, ale może pomóc innym odkryć, jakie sztuczki zostały zastosowane, aby je skrócić. Chociaż mam też do tego historię SVN.
Joey
8

fortran 77 - 484 znaków

      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

Nie ma sensu oferowanie wersji „nieobsługiwanej”. I zauważ, że przecena nie zgadza się dobrze z wymaganiami dotyczącymi wcięć.

Próbowałem fortran ze względu na wbudowane pętle dla writeinstrukcji. Oczywiście pomagają, ale nie sumują się w wystarczającym stopniu, aby zabić słownictwo języka. Można to zmniejszyć za pomocą dowolnego wejścia.

Uprawomocnienie:

 $ 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
    +--------+ 
   /        /|
  /        / |
 +--------+  |
 |        |  |
 |        |  +
 |        | /
 |        |/
 +--------+ 

Na szczęście specyfikacja nie mówi, jak powinien wyglądać rozmiar:

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

ale inne nieparzyste rozmiary są rozsądne:

 $ echo 3 | ./a.out
   +------+ 
  /      /|
 +------+ |
 |      | +
 |      |/
 +------+ 
dmckee
źródło
Ciekawy wybór języka :-). Rozmiar 1 nie wygląda źle. Moje rozwiązanie wywołuje niekończącą się pętlę. Różne zachowania w zakresie zaokrąglania były powodem, aby wyrzucić nieparzyste rozmiary, jeśli dobrze pamiętam (i górna granica 30 dla dopasowania do szerokości 80 znaków).
Joey
1
@joey: Od czasu do czasu robię fortran i jestem szczęśliwy, jeśli jestem mniej niż 10 razy dłuższy niż zwycięzca.
dmckee
4

Moje własne rozwiązanie, ponieważ zostało już pobite na śmierć przez Pythona:

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
źródło
Ach ... języki, które pozwalają „wielokrotne” struny przez skalarnego pomoc dla tego ...
dmckee
Cóż, wciąż jest daleko w tyle za Ventero's Ruby or Golfscript - jak zwykle;)
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) Pierwsza próba.
  • 2011-03-01 02:01 (342) def wydała jeszcze kilka rzeczy, które pojawiały się często.
  • 2011-03-01 02:24 (283) Jeszcze więcej defs.
  • 2011-03-01 02:42 (281) Kolejny, defktóry oszczędza dwa kolejne bajty.
  • 2011-03-01 03:01 (260) [ i ]mają ładne właściwości, gdy są używane jako zmienne :-). Dzięki KirarinSnow .
  • 2011-03-01 03:12 (246) Inline przerywa linię, używając dykta zamiast wielu defs. Jeszcze raz Thansk :-).
  • 2011-03-01 03:26 (237) Więcej podziękowań dla KirarinSnow .
Joey
źródło
3

Ruby 1.9, 172 165 162 znaków

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
źródło
1

Rubin - 423 znaków

Naprawdę nie chcę się tym dzielić, ponieważ jest to tak okropna liczba, ale odkąd napisałem, równie dobrze.

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}

Prawdopodobnie można by to trochę zmniejszyć, ale wątpię, aby to podejście brutalnej siły miało miejsce gdziekolwiek w pobliżu przyzwoitej liczby postaci, więc nie mogę się tym przejmować.

Nemo157
źródło
1

PHP, 401 392 382 363 znaków:

<? $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";

Zrobiłem to początkowo, aby zobaczyć, jak krótko mogę to zrobić w PHP, ponieważ wiedziałem, że będzie to dość długie. Jestem pewien, że można to zmniejszyć, ale niewiele, biorąc pod uwagę, że PHP nie ma wielu skrótów.

Walidacja:
http://codepad.viper-7.com/ftYYz9.php53

Wersja Ungolfed: http://codepad.viper-7.com/4D3kIA

Kevin Brown
źródło
Właśnie zmodyfikowałem go, aby czytać ze standardowego wejścia, pominąłem to w pytaniu. Z tego powodu nie potrzebuje już tej funkcji.
Kevin Brown
Zmodyfikowano kod, aby poprawnie odczytywał ze standardowego wejścia. Grałem też w golfa, aby zmniejszyć rozmiar.
Kevin Brown
Nie ma prawej dolnej linii przekątnej, a zamiast niej pojawia się przesunięta linia pionowa. Chyba że robię coś złego, wywołując to.
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 lub nowszy, uruchom z perl -E '<code here>'

Wersja Respaced:

$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
źródło
1

Perl, 269 ​​269 262 256 245 244 237 226 228 224 217 znaków

sub p {y / xS / + \ //; print; y / + \ // xS /} $ b = / 2; $ a = $ b; $ _ = "xx \ n"; s / x / x- --- / while ($ a -); till (/ ^ 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

Podstawową ideą jest zrobienie wszystkiego z podstawieniami wyrażeń regularnych. Ponieważ dwa z używanych znaków (+ i /) są znakami specjalnymi i często pojawiają się w wyrażeniach regularnych, warto używać innych znaków i zastępować je drukiem.

Nieco bardziej czytelna wersja:

# Podprogram, aby zastąpić, wydrukować i cofnąć, jak opisano powyżej
sub p {y / xS / + \ //; print; y / + \ // xS /}
# Odczytaj ze standardowego wejścia i ustaw linię początkową
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# Wydrukuj górną twarz
do (/ ^ S /) {
  p;
  s / [xS] / S / g; # Pierwsza runda: w lewo + -> /; kolejne czasy ruchu / w lewo
  s / -x / S | /; # Tylko istotne za pierwszym razem w pętli
  y / - / / # Dotyczy tylko pierwszego okrążenia pętli
}
# Przygotuj i wydrukuj linię zawierającą drugą linię poziomą
s / (? = * S) / - / g;
y / S / x /;
p;
# Teraz wydrukuj (n-1) / 2 identyczne linie
y / -x / | /;
p podczas (- $ b);
# Wprowadź prawą krawędź
s /.$/ x /;
podczas gdy (/ \ | /)
{
  p;
  s /..$/ S /
}
# Ostatnia linia
y / | S / ++ - /;
p

W pewnym sensie oszukuję, używając $ b jako licznika w pętli pośredniej - zamiast tego mogę dodać białe znaki w pętli powyżej $ a, a następnie użyć zamienników regularnych dla tej pętli - ale pozwolę na to niewielkie odchylenie z rozwiązania opartego wyłącznie na wyrażeniach regularnych.

Bez wątpienia przerażająca osoba może zmienić to w znacznie krótszy skrypt sed.

Peter Taylor
źródło
„Nieco bardziej czytelna wersja” - uwielbiam to, że Perl staje się nieco bardziej czytelny, gdy uwzględnione są nowe wiersze i białe znaki. :)
Steve
@ Steve, nawet z komentarzami musisz znać trochę Perla, aby to zrozumieć. Używanie ydla trnie jest oczywiste, a jeśli chodzi o drogę „while” może iść przed lub po ...
Peter Taylor
1

Lua, 294 302 292 bajtów

Gra w golfa:

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)

Nie golfowany:

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)
Leaky Nun
źródło
Dane wejściowe są podawane w standardowym strumieniu wejściowym. To chyba nie działa tutaj.
Joey
Możesz także pominąć połączenie or 6po read(), co oszczędza cztery bajty :-)
Joey
Hm, teraz z tym (...)nie działa już dla mnie na Lua 5.1.4.
Joey
1

Płótno , 63 bajty

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

Wypróbuj tutaj!

dzaima
źródło