Vẽ một khối lập phương trong nghệ thuật ASCII


32

Mô tả công việc:

Vẽ một khối lập phương trong nghệ thuật ASCII trong một hình chiếu tủ.

Monospaced fontsthường có các ký tự cao gấp đôi chúng. Vì đầu vào là chiều dài của các đường thẳng đứng (không bao gồm các góc), các đường ngang được vẽ với số ký tự nhiều gấp đôi để hình ảnh thu được thực sự gần như là một khối. Các đường rút được vẽ ở một nửa chiều dài theo quy định của phép chiếu tủ.

Các góc của khối được thể hiện bằng +, các đường ngang bằng -, các đường thẳng đứng |và các đường chéo sử dụng /.

Tóm tắt: Đặt đầu vào là n , sau đó

  • Một cạnh ngang của khối được vẽ -và bao gồm 2  n ký tự.
  • Một cạnh thẳng đứng của khối được vẽ |và bao gồm n ký tự.
  • Một cạnh chéo của khối được vẽ bằng /và bao gồm n / 2 ký tự.
  • Các góc của khối được vẽ bằng +. Các góc không được tính cho chiều dài của cạnh như chi tiết ở trên (xem ví dụ bên dưới).

Đầu vào:

Đầu vào, được đưa ra trên đầu vào tiêu chuẩn, là một số dương duy nhất, chẵn n (2 n 30) cho độ dài của các đường thẳng đứng của khối. Nó được theo sau bởi một ngắt dòng duy nhất.

Đầu ra:

Đầu ra là một khối lập phương trên đầu ra tiêu chuẩn theo các quy tắc trên. Trailing khoảng trắng trên các dòng được bỏ qua.

Mẫu đầu vào 1:

2

Mẫu đầu ra 1:

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

Mẫu đầu vào 2:

4

Mẫu đầu ra 2:

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

ETA: Bây giờ tôi đã chấp nhận giải pháp ngắn nhất. Tôi sẽ cập nhật câu trả lời được chấp nhận khi có câu trả lời ngắn hơn.

Vì một số người hỏi các bài dự thi của chúng tôi là bao lâu:

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

Cũng như các giải pháp riêng của chúng tôi (không được xếp hạng với các giải pháp khác):

140 - Golfscript
172 - Ruby
183 - PowerShell


bạn có thể nói một chút về các giải pháp tốt nhất bạn có? Có bao nhiêu ký tự nhỏ nhất có?
Juan

@Juan: Đã thêm thông tin được yêu cầu
Joey

1
Thật thú vị, C ++ có thể sử dụng các bản vẽ tương tự như "chữ tương tự": hostilefork.com/2009/08/29/tweakinganalog-literals-humor
Tiến sĩ Rebmu

@Hostile: Đúng, cái đó thật tuyệt, nếu hơi ác ;-)
Joey

Câu trả lời:


10

Golfscript - 96 ký tự

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

Hầu hết sự gọn nhẹ đến từ việc tích cực lưu trữ hầu hết mọi thứ vào một biến số (trừ khi bạn bao gồm việc được viết bằng golf).

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

Một vài thủ thuật nhỏ khác ở đây.

  1. 'LR''str'*-> 'LstrR'.
  2. Vì chúng ta cần đảo ngược thứ tự các dòng trong mảng cuối cùng, chúng tôi chọn thực hiện việc này sau khi tạo văn bản thay vì trước đó. Điều này cho phép chúng ta lưu một ký tự vì các khoảng trắng trước '/'chỉ cần đi qua hai phần tử ngăn xếp ( @) thay vì 3 ( @ .. \).

16

Con trăn - 248 243 230 227 191

Hơi lộn xộn nhưng về cơ bản nó in dòng lập phương theo dòng (sử dụng bộ đệm chuỗi).

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

Cảm ơn @marcog, vì đã chỉ ra dòng đầu tiên, @ThomasO đã chỉ ra dòng thứ hai và @Juan vì đã khiến tôi nhận ra mình có thể kết hợp các dòng.


4
Để tiết kiệm thêm một số không gian thay đổi s=" ";p="+";b="|";f="/";n="\n"để s,p,b,f,n=" +|/\n".
Thomas O

1
Một phiếu bầu là không đủ. Bạn đã thúc đẩy tôi cải thiện giải pháp của mình đến những giới hạn mà tôi nghĩ là không thể, cảm ơn: D
Juan

