ASCII Art Octagons


22

Учитывая входное целое число n > 1, выведите восьмиугольник в стиле ASCII с длинами сторон, состоящими из nсимволов. Смотрите примеры ниже:

n=2
 ##
#  #
#  #
 ##

n=3
  ###
 #   #
#     #
#     #
#     #
 #   #
  ###

n=4
   ####
  #    #
 #      #
#        #
#        #
#        #
#        #
 #      #
  #    #
   ####

n=5
    #####
   #     #
  #       #
 #         #
#           #
#           #
#           #
#           #
#           #
 #         #
  #       #
   #     #
    #####

and so on.

Вы можете распечатать его в STDOUT или вернуть как результат функции.

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

Правила и ввод / вывод

  • Вход и выход могут быть заданы любым удобным способом .
  • Вы можете использовать любой печатный символ ASCII вместо #(кроме пробела), но символ "фона" должен быть пробелом (ASCII 32).
  • Либо полная программа или функция приемлемы.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

1
Можем ли мы использовать разные выходные символы или они должны быть согласованными?
Emigna

@Emigna Разные персонажи в порядке.
AdmBorkBork

Ответы:


22

05AB1E , 3 байта

7ÝΛ

Попробуйте онлайн!

объяснение

      # implicit input as length
      # implicit input as string to print
7Ý    # range [0...7] as directions
  Λ   # canvas print

Посмотрите этот ответ, чтобы понять холст 05AB1E.


Конечно, это должно быть 5 байтов? Или вызовы кода в гольф рассматривают байты и символы как взаимозаменяемые
Даг

3
@Doug: Это 3 байта в кодовой странице
05ab1e

О, круто! Спасибо за ссылку на документы!
Дуг

> :( Черт, Аднан
только для ASCII

11

JavaScript (ES6), 114 106 105 104 103 байт

n=>(g=x=>v=x*2>w?w-x:x,F=x=>~y?`# 
`[~x?(h=g(x--))*g(y)>0&h+v!=n|n>h+v:(y--,x=w,2)]+F(x):'')(y=w=--n*3)

Попробуйте онлайн!

Как?

Это создает выходной символ за символом.

Учитывая вход n , мы вычисляем:

n=n1w=3n

Для каждого символа в (x,y) мы вычисляем (h,v) :

h=w/2|xw/2|v=w/2|yw/2|

Ячейки, принадлежащие восьмиугольнику, удовлетворяют одному из следующих условий:

  • ( h=0 ИЛИ v=0 ) И h+vn (красным цветом внизу)
  • h+v=n (оранжевым цветом ниже)

Например, при n=4n=3 ):

(0,0)(1,0)(2,0)(3,0)(4,0)(4,0)(3,0)(2,0)(1,0)(0,0)(0,1)(1,1)(2,1)(3,1)(4,1)(4,1)(3,1)(2,1)(1,1)(0,1)(0,2)(1,2)(2,2)(3,2)(4,2)(4,2)(3,2)(2,2)(1,2)(0,2)(0,3)(1,3)(2,3)(3,3)(4,3)(4,3)(3,3)(2,3)(1,3)(0,3)(0,4)(1,4)(2,4)(3,4)(4,4)(4,4)(3,4)(2,4)(1,4)(0,4)(0,4)(1,4)(2,4)(3,4)(4,4)(4,4)(3,4)(2,4)(1,4)(0,4)(0,3)(1,3)(2,3)(3,3)(4,3)(4,3)(3,3)(2,3)(1,3)(0,3)(0,2)(1,2)(2,2)(3,2)(4,2)(4,2)(3,2)(2,2)(1,2)(0,2)(0,1)(1,1)(2,1)(3,1)(4,1)(4,1)(3,1)(2,1)(1,1)(0,1)(0,0)(1,0)(2,0)(3,0)(4,0)(4,0)(3,0)(2,0)(1,0)(0,0)


