Рисование куба в искусстве 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
Доктор Ребму,

@Hostile: Да, это было хорошо, если немного зла ;-)
Джои

Ответы:


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

Питон - 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
Хуан,

:) теперь, чтобы увидеть, возможно ли лучше.
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 для этого.
Джои

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заявлении. Очевидно, они помогают, но не суммируют достаточно, чтобы убить словесности языка. Это может быть уменьшено с помощью ввода произвольной формы.

Проверка:

 $ 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 символов).
Джои

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

Ну, это все еще далеко позади 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 Еще несколько вещей, которые появлялись часто.
  • 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

Версия без поддержки: http://codepad.viper-7.com/4D3kIA


Просто изменил его для чтения из stdin, пропустил это в вопросе. Из-за этого функция больше не нужна.
Кевин Браун

Изменен код, чтобы он правильно читал из стандартного ввода. Также игра в гольф это немного больше, чтобы уменьшить размер.
Кевин Браун

Нижняя правая диагональная линия отсутствует, и вместо этого появляется смещенная вертикальная линия. Если, конечно, я не делаю что-то неправильно, вызывая это.
Джои

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

Основная идея состоит в том, чтобы делать все с подстановками регулярных выражений. Поскольку два используемых символа (+ и /) являются специальными символами и часто встречаются в регулярных выражениях, стоит использовать другие символы и подставить их для печати.

Чуть более разборчивая версия:

# Подпрограмма для замены, печати и замены, как описано выше
sub p {y / xS / + \ //; print; y / + \ // xS /}
# Прочитать из стандартного ввода и установить начальную строку
$ b = <> / 2; $ a = $ b; $ _ = "xx \ n";
s / x / x ---- / while ($ a--);
# Распечатать верхнее лицо
до (/ ^ S /) {
  п;
  с / [хС] / с / г; # Первый раунд: слева + -> /; последующие времена двигаться / влево
  s / -x / S | /; # Относится только к первому циклу
  y / - / / # Относится только к первому циклу
}
# Подготовить и распечатать строку, содержащую вторую горизонтальную линию
с / (? = * S) / - / г;
г / S / х /;
п;
# Теперь выведите (n-1) / 2 одинаковых строки
у / -х / | /;
p while (- $ b);
# Приведите правый край в
с /.$/ х /;
пока (/ \ | /)
{
  п;
  с /..$/ S /
}
# Последняя строка
y / | S / ++ - /;
п

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

Без сомнения, какой-то страшный человек может превратить это в гораздо более короткий сценарий sed.


«Чуть более разборчивая версия» - нужно любить, что Perl становится немного более читабельным, когда включены переводы строк и пробелы. :)
Стив

@ Стив, даже с комментариями вы должны знать немного Perl, чтобы понять это. Использование yfor trне очевидно, а что касается пути "while", может идти до или после ...
Питер Тейлор

1

Lua, 294 302 292 байта

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)

Ввод дан в стандартный поток ввода. Это не похоже на работу здесь.
Джои

Вы также можете пропустить or 6после read()вызова, который сохраняет четыре байта :-)
Joey

Хм, теперь с (...)этим у меня больше не работает на Lua 5.1.4.
Джои

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.