Построй мне пирамиду


16

Вам нужно построить пирамиду из кубиков. Кубики можно смотреть с 2 углов:

  _____        _____
 /\    \      /    /\
/  \____\    /____/  \
\  /    /    \    \  /
 \/____/      \____\/

Это пример для двухразмерных кубов с двух возможных углов. Высота кубов - $sizeкосая черта (или обратная косая черта), а ширина куба - 2 * $sizeподчеркивание. Ширина верхнего уровня должна содержать дополнительный символ подчеркивания.

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

Примеры:

Входные данные:

1/1

Выход:

 ___
/\__\
\/__/

Входные данные:

1\1

Выход:

 ___
/__/\
\__\/

Входные данные:

2/1

Выход:

  _____
 /\    \
/  \____\
\  /    /
 \/____/

Входные данные:

1/2

Выход:

     ___ 
 ___/\__\
/\__\/__/
\/__/\__\
    \/__/

Входные данные:

2\2

Выход:

  _____          
 /    /\         
/____/  \_____   
\    \  /    /\ 
 \____\/____/  \ 
 /    /\    \  /
/____/  \____\/ 
\    \  /        
 \____\/        

Входные данные:

1/3

Выход:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Конечные / ведущие пробелы в порядке.
  • Стандартные лазейки запрещены.
  • Вы можете предположить, что ввод всегда будет действительным.
  • Вы можете предположить, что ввод не вызовет слишком большой вывод, то есть: нет переноса строк при выводе вывода на терминал.
  • Размер куба и высота пирамиды положительны (т.е. ≥ 1)
  • Это код-гольф, поэтому выигрывает самый короткий код в байтах.

Текущий победитель:

Глен О с 270 байтами в юлии

вызов остается открытым. если ты побьешь текущий лучше, я обновлю принятый ответ.


2
Ваши кубы отличаются от тех, что были в недавних испытаниях с ромбовидным узором, в том, что в верхнем ряду подчеркивания 2 с + 1, тогда как у других испытаний подчеркивания 2 с в верхнем ряду и 2 с -1 в других рядах. Это означает, что ваш горизонтальный шаг составляет 3 с + 1. Я думаю, это хорошо, чтобы смешать вещи вокруг. Просто сделать наблюдение на случай, если кто-то пропустит это.
Уровень Река St

1
Каковы максимальные значения размера и высоты? мы можем предположить, что они одна цифра?
Уровень Река St

нет, вы не можете предполагать, что это одна цифра, но вы можете предположить, что предоставленный вход не приведет к тому, что выход будет слишком большим, то есть не вызовет перенос строки в вашем терминале.
Гилад Хох

Ответы:


3

Юлия - 503 455 369 346 313 270 байт

f=A->(t=47A;h='/'+45t;(m,n)=int(split(A,h));W=2m*n+1;X=(l=3m+1)n+m+1;s=fill(' ',X,W);s[end,:]=10;for i=1:n,j=i:n,M=1:m s[M+i*l+[[L=[J=(2j-i)m,J,J-m]+M W-L]X.-[l,m,0] [0 m].+[1,m,m].+[J,J+m,J-m]X-l]]=[1,1,1]*[h 139-h 95 s[i*l,i*m-m+1]=95]end;print((t?s:flipud(s))...))

Ungolfed:

function f(A)
  t=47A      # Determine if '/' is in A ('/' = char(47))
  h='/'+45t   # Set h to the appropriate slash ('\\' = char(92), 92=47+45)
  (m,n)=int(split(A,h)) # Get the two integers from A
  W=2m*n+1    # Get number of rows of output (vertical height of pyramid)
  X=(l=3m+1)n+m+1 # Get columns of output + 1 (for newlines)
  s=fill(' ',X,W) # Create 'canvas' of size X x W
  s[end,:]=10 # Put newlines at end of each output row
  for i=1:n, j=i:n, M=1:m
    # This is where the fun happens.
    # K and L represent the shifting points for '/' and '\\' in the
    # horizontal and vertical directions.
    # They are used to make the code neater (and shorter).
    K=M+i*l-[l,m,0]
    L=[J,J,J-m]+M
    # The next two assign the slashes to appropriate places
    s[K+L*X]=h
    s[K+(W-L)X]=139-h
    # This one puts the first 2m underscores in each of the underscore sets
    s[M+i*l-l+[0 m].+[1,m,m].+[J,J+m,J-m]X]=95
    # This places the final underscores on the top edges (repeatedly)
    s[i*l,i*m-m+1]=95
  end
  # The above produces the array orientation for backslash, but uses
  # the "wrong" slashes along the diagonals if there's a forward slash.
  # This line flips the matrix in that case, before printing it.
  print((t?s:flipud(s))...))
