ASCII sanatında küp çizimi


32

Görev tanımı:

ASCII sanatında kabaca bir kabin çıkıntısında bir küp çizin.

Monospaced fontsgenellikle genişlerinin iki katı kadar yüksek karakterlere sahiptir. Giriş, dikey çizgilerin uzunluğundan (köşeler hariç) olduğundan, yatay çizgiler iki kat fazla karakterle çizilir, böylece elde edilen görüntü kabaca bir küp olur. Geri çekilme çizgileri, bir kabin çıkıntısı tarafından zorunlu kılınan uzunlukta yarıda çizilir.

Küpün köşeleri +yatay çizgilerle -, dikey çizgilerle |ve çapraz çizgilerle gösterilir /.

Özetleme: Girdi n olsun , sonra

  • Küpün yatay bir kenarı ile çizilir -ve 2 n karakterden oluşur  .
  • Küpün dikey bir kenarı ile çizilir |ve n karakterden oluşur .
  • Küpün çapraz bir kenarı ile çizilir /ve n / 2 karakterden oluşur .
  • Küpün köşeleri ile çizilir +. Köşeler yukarıda detaylandırıldığı gibi bir kenar uzunluğu için sayılmaz (aşağıdaki örneklere de bakınız).

Giriş:

Standart girişte verilen giriş, küpün dikey çizgilerinin uzunluğunu veren tek bir pozitif, n sayısı (2 ≤ n ≤ 30). Bunu tek bir satır sonu izler.

Çıktı:

Çıktı, yukarıdaki kuralları izleyen standart çıktıdaki bir küptür. Çizgilerdeki beyaz boşluk yok sayılıyor.

Örnek giriş 1:

2

Örnek çıktı 1:

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

Örnek giriş 2:

4

Örnek çıktı 2:

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

ETA: Şimdi en kısa çözümü kabul ettim. Kısa bir cevap geldiğinde kabul edilen cevabı güncelleyeceğim.

Bazı insanlar yarışmacılarımızın kayıtlarının ne kadar sürdüğünü sorduğundan:

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

Kendi çözümlerimizin yanı sıra (diğerleriyle birlikte sıralanmamıştır):

140 - Golfscript
172 - Yakut
183 - PowerShell


Sahip olduğunuz en iyi çözümler hakkında biraz bilgi verebilir misiniz? En küçüğünün kaç karakteri var?
Juan

@Juan: İstenen bilgileri ekledi
Joey

1
C ++, yeterince eğlenceli
Dr. Rebmu

@Hostile: Evet, biraz kötüyse güzeldi ;-)
Joey

Yanıtlar:


10

Golfscript - 96 karakter

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

Kompaktlığın çoğu hemen hemen her şeyi agresif bir şekilde depolamaktan (değişkene golf yazıcısına dahil edilmediğiniz sürece) gelir.

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

Burada birkaç küçük numara daha var.

  1. 'LR''str'*-> 'LstrR'.
  2. Son dizideki satırların sırasını tersine çevirmemiz gerektiğinden, bunu önce metin yerine oluşturduktan sonra yapmayı tercih ediyoruz. Bu, bir karakter kaydetmemize izin verir, çünkü '/'sadece önceki boşlukların @3 ( @ .. \) yerine iki yığın elemanını ( ) geçmesi gerekir .

16

Python - 248 243 230 227 191

Biraz dağınık ama temelde küp satır satır satır yazdırır (bir dizge tamponu kullanarak).

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

@Marcog, ilk satırı işaret etmek için, ikinci satırı işaret etmek için @ThomasO ve çizgileri birleştirebileceğimin farkına varmak için @Juan'a teşekkürler.


4
Biraz daha uzay değişikliği kaydetmek için s=" ";p="+";b="|";f="/";n="\n"için s,p,b,f,n=" +|/\n".
Thomas O

1
Bir oylama yeterli değil. Beni, imkansız olduğumu düşündüğüm sınırlamalara olan çözümümüzü geliştirmeye zorluyorsunuz, teşekkürler: D
Juan

:) şimdi daha iyi olup olmadığını görmek için.
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

