การวาดภาพลูกบาศก์ในงานศิลปะ ASCII


32

คำอธิบายงาน:

วาดลูกบาศก์ในศิลปะ ASCII โดยประมาณเป็นโครงตู้

Monospaced fontsมักจะมีตัวละครที่สูงประมาณสองเท่ากว้าง เนื่องจากอินพุตคือความยาวของเส้นแนวตั้ง (ไม่รวมมุม) เส้นแนวนอนจะถูกวาดด้วยอักขระจำนวนมากเป็นสองเท่าเพื่อให้ภาพที่ได้เป็นลูกบาศก์จริงๆ เส้นที่ถอยกลับจะถูกวาดที่ความยาวครึ่งหนึ่งตามที่กำหนดโดยการฉายภาพของคณะรัฐมนตรี

มุมของก้อนจะถูกแทนด้วย+เส้นแนวนอนโดย-เส้นแนวตั้งโดยและคนที่ใช้เส้นทแยงมุม|/

สรุป: ให้อินพุตเป็นnจากนั้น

  • ขอบแนวนอนของคิวบ์ถูกวาดด้วย-และประกอบด้วย 2  nอักขระ
  • ขอบแนวตั้งของคิวบ์ถูกวาดด้วย|และประกอบด้วยอักขระnตัว
  • เส้นทแยงมุมของลูกบาศก์ถูกวาดด้วย/และประกอบด้วยอักขระn / 2
  • +มุมของก้อนจะมีการวาด มุมจะไม่นับตามความยาวของขอบตามรายละเอียดด้านบน (ดูตัวอย่างด้านล่างเช่นกัน)

การป้อนข้อมูล:

การป้อนข้อมูลให้กับการป้อนข้อมูลมาตรฐานเป็นบวกเดียวเลขคู่n (2 ≤ n ≤ 30) ที่ให้ความยาวของเส้นแนวตั้งของลูกบาศก์ ตามด้วยตัวแบ่งบรรทัดเดียว

เอาท์พุท:

เอาต์พุตเป็นคิวบ์บนเอาต์พุตมาตรฐานตามกฎข้างต้น ช่องว่างต่อท้ายบนบรรทัดจะถูกละเว้น

ตัวอย่างอินพุต 1:

2

ตัวอย่างผลลัพธ์ 1:

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

ตัวอย่างอินพุต 2:

4

ตัวอย่างผลลัพธ์ 2:

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

การทางพิเศษแห่งประเทศไทย:ตอนนี้ฉันได้รับการยอมรับทางออกที่สั้นที่สุด ฉันจะอัปเดตคำตอบที่ยอมรับได้เมื่อคำตอบสั้นลง

เนื่องจากบางคนถามว่ารายการของผู้แข่งขันของเรานานแค่ไหน:

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

เช่นเดียวกับการแก้ปัญหาของเราเอง (ไม่ได้จัดอันดับกับคนอื่น ๆ ):

140 - Golfscript
172 - Ruby
183 - PowerShell


คุณพอจะบอกได้บ้างเกี่ยวกับวิธีแก้ปัญหาที่ดีที่สุดที่คุณมี? ตัวเล็กที่สุดมีกี่ตัวอักษร?
Juan

@Juan: เพิ่มข้อมูลที่ร้องขอ
Joey

1
ที่น่าประหลาดใจก็คือ C ++ สามารถใช้ภาพวาดที่คล้ายกันเป็น "ตัวอักษรแบบอะนาล็อก": hostilefork.com/2009/08/29/tweakinganalog-literals-humor
ดร. Rebmu

@Hostile: อ๋อนั่นเป็นคนที่ดีถ้าเป็นคนชั่ว ;-)
Joey

คำตอบ:


10

Golfscript - 96 ตัวอักษร

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

ความกะทัดรัดส่วนใหญ่มาจากการเก็บทุกอย่างลงในตัวแปรอย่างจริงจัง (ยกเว้นกรณีที่คุณเขียนด้วย Golfscript)

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

