Menggambar kubus dalam seni ASCII

32

Deskripsi tugas:

Gambar kubus dalam seni ASCII dalam proyeksi kabinet secara kasar.

Monospaced fontssering memiliki karakter yang sekitar dua kali lebih tinggi dari lebar. Karena input adalah panjang garis vertikal (tidak termasuk sudut), garis horizontal digambar dengan karakter dua kali lebih banyak sehingga gambar yang dihasilkan benar-benar kira-kira kubus. Garis surut ditarik setengah panjang seperti yang diamanatkan oleh proyeksi kabinet.

Sudut kubus diwakili oleh +, garis horizontal oleh -, garis vertikal oleh |dan yang diagonal digunakan /.

Meringkas: Biarkan input menjadi n , lalu

  • Tepi horizontal kubus digambar dengan -dan terdiri dari 2  n karakter.
  • Tepi vertikal kubus digambar dengan |dan terdiri dari n karakter.
  • Tepi diagonal kubus digambar dengan /dan terdiri dari n / 2 karakter.
  • Sudut kubus digambar dengan +. Sudut tidak dihitung untuk panjang tepi seperti yang dijelaskan di atas (lihat contoh di bawah ini juga).

Memasukkan:

Input, diberikan pada input standar, adalah bilangan positif tunggal, genap n (2 ≤ n ≤ 30) yang memberikan panjang garis vertikal kubus. Diikuti oleh satu baris break.

Keluaran:

Outputnya adalah kubus pada output standar mengikuti aturan di atas. Trailing whitespace pada garis diabaikan.

Masukan sampel 1:

2

Output sampel 1:

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

Masukan sampel 2:

4

Output sampel 2:

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

ETA: Saya sekarang menerima solusi terpendek. Saya akan memperbarui jawaban yang diterima ketika jawaban yang lebih pendek muncul.

Karena beberapa orang bertanya berapa lama entri dari para kontestan kami adalah:

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

Serta solusi kami sendiri (tidak diberi peringkat dengan yang lain):

140 - Golfscript
172 - Ruby
183 - PowerShell

Joey
sumber
dapatkah Anda memberi tahu sedikit tentang solusi terbaik yang Anda miliki? Berapa banyak karakter yang dimiliki oleh yang terkecil?
Juan
@Juan: Menambahkan info yang diminta
Joey
1
Cukup mengherankan, C ++ dapat menggunakan gambar yang mirip dengan "literal analog": hostilefork.com/2009/08/29/tweakinganalog-literals-humor
Dr. Rebmu
@Hostile: Ya, yang itu bagus, jika agak jahat ;-)
Joey

Jawaban:

10

Golfscript - 96 karakter

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

Sebagian besar kekompakan berasal dari penyimpanan yang agresif hampir semuanya ke variabel (kecuali Anda termasuk yang ditulis dalam skrip golf).

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

Beberapa trik kecil lainnya di sini.

  1. 'LR''str'*-> 'LstrR'.
  2. Karena kita perlu membalik urutan baris dalam array terakhir, kita memilih untuk melakukan ini setelah membuat teks daripada sebelumnya. Ini memungkinkan kita untuk menyimpan satu karakter karena spasi sebelum '/'hanya perlu melewati dua elemen stack ( @) bukannya 3 ( @ .. \).
Nabb
sumber
16

Python - 248 243 230 227 191

Sedikit berantakan tetapi pada dasarnya mencetak garis kubus demi baris (menggunakan penyangga string).

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

Terima kasih kepada @marcog, untuk menunjukkan baris pertama, @ThomasO untuk menunjukkan baris kedua dan @Juan untuk membuat saya sadar bahwa saya dapat menggabungkan baris.

JPvdMerwe
sumber
4
Untuk menghemat lebih banyak perubahan ruang s=" ";p="+";b="|";f="/";n="\n"untuk s,p,b,f,n=" +|/\n".
Thomas O
1
Satu suara saja tidak cukup. Anda telah mendorong saya untuk meningkatkan solusi saya sampai batas yang saya pikir tidak mungkin, terima kasih: D
Juan
:) sekarang untuk melihat apakah lebih baik mungkin.
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