Вау, это круто! Я думаю, что можно упростить до h + v > n , хотя я не уверен, поможет ли это вообще логике игры в гольф. h+vnh+v>n
Джузеппе

@Giuseppe Это действительно может быть упрощено, если оба условия были проверены. Но в коде случаи и h v 0 разделены. Однако на самом деле я тестирую противоположное условие ( n > h + v ), которое уже на 1 байт короче. hv=0hv0n>h+v
Арно

@Giuseppe Ваш комментарий побудил меня поближе взглянуть на формулу, и я наконец сохранил байт, написав его немного по-другому. :)
Арно

1
хех, хорошо, ваш комментарий о побудил меня пойти посмотреть на мой порт вашей логики и сохранить еще пару байтов! hv=0
Джузеппе



4

R , 122 117 115 байт

function(n){n=n-1
m=matrix(0,y<-3*n+1,y)
v=t(h<-(w=3*n/2)-abs(row(m)-1-w))
m[h*v&h+v-n|h+v<n]=' '
write(m,1,y,,"")}

Попробуйте онлайн!

Переносит логику из ответа Арно , в частности, это пересмотр на случай дальнейших улучшений. Еще 2 байта сэкономлено благодаря предложению Арно об изменении логики!


-2 байта , делая это наоборот (я не могу сделать h*v&h+v-nв JS, потому что &это побитовый оператор; но это логический оператор в R, так что это работает).
Арно

@ Арнаулд спасибо!
Джузеппе



3

Powershell, 91 байт

param($n)($s=' '*--$n+'#'*$n+'#')
--$n..0+,0*$n+0..$n|%{' '*$_+"#$(' '*(3*$n-2*$_+2))#"}
$s

2

PowerShell , 107 97 байт

param($n)($z=$n-1)..1+,0*$n+1..$z|%{" "*$_+"#"+($x=" "*($z-$_))+(" ","#")[!($_-$z)]*($n-2)+"$x#"}

Попробуйте онлайн!

Если бы был дешевый способ изменить первый тайм, этот ответ был бы намного лучше. Он строит левую половину, затем ядро ​​(или x, #'sили пробелы), а затем отражает логику левого, чтобы сделать правое. Забавный факт, вам не нужно копировать конечный пробел.

Развернул и объяснил:

param($n)
($z=$n-1)..1 + ,0*$n + 1..$z |%{  #Range that repeats 0 n times in the middle
" "*$_ + "#" +($x=" "*($z-$_)) +  #Left side
(" ","#")[!($_-$z)]*($n-2) +      #Core that swaps when it's the first or last row
"$x#"}                            #Right side which is left but backwards

2

C (лязг) , -DP=printf( -DF=for(i + 179 = 199 180 байт

i;*m="%*s%*s\n";g(n){P"%*s",n,H;F;--i;)P H;P"\n");}f(n){g(n);F;--i;)P m,i,(H,3*n-i+~i,H;F-2;i--;)P"#%*s\n",3*n-3,H;F;--i;)P m,n-i,(H,n+i+i-1,H;g(n);}

Попробуйте онлайн!

Ungolfed:

f(n){
	int i;
	printf("%*d",n,0);
	for(i=0;i<n-1;i++){
		printf("0");
	}
	printf("\n");
	for(i=1;i<n;i++){
		printf("%*d%*d\n",n-i,0,n+i+i-1,0);
	}
	for(i=0;i<n-2;i++){
		printf("0%*d\n",n+n+n-3,0);
	}
	for(i=n-1;i>0;i--){
		printf("%*d%*d\n",n-i,0,n+i+i-1,0);
	}
	printf("%*d",n,0);
	for(i=0;i<n-1;i++){
		printf("0");
	}
}

-19 байт благодаря @ceilingcat



1

Python 2 , 130 байт

