ASCII 아트로 큐브 그리기


32

과업 설명:

대략 캐비닛 투영에서 ASCII 아트로 큐브를 그립니다.

Monospaced fonts종종 폭보다 약 2 배 높은 문자가 있습니다. 입력은 수직선 (코너 제외)의 길이이므로 수평선은 거의 두 배의 문자로 그려 지므로 결과 이미지는 대략 정육면체입니다. 후퇴 선은 캐비닛 투영에 의해 요구되는 길이의 절반으로 그려집니다.

큐브의 모서리는 +가로줄 -, 세로줄 |및 대각선으로 표시됩니다 /.

요약 : 입력을 n 으로 설정 한 다음

  • 정육면체의 가로 가장자리는 2n 문자 -로 그려지며 2n 자로 구성됩니다  .
  • 정육면체의 수직 모서리 |n 문자 로 그려지며 n 문자 로 구성됩니다 .
  • 큐브의 대각선 가장자리는 n / 2 문자 /로 그려지며 n / 2 문자 로 구성됩니다 .
  • 큐브의 모서리는로 그려집니다 +. 모서리는 위에서 설명한대로 모서리 길이에 포함되지 않습니다 (아래 예도 참조).

입력:

표준 입력에 제공된 입력 은 큐브의 수직선 길이를 제공 하는 단일 양의 짝수 n (2 ≤ n ≤ 30)입니다. 한 줄 바꿈이 이어집니다.

산출:

출력은 위의 규칙에 따라 표준 출력의 큐브입니다. 줄의 후행 공백은 무시됩니다.

샘플 입력 1 :

2

샘플 출력 1 :

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

샘플 입력 2 :

4

샘플 출력 2 :

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

ETA : 이제 가장 짧은 해결책을 받아 들였습니다. 더 짧은 답변이 나오면 허용 된 답변을 업데이트 할 것입니다.

어떤 사람들은 참가자의 참가 시간을 물었습니다.

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

@ 적대적 : 네, 조금 악한 일이라면 좋았습니다. ;-)
Joey

답변:


10

골프 스크립트-96 자

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

대부분의 소형화는 거의 모든 것을 변수에 적극적으로 저장하는 것에서 비롯됩니다 (골프 스크립트로 작성하는 것을 포함하지 않는 한).

<    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 ( ) 대신 '/'2 개의 스택 요소 ( @)를 지나야하기 때문에 하나의 문자를 저장할 수 있습니다 @ .. \.

16

파이썬 - 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".
Thomas O

1
한 번의 투표로 충분하지 않습니다. 당신은 내가 불가능하다고 생각한 한계까지 내 솔루션을 향상 시키도록 나를 밀어
Juan

:) 이제 더 나은지 확인하십시오.
JPvdMerwe

10

파이썬-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 죄송합니다, 그것을 잡아 주셔서 감사합니다!
Juan

1
어쩌면 결과처럼 문자열로 결과를 캐시하고 한 번만 인쇄 할 수 있습니까?
JPvdMerwe

1
@ Juan 두 버전이 크게 다르지 않으면 게시물에 오래된 사본을 보관하지 않아야한다고 생각합니다. 누군가 편집 기록을 보려면 편집 기록에서 볼 수 있습니다.
marcog

2
FAQ에 관해서는 : 종종 게시물에 길이 기록을 포함시킵니다 (  여기 에 포함하기에는 너무 긴 예제가 있습니다). 그러한 일이 도움이되는지 모르지만 다른 사람들이 간결하게 유지하는 데 사용 된 트릭을 발견하는 데 도움이 될 수 있습니다. 나는 또한 그것에 대한 SVN 역사를 가지고 있지만.
Joey

8

포트란 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

"비난 독화"버전을 제공하는 데는 아무런 의미가 없습니다. 그리고 마크 다운은 들여 쓰기 요구 사항과 잘 맞지 않습니다.

write명령문에서 제공하는 인라인 for 루프로 인해 포트란을 시도했습니다 . 분명히 그들은 도움이되지만 언어의 말을 죽일만큼 충분하지는 않습니다. 자유형 입력을 사용하여 줄일 수 있습니다.

확인:

 $ 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은 그리 나쁘지 않습니다. 내 솔루션은 끝없는 루프를 던졌습니다. 다른 반올림 동작은 올바르게 기억한다면 홀수 크기를 버리는 이유였습니다 (80 자 너비에 맞추기 위해 상한 30).