คู่ของเคล็ดลับเล็ก ๆ อื่น ๆ ที่นี่

  1. 'LR''str'*'LstrR'->
  2. เนื่องจากเราจำเป็นต้องกลับลำดับของบรรทัดในอาร์เรย์สุดท้ายเราเลือกที่จะทำสิ่งนี้หลังจากสร้างข้อความแทนที่จะเป็นมาก่อน สิ่งนี้ช่วยให้เราสามารถบันทึกอักขระหนึ่งตัวเนื่องจากช่องว่างก่อน'/'ความต้องการเพียงอย่างเดียวที่จะผ่านองค์ประกอบสแต็กสองรายการ ( @) แทน 3 ( @ .. \)

16

Python - 248 243 230 227 191

ยุ่งเล็กน้อย แต่โดยทั่วไปแล้วพิมพ์คิวบ์ทีละบรรทัด (ใช้บัฟเฟอร์สตริง)

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 สำหรับการชี้บรรทัดแรก @ThomasO สำหรับการชี้บรรทัดที่สองและ @Juan ที่ทำให้ฉันรู้ว่าฉันสามารถรวมกันเป็นเส้นได้


4
การบันทึกการเปลี่ยนแปลงพื้นที่บางส่วนเพิ่มเติมไปs=" ";p="+";b="|";f="/";n="\n" s,p,b,f,n=" +|/\n"
โทมัสโอ

1
การโหวตหนึ่งครั้งยังไม่เพียงพอ คุณได้ผลักดันฉันให้ปรับปรุงวิธีการแก้ปัญหาของฉันให้ถึงขีด จำกัด ที่ฉันคิดว่าเป็นไปไม่ได้ขอบคุณ: D
Juan

:) ตอนนี้เพื่อดูว่าเป็นไปได้ที่ดีขึ้น
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 (การใช้สตริงเพื่อพิมพ์ครั้งเดียวและหนึ่งซับสำหรับที่ฉันไม่ทราบว่าเป็นไวยากรณ์ที่ถูกต้องใน Python)


บรรทัดที่ 3 ขาด 2 ตอนท้ายซึ่งน่าเสียดายที่เพิ่มจำนวนขึ้นเป็น 256
JPvdMerwe

@JPvdMerwe โอ๊ะขอบคุณสำหรับการจับที่!
Juan

1
บางทีคุณอาจลองแคชผลลัพธ์เป็นสตริงเหมือนที่ฉันทำและพิมพ์เพียงครั้งเดียว
JPvdMerwe

1
@ หยวนฉันคิดว่าเราควรหลีกเลี่ยงการเก็บสำเนาเก่าไว้ในโพสต์เว้นแต่ว่าทั้งสองรุ่นจะแตกต่างกันอย่างมาก พวกเขาสามารถดูได้ในประวัติการแก้ไขหากมีคนต้องการอ่าน
marcog

2
สำหรับคำถามที่พบบ่อย: ฉันมักจะรวมประวัติความยาวในโพสต์ของฉัน (  นี่คือตัวอย่างที่ยาวเกินไปที่จะรวมไว้) ไม่ทราบว่าสิ่งนั้นเป็นประโยชน์หรือไม่ แต่อาจช่วยให้ผู้อื่นค้นพบว่ามีการใช้กลอุบายในการทำให้สั้นหรือไม่ แม้ว่าฉันจะมีประวัติ SVN สำหรับสิ่งนั้นเช่นกัน
Joey

8

fortran 77 - 484 ตัวอักษร

      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

ไม่มีจุดจริงในการให้บริการรุ่น "unobsfucated" และโปรดทราบว่ามาร์คดาวน์ไม่สอดคล้องกับข้อกำหนดเยื้อง

ฉันลอง Fortran เพราะอินไลน์สำหรับการวนwriteซ้ำที่จัดทำโดยคำสั่ง เห็นได้ชัดว่าพวกเขาช่วย แต่ไม่เพิ่มขึ้นมากพอที่จะฆ่า wordiess ของภาษา อาจลดลงได้โดยใช้อินพุตอิสระ

การตรวจสอบ:

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

โชคดีที่สเป็คไม่ได้บอกขนาดที่ควรจะเป็น:

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

แต่ขนาดคี่อื่น ๆ ที่เหมาะสม:

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

