Побудуй мені піраміду


16

Вам потрібно побудувати піраміду з кубиків. Кубики можна переглянути з двох кутів:

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

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

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

Приклади:

Вхід:

1/1

Вихід:

 ___
/\__\
\/__/

Вхід:

1\1

Вихід:

 ___
/__/\
\__\/

Вхід:

2/1

Вихід:

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

Вхід:

1/2

Вихід:

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

Вхід:

2\2

Вихід:

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

Вхід:

1/3

Вихід:

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

Поточний переможець:

Глен О з 270 байтами в Джулії

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


2
Ваші кубики відрізняються від останніх викликів з алмазним малюнком тим, що у верхньому ряду є підкреслення 2s + 1, а в інших викликах підкреслення 2s у верхньому рядку та 2s-1 в інших рядах. Це означає, що ваш горизонтальний крок 3s + 1. Я думаю, що добре змішати речі навколо. Просто робити спостереження у випадку, якщо хтось пропустить його.
Рівень річки Св.

1
які максимальні значення розміру та висоти? чи можна вважати, що вони є однією цифрою?
Рівень річки Св.

ні, ви можете не вважати, що це одна цифра, але ви можете припустити, що наданий вхід не призведе до того, що результат буде занадто великим, тобто не спричинить загортання рядків у вашому терміналі.
gilad hoch

Відповіді:


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))...))

Безголівки:

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=c89під gcc, щоб залишити 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(k+1;z--;)може також допомогти, але складніше.
Рівень річки Св.

Також я думаю, що eможе бути int за умови, що ви ініціалізуєте його до нуля. sscanf буде замінено лише найменш значущий байт і може залишити будь-яке наявне сміття в інших трьох байтах.
Рівень річки Св.

нарешті, я думаю, що в цьому випадку повна програма піде краще, ніж функція. 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.