JPvdMerwe'den bazı fikirler aldığımı belirtmek isterim (Bir kez basmak için bir dize kullanmak, ve bilmediğim bir liner Python'da doğru sözdizimidir).


Satır 3 sonunda bir 2 eksik, maalesef sayıyı 256'ya itiyor.
JPvdMerwe

@JPvdMerwe ayy, bunu yakaladığınız için teşekkürler!
Juan

1
Belki de sonuçları benim yaptığım dizgede önbelleğe almayı deneyebilir ve yalnızca bir kere yazdırabilirsiniz?
JPvdMerwe,

1
@Juan İki sürüm büyük ölçüde farklı olmadıkça eski kopyaları postada tutmaktan kaçınmamız gerektiğini düşünüyorum. Birisi okumak isterse düzenleme geçmişinde görülebilirler.
marcog

2
Sıkça Sorulan Sorular'a gelince: Sık sık gönderilerime bir uzunluk geçmişi eklerim (  burada buna dahil edilmesi çok uzun süren bir örnek vardı). Böyle bir şeyin faydalı olup olmadığını bilmeyin ama başkalarının kısa tutmak için hangi numaraların kullanıldığını keşfetmesine yardımcı olabilir. Yine de bunun için de bir SVN geçmişim var.
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

"Doğaçlama yapılmamış" bir sürüm sağlamada gerçek bir nokta yok. Ve not alma işleminin girinti gereklilikleriyle iyi geçinemediğini unutmayın.

Ben writeifade tarafından sağlanan döngüler için satır içi nedeniyle fortran çalıştı . Açıkçası onlar yardım eder, ancak dilin tarikatını öldürecek kadar eklemezler. Serbest biçimli girdi kullanılarak azaltılabilir.

Doğrulama:

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

Neyse ki, teknik özellik hangi boyutta olması gerektiğini söylemiyor:

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

ancak diğer garip boyutlar makul:

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

Dilin ilginç seçimi :-). Peki, beden 1 çok da kötü gözükmüyor. Benim çözümüm sonsuz bir döngü oluşturuyor. Farklı yuvarlama davranışları, doğru hatırlıyorsam (ve 80 karakter genişliğine sığdırmak için 30 üst sınır), tek boyutları atma sebebiydi.
Joey

1
@joey: Zaman zaman fortran yapıyorum ve kazanandan 10 kat daha uzun bir faktör olduğumda mutluyum.
dmckee

4

Kendi çözümüm, Python tarafından öldürüldüğü için:

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

Ah ... bunun için bir skaler yardımı ile "çoklu" dizeleri sağlayan diller ...
dmckee

Eh, hala Ventero'nun Ruby veya Golfscript'inin gerisinde - her zamanki gibi;)
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

Tarihçe:

  • 2011-03-01 01:54 (427) İlk deneme.
  • 2011-03-01 02:01 (342) def , sıkça ortaya çıkan birkaç şeyi daha yayınladı.
  • 2011-03-01 02:24 (283) Daha da fazlası defs.
  • 2011-03-01 02:42 (281) Veee başka defiki bayt kaydeder.
  • 2011-03-01 03:01 (260) [ ve ]değişken olarak kullanıldığında hoş özelliklere sahip :-). KirarinSnow'a teşekkürler .
  • 2011-03-01 03:12 (246) Satır içi satır çok sayıda defs yerine bir dict kullanarak kopuyor . Tekrar Thansk :-).
  • 2011-03-01 03:26 (237) Kirarin'e teşekkür ederiz .

3

Yakut 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

1

Yakut - 423 karakter

Gerçekten bu kadar korkunç bir sayım olduğundan bunu paylaşmak istemiyorum, ama yazdığımdan beri de olabilir.

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}

Muhtemelen biraz azaltılabilirdi ama bu kaba kuvvet yaklaşımının iyi bir karaktere yakın bir yere geleceğinden şüpheliyim, bu yüzden rahatsız edilemem.


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

Aslında, PHP'nin bunu yapmayı ne kadar kısa sürebildiğini görmek için yaptım, çünkü oldukça uzun olacağını biliyordum. Küçültülebileceğinden eminim, ancak PHP'nin çok fazla kısayolu olmadığı düşünülüyor.