Joey

1
@joey : 나는 때때로 포트란을하고, 내가 승자보다 10보다 작을 때 행복합니다.
dmckee

4

내 자신의 솔루션은 이미 Python에 의해 치러 졌기 때문에 :

윈도우 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

글쎄, 그것은 여전히 ​​Ventero의 Ruby 나 Golfscript보다 훨씬 뒤쳐져있다 – 평소와 같이;)
Joey

4

포스트 스크립트, 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 는 자주 등장하는 몇 가지 사항을 더했습니다.
  • 2011-03-01 02:24 (283) 더 많은 defs.
  • 2011-03-01 02:42 (281)def 두 바이트를 더 절약하는 또 다른 하나 .
  • 2011-03-01 03:01 (260) []변수 :-)로 사용될 때 좋은 속성을 갖습니다. KirarinSnow 에게 감사합니다 .
  • 2011-03-01 03:12 (246) 수많은 defs 대신 dict를 사용하여 인라인 줄 바꿈 . 다시 감사합니다 :-).
  • 2011-03-01 03:26 (237) KirarinSnow 에게 더 감사합니다 .

3

루비 1.9, 172165 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

루비-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에서 올바르게 읽을 수 있도록 코드를 수정했습니다. 또한 크기를 줄이기 위해 조금 더 골프를 쳤다.
케빈 브라운

오른쪽 하단 대각선이없고 대신 오프셋 수직선이 나타납니다. 그래도 내가 전화를 잘못하고 있지 않는 한.
Joey

1

펄, 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

펄, 269 ​​2262262256245244237228226228224217 문자

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

기본 아이디어는 정규식 대체로 모든 것을 수행하는 것입니다. 사용 된 두 문자 (+ 및 /)는 특수 문자이며 정규 표현식에서 많이 나타나기 때문에 다른 문자를 사용하여 인쇄하도록 대체하는 것이 좋습니다.

약간 더 읽기 쉬운 버전 :

# 위에서 설명한대로 대체, 인쇄 및 대체 할 서브 루틴
하위 p {y / xS / + \ //; print; y / + \ // xS /}
# stdin에서 읽고 초기 라인을 설정하십시오
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# 윗면 인쇄
까지 (/ ^ S /) {
  피;
  s / [xS] / S / g; # 첫 라운드 : 왼쪽 +-> /; 이후 시간 이동 / 왼쪽
  s / -x / S | /; # 루프 내에서 처음으로 관련된 것
  y /-/ / # 루프에서 처음으로 관련된 첫 번째
}
# 두 번째 수평선을 포함하는 줄을 준비하고 인쇄하십시오.
s / (? = * S) /-/ g;
y / S / x /;
피;
# 이제 (n-1) / 2 개의 동일한 줄을 인쇄하십시오
y / -x / | /;
p 동안 (-$ b);
# 오른쪽 가장자리를 가져와
s /.$/ x /;
while (/ \ | /)
{
  피;
  s /..$/ S /
}
# 마지막 라인
y / | S / ++-/;
피

어떤 의미에서 중간 루프에서 $ b를 카운터로 사용하여 부정 행위를합니다. 대신 $ a 위에 루프에서 공백을 추가 한 다음 해당 루프에 대해 정규식 대체를 사용할 수 있습니다.하지만 약간의 편차를 허용합니다. 순수한 정규식 솔루션에서.

의심 할 여지없이 일부 무서운 사람은 이것을 훨씬 짧은 sed 스크립트로 바꿀 수 있습니다.


"약간 더 읽기 쉬운 버전"-줄 바꿈과 공백이 포함 된 경우 Perl 만 읽을 수있게됩니다. :)
Steve

@Steve, 의견이 있더라도 그것을 이해하려면 약간의 Perl을 알아야합니다. 사용 y에 대한 것은 tr분명하지 않고, 전에 갈 수있다 "동안"방법에 대한 같은 또는 이후에 ...
피터 테일러

1

루아, 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)

언 골프 드 :

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() 4 바이트를 절약 호출 :-)
Joey

흠, 이제 (...)Lua 5.1.4에서 더 이상 작동하지 않습니다.
Joey

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.