Фрактальний собор


22

Давши додатне ціле число n >= 1, виведіть перші nрядки наступної структури:

   #
  # #
  ###
 #   #
 # # #
 ## ##
 #####
#     #
#  #  #
# # # #
# ### #
##   ##
## # ##
### ###
#######

n-Й 1-індексований рядок є двійковим поданням n, дзеркальним без копіювання останнього символу, з #замість 1 і <space>замість 0. Всіх рядків центруються.

Ви повинні виводити як ASCII-art, але ви можете використовувати будь-який символ, що не пробіляє, замість того, де я використовую #в прикладі. Доступний пробільний пробіл, а також можливий останній рядок. Вихід повинен виглядати як приклад, а не зайвих провідних пробілів або провідних нових рядків.

Перші 1023 ряди фрактального собору ви можете переглянути тут .

Щоб генерувати більші тестові випадки, ось реалізація непрограшних посилань у Python


Хороша ідея. Я б не здогадувався, що двійкові числа дають таке гарне мистецтво в ассії.
Іона

@Jonah Спасибі :) Радий, що вам це подобається
HyperNeutrino

7
Обидві ланки вказують на створений собор.
Otávio

@ Otávio: Я
виправлю

Відповіді:


6

MATL , 10 байт

:B2&Zv35*c

Спробуйте в Інтернеті!

Пояснення

:      % Implicitly input n. Push range [1 2 ... n]
B      % Convert to binary. Gives a matrix where each row corresponds to
       % a number. Rows have left-padding zeros if needed
2      % Push 2
&Zv    % Symmetrize along sepecified dimension (2nd means horizontally),
       % without repeating the last element
35*    % Multiply by 35 (ASCII code for '#')
c      % Convert to char. Char 0 is shown as space. Implicitly display

1
Цікаво, чи було б корисно додати якийсь вбудований, який відповідає множенню на 35, а потім перетворенню на char. Здається, його часто використовують
Conor O'Brien

@ ConorO'Brien Він використовується часто, так. Але це буде двоярусна вбудована система, тому виграшу не буде
Луїс Мендо

Ніякої вигоди? 35*cце 4 символи
Conor O'Brien

@ ConorO'Brien Ах, ти маєш на увазі 35фіксовану? Це здається трохи специфічним. З іншого боку, деякі виклики дозволяють отримати будь-яке завдання, тому це може бути хорошою ідеєю. Як ви вважаєте, #це найпоширеніше?
Луїс Мендо

2
Для довідки ця функція була реалізована (функція Zc, з символом 35, тобто #). Дякую, @ ConorO'Brien!
Луїс Мендо



3

Python 2 , 92 байти

n=input()
for x in range(n):s=bin(2**len(bin(n))/4+x+1)[3:].replace(*'0 ');print s+s[-2::-1]

Спробуйте в Інтернеті!

У Python 3 s=f'{x+1:0{len(bin(n))-2}b}'.replace(*'0 ')він коротший, але int(input())паролі навколо printаргументу підштовхують його до 95 байт.


Це моя копія :) (але розумне використання у 2**len(bin(n))/4будь-якому разі)
Ерік Вигнавець

3

JavaScript (ES6), 106 байт

Використовується 1як символ без пробілу.

f=(n,k=0)=>k++<n?[...Array(32-Math.clz32(n))].reduce((s,_,i)=>(c=k>>i&1||' ')+s+(i?c:''),'')+`
`+f(n,k):''

Демо

Альтернативна версія (однаковий розмір)

Без Math.clz32():

f=(n,a=[k=i=0])=>n>>i+1?f(n,a,a[++i]=i):k++<n?a.reduce((s,i)=>(c=k>>i&1||' ')+s+(i?c:''),'')+`
`+f(n,a):''

1
Дуже хороша! Перший раз я бачив Math.clz32- я навіть не знав, що воно існує!
Birjolaxew

@Birjolaxew Так, це доповнення ES6. Це стає корисним раз у раз.
Арнольд

3

Лушпиння , 21 20 18 байт

Дякуємо @Zgarb за те, що ти граєш на 2 байти!