ตัวเลือกภาษาที่น่าสนใจ :-) ขนาด 1 ดูไม่เลวร้ายเกินไป วิธีการแก้ปัญหาของฉันพ่นวนไม่สิ้นสุด พฤติกรรมการปัดเศษที่แตกต่างกันเป็นเหตุผลที่ทำให้มีขนาดที่แปลกออกไปถ้าฉันจำได้อย่างถูกต้อง
Joey

1
@joey: ฉันทำ fortran เป็นครั้งคราวและมีความสุขถ้าฉันน้อยกว่า 10 ผู้ชนะ
dmckee

4

วิธีการแก้ปัญหาของฉันเองเพราะมันถูกตีจนตายโดย 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

อ่า ... ภาษาที่ให้คุณใช้สตริง "หลายตัว" โดยวิธีใช้สเกลาร์สำหรับสิ่งนี้ ...
dmckee

ก็ยังห่างไกลจาก Ruby หรือ Golfscript ของ Ventero - ตามปกติ;)
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

ประวัติความเป็นมา:

  • 2011-03-01 01:54 (427)ความพยายามครั้งแรก
  • 2011-03-01 02:01 (342) ได้ defเพิ่มสิ่งต่าง ๆ ที่ปรากฏขึ้นบ่อยๆ
  • 02:24 2011-03-01 (283)มากยิ่งขึ้นdefs
  • 2011-03-01 02:42 (281) Aa และอีกอันdefที่บันทึกสองไบต์เพิ่มเติม
  • 2011-03-01 03:01 (260) [และ]มีคุณสมบัติที่ดีเมื่อใช้เป็นตัวแปร :-) ขอขอบคุณที่KirarinSnow
  • 2011-03-01 03:12 (246) Inline แบ่งบรรทัดใช้ Dict แทนหลายdefs ภาษาไทยอีกครั้ง :-)
  • 03:26 2011-03-01 (237)ขอบคุณเพิ่มเติมเพื่อKirarinSnow

3

ทับทิม 1.9 172 165 162 ตัวอักษร

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

Ruby - 423 ตัวอักษร

ไม่ต้องการแบ่งปันสิ่งนี้เพราะมันนับได้ว่าน่ากลัว แต่เมื่อฉันเขียนมันก็อาจจะเป็นเช่นนั้น

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}

อาจจะลดลงได้เล็กน้อย แต่ฉันสงสัยว่าวิธีการอันโหดร้ายกำลังจะมาถึงทุกที่ที่มีจำนวนตัวละครที่เหมาะสมดังนั้นฉันจึงไม่สามารถใส่ใจได้


1

PHP, 401 392 382 363 ตัวอักษร:

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

เดิมทีฉันทำสิ่งนี้เพื่อดูว่าฉันสามารถจัดการกับ PHP ได้สั้นเพียงใดเพราะฉันรู้ว่ามันจะค่อนข้างยาว ฉันแน่ใจว่ามันจะลดลง แต่ไม่มากนักเมื่อพิจารณาถึง PHP ไม่มีทางลัดมากมาย

การตรวจสอบความถูกต้อง:
http://codepad.viper-7.com/ftYYz9.php53

เวอร์ชั่น Ungolfed: http://codepad.viper-7.com/4D3kIA


เพิ่งแก้ไขมันเพื่ออ่านจาก stdin ที่พลาดในคำถาม ไม่ต้องการฟังก์ชั่นอีกต่อไปเพราะสิ่งนั้น
เควินบราวน์

แก้ไขรหัสเพื่อให้อ่านได้จาก stdin อย่างถูกต้อง แถมยังเพิ่มขนาดให้เล็กลงอีกเล็กน้อย
Kevin Brown

เส้นทแยงมุมล่างขวาไม่ได้อยู่ที่นั่นและจะมีเส้นแนวตั้งชดเชยปรากฏขึ้นแทน แม้ว่าฉันจะทำอะไรผิดในการเรียกใช้ก็ตาม
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 หรือใหม่กว่าทำงานด้วย perl -E '<code here>'

รุ่นที่เกี่ยวข้อง:

$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 ตัวอักษร