Saya ingin mencatat bahwa saya mengambil beberapa ide dari JPvdMerwe (Menggunakan string untuk mencetak sekali, dan satu-liner untuk itu saya tidak tahu adalah sintaks yang benar dalam Python).

Juan
sumber
Jalur 3 tidak memiliki angka 2 di bagian akhir, yang, sayangnya, mendorong hitungan ke 256.
JPvdMerwe
@JPvdMerwe oops, terima kasih sudah menangkapnya!
Juan
1
Mungkin Anda dapat mencoba menyimpan hasil dalam string seperti yang saya lakukan dan hanya mencetak sekali?
JPvdMerwe
1
@Juan Saya pikir kita harus menghindari menyimpan salinan lama di posting, kecuali kedua versi itu sangat berbeda. Mereka dapat dilihat dalam riwayat edit jika seseorang ingin membacanya.
marcog
2
Adapun untuk FAQ: Saya sering memasukkan sejarah panjang di posting saya (di  sini ada contoh yang terlalu panjang untuk dimasukkan). Tidak tahu apakah hal seperti itu bermanfaat tetapi mungkin membantu orang lain menemukan trik apa yang digunakan untuk membuatnya singkat. Meskipun saya juga memiliki sejarah SVN untuk itu juga.
Joey
8

fortran 77 - 484 karakter

      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

Tidak ada gunanya memberikan versi "tidak tersentuh". Dan perhatikan bahwa penurunan harga tidak sesuai dengan persyaratan indentasi.

Saya mencoba fortran karena inline untuk loop yang disediakan oleh writepernyataan itu. Jelas mereka membantu tetapi tidak menambahkan cukup untuk membunuh kata-kata bahasa. Ini dapat dikurangi dengan menggunakan input bentuk bebas.

Validasi:

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

Untungnya spec tidak mengatakan seperti apa ukurannya:

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

tetapi ukuran aneh lainnya masuk akal:

 $ echo 3 | ./a.out
   +------+ 
  /      /|
 +------+ |
 |      | +
 |      |/
 +------+ 
dmckee
sumber
Pilihan bahasa yang menarik :-). Nah, ukuran 1 tidak terlihat terlalu buruk. Solusi saya memuntahkan loop tanpa akhir. Perilaku pembulatan yang berbeda adalah alasan untuk membuang ukuran aneh, jika saya ingat dengan benar (dan batas atas 30 untuk pas ke dalam 80 karakter lebar).
Joey
1
@ Joey: Saya melakukan fortran dari waktu ke waktu, dan senang jika saya kurang dari faktor 10 lebih lama dari pemenang.
dmckee
4

Solusi saya sendiri, karena sudah dipukuli sampai mati oleh Python:

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
sumber
Ah ... bahasa yang memungkinkan Anda menggunakan "beberapa" string oleh bantuan skalar untuk ini ...
dmckee
Yah, itu masih jauh di belakang Ventero Ruby atau Golfscript - seperti biasa;)
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

Sejarah:

  • 2011-03-01 01:54 (427) Upaya pertama.
  • 2011-03-01 02:01 (342) def ed beberapa hal lagi yang sering muncul.
  • 2011-03-01 02:24 (283) Bahkan lebih lanjut defs.
  • 2011-03-01 02:42 (281) Aaand yang lain defyang menyimpan dua byte lagi.
  • 2011-03-01 03:01 (260) [ dan ]memiliki properti bagus saat digunakan sebagai variabel :-). Terima kasih untuk KirarinSnow .
  • 2011-03-01 03:12 (246) Inline line break, menggunakan dict bukannya banyak defs. Thansk lagi :-).
  • 2011-03-01 03:26 (237) Terima kasih banyak lagi untuk KirarinSnow .
Joey
sumber
3

Ruby 1.9, 172 165 162 karakter

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

Ruby - 423 karakter

Benar-benar tidak ingin membagikan ini karena ini adalah hitungan yang mengerikan, tetapi karena saya sudah menulisnya mungkin juga.

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}