S↑(tfS=↔ΠR" #"←DLḋ

Спробуйте в Інтернеті!

Безголів / пояснення

Щоб уникнути тривалого набивання, це визначає ширину фрактала, яка задається як 2*len(bin(N))-1і генерує всі послідовності такої довжини із символами#,_ ("_" позначає пробіл).

Оскільки декартові сили генеруються в порядку і двійкові числа теж, це добре. Все, що нам потрібно зробити, щоб отримати фрактал в цій точці, - це фільтрувати всі паліндроми, і це в основному це:

                    -- implicit input N
S↑(                 -- take N from the following list
        ΠR" #"      --   Cartesian power of [" #"] to
                Lḋ  --     number of bits in bin(N)
               D    --     2*
              ←     --     -1
    fS=↔            --   filter out palindromes
   t                --   drop the first line (all spaces)

1
Ṙ;може бути справедливим R, і ȯнепотрібним. Гарна ідея відповіді!
Згарб

2

Математика, 94 байти

Column[Row/@Table[s=IntegerDigits[i,2];Join[s,Reverse@Most@s]/.{0->" ",1->"#"},{i,#}],Center]&

2
Я теж повинен поїхати ...
J42161217

2

Математика, 98 байт

Riffle[Nest[ArrayFlatten@{{0,#,0},{1,0,1},{1,#,1}}&,{1},⌊Log2@#⌋]~Take~#"#"/. 0->" ","
"]<>""&

Спробуйте це в пісочниці Wolfram ! І три байта кожен.

Це інший підхід від інших відповідей поки що, використовуючи фрактальну природу візерунка. Ключовим кроком є ​​те ArrayFlatten@{{0,#,0},{1,0,1},{1,#,1}}&, що робиться фрактально, найкраще пояснюється у формі зображення:

                 [    ]
                 [grid]
[    ]           [    ]
[grid]   --->   #      #
[    ]          #[    ]#
                #[grid]#
                #[    ]#

Код повторює цей крок достатньо разів, щоб отримати принаймні n рядків, а потім обрізає зайві рядки і добре відображає його.




2

C # (.NET Core) , 192 178 байт 168 + 23

дякую TheLethalCoder за допомогу.

x=>new int[x].Select((_,z)=>Convert.ToString(z+1,2).PadLeft((int)Math.Log(x,2)+2).Replace('0',' ')).Aggregate((y,z)=>y+"\n"+z+new string(z.Reverse().Skip(1).ToArray()))

Спробуйте в Інтернеті!

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


Ласкаво просимо до PPCG! На даний момент ця відповідь є лише фрагментом коду. Це можна виправити, додавши x=>в число байтів і зауваживши, що вам не потрібно включати крапку з двокрапкою. Enumerable.Range(1,x).Select(zкоротше як new int[x].Select((_,z)(я думаю, що це правильно). Коли ви використовуєте Linq, ви повинні включити using System.Linq;до свого числа байтів. Ви також використовуєте, Mathтому вам слід включити using System;або повністю кваліфікувати його. Зауважте, що це потім коротше, ніжnamespace System.Linq{}
TheLethalCoder

Вам не потрібно включати ,' 'в PadLeftдзвінок, оскільки пробіл є за замовчуванням.
TheLethalCoder


@TheLethalCoder вибачте за незручності, це тепер виправлено.
Dennis.Verweij

Не хвилюйтесь +1 від мене, це приємна відповідь :)
TheLethalCoder

1

Вугілля деревне , 28 байт

A…·¹NθW⌈θ«Eθ§ #κ↓⸿AEθ÷κ²θ»‖O

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

A…·¹Nθ

Створіть список перших nнатуральних чисел.

W⌈θ«

Повторюйте, поки всі елементи не дорівнюють нулю.

Eθ§ #κ

Друкуйте останню двійкову цифру кожного елемента списку у вигляді або #.

↓⸿

Перехід до попереднього стовпця.

AEθ÷κ²θ

Розділіть усі елементи списку на два.

»‖O

Once the left half has been drawn, reflect it.


Current versions of Charcoal have MapAssignRight(IntDivide, 2, q); which saves 3 bytes.
Neil

1

J, 29 bytes

' #'{~(],}.@|.)"1@(#.^:_1)@i.

Try it online!

explanation

  • i. integers up to n, the input
  • (#.^:_1) converted to base 2
  • (],}.@|.) row by row ("1 does that part), take the binary number (] is the identity fn), and cat it (,) with its reverse (|.), where the reverse is beheaded (}.).
  • ' #'{~ converts the 1s and 0s to hashes and spaces.

You can use #.inv instead of #.^:_1.
Conor O'Brien

@ConorO'Brien, thanks, wasn't aware of that.
Jonah

Isn't this off by one? For n = 1, you print nothing. Anyways, you can shave off a few bytes with a few changes like so ' #'{~(,|.@}:)"1@#:@:>:@i. (if you're allowed to be off by one you can remove 4 more bytes). Basically, use a hook because it performs just like a fork when the left tine is ] and use the built-in #: which AFAIK is about the same as #.inv. EDIT: I figure my answer is similar enough to warrant being a comment, let me know if you think it should be an answer of its own.
cole

@cole, thanks! i'll update it a bit later. i thought i'd tried #: and it didn't work, but i must be remembering wrong because you're right that it does.
Jonah

@Jonah you may have tried 2 #: which will only get the right-most digit. Monadic #: functions just like #.inv (or #.&:_1). This differs from dyadic #:, which only gives as many digits as there are atoms in its left argument.
cole

1

Proton, 95 bytes

r=>{for i:range(1,r)print(((bin(i)[2to]).rjust(len(bin(r))-2)[to-1,to by-1]).replace('0',' '))}

Try it online!

There are too many bugs to not have too many brackets... I need to fix up the parser...



1

PHP, 98 97 95 94+1 bytes

while($r++<$argn)echo$s=strtr(sprintf("%".-~log($argn,2).b,$r),0," "),substr(strrev("
$s"),1);

Run as pipe with -nR or try it online. Uses 1 as non-whitespace.


sorry to spoil it, but something is wrong here. output for $argn=1 and $argn=3 is not correct, and $argn is 0-based (specified was 1-based)
Felix Palmen

1
@FelixPalmen fixed. The incorrectness was caused by the wrong base. Thanks for noticing.
Titus




0

C (gcc), 146 108 105 bytes

#define o putchar(33-!(c&(1<<n)))
b;c;p(n){--n?o,p(n),o:o;}f(n){while(n>>++b);while(c++<n)p(b),puts("");}

Try it online!

This is a function f(n) called with the number of rows n, using an exclamation mark (!) as non-whitespace character.

Explanation:

#define o putchar(33-!(c&(1<<n)))
b;c;
p(n)
{
    // least significant bit not yet reached?
    --n?
            // print bit twice with recursive step between
            o,
            p(n),
            o
        // for least significant, just print this bit
        :o;
}

// the main "cathedral function":
f(r)
{
    // determine max number of bits to shift
    while(r>>++b);

    // iterate over rows
    while(c++<r)

        // print row recursively
        p(b),

        // newline
        puts("");
}

/**
 * footer, just calling the function
 */
main(int argc, char **argv)
{
    f(atoi(argv[1]));
}

Suggest --n&&o+p(n);o; instead of --n?o,p(n),o:o; and for(;c++<n;puts(""))p(b); instead of while(c++<n)p(b),puts("");
ceilingcat

0

JavaScript (Node.js), 156 149 bytes

-7 bytes by @ConorO'Brien

f=(n,w=n.toString(2).length,b=n.toString(2).replace(/0/g," "),s=" ".repeat(w-b.length))=>`${--n?f(n,w)+s+b+[...b].reverse().join``.substr(1):s+"1"}
`

Try it online!

Recursive function. Unfortunately JS does not support reversing a string, so 19 bytes are used on turning it into an array and back.


1
You can use [...b] instead of b.split(""); you can also use .join``.substr(1) instead of .join("").substr(1); finally, I think you can use s+1 instead of s+"1"
Conor O'Brien

0

Perl 5, 77 + 1 (-n) = 78 bytes

$x=1+(log$_)/log 2;map{$_=sprintf"%0${x}b",$_;y/0/ /;say$_.chop.reverse}1..$_

Try it online!

Using '1' instead of '#' because it saves a couple bytes.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.