sub p {y / xS / + \ //; print; y / + \ // xS /} $ b = / 2; $ a = $ b; $ _ = "xx \ n"; s / x / x- --- / ขณะที่ ($ a -); จนกระทั่ง (/ ^ S /) {p; s / [xS] / S / g; s / -x / S | /; y / - / /} s / ( ? = * S) / - / g; y / S / x /; p; y / -x / | /; p ขณะที่ (- $ b); s /.$/ x /; ในขณะที่ (/ \ | / ) {p; s /..$/ S /} y / | S / ++ - /; p

แนวคิดพื้นฐานคือการทำทุกอย่างด้วยการทดแทน regex เนื่องจากตัวละครสองตัวที่ใช้ (+ และ /) เป็นตัวละครพิเศษและมีจำนวนมากขึ้นในภาคผนวกดังนั้นจึงคุ้มค่าที่จะใช้ตัวละครอื่นและแทนที่มันเพื่อพิมพ์

รุ่นที่ชัดเจนมากขึ้นเล็กน้อย:

# รูทีนย่อยเพื่อทดแทนพิมพ์และยกเลิกการเป็นสมาชิกตามที่อธิบายไว้ข้างต้น
sub p {y / xS / + \ //; print; y / + \ // xS /}
# อ่านจาก stdin และตั้งค่าบรรทัดเริ่มต้น
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / ในขณะที่ ($ a--);
# พิมพ์หน้าด้านบน
จนถึง (/ ^ S /) {
  p;
  s / [xS] / S / g; # รอบแรก: left + -> /; ครั้งต่อมาย้าย / ซ้าย
  S / -x / S | /; # เฉพาะครั้งแรกที่เกี่ยวข้องรอบการวนซ้ำ
  y / - / / # เฉพาะครั้งแรกที่เกี่ยวข้องรอบลูป
}
# เตรียมและพิมพ์บรรทัดที่มีเส้นแนวนอนที่สอง
s / (? = * S) / - / g;
Y / S / x /;
p;
# Now พิมพ์ (n-1) / 2 บรรทัดที่เหมือนกัน
y / -x / | /;
p ในขณะที่ (- $ b);
# นำขอบด้านขวามา
s /.$/ x /;
ในขณะที่ (/ \ | /)
{
  p;
  s /..$/ S /
}
# บรรทัดสุดท้าย
y / | S / ++ - /;
พี

ในความรู้สึกฉันกำลังโกงโดยใช้ $ b เป็นตัวนับใน loop loop - ฉันสามารถเพิ่ม whitespace ใน loop มากกว่า $ a และใช้ regex แทนที่สำหรับ loop นั้นแทน แต่ฉันจะยอมให้เบี่ยงเบนเล็กน้อยนั้น จากโซลูชัน pure-regex

ไม่ต้องสงสัยเลยว่าบางคนที่น่ากลัวสามารถเปลี่ยนสิ่งนี้ให้กลายเป็นบทสั้น ๆ


"เวอร์ชั่นที่อ่านง่ายขึ้นเล็กน้อย" - ต้องรักว่า Perl จะสามารถอ่านได้ง่ายขึ้นเมื่อรวมบรรทัดใหม่และช่องว่าง :)
Steve

@ Steve แม้จะมีความคิดเห็นที่คุณต้องรู้ Perl เล็กน้อยเพื่อทำความเข้าใจ ใช้yสำหรับการtrไม่ชัดเจนและเป็นสำหรับวิธีการ "ขณะที่" สามารถไปก่อนหรือหลังจากที่ ...
ปีเตอร์เทย์เลอร์

1

Lua, 294 302 292 ไบต์

แข็งแรงเล่นกอล์ฟ:

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)

อินพุตได้รับจากอินพุตสตรีมมาตรฐาน ดูเหมือนจะไม่ทำงานที่นี่
Joey

นอกจากนี้คุณยังสามารถออกจากสายor 6หลังread()ได้ซึ่งช่วยประหยัดสี่ไบต์ :-)
Joey

หืมตอนนี้(...)มันใช้ไม่ได้กับ Lua 5.1.4 อีกแล้ว
Joey

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.