:) bây giờ để xem nếu tốt hơn là có thể.
JPvdMerwe

10

Con trăn - 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

Tôi muốn lưu ý rằng tôi đã lấy một số ý tưởng từ JPvdMerwe (Sử dụng một chuỗi để in một lần và một lớp lót mà tôi không biết là cú pháp chính xác trong Python).


Dòng 3 bị thiếu 2 ở cuối, thật không may, đẩy số đếm lên 256.
JPvdMerwe

@JPvdMerwe oops, cảm ơn vì đã nắm bắt điều đó!
Juan

1
Có lẽ bạn có thể thử lưu trữ kết quả trong một chuỗi như tôi đã làm và chỉ in một lần?
JPvdMerwe

1
@Juan Tôi nghĩ rằng chúng ta nên tránh giữ các bản sao cũ trong bài, trừ khi hai phiên bản chủ yếu khác nhau. Chúng có thể xem được trong lịch sử chỉnh sửa nếu ai đó muốn đọc nó.
marcog

2
Đối với Câu hỏi thường gặp: Tôi thường bao gồm lịch sử độ dài trong các bài đăng của mình (  tuy nhiên đây là một ví dụ có quá dài để đưa vào). Không biết liệu một thứ như vậy có hữu ích hay không nhưng nó có thể giúp người khác khám phá những thủ thuật nào được sử dụng để giữ cho nó ngắn. Mặc dù tôi cũng có một lịch sử SVN cho điều đó.
Joey

8

fortran 77 - 484 ký tự

      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

Không có điểm thực sự trong việc cung cấp một phiên bản "chưa hoàn thành". Và lưu ý rằng markdown không phù hợp với các yêu cầu thụt lề.

Tôi đã thử fortran vì các vòng lặp nội tuyến được cung cấp bởi writetuyên bố. Rõ ràng là họ giúp đỡ nhưng không bổ sung đủ để giết chết ngôn từ. Nó có thể được giảm bằng cách sử dụng đầu vào dạng tự do.

Xác nhậ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
    +--------+ 
   /        /|
  /        / |
 +--------+  |
 |        |  |
 |        |  +
 |        | /
 |        |/
 +--------+ 

Rất may, thông số kỹ thuật không nói kích thước người ta sẽ trông như thế nào:

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

nhưng kích thước lẻ khác là hợp lý:

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

Lựa chọn ngôn ngữ thú vị :-). Chà, size 1 trông không tệ lắm. Giải pháp của tôi ném lên một vòng lặp vô tận. Các hành vi làm tròn khác nhau là lý do để loại bỏ các kích thước lẻ, nếu tôi nhớ chính xác (và giới hạn trên của 30 để khớp với chiều rộng 80 ký tự).
Joey

1
@joey: Thỉnh thoảng tôi làm fortran và rất vui nếu tôi ít hơn 10 lần so với người chiến thắng.
dmckee

4

Giải pháp của riêng tôi, vì nó đã bị Python đánh đến chết:

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

À ... các ngôn ngữ cho phép bạn "nhiều" chuỗi bằng một trợ giúp vô hướng cho việc này ...
dmckee

Chà, nó vẫn còn thua xa Ruby hoặc Golfscript của Venter - như thường lệ;)
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

Lịch sử:

  • 2011 / 03-01 01:54 (427) Lần thử đầu tiên.
  • 2011 / 03-01 02:01 (342) def ed một vài điều nữa xuất hiện thường xuyên.
  • 2011 / 03-01 02:24 (283) Thậm chí nhiều hơn defs.
  • 2011 / 03-01 02:42 (281) Aaand khác deftiết kiệm thêm hai byte.
  • 2011 / 03-01 03:01 (260) []có các thuộc tính đẹp khi được sử dụng làm biến :-). Nhờ vào KirarinSnow .
  • 2011 / 03-01 03:12 (246) Ngắt dòng nội tuyến, sử dụng một lệnh thay vì nhiềudef s. Lại một lần nữa :-).
  • 2011 / 03-01 03:26 (237) Cảm ơn nhiều hơn đến KirarinSnow .

3

Ruby 1.9, 172 165 162 ký tự

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 ký tự

Thực sự không muốn chia sẻ điều này vì nó là một con số khủng khiếp, nhưng vì tôi đã viết nó cũng có thể.

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}

