Нарисуйте шестиугольник ASCII со стороной n.
Для целого положительного числа \$n\$вывести шестиугольник ASCII с диагональной стороной \$n\$, как на фото (обратите внимание, что есть \$2n\$ _
символы на верхнем краю)
Примеры:
\$n = 1\$
__
/ \
\__/
\$n = 2\$
____
/ \
/ \
\ /
\____/
\$n = 5\$
__________
/ \
/ \
/ \
/ \
/ \
\ /
\ /
\ /
\ /
\__________/
и т.п.
Самый короткий код в байтах побеждает. Применяются обычные методы ввода / вывода .
Ответы
Холст , 15 9 байт
_;1*⁸/∔╬
Попробуйте здесь!
-6 байт после исправления программы.
Рисует четверть шестиугольника, и четырехугольник палиндромизирует.
Python 2 , 92 байта
k=n=input()
while 1:a=k^k>>n;print" "*a+"\/_"[k/n-2]+"_ "[-n<k<n]*2*(2*n+~a)+"\_/"[k/n];k-=1
Попробуйте онлайн!
Уголь , 14 байт
←×_θ↖θ→↗θ×_θ‖M
Попробуйте онлайн!
+1 байт исправление из ASCII-Only.
Рисует половину шестиугольника и отражает его.
C (gcc) , 119 109 байт
a,i,j;f(n){for(i=a+=a=j=n*2;~j;)putchar(!i--?i=a,j--,13:i%(n*3)<n|j%(n*2)?(i-~j-n)%a?(i-j+n)%a?32:92:47:95);}
Попробуйте онлайн!
- сэкономлено 2 благодаря @ceilingcat
Таблица ниже не обновляется, поэтому значения могут отличаться, но концепция такова:
- у нас есть 2 пары параллельных линий
. . _______.______.________ | / \ | . . | / \ | . . | / \ |. | / \ | | \ / |. . | \ / | . . | \ / | __ | ___ \ ________ / ___ | ___ | . .
мы выполняем итерацию x, y от размера до 0 и суммируем их, чтобы проверить, следует ли печатать /, вычитаем, чтобы проверить \, мы используем по модулю, чтобы проверить обе параллели.
я 65432109876543210. j i + jn ________ 8 13 + 7-4 => / \ 7 14 + 6-4 / \ 6 15 + 5-4 / \ 5 / \ 4 \ 1 + 3-4 => / 3 \ 2 + 2-4 / 2 \ 3 + 1-4 / 1 \ ________ / 0
Perl 5 ( -p
), 102 байта
s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$& /gm,s-( +)\\ -$&/ $1 \\ \\ $1 /
- for($\=' __ / \ \__/')x--$_}{
Попробуйте онлайн!
-p
и }{
в конце есть уловка, чтобы напечатать только разделитель выходной записи $\
в конце. Это работает только для одной входной записи; заголовок используется для печати всего в одной ссылке.
$\=' __
/ \
\__/' # output record separator initialized with hexagon (size 1)
s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$& /gm,s-( +)\\ -$&/ $1 \\ \\ $1 /
- # regexes to increase the hexagon by 1
for .. --$_ # to repeat n-1 times where n is the input
Haskell , 150 байт
r=reverse
m(o:c:k)=o:c:c:c:k++" "
f 1=[["\\ /","__ "],["/__\\"]]
f n|[w:i,j]<-map m<$>f(n-1),_:_:k<-r$m w=[r k:w:i,k:j]
h[i,j]=unlines$r<$>r i++j
h.f
Попробуйте онлайн!
Более рекурсивная версия этого ответа. Произвол этого вызова делает это довольно неприятным.
Объяснение
Этот ответ сложно объяснить. Проблема, как я уже сказал, произвольна в нескольких отношениях, поэтому код представляет собой своего рода набор символов.
Идея
Идея программы состоит в том, чтобы построить две половинки. То есть при вычислении n-го шестиугольника мы получаем две половины для n-1-го шестиугольника и используем их для создания следующей по величине.
Однако есть некоторые предостережения. Мы строим верхнюю половину в перевернутом виде и строим обе половинки зеркально слева направо. Мы делаем это потому, что так удобно. Нет веских причин, что это просто делает вещи короче, даже если это делает их немного непонятными.
подробности
Первая строка довольно прямолинейна r
- это псевдоним для reverse
. Вторая линия не так прямолинейна. m
- бессмысленная функция, она существует потому, что ее или аналогичную операцию нужно выполнить в нескольких местах. На самом деле это не имеет смыслового значения. Лучшее объяснение того, что он здесь делает, - это код.
m(o:c:k)=o:c:c:c:k++" "
Отсюда мы начинаем переходить к тому, f
что обрабатывает в основном всю логику. Первый случай f
- это базовый вариант, он довольно стандартный
f 1=[["\\ /","__ "],["/__\\"]]
Обратите внимание, что мы возвращаем список из двух элементов вместо кортежа. В любой разумной программе мы будем использовать кортеж, поскольку он состоит из двух элементов. Однако позже мы сопоставим оба аргумента this с той же функцией. Это сложно сделать с кортежем, но легко со списком, и список не имеет никаких недостатков, поэтому мы его используем.
Тогда у нас есть индуктивный случай. Сначала мы извлекаем предыдущий случай и дважды сопоставляем m
его. Это делает шестиугольник на 1 единицу шире (2 символа) и перемещает его на половину единицы (1 символ) вправо (хотя, поскольку все это происходит в обратном направлении, символы пробела добавляются справа ). Мы сопоставим это с шаблоном, [w:i,j]
потому что хотим использовать его w
для создания новых строк позже. Говоря о том, что дальше делаем ряды. Мы делаем это с сопоставлением с образцом:
_:_:k<-r$m w
Это вроде бредового кода. Он просто объединяет вещи, которые мы уже должны были произвести, чтобы получить правильный результат. k
и его обратная форма формируют новые строки, поэтому мы добавляем их. и возвращаем это.
После того, как f
у нас есть, h
который превращает вывод f
в строку. Он отменяет все дурацкие преобразования, которые мы использовали во время конструирования, и упаковывает их для использования.
При этом мы просто сочиняем f
и h
для финальной функции.
Haskell , 100 байт
f n=unlines[q<$>[1..3*n]++[1-n..0]|y<-[-n..n],let q x|abs y==n,x>n='_'|x==y='\\'|x+y==1='/'|1>0=' ']
Попробуйте онлайн!
Ответ AZTECCO на гольф плюс некоторые новые техники.
Основная идея в том, что шестиугольник проще, если первые n
столбики пересадить в конец.
|-|
______
/ \
/ \
/ \
\ /
\ /
\______/
|-|
______
\ /
\ /
\/
/\
/ \
______/ \
Теперь все /
и \
находятся в одной строке, а _
все слева от них. Это значительно упрощает реализацию стратегии AZTECCO по определению символа по координате. Чтобы реализовать эти перемаркированные координаты, мы заменяем x
-координаты [1..4*n]
на зацикленную и сдвинутую версию [1..3*n]++[1-n..0]
.
Retina 0.8.2 , 94 байта
.+
$* ¶$&$* \G ¶$%'/$`$%_$%_$`\
r` \G
$%`\$'$%_$%_$%'/¶ ^¶( *) $1 $.&$*_$.&$*_$& T` `\_` +/$
Попробуйте онлайн! Ссылка включает тестовые примеры. Пояснение:
.+
$* ¶$&$*
Вставьте два ряда n
пробелов.
\G
¶$%'/$`$%_$%_$`\
Преобразуйте первый ряд в верхние стороны шестиугольника.
r` \G
$%`\$'$%_$%_$%'/¶
Преобразуйте второй ряд в нижние стороны шестиугольника.
^¶( *)
$1 $.&$*_$.&$*_$&
Вставьте верхнюю строку.
T` `\_` +/$
Заменить нижнюю строчку.
Python 2 , 119 114 байт
i=n=input()
d=0
exec"k=i/n|d;print' '*i+'\_/'[~k]+'_ '[i-d<n]*2*(2*n+~i)+'\_/'[k]\nif i==d:d=i=-1\ni-=d|1;"*(n-~n)
Попробуйте онлайн!
JavaScript (ES6), 109 107 байт
w=>(x=0,W=w*4,i=g=y=>~y?`
/\\_`[x++-W?y*!i|w/x|x>w*3?(x+~y+w)%W?(x+y)%W-w?1:3:2:4:x=i=0&y--]+g(y):'')(w*2)
Попробуйте онлайн!
Прокомментировал
w => ( // w = input
x = 0, // initialize x to 0
W = w * 4, // W = total width
i = // initialize i to a non-zero value
g = y => // g is a recursive function taking y
~y ? // if y is not equal to -1:
`\n /\\_`[ // list of characters
x++ - W ? // if this is not the end of the row:
y * !i | // if this is neither the first nor the last row
w / x | // or x is less than or equal to w
x > w * 3 ? // or x is greater than w * 3:
(x + ~y + w) % W ? // if (x - y - 1 + w) mod W is not equal to 0:
(x + y) % W - w ? // if (x + y) mod W is not equal to w:
1 // draw a space
: // else:
3 // draw a '\'
: // else:
2 // draw a '/'
: // else:
4 // draw a '_'
: // else:
x = i = 0 & y-- // decrement y, set x and i to 0 and draw a linefeed
] + g(y) // append the result of a recursive call
: // else:
'' // stop the recursion
)(w * 2) // initial call to g with y = w * 2
С (gcc) , 194 \$\cdots\$ 149 144 байта
Сохранено 13 14 19 байт благодаря потолку !!!
p(n,c){for(;n--;)printf(L"/\\ _\n"+c);}i;t;f(n){p(n,2);for(i=t=p(2*n,3);i>=p(1,4);t=i/n?--i,1:t)i+=!p(!p(n+i<<!p(!p(n+~i,2),t),t&!i|2),!t)-2*t;}
Попробуйте онлайн!
Объяснение (перед гольфом)
p(n,c){for(;n--;) // Helper function to print
putchar("/\\ _\n"[c]);} // one of '/', '\', ' ', '_' , or
// newline n times, this function
// also returns 0
i;t;f(n){ // Main function prints an n hexagon
p(n,2); // Print n leading spaces for the 1st
// line
for( // Main loop
i=t=p(2*n,3); // Set i and t to 0,
// and print 2*n '_'s for the 1st line
i>=p(1,4); // Loop until i goes below 0, and
// print a newline
// At the end of each loop:
i+=1-2*t, // increment i for the 1st half
// and then decrement i in the 2nd
t=i/n?--i,1:t) // keep t as t unless i equals n,
// then make t 1 and decrement i
// In the main loop:
p(n+~i,2), // print n-i-1 leading spaces
p(1,t), // print a '/' in the 1st half and a
// '\' in the 2nd
p(n+i<<1,t&!i|2), // print the 2*(n+i) middle spaces
// unless at the bottom print '_'s
p(1,!t); // print a '\' in the 1st half and a
// '/' in the 2nd
}
05AB1E , 33 29 25 байт
-4 ( 7 ) байта благодаря Кевину Кройссену !
L+<'/úíºI·'_ך»∊¶¡`ðs‡).c
Попробуйте онлайн!
05AB1E имеет брезентовую встроенную команду , которая может оказаться полезной, но довольно сложно получить работу, это просто зеркало встроенных функций º
и ∊
и централизовать встроенный .c
.
J , 50 47 байт
-3 спасибо Ионе!
' \/_'{~]|."1((0,]+2*|.)@=@i.,.3,3,~0$~<:,])@+:
Попробуйте онлайн!
((0,]+2*|.)@=@i. ,. 3,3,~0$~<:,])@+:
0 0 0 0 3 3 3 3
1 0 0 2 0 0 0 0
0 1 2 0 0 0 0 0
0 2 1 0 0 0 0 0
2 0 0 1 3 3 3 3
]|."1
0 0 3 3 3 3 0 0
0 2 0 0 0 0 1 0
2 0 0 0 0 0 0 1
1 0 0 0 0 0 0 2
0 1 3 3 3 3 2 0
' \/_'{~
____
/ \
/ \
\ /
\____/
Python 3.8 (предварительная версия) , 174 байта
n=int(input())
b,a,s="\/ "
z,f=range(n),lambda c,d,t:((n-1-i)*s+c+2*(n+i)*s+d for i in t)
print(f"{'_'*2*n:^{4*n}}",*f(a,b,z),*f(b,a,z[:0:-1]),f"{b:>{n}}{'_'*2*n}/",sep="\n")
Попробуйте онлайн!
-1 байт благодаря @Duncan
-8 байт благодаря @Danis
Haskell , 129 120 байт
g=mod
f n|a<-n*4=[c|y<-[-n..n],x<-[0..a],let c|x<1='\n'|g x(n*3+1)>n,abs y==n='_'|g(x+y)a==1='/'|g(x-y)a<1='\\'|1>0=' ']
Попробуйте онлайн!
спасло 9 благодаря @Wheat Wizard и @xnor.
Проверьте ответ @xnor и его большое улучшение в подходе к проблеме (избегая по модулю и параллельных линий)!
Эквивалент моего ответа C
Мы составляем декартовы координаты, используя понимание списка | y <- [0..n * 2], x <- [0..a]
[c | ..., пусть c | ... | ... | ...] и мы выделили необходимый символ на основе xy или x + y для рисования линий.
Мы используем модуль для рисования нескольких линий (2).
Особый случай, _
когда не требуется соотношение осей / y, а требуется диапазон, мы используется по модулю, чтобы выполнить только одно сравнение >
вместо a> x> b, например
Ruby , 141 байт
->(n,g=->c,d{(1..n).map{|i|" "*(n-i)+d+" "*2*(n+i-1)+c}},l=g[?/,e=?\\].reverse){[" "*n+?_*n*2,g[e,?/],l[0..-2],l[-1].sub(/ +(?=\/)/,?_*n*2)]}
Попробуйте онлайн!
Если верхнее подчеркивание разрешено, то потребуется немного меньше байтов, а шестиугольник будет таким же красивым, как и раньше ;-)
Рубин , 114 байтов
->n{[" "*n+?_*2*n,(g=->c,d{(1..n).map{|i|" "*(n-i)+c+" "*2*(n+i-1)+d}})[?/,e=?\\],g[e,?/].reverse," "*n+?‾*n*2]}
Попробуйте онлайн!
05AB1E , 70 байт
ðש'_¹·×«©¶«©¹'/1Λ¹·Ì'.2Λ¹'\3.Λ«©„./`.;©¶¡Â‚€»`s'.ð:,¹3*>(£„._`:„/\‡,
Попробуйте онлайн!
Perl 5 , 143 байта
sub f{$n=pop;@b=map{join'',$"x($n-$_),'/',' 'x($n+$_-1),'\\',$/}1..$n;join('',$"x$n,$u=__ x$n,$/,@b,map y|/\\|\\/|r,reverse@b)=~s| +/$|$u/|sr}
Попробуйте онлайн!
sub f{
$n=pop; #n = input
@b=map{ #set array @b to line 2 - n+1
join'', #join parts into a line string
$" x ($n-$_), #space times n-1 '/', #char / ' ' x ($n+$_-1), #space times n+iterator minus 1 '\\', #char \ $/ #char newline
} 1..$n; #n lines join('', #return string of these joined: $" x $n, #n spaces $u = __ x$n, #n*2 underscores $/, #char newline
@b, #lines 2 to n+1 constructed above
map y|/\\|\\/|r, #and bottom part which is the same
reverse@b #as top part reversed and /\ rotated
)=~s| +/$|$u/|sr #and change last spaces of last line to _'s
}
Haskell ,
186
168 байт
-18 байт с исправлениями xnor и удалением ненужных пробелов в последней строке
s=' '
(!)=replicate
e=reverse
h n=unlines$(\m->(n!s++(2*n)!'_'++n!s):e(e<$>m)++init m++[(n-1)!s++'\\':(2*n)!'_'++"/"])$(\i->i!s++'\\':(4*n-2*i-2)!s++'/':i!s)<$>[0..n-1]
Попробуйте онлайн!
Без гольфа:
hex :: Int -> String
hex n = unlines $ first: middle ++ (init $ reverse (map reverse middle)) ++ [last]
where
first = replicate n ' ' ++ replicate (2*n) '_' ++ replicate n ' '
f i = replicate i ' ' ++ "/" ++ replicate (n-i + 2*n + n-i -2) ' ' ++ "\\" ++ replicate i ' '
middle = map f [n-1,n-2..0]
last = replicate (n-1) ' ' ++ "\\" ++ replicate (2*n) '_' ++ "/" ++ replicate (n-2) ' '