end

Использование:

f("3/2")

или

f("2\\3")

9

Perl, 343 байта

$_=<>;$_=~/(\d+)(\S)(\d+)/;$v=$2eq'/';$w=$1*3+1;for$y(0..$1*2*$3){$k=$w*$3+$1-1;for$z(0..$k){$x=$v?$k-$z:$z;$q=($y+$1-1)/$1|0;$r=$x/$w|0;$d=$q+$r&1;$f=($y-1)%$1;$f=$1-$f-1if$d;$g=($x-$f)%$w;$u=$r;$q=2*$3-$q+1,$u++if$q>$3;print(($q>=$r&&$q&&$g==0)||($q>$r&&$g==$w-$1)?$d^$v?'/':'\\':$q>=$u&&$y%$1==0&&$g>0&&$g<($w-$1+($q==$r))?"_":$")}print$/}

Многострочный с комментариями:

$_=<>;$_=~/(\d+)(\S)(\d+)/;$v=$2eq'/'; # read input
$w=$1*3+1; # compute width of each cube in chars
for$y(0..$1*2*$3){$k=$w*$3+$1-1;for$z(0..$k){ # iterate over rows, columns
    $x=$v?$k-$z:$z;   # flip x co-ordinate based on 2nd param
    $q=($y+$1-1)/$1|0;$r=$x/$w|0;   # parallelogram row and column index
    $d=$q+$r&1;  # flag parallelogram as left or right leaning
    $f=($y-1)%$1;$f=$1-$f-1if$d;  # compute a zig-zag offset
    $g=($x-$f)%$w;  # compute column position, offset by zig-zag
    $u=$r;$q=2*$3-$q+1,$u++if$q>$3; # vertical threshold for printing chars   
    print(($q>=$r&&$q&&$g==0)||($q>$r&&$g==$w-$1)?$d^$v?'/':'\\': # output slash
    $q>=$u&&$y%$1==0&&$g>0&&$g<($w-$1+($q==$r))?"_":$") # underscore or space
}print$/}   # print out newline at end of row

Пример вывода:

2/3
                _____  
               /\    \ 
         _____/  \____\
        /\    \  /    /
  _____/  \____\/____/ 
 /\    \  /    /\    \ 
/  \____\/____/  \____\
\  /    /\    \  /    /
 \/____/  \____\/____/ 
       \  /    /\    \ 
        \/____/  \____\
              \  /    /
               \/____/ 

Я также попытался реализовать ее как функцию C с использованием того же алгоритма, надеясь спасти байты от роскоши имен односимвольных переменных, но в итоге получилось на 15 байт больше, на 358 байт (необходимо скомпилировать с помощью -std=c89gcc, чтобы исключить voidв заголовке функции):

j(char*s){int c,p,v,x,y,k,z,u,g,w,r,d,q,f;char e;sscanf(s,"%d%c%d",&c,&e,&p);v=e=='/';w=c*3+1;for(y=0;y<=c*2*p;y++){k=w*p+c-1;for(z=0;z<=k;z++){x=v?k-z:z;q=(y+c-1)/c;r=x/w;d=q+r&1;f=(y+c-1)%c;if(d)f=c-f-1;g=(x-f)%w;u=r;if(q>p){q=2*p-q+1;u++;}printf("%c",(q>=r&&q&&g==0)||(q>r&&g==w-c)?d^v?'/':'\\':q>=u&&y%c==0&&g>0&&g<(w-c+(q==r))?'_':' ');}printf("\n");}}

Вы должны быть в состоянии получить большинство, если не все эти 15 байт обратно на версии C: printf("%c" --> putchar(, printf("\n") --> puts("")переместите все объявления INT вне функции, то вы можете устранитьint (см meta.codegolf.stackexchange.com/q/5532/15599 ), измените все символьные литералы для их кодов ascii, например ' ' --> 32. Рефакторинг циклов for, например, for(k+1;z--;)также может помочь, но сложнее.
Уровень Река Сент-

Также я думаю, что eможет быть int, если вы инициализируете его в ноль. sscanf будет перезаписывать только наименее значащий байт и может оставить любой существующий мусор в остальных трех байтах.
Уровень Река St

наконец, я думаю, что полная программа пойдет лучше, чем функция в этом случае. Вы получаете три дополнительных символа mainвместо, jно вам не нужно передавать параметр s, и вы можете воспользоваться автоматической инициализацией глобальных переменных.
Уровень Река Сент-

3

Рубин, 332

Пока что выполняется только игра в гольф - это удаление комментариев и отступов. Я буду в гольф позже.

gets.match(/\D/)
d=$&<=>"@"
n=$`.to_i
m=2*n
p=$'.to_i
a=(0..h=4*n*p).map{' '*h*2}
(p*p).times{|j|
x=h-j/p*(3*n+1)*d
y=h/2+(j/p-j%p*2)*n
if j%p<=j/p
(-n).upto(n){|i|
a[y+i][i>0?x+m+1-i :x-m-i]=?/
a[y+i][i>0?x-m-1+i :x+m+i]='\\'
a[y+n][x+i]=a[y-n][x+i]=a[y][x-d*(n+i-1)]=?_
a[y+i+(i>>9&1)][x+d*i.abs]='\_/'[(0<=>i*d)+1]
}
end
}
puts a

Я установил массив пробелов и вставил в него отдельные символы. Существует достаточно много перерисовок как одного куба поверх другого (работа снизу вверх), так и внутри самого куба, чтобы избежать лишнего кода. Я делаю пирамиду, рисуя ромб (аналогично /codegolf//a/54297/15599 ) и выделяя верхнюю половину.

Трудной частью было рисование масштабируемого куба. Я начал с шестиугольника по периметру с 2n + 1 _символами по горизонтали. У меня также было 2n + 1 /и \, таким образом, у меня было слишком много, но, нанося _последние, я перезаписывал их.

Внутренние линии - единственные, которые изменяются в зависимости от направления, к которому обращен куб. Я строю все /и \с одного задания. absпомогает изменить направление и i>>9&1добавляет 1 к отрицательным значениям i, что понижает верхнюю часть вниз. для i= 0 один из обязательных _переполнен, поэтому строка выбора '\_/'содержит все три символа, выбранных в соответствии со знакомi .

Пробелы вокруг вывода достаточно, но не чрезмерны: 4 * p * n в высоту и 8 * p * n в ширину (последний позволяет кубу вершины всегда быть в центре вывода.) Я понимаю "трейлинг / ведущий" пробелы ", чтобы включить целые строки, но может пересмотреть при необходимости.

Код без правил

gets.match(/\D/)                                   #find the symbol that is not a digit. it can be extracted from $&
d=$&<=>"@"                                         #direction, -1 or 1 depends if ascii code for symbol is before or after "@"
n=$`.to_i                                          #side length extracted from match variable $`
m=2*n
p=$'.to_i                                          #pyramid height extracted from match variable $'
a=(0..h=4*n*p).map{' '*h*2}                        #setup an array of h strings of h*2 spaces

(p*p).times{|j|                                    #iterate p**2 times
  x=h-j/p*(3*n+1)*d                                #calculate x and y coordinates for each cube, in a rhombus
  y=h/2+(j/p-j%p*2)*n                              #x extends outwards (and downwards) from the centre, y extends upwards 

  if j%p<=j/p                                      #only print the bottom half of the rhombus, where cube y <= cube x  
    (-n).upto(n){|i|                               #loop 2n+1 times, centred on the centre of the cube 
      a[y+i][i>0?x+m+1-i :x-m-i]=?/                #put the / on the perimeter of the hexagon into the array          
      a[y+i][i>0?x-m-1+i :x+m+i]='\\'              #and the \ also.
      a[y+n][x+i]=a[y-n][x+i]=a[y][x-d*(n+i-1)]=?_ #plot all three lines of _ overwriting the / and \ on the top line    
      a[y+i+(i>>9&1)][x+d*i.abs]='\_/'[(0<=>i*d)+1]#plot the internal / and \ overwriting unwanted _
    }
  end
}
puts a
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.