Doğrulama:
http://codepad.viper-7.com/ftYYz9.php53

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


Sadece stdin'den okumak için değiştirdi, soruda bunu kaçırdı. Bundan dolayı işleve artık ihtiyaç duymuyor.
Kevin Brown

Kodu stdin'den doğru şekilde okuyacak şekilde değiştirildi. Ayrıca boyutunu azaltmak için biraz daha golf oynadı.
Kevin Brown

Sağ alt köşegen çizgi orada değil ve bunun yerine dikey bir çizgi görünüyor. Yine de onu çağırmakta yanlış bir şey yapmıyorsam.
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 veya üstü, ile koşmak perl -E '<code here>'

Sıkışık sürüm:

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

1

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

alt p {y / xS / + \ //; yazdır; y / + \ // xS /} $ b = / 2; $ a = $ b; $ _ = "xx \ n"; s / x / x- --- / while ($ a -); ((/ ^ S /) 'a kadar {p; s / [xS] / S / g; s / -x / S | /; y / - / /} s / ( A = * S) / - / g; y / S / x /; p; y / -x / | /; p iken (- $ b); s /.$/ x /; iken (/ \ | / ) {p; s /..$/ S /} y / | S / ++ - /; p

Temel fikir her şeyi düzenli ifade ile yapmaktır. Kullanılan karakterlerden ikisi (+ ve /) özel karakterler olduğundan ve regex'lerde çok fazla olduğu için, diğer karakterleri kullanıp bunları yazdırmak için kullanmaya değer.

Biraz daha okunaklı versiyon:

# Yukarıda açıklanan şekilde ikame etmek, yazdırmak ve yerine geçmek için alt yordam
alt p {y / xS / + \ //; yazdırma; y / + \ // xS /}
# Stdin'den oku ve ilk satırı kur
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / süre ($ a--);
# Üst yüzü yazdır
kadar (/ ^ S /) {
  p;
  s / [xS] / S / g; # İlk kez tur: sol + -> /; sonraki zamanlar hareket / sola
  s / -x / S | /; # Döngünün ilk sadece ilgili zamanı
  y / - / / # Sadece döngü boyunca ilk kez ilgili
}
# İkinci yatay çizgi içeren çizgiyi hazırlayın ve yazdırın
s / (8 = S) / - / g;
y / S / x /;
p;
# Şimdi (n-1) / 2 aynı satırları yazdır
y / -x / | /;
p süre (- $ b);
# Sağ kenarı getir
s /.$/ x /;
iken (/ \ | /)
{
  p;
  s /..$/ S /
}
# Son satır
y / | S / ++ - /;
p

Bir anlamda ara döngüde bir sayaç olarak $ b kullanarak hile yapıyorum - bunun yerine döngüde $ a üzerinde boşluk ekleyebilir ve sonra da bu döngü için regex yerine kullanabilirsiniz - ama bu küçük sapmaya izin vereceğim saf regex çözümünden.

Hiç şüphe yok ki, bazı korkutucu insanlar bunu çok daha kısa bir betiğe dönüştürebilir.


"Biraz daha okunaklı versiyon" - Perl'in sadece yeni satırlar ve boşluklar dahil edildiğinde biraz daha okunaklı hale gelmesine bayıldım. :)
Steve

@Steve, yorumlarda bile bunu anlamak için biraz Perl bilmek zorundasınız. Kullanılması yiçin traçık değildir ve daha önce gidebilir "ise" yol olarak veya sonrasında ...
Peter Taylor

1

Lua, 294 302 292 bayt

golfed:

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)

Ungolfed:

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)

Giriş standart giriş akışında verilir. Bu burada işe görünmüyor.
Joey

Ayrıca or 6, read()aramadan sonra dört byte kaydeder :-) dışında bırakabilirsiniz :-)
Joey

Hm, şimdi bununla birlikte (...)benim için artık Lua 5.1.4'te işe yaramıyor.
Joey,

1

Tuval , 63 bayt

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

Burada dene!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.