Малювання куба в мистецтві 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: Додано запитувану інформацію
Joey

1
Забавно, що C ++ може використовувати подібні малюнки як "аналогові літерали": hostilefork.com/2009/08/29/tweakinganalog-literals-humor
Dr. Rebmu

@Hostile: Так, це було приємно, якщо трохи зла ;-)
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 ( @ .. \).

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".
Томас О

1
Одного голосу недостатньо. Ти підштовхуєш мене до вдосконалення мого рішення до тих меж, які я вважав неможливими, дякую: D
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

@JPvdMerwe На жаль, дякую, що це зробив!
Хуан

1
Можливо, ви можете спробувати кешувати результати в рядку, як я, і надрукувати лише один раз?
JPvdMerwe

1
@Juan Я думаю, що нам слід уникати збереження старих копій у пості, якщо тільки дві версії не відрізняються між собою. Їх можна переглянути в історії редагування, якщо хтось хоче її прочитати.
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

Немає реального сенсу в наданні "безперешкодної" версії. І зауважте, що розмітка не узгоджується з вимогами до відступу.

Я спробував fortran через вкладений цикл для петель write. Очевидно, вони допомагають, але не складаються з достатньою мірою, щоб знищити загарбність мови. Це можна зменшити, використовуючи введення вільної форми.

Перевірка:

 $ 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 виглядає не надто погано. Моє рішення підкидає нескінченну петлю. Якщо я правильно пам’ятаю, різні поведінки округлення були причиною викинути непарні розміри (і верхня межа 30 - для ширини 80 символів).
Joey

1
@joey: Я час від часу займаюся фортран, і я щасливий, якщо мені менше, ніж у 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

Ну, це все ще далеко за рубіном або Гольфскриптом Вентеро - як завжди;)
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 редагував ще кілька речей, які часто з’являлися.
  • 2011-03-01 02:24 (283) Ще більше defс.
  • 2011-03-01 02:42 (281) І ще один, defякий зберігає ще два байти.
  • 2011-03-01 03:01 (260) [ та ]мають хороші властивості, коли використовуються як змінні :-). Завдяки KirarinSnow .
  • 2011-03-01 03:12 (246) Розрив рядкових рядків, використовуючи dict замість численних defs. Знову Танськ :-).
  • 2011-03-01 03:26 (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

Рубін - 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 правильно. Також гольф трохи більше, щоб зменшити розмір.
Кевін Браун

Діагоналі в нижньому правому куті немає, і натомість з'являється зміщення вертикальної лінії. Але якщо я щось не так роблю, коли я викликаю це.
Джой

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

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 while (- $ b); s /.$/ x /; while (/ \ | / ) {p; s /..$/ S /} y / | S / ++ - /; p

Основна ідея - робити все з заміною регулярних виразів. Оскільки два використовувані символи (+ та /) - це спеціальні символи та багато виникають у регулярних виразах, варто використовувати інші символи та замінити їх для друку.

Трохи розбірливіша версія:

# Підпрограма для заміни, друку та незаміни, як описано вище
sub 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) / - / г;
y / S / x /;
р;
# Тепер надрукуйте (n-1) / 2 однакових лінії
у / -х / | /;
p, поки (- $ b);
# Введіть правий край
s /.$/ x /;
while (/ \ | /)
{
  р;
  s /..$/ S /
}
# Заключний рядок
у / | S / ++ - /;
p

У певному сенсі я обманюю, використовуючи $ b як лічильник в проміжному циклі - я міг би замість цього додати пробіл у циклі понад $ a, а потім також використовувати заміни регулярного вираження для цього циклу - але я дозволю це незначне відхилення з розчину чистого регексу.

Без сумніву, якась страшна людина може перетворити це на набагато коротший сценарій sed.


"Трохи розбірливіша версія" - треба любити, що Perl стає лише трохи читабельнішим, коли входять нові рядки та пробіли. :)
Стів

@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()дзвінка, який заощаджує чотири байти :-)
Joey

Гм, тепер з цим (...)він більше не працює для Lua 5.1.4.
Joey

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.