Треугольник Серпинского - это фрактал, созданный путем взятия треугольника, уменьшения высоты и ширины на 1/2, создания 3 копий получившегося треугольника и размещения их таким образом, чтобы каждый треугольник касался двух других по углу. Этот процесс повторяется снова и снова с полученными треугольниками для получения треугольника Серпинского, как показано ниже.
Напишите программу для генерации треугольника Серпинского. Вы можете использовать любой метод, который вы хотите сгенерировать, либо рисуя фактические треугольники, либо используя случайный алгоритм для генерации изображения. Вы можете рисовать в пикселях, в ascii art или как угодно, при условии, что результат будет похож на последний рисунок, показанный выше. Побеждает несколько персонажей.
Ответы:
HTML + JavaScript, 150 символов (см. Примечания для 126 символов)
Пробелы вставлены для удобства чтения и не учитываются.
Суть его заключается в применении правила раскраски пикселей, для которого
x & y == 0
по условиюx&y||
получается «прямоугольный треугольник Серпинского»; иx-~y/2,k-y
преобразование координат для получения приблизительно равностороннего отображения.Менее правильная (с точки зрения HTML) версия - 126 символов:
(Способ, которым это менее верно, состоит в том, что он пропускает
title
элемент и конечный тегcanvas
элемента, оба из которых требуются для правильного документа, даже если их пропуск не меняет интерпретацию документа.)Три символа могут быть сохранены путем исключения
k
в пользу константы64
за счет меньшего результата; Я бы не посчитал8
вариант, так как в нем недостаточно деталей.Обратите внимание, что размер 256 или выше требует атрибутов
<canvas>
для увеличения размера холста по умолчанию.источник
<canvas id=c>
и потомc.getContext
. Укоротить петли:for(x=k=128;x--;)for(y=k;y--;)
x&y?0:
можно заменить наx&y||
В противном случае хорошее решение.GolfScript (
4342 символа)Выход:
Измените «3» на большее число для большего треугольника.
источник
Python (234)
Максимальный гольф, крошечное изображение:
Требуется
python3-cairo
.Чтобы получить хорошее большое изображение мне понадобилось 239 символов.
источник
import cairo as c
что бы спасти вас от нескольких персонажейMathematica - 32 персонажа
Mathematica - 37 символов
Это создаст 2D таблицу с 0 и 1, где 1s рисуют треугольник Серпинского.
источник
ArrayPlot@CellularAutomaton[90, {{1}, 0}, 31]
илиMatrixPlot@CellularAutomaton[90, {{1}, 0}, 31]
.ReliefPlot@
...Python,
10186Использует правило 90 автомат.
Это длиннее, но красивее.
Редактировать: играть со строками напрямую, избавиться от неприятно длинных срезов, сделать вывод более красивым.
Выход:
источник
J
Не идеально, так как треугольник наклонен и сопровождается множеством пробелов - но, тем не менее, я подумал, что это интересно.
Выход:
Быстрое объяснение:
Глагол
(,~,.~)
- это то, что делает работу здесь. Это хук, который сначала,.
присоединяет аргумент к себе (o
->oo
), а затем добавляет исходный аргумент к выводу:становится
Этот глагол повторяется 6 раз,
^:6
и выходные данные каждой итерации становятся входными данными следующей итерации. Такстановится
который в свою очередь становится
и т. д. Затем я использовал косое наречие при добавлении,
,/.
чтобы прочитать строки по диагонали, чтобы выпрямить треугольник. Мне не нужно было этого делать, как указывает Рандомера . Я мог бы просто перевернуть|.
все, чтобы получить тот же результат. Даже лучше, я мог бы просто(,,.~)^:6,'o'
сохранить полностью обратный шаг.Ах, хорошо, вы живете и учитесь. :-)
источник
|.(,~,.~)^:6,'o'
короче и без лишних пробелов. А(,~,.~)^:6,1
также дает достойный вклад всего в 12 символов!APL (51)
Объяснение:
A←67⍴0
: A - вектор из 67 нулейA[34]←1
: 34-й элемент равен 1{...}A
: начиная с A, сделайте:~⊃⍵:
: если первый элемент текущей строки равен нулю⍵,∇
: добавьте текущую строку к ответу и повторите с:(1⌽⍵)≠¯1⌽⍵
: вектор, где каждый элемент является XOR своих соседей в предыдущем поколении⋄⍬
: иначе мы закончили32 67⍴
: отформатировать в матрице 67x321+
: добавьте единицу, чтобы выбрать правильное значение из массива символов' ○'[
...]
: вывести либо пробел (не являющийся частью треугольника), либо круг (если он является частью треугольника)Выход:
источник
Хаскелл (291)
Я не очень хорошо разбираюсь в гольфе.
Выход
solve 4
составляет:источник
QBasic 151 символов
В качестве примера, вот как это можно сделать в QBasic.
источник
Python (42)
Первоначально я хотел опубликовать несколько предложений по решению Boothbys (которое на самом деле использует правило 18 :), но у меня не было достаточно репутации, чтобы комментировать, поэтому я перешел к другому ответу. Поскольку он изменил свой подход, я добавил некоторые объяснения. Мои предложения были бы:
что привело бы к следующему коду (93 символа):
Но я оптимизировал дальше, сначала используя longint вместо целочисленного массива и просто печатая двоичное представление (75 символов):
И наконец, печатая восьмеричное представление, которое уже поддерживается интерполяцией printf (42 символа):
Все они напечатают:
Конечно, есть и графическое решение (131 символ):
: D
источник
x=8**31;exec"print'%o'%x;x^=x/8;"*32
8086 Машинный код - 30 байт.
ПРИМЕЧАНИЕ. Это не мой код, и его не следует принимать в качестве ответа . Я нашел это во время работы над другой проблемой CG для эмуляции процессора 8086 . Включенный текстовый файл относится к Дэвиду Стаффорду , но это лучшее, что я мог придумать.
Я публикую это, потому что это умно, коротко, и я подумал, что вы захотите это увидеть.
Он использует перекрывающиеся коды операций, чтобы упаковать больше инструкций в меньшем пространстве. Удивительно умный Вот машинный код:
Прямое декодирование выглядит так:
При запуске, когда происходит переход на 0x0115, обратите внимание, что он возвращается к 0x010C, прямо в середину предыдущей инструкции:
Brilliant! Надеюсь, вы, ребята, не возражаете, я поделюсь этим. Я знаю, что это не ответ сам по себе, но он представляет интерес для вызова.
Вот оно в действии:
источник
C
12711911610865В этом случае используется хитрость HTML-ответа, заключающаяся в
^ i & j
том, что для вывода симпатичных выходных данных потребуется еще 1 символ (вы можете получить действительно ужасный вывод, пожертвовавa^
).Чтобы сделать это довольно повернуть
(32^i&j)
к(32|!(i&j))
и повернуть его от++i<a
к++i<=a
. Однако тратить впустую символы на внешность кажется мне нелепым.Уродливый вывод:
Мне действительно нравится, как это выглядит. Но если вы настаиваете на том, чтобы это было красиво, вы можете состыковать четыре символа. Симпатичный выход:
Оставив старшие 108 символов, версия сотовых автоматов.
Так что я не думаю, что получу это намного короче, поэтому объясню код.Я оставлю это объяснение, так как некоторые уловки могут быть полезны.Некоторый вывод
источник
Код 80x86 / MsDos - 10 байт
В качестве кодировщика размеров, специализирующегося на очень маленьких вступлениях на MsDos, мне удалось создать программу, занимающую всего 10 байт.
в шестнадцатеричном виде:
в ассм:
Первой версией, которую я кодировал, была «Colpinski», которая имеет размер 16 байт и даже интерактивна, так что вы можете изменить цвет с помощью клавиатуры и мыши. Вместе с «Frag» - еще одним кодировщиком размеров - мы сократили его до 13 байт, что позволило создать 10-байтовую программу, которая содержит только базовую подпрограмму.
Это становится немного интереснее, когда вещи анимированы, поэтому я упомяну другую версию, Zoompinski 64 - пытающуюся имитировать точное поведение «Zoompinski C64» в 512 байтах - также для MsDos, размером 64 байта, как следует из названия.
Это можно оптимизировать до 31 байта, потеряв при этом элегантность, цвета и симметрию (исходные и исполняемые файлы доступны по ссылке выше)
Скачайте оригинал и комментируйте "Pouet"
источник
PostScript, 120 символов
Вывод Ghostscript:
Это рисует фигуру путем рекурсивного утроения того, что уже нарисовано.
Первым шагом является рисование линии. Строка сохраняется как пользовательский путь, затем пользовательский путь добавляется еще два раза после поворота на 120 градусов каждый раз.
[2 0 0 2 7 4]concat
перемещает «точку вращения» в центр следующего большого белого «центрального треугольника», который должен быть заключен в копии того треугольника, который у нас уже есть. Здесь мы возвращаемся к шагу 1 (создание upath, которое утроено вращением).Количество итераций контролируется первым числом в строке 3.
источник
J (9 знаков)
Без сомнения, вам действительно нужно щуриться, чтобы увидеть результат;)
производит вывод
Конечно, вы можете отобразить это графически:
источник
APL,
3732 (2823)Вертикальный треугольник (
3732 символа)объяснение
1 2⍴'/\'
: Создать матрицу символов 1 × 2/\
{((-1⌷⍴⍵)⌽⍵,∊⍵)⍪⍵,⍵}
: Функция, которая дополняет правый аргумент с обеих сторон пробелами, чтобы создать матрицу, удваивающую ширину, а затем ламинирует сам правый аргумент, удвоенный вниз.Например
/\
стал бы⍣⎕
: Повторить функцию (пользовательский ввод) раз.Пример вывода
Перекошенный треугольник (
2823 знака)Explaination
1 1⍴'○'
: Создать матрицу символов 1 × 1○
{(⍵,∊⍵)⍪⍵,⍵}
: Функция, которая дополняет правый аргумент справа пробелами, чтобы создать матрицу, удваивающую ширину, а затем ламинирует сам правый аргумент, удвоенный снизу.Например
○
стал бы⍣⎕
: Повторить функцию (пользовательский ввод) раз.Пример вывода
источник
Python (75)
Я опоздал на вечеринку на два года, но я удивлен, что никто еще не использовал этот подход
Использует продукт Kronecker для замены матрицы несколькими копиями самой себя.
Я мог бы сохранить два символа, используя
x=kron(x,x);x=kron(x,x)
в третьей строке, чтобы получить изображение 16x16 пикселей с тремя видимыми уровнями, или добавить еще один символ в итератор и в итоге получить изображение размером 2 ^ 16 x 2 ^ 16 = 4,3 гигапикселя и 15 уровней треугольника.источник
Логотип, 75 знаков
59 символов только для первой функции, вторая вызывает первую с размером и глубиной / числом итераций. Таким образом, вы можете просто вызвать первую функцию из интерпретатора с помощью команды: e 99 5 или любой другой размер, который вы хотите вывести
источник
to f
иend
вокругe 99 5
, у вас будет полная работоспособная программа с меньшим количеством символов. Кроме того, в UCBLogo (но не в других версиях) вы можете потерять двоеточия для переменных, чтобы сохранить больше символов.Matlab 56
источник
J (18 знаков)
Результат
источник
Питон (90 символов)
Попробуйте онлайн
Нарисуйте фрактальную линию заливки Серпинского треугольника
источник
ht();speed(0);up();goto(20-window_width()/2, 20-window_height()/2);down()
после импорта. Это запустит его намного быстрее и гарантирует, что вывод помещается на холст.Mathematica 67
Mathematica 92
источник
Mathematica , 29 байт
Тетраэдр Серпинского можно нарисовать аналогичным образом:
источник
J ,
3735 байт-2 байта благодаря FrownyFrog
Попробуйте онлайн!
Это художественная версия ascii Питера Тейлора, преобразованная в J. Могли бы сэкономить байты с менее симпатичной версией, но почему?
источник
@]^:[
->@[&0
и' /\ '
->' /\'
&0
описан трюк?,~
.Скрипт Lua на Golly , 54 байта
Golly - это симулятор сотовых автоматов с поддержкой сценариев Lua и Python.
Этот сценарий устанавливает правило для правила Вольфрама 60, устанавливает ячейку с (0,0) в 1 и выполняет 512 шагов.
источник
Постскриптум,
205203Переписать, используя строки, и рекурсия заканчивается с одинаковым счетом. Но ограничения глубины макроподхода преодолены.
Изменить:
fill
короче, чемstroke
.Отступы и комментарии.
Добавление
0 setlinewidth
дает лучшее представление о том, как глубоко это заходит.источник
APL (Dyalog Classic) , 12 байт
Попробуйте онлайн!
источник
Асимптота, 152 байта
Я добавлю это, в основном, потому что я видел более-менее нет ответов в асимптоте на этом сайте. Несколько потраченных впустую байтов для хорошего форматирования и обобщения, но я могу жить с этим. Изменение A, B и C изменит расположение углов содержащего треугольника, но, вероятно, не так, как вы думаете. Увеличьте число в неравенстве, чтобы увеличить глубину.
или негольфированный и читаемый
Таким образом, asymptote - это аккуратный язык векторной графики с несколько C-подобным синтаксисом. Весьма полезно для несколько технических диаграмм. Вывод, конечно, по умолчанию в векторном формате (eps, pdf, svg), но его можно конвертировать практически во все, что поддерживает imagemagick. Выход:
источник
Haskell ,
166154 байта(-12 байт, благодаря Laikoni, (понимание zip и списка вместо zipWith и lambda, лучший способ генерации первой строки))
Попробуйте онлайн!
Объяснение:
Функция
i#n
рисует ASCII-треугольник высоты2^n
послеi
шагов итерации.Используемое внутреннее кодирование кодирует пустые позиции как
1
и полные позиции как0
. Поэтому первая линия треугольника закодирована так же, как и[1,1,1..0..1,1,1]
с2^n-1
обеих сторон от нуля. Чтобы построить этот список, мы начнем со спискаx=1<$[2..2^n]
, то есть со списком,[2..2^n]
на который все сопоставлено1
. Затем мы строим полный список какx++0:x
Оператор
k!p
(подробное объяснение ниже), учитывая индекс строкиk
и соответствующий ей,p
генерирует бесконечный список следующих строкp
. Мы вызываем его с1
помощью стартовой линии, описанной выше, чтобы получить весь треугольник, а затем только первые2^n
строки. Затем мы просто печатаем каждую строку, заменяя ее1
пробелом и0
наM
(путем доступа к списку"M "
в местоположении0
или1
).Оператор
k!p
определяется следующим образом:Во- первых, мы создаем три версии
p
:1:p
что являетсяp
с1
префиксом,p
себя иtail p++[1]
что все , кроме первого элементаp
, с1
прилагается. Затем мы упаковываем эти три списка, давая нам эффективно все элементыp
со своими левыми и правыми соседями, как(l,m,r)
. Мы используем понимание списка, чтобы затем вычислить соответствующее значение в новой строке:Чтобы понять это выражение, нам нужно понять, что нужно рассмотреть два основных случая: либо мы просто расширяем предыдущую строку, либо мы находимся в точке, где начинается пустое место в треугольнике. В первом случае мы имеем заполненное пятно, если любое из соседних пятен заполнено. Это можно рассчитать как
m*l*r
; если любой из этих трех равен нулю, то новое значение равно нулю. Другой случай немного сложнее. Здесь нам в основном нужно обнаружение краев. В следующей таблице приведены восемь возможных окрестностей с результирующим значением в новой строке:Простая формула для получения этой таблицы будет
1-m*r*(1-l)-m*l*(1-r)
упрощена доm*(2*l*r-l-r)+1
. Теперь нам нужно выбрать между этими двумя случаями, где мы используем номер строкиk
. Еслиmod k (2^(n-i)) == 0
мы должны использовать второй случай, в противном случае мы используем первый случай. Таким0^(mod k(2^n-i))
образом, этот термин означает,0
что мы должны использовать первый случай и1
если мы должны использовать второй случай. В результате мы можем использоватьв общем - если мы используем первый случай, мы просто получаем
m*l*r
, а во втором случае добавляется дополнительный термин, давая общую суммуm*(2*l*r-l-r)+1
.источник
C 106 символов
(Меня до сих пор удивляет, что
puts("")
это самый короткий способ вывода новой строки в C.)Обратите внимание, что вы можете создать большие (или меньшие) прокладки, заменив тест
32
вfor
цикле на большую (меньшую) мощность, равную двум, при условии, что вы также замените33
середину наprintf()
степень двойки плюс один.источник