Có lẽ có thể giảm đi một chút nhưng tôi nghi ngờ cách tiếp cận vũ phu này sẽ đến bất cứ nơi nào gần một số lượng nhân vật kha khá nên tôi không thể bị làm phiền.


1

PHP, 401 392 382 363 ký tự:

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

Ban đầu tôi đã làm điều này để xem tôi có thể quản lý để làm điều này trong PHP ngắn đến mức nào, vì tôi biết rằng nó sẽ khá dài. Tôi chắc chắn rằng nó có thể được giảm bớt, nhưng không nhiều bằng cách xem xét PHP không có nhiều phím tắt.

Xác thực:
http://codepad.viper-7.com/ftYYz9.php53

Phiên bản bị hủy: http://codepad.viper-7.com/4D3kIA


Chỉ cần sửa đổi nó để đọc từ stdin, bỏ lỡ điều đó trong câu hỏi. Không cần chức năng nữa vì điều đó.
Kevin Brown

Sửa đổi mã để nó đọc từ stdin chính xác. Cũng đánh gôn thêm một chút để giảm kích thước.
Kevin Brown

Đường chéo bên phải thấp hơn không có ở đó và thay vào đó là một đường thẳng đứng bù xuất hiện. Trừ khi tôi đang làm gì đó sai trong việc gọi nó, mặc dù.
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 trở lên, chạy với perl -E '<code here>'

Phiên bản tôn trọng:

$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 ký tự

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

Ý tưởng cơ bản là làm mọi thứ với sự thay thế regex. Vì hai trong số các ký tự được sử dụng (+ và /) là các ký tự đặc biệt và xuất hiện rất nhiều trong các biểu thức, nên sử dụng các ký tự khác và thay thế chúng để in.

Phiên bản dễ đọc hơn một chút:

# Chương trình con để thay thế, in và hủy đăng ký như được mô tả ở trên
phụ p {y / xS / + \ //; in; y / + \ // xS /}
# Đọc từ stdin và thiết lập dòng ban đầu
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# In mặt trên
cho đến khi (/ ^ S /) {
  p;
  s / [xS] / S / g; # Vòng đầu tiên: trái + -> /; lần sau di chuyển / trái
  s / -x / S | /; # Chỉ có liên quan lần đầu tiên quanh vòng lặp
  y / - / / # Chỉ có liên quan lần đầu tiên vòng quanh vòng lặp
}
# Chuẩn bị và in dòng chứa dòng ngang thứ hai
s / (? = * S) / - / g;
y / S / x /;
p;
# Bây giờ in (n-1) / 2 dòng giống hệt nhau
y / -x / | /;
p trong khi (- $ b);
# Mang cạnh phải vào
s /.$/ x /;
trong khi (/ \ | /)
{
  p;
  s /..$/ S /
}
# Dòng cuối cùng
y / | S / ++ - /;
p

Theo một nghĩa nào đó, tôi gian lận bằng cách sử dụng $ b làm bộ đếm trong vòng lặp trung gian - thay vào đó tôi có thể nối thêm khoảng trắng trong vòng lặp trên $ a và sau đó sử dụng regex thay thế cho vòng lặp đó - nhưng tôi sẽ cho phép độ lệch nhẹ đó từ một giải pháp regex tinh khiết.

Không nghi ngờ gì một số người đáng sợ có thể biến điều này thành một kịch bản sed ngắn hơn nhiều.


"Phiên bản dễ đọc hơn một chút" - phải yêu rằng Perl chỉ trở nên dễ đọc hơn một chút khi có dòng mới và khoảng trắng. :)
Steve

@Steve, ngay cả với các bình luận bạn phải biết một chút về Perl để hiểu nó. Sử dụng ycho trkhông rõ ràng và đối với cách "trong khi" có thể đi trước hoặc sau ...
Peter Taylor

1

Lua, 294 302 292 byte

Chơi gôn

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)

Ung dung:

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)

Đầu vào được đưa ra trên luồng đầu vào tiêu chuẩn. Điều này dường như không hoạt động ở đây.
Joey

Bạn cũng có thể bỏ qua or 6sau read()cuộc gọi, giúp tiết kiệm bốn byte :-)
Joey

Hừm, bây giờ với (...)nó không còn hoạt động với tôi nữa trên Lua 5.1.4.
Joey

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.