Mungkin bisa dikurangi sedikit tapi saya ragu pendekatan brute-force ini akan mendekati jumlah karakter yang layak jadi saya tidak bisa diganggu.

Nemo157
sumber
1

PHP, 401 392 382 363 karakter:

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

Saya awalnya melakukan ini untuk melihat seberapa pendek saya bisa melakukan ini dalam PHP, karena saya tahu itu akan cukup panjang. Saya yakin itu bisa dikurangi, tetapi tidak banyak mengingat PHP tidak memiliki banyak pintasan.

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

Versi Tidak Digubah: http://codepad.viper-7.com/4D3kIA

Kevin Brown
sumber
Hanya memodifikasinya untuk dibaca dari stdin, melewatkan itu dalam pertanyaan. Tidak perlu fungsi lagi karena itu.
Kevin Brown
Memodifikasi kode sehingga membaca dari stdin dengan benar. Juga golf sedikit untuk mengurangi ukuran.
Kevin Brown
Garis diagonal kanan bawah tidak ada dan alih-alih muncul garis vertikal offset. Namun, kecuali saya melakukan kesalahan dalam memintanya.
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 atau lebih baru, jalankan dengan perl -E '<code here>'

Versi yang diganti:

$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
sumber
1

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

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

Ide dasarnya adalah melakukan segalanya dengan penggantian regex. Karena dua karakter yang digunakan (+ dan /) adalah karakter khusus dan banyak muncul di regex, layak menggunakan karakter lain dan menggantikannya untuk mencetak.

Versi yang sedikit lebih terbaca:

# Subrutin untuk mengganti, mencetak, dan menggantikan seperti yang dijelaskan di atas
sub p {y / xS / + \ //; cetak; y / + \ // xS /}
# Baca dari stdin dan siapkan baris awal
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# Cetak bagian atas wajah
sampai (/ ^ S /) {
  p;
  s / [xS] / S / g; # Putaran waktu pertama: kiri + -> /; waktu berikutnya bergerak / kiri
  s / -x / S | /; # Hanya relevan untuk pertama kalinya sepanjang loop
  y / - / / # Hanya relevan untuk pertama kalinya sepanjang loop
}
# Mempersiapkan dan mencetak garis yang berisi garis horizontal kedua
s / (? = * S) / - / g;
y / S / x /;
p;
# Sekarang cetak (n-1) / 2 garis yang identik
y / -x / | /;
p while (- $ b);
# Bawa tepi kanan masuk
s /.$/ x /;
sementara (/ \ | /)
{
  p;
  s /..$/ S /
}
# Baris terakhir
y / | S / ++ - /;
hal

Dalam arti saya curang dengan menggunakan $ b sebagai penghitung di loop perantara - Saya malah bisa menambahkan spasi putih di loop lebih dari $ a dan kemudian menggunakan pengganti regex untuk loop itu juga - tapi saya akan membiarkan sedikit penyimpangan dari solusi regex murni.

Tidak diragukan lagi beberapa orang yang menakutkan dapat mengubah ini menjadi skrip sed yang lebih pendek.

Peter Taylor
sumber
"Versi yang sedikit lebih mudah dibaca" - pasti menyukai Perl yang menjadi sedikit lebih mudah dibaca ketika baris baru dan spasi putih dimasukkan. :)
Steve
@Steve, bahkan dengan komentar Anda harus tahu sedikit Perl untuk memahaminya. Menggunakan yuntuk trtidak jelas, dan untuk cara "sementara" bisa pergi sebelum atau sesudah ...
Peter Taylor
1

Lua, 294 302 292 byte

Golf:

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)

Tidak Disatukan:

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)
Biarawati Bocor
sumber
Input diberikan pada aliran input standar. Ini sepertinya tidak berfungsi di sini.
Joey
Anda juga dapat mengabaikan panggilan or 6setelah read(), yang menghemat empat byte :-)
Joey
Hm, sekarang dengan (...)itu tidak berfungsi untuk saya lagi di Lua 5.1.4.
Joey
1

Kanvas , 63 byte

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

Coba di sini!

dzaima
sumber