def f(n):
 a=[' '*~-n+n*'#']
 b=[' '*(n-i-2)+'#'+' '*(n+2*i) +'#'for i in range(n-2)]
 return a+b+['#%*s'%(3*n-3,'#')]*n+b[::-1]+a

Попробуйте онлайн!

На мобильном, поэтому не невероятно играли в гольф.


Вы можете удалить пространство после (n+2*i).
Захари

1

Пакет, 260 байт

@echo off
set s=
for /l %%i in (1,1,%1)do call set s= %%s%%
echo %s% %s: =#%
call:c %1,-1,3
for /l %%i in (1,1,%1)do echo   #%s:~2%%s%%s:~2%#
call:c 3,1,%1
echo %s% %s: =#%
exit/b
:c
for /l %%i in (%*)do call echo %%s:~,%%i%%#%%s:~%%i%%%s%%%s:~%%i%%#

Выводит два пробела в каждой строке. Объяснение: Пакет не имеет оператора повторения строк, ограничена возможность нарезки строк и требует отдельных операторов для выполнения арифметики. Поэтому было лучше всего составить строку входной длины в пробелах (Пакет может, по крайней мере, перевести их в #s для верхней и нижней линий), а затем вырезать из или в определенную позицию в диапазоне от 3 до длины, чтобы получить диагонали (это то, чего достигает последняя строка скрипта).



1

Красный , 171 байт

func[n][c:(a: n - 1)* 2 + n
b: collect[loop c[keep pad/left copy"^/"c + 1]]s: 1x1 s/1: n
foreach i[1x0 1 0x1 -1x1 -1x0 -1 0x-1 1x-1][loop a[b/(s/2)/(s/1): #"#"s: s + i]]b]

Попробуйте онлайн!

Объяснение:

Red[]
f: func [ n ] [
    a: n - 1                                         ; size - 1
    c: a * 2 + n                                     ; total size of widht / height 
    b: collect [                                     ; create a block
        loop c [                                     ; composed of size - 1 rows
            keep pad/left copy "^/" c + 1            ; of empty lines of size c (and a newline)
        ]
    ]
    s: a * 1x0 + 1                                   ; starting coordinate
    foreach i [ 1x0 1 0x1 -1x1 -1x0 -1 0x-1 1x-1 ] [ ; for each offset for the 8 directions
        loop a [                                     ; repeat n - 1 times  
            b/(s/2)/(s/1): #"#"                      ; set the array at current coordinate to "#"
            s: s + i                                 ; next coordinate
        ]        
    ]
    b                                                ; return the block 
]

1

APL (Dyalog Unicode) , 46 байтов SBCS

(' '@~5 6∊⍨1⊥⊢∘,)⌺3 3⊢<(⍉⌽⌊⊢)⍣2∘(∘.+⍨∘⍳¯2+3×⊢)

Это решение было предоставлено Adám - спасибо!

Попробуйте онлайн!

Мое (почти) оригинальное решение:

APL (Dyalog Unicode) , 61 байт SBCS

(((⊃∘' #'¨1+5∘=+6∘=)⊢)1⊥⊢∘,)⌺3 3⊢<(((⊖⌊⊢)⌽⌊⊢)(∘.+⍨(⍳¯2+3×⊢)))

Попробуйте онлайн!

Спасибо Адаму за помощь!

Идея состоит в том, чтобы найти «ромб», который частично лежит в квадрате, и применить фильтр обнаружения краев, чтобы «очертить» восьмиугольник.



1
Вы не можете использовать Классический здесь из-за . Скорее считайте 1 байт / символ, ссылаясь на SBCS в соответствии с мета .
Адам

@ Adám Спасибо! Я не знаю, как редактировать заголовок, вы можете сделать это для меня?
Гален Иванов

Что вы имеете в виду, редактируя заголовок?
Адам

1
Отредактируйте и скопируйте отсюда .
Адам

1

Perl 5, 201 197 188 187 186 байт:

$a=<>;$b=3*$a-4;$c='$"x($e-$_)."#".$"x$f."#\n"';$e=($b-$a)/2+1;$d=$"x$e."#"x$a.$/;$f=$a;print$d,(map{(eval$c,$f+=2)[0]}1..$a-2),("#".$"x$b."#\n")x$a,(map{$f-=2;eval$c}reverse 1..$a-2),$d

Попробуйте онлайн!

Читает размер восьмиугольника из первой строки STDIN.


Добро пожаловать в PPCG! Вероятно, вы можете сбрить несколько байтов здесь и там, используя приемы, описанные в этом посте .
Мего

@Mego Да. Я смог сохранить 4 байта, используя $"вместо " ".
Натан Миллс

1

Perl 5, 176 байт

$f=$a=<>;$b=3*$a-4;$c='$"x($e-$_)."#".$"x$f."#\n"';$e=$a-1;$d=$"x$e."#"x$a.$/;print$d,(map{(eval$c,$f+=2)[0]}1..$a-2),("#".$"x$b."#\n")x$a,(map{$f-=2;eval$c}reverse 1..$a-2),$d

Основано на ответе Натана Миллса выше (у меня недостаточно репутации, чтобы комментировать!).

$eможно упростить до $a-1экономии 6 байт; $fможет быть назначен цепочкой; сохранение двух байтов; Не уверен, откуда двое других!

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

Ungolfed:

$f = $a = <>;
$b = 3 * $a - 4;
$c = '$"x($e-$_)."#".$"x$f."#\n"';
$e = $a - 1;
$d = $" x $e . "#" x $a . $/;
print $d, ( map { ( eval $c, $f += 2 )[0] } 1 .. $a - 2 ),
  ( "#" . $" x $b . "#\n" ) x $a,
  ( map { $f -= 2; eval $c } reverse 1 .. $a - 2 ), $d




0

Perl 5, 170 168 166 байт

$a=<>-1;$\="#\n";print$x=$_=$"x$a."#"x$a;if(s/^( *)  #*/$1 #  $1 /){print}while (s/ #/#  /){print}$z=$_;for(1..$a){print$_=$z}while(s/#  (\s{$a})/ #$1/){print}print$x

Это работает с помощью магии регулярных выражений. «Если» необходимо только для решения патологического случая n = 2, который в противном случае выдает что-то вроде:

 ##
 ##
#  #
 ##

вероятно, это можно закодировать.

Я думаю, что можно получить гораздо больше, создав строку до середины, а затем перевернув ее. Конечно, тогда нам нужно вставить / удалить дополнительный пробел, если n нечетно (или использовать thin-space: p).

Ungolfed

$a = <> -1;                          # Subtracting one is very useful! 
$\ = "#\n";                          # Every line ends with a '#' let perl provide.  
$x=$_ = " " x $a. "#" x $a;          # The horiz line (one short)  
print;                               # print it plus the extra #
if(s/^( *)  #*/$1 #  $1 /){print}    # create a hole and remove a leading space(if n=2 this fails)
while (s/ #/#  /){                   # make the hole bigger      
    print;                           # and print (with a trailing #)
}
$z=$_;                               # store $_ for later use
for (1 .. $a) {                      # nice that we don't have to do 2..$a but not golf-nice  
  $_ =$z;                            # restore $_ (we could use $z but since we have
  print;                             # to restore somewhere, doing  it here saves us bytes)
}
while (s/#  (\s{$a})/ #$1/){         # now move the # to the right and reduce the trailing spaces  
  print;
}
print $x;                            # and finish...

Я думаю, что это, вероятно, может быть немного больше, помимо значительных изменений, таких как подталкивание $@и печать в конце.

[Гольф-поля вокруг ..и перемещение печати до назначения в двух случаях, экономя на точках с запятой.]


сэкономил 20 байт, переупорядочив некоторые инструкции TIO , почему, \sа не просто пробел в последнем регулярном выражении
Науэль Фуйе


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