Плитка самолет с этим измененным кругом


22

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

Получив форму, вы можете разбить плоскость:

круг тесселяции

Я сделал это изображение с потрясающей 2D песочницей физики Algodoo !

Напишите программу, которая выводит изображение, похожее на это, в некотором распространенном формате файла изображений без потерь. Вы можете сохранить изображение в виде файла с выбранным вами именем или просто отобразить его. Вклад не должен быть взят.

Правила:

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

  • Радиус круга плиток должен быть не менее 32 пикселей. (Радиус на изображении выше составляет около 110 пикселей.)

  • Изображение должно быть не менее 4 плиток в ширину и 4 плитки в высоту. Это в сочетании с приведенным выше правилом означает, что изображения могут иметь минимальный размер 256 × 256 пикселей. (Изображение выше - 4 плитки на 4 плитки.)

  • Тесселяция может быть переведена на любую сумму. Например, верхний левый угол изображения не обязательно должен быть вершиной, в которой встречаются плитки. (Однако тесселяция не должна вращаться.)

  • Вы можете использовать внешние графические библиотеки, которые имеют команды для рисования кругов и вывода изображений и т.п.

  • Кривые действительно должны приближаться к окружности, как это можно сделать с помощью алгоритма окружности средней точки , что большинство графических библиотек сделает для вас.

  • Сглаживание по краям плитки разрешено, но не обязательно.

Самая короткая подача в байтах побеждает.

Ответы:


4

GS2, 49 байт

50 31 05 0d 1f 2a 48 0a 1e 2e 40 83 2c e8 64 2d
1e 73 ed 1e 33 40 20 30 9a a2 22 e8 e9 40 20 30
9a 30 40 20 30 ee 40 20 30 12 32 e9 12 32 55 e8
2b

Создает изображение PBM:

выход

Мнемоника:

# Print header
"P1" space 256 double
2dup new-line

# Make 1/4 circle
64 range dup cartesian-product
square m1 sum sqrt 64 >= m6
64 /

# Make tile
dup reverse + transpose
@2 not m1 m2
dup reverse + transpose
+

# Make quarter of image
dup reverse + z1
dup reverse +

# Loop
2 * m2
2 *

# Format
show-words m1
unlines

36

POV-Ray, 199 163

Old version
camera{location -9*z}light_source{-9*z}#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{X*x+x+Y*y,<.001*pow(-1,(X+Y)/2),0,.1>+X*x+x+Y*y,1}#end#end}object{L pigment{color x}}object{L rotate z*90}

Same output, but golfed down further by using default light/camera, so I dont even need to specify them
#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{<X+1,Y,9>,<.001*pow(-1,(X+Y)/2),0,.1>+<X+1,Y,9>,1}#end#end}object{L pigment{color rgb x}rotate z*90}object{L}

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

camera{location 9*z look_at 0}
light_source{9*z color 1} 
#declare L=union{
    #for(X,-9,9,2)
        #for(Y,-9,9,2)
            cylinder{<1+X,Y,0>,                                 //central axis, start
                     <1+X,Y,0> + <.001*pow(-1,(X+Y)/2), 0, .1>, //central axis, end
                      1}                                        //radius
        #end         
    #end
}                         
object{L pigment{color x}} // x is the <1,0,0> vector, here interpreted as RGB
object{L rotate<0,0,90>}

Очевидно, что происходит, когда мы увеличиваем смещение оси цилиндра и меняем перспективу

введите описание изображения здесь


1
Не будут ли края слегка искажены благодаря трехмерной перспективе?
orlp

6
При высоте 0.1и смещении 0.001диска оно наклоняется на $ \ phi = \ arctan (0.01) = 0.57 ° $, при взгляде сверху диски выглядят сжатыми с коэффициентом $ \ cos (\ phi) = 0.99995 $, это гораздо меньше, чем пиксель.
DenDenDo

@DenDenDo pov-ray не может поставить камеру на бесконечность?
Random832

@ Random832 это может, с camera{orthographic location -9z}. Но поскольку сцена в основном двумерная, это не имеет значения, вы даже можете визуализировать ее с просмотром angle 170без каких-либо искажений типа «рыбий глаз» в результате.
DenDenDo

11

Гнуплот, 182

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

set view map
set isosamples 900
f(x,y)=.3*sin(x*3.14)+y
splot(ceil(f(x,y))+ceil(f(y,x)))%2?1:NaN   #can only modulo integers

введите описание изображения здесь
Хотя это выглядит похоже, круги слишком квадратные. С той же идеей я заменяю sinкривой, составленной из конкатенированных дуг четвертого круга, и поворачиваю ее на 45 °, заменяя xи yна x+yиx-y

set view map
set samples 800
set isosamples 800
d=.5**.5
c(x,k)=(-1)**k*sqrt(1-(x-d*(1+2*k))**2)-(-1)**k*d  # k-th circle arc
# s(x)=c(x,floor(x/d/2))                           # circlified sinus
# f(x,y)=d*s(x/d)+y
f(x,y)=d*c(x/d,floor(x))+y                         # combined commented functions
splot(ceil(f(x+y,x-y))+ceil(f(x-y,x+y)))%2?1:NaN

введите описание изображения здесь


9

Без контекста, 99 байт

startshape d CF::Tile=[s 4]CF::Symmetry=CF::pmg,0,1,0path d{ARCTO(-1,1,1)ARCTO(1,1,-1)ARCTO(0,0,1)}

Вы можете увидеть результат в Context Free Gallery .


Хороший, это удивительное использование Context Free. :)
Мартин Эндер

7

HTML + JavaScript, 277

<canvas id=C></canvas><script>r=50,C.width=C.height=9*r,T=C.getContext('2d');
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)x=2*r*(i%8-2),y=2*r*(i>>3),T.moveTo(x,y+f*r),
T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),T.arc(x,y,r,0,P,f>0),T.arc(x-r,y+f*r,r,-f*P/2,0,f<0);
T.fill()</script>

Чтобы проверить, сохраните как HTML-файл и откройте с помощью браузера. Или еще, запустить фрагмент

r=50,C.width=C.height=9*r,T=C.getContext('2d')
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)
  x=2*r*(i%8-2),y=2*r*(i>>3),
  T.moveTo(x,y+f*r),
  T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),
  T.arc(x,y,r,0,P,f>0),
  T.arc(x-r,y+f*r,r,-f*P/2,0,f<0)
T.fill()
<canvas id=C></canvas>

Из-за широкого спроса, вот выходное изображение. Не так интересно, в конце концов ...

плитки


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

@ Calvin'sHobbies, ну, это достаточно быстро и работает в любом современном браузере. Вместо этого я
увеличу

Это правда. Я думал, что он использует =>как много ваших сообщений и будет работать только в Firefox. Но не стоит беспокоиться.
Увлечения Кэлвина

1
Лучшая причина для размещения изображения: эти фрагменты не очень хорошо работают на мобильных устройствах :(
Sp3000

6

IDL 8,3, 201 193 183 байта

Изображение выводится в графическое окно IDL; Я сделал скриншот ниже.

РЕДАКТИРОВАТЬ: благодаря @AlexA. и @ Sp3000 за помощь в бритье

p=!pi/99*[0:99]
q=p[49:0:-1]
o=p[99:50:-1]
window,xs=(ys=400)
for i=0,24 do cgpolygon,i mod 5*100+50*[cos(p),cos(q)-1,cos(o)+1],i/5*100+(-1)^i*50*[sin(p),sin(q)-1,sin(o)-1],/d,/fi
end

введите описание изображения здесь


6

Mathematica: 86 байтов (или 82 байта)

Спасибо бесконечной @alephalpha за умный метод на основе массива:

Image@ArrayFlatten@Array[DiskMatrix@32~RotateLeft~32/.a_/;OddQ@+##:>1-Thread@a&,{5,5}]

Внутри массива находится анонимная функция, которая использует хитрый трюк для добавления своих аргументов ( +##) и определения, является ли сумма нечетной. Это логическое значение используется в качестве условия для шаблона, который заменяет всю «белую» плитку на преобразованную «черную» плитку. Оттуда ArrayFlattenсоединяет плитки и Imageотображает их.

Обратите внимание на использование более коротких Threadдля замены Transpose. Мы все еще можем сохранить 4 байта, используя вместо этого символ транспонирования.

Предыдущий: 97 байт (или 90 байт)

Image@ArrayFlatten@Partition[
 Join@@Table[{#,1-Transpose@#}&@RotateLeft[DiskMatrix@32,32],{13}],5]

Вы можете уменьшить количество байтов, заменив Transpose@#символ superscript-t (кодовая точка U + F3C7, ярлык ESCtrESC). В UTF-8 это приносит до 90 байтов в 88 символов .

введите описание изображения здесь

Начнем с того DiskMatrix, что генерирует двоичную матрицу:

DiskMatrix@32 // Image

введите описание изображения здесь

Затем мы смещаем по кругу строки матрицы, чтобы получить элементарную ячейку для тайлинга:

RotateLeft[DiskMatrix@32, 32] // Image

введите описание изображения здесь

Если самолет шахматная доска, это «белые» квадраты. Для «черных» квадратов нам нужно инвертировать цвета и повернуть на 90 градусов. Мы можем инвертировать, вычитая из 1 ( 1 - 1 -> 0и 1 - 0 -> 1), и вращать, беря транспонирование:

Image /@ {#, 1 - Transpose@#} &@RotateLeft[DiskMatrix@32, 32]

введите описание изображения здесь

Если размеры изображения равны (как минимальный размер, 4), то плитка на правом краю будет такой же, как и следующая на левом краю. Однако добавление одной плитки для получения нечетного размера (5) и последующая конкатенация строк дает регулярный чередующийся шаблон.

Это говорит о том, что мы можем получить полное изображение, обернув один ряд чередующихся плиток с Partition. Мы используем, Tableчтобы составить список 13чёрно-белых пар плиток и Joinсгладить список пар до списка из 26 плиток. Тогда мы Partitionсписок в 5по 5матрице плитки ( Partitionотбрасывает отставая 26 - й плитку):

Map[Image] /@ 
  Partition[
   Join @@ Table[{#, 1 - #\[Transpose]} &@
      RotateLeft[DiskMatrix@32, 32], {13}], 5] // MatrixForm

введите описание изображения здесь

Наконец, ArrayFlattenпревращает матрицу матриц в плоскую матрицу и Imageотображает результат.

Предыдущая: 111 байт

Image[ArrayFlatten[{{#, #}, {#, #}}] &[
  Join[#, Reverse@#, 2] &[
   Join[1 - Transpose@#, #] &@RotateLeft[DiskMatrix[32], 32]]]]

введите описание изображения здесь


Image@ArrayFlatten@Array[RotateLeft[DiskMatrix@32,32]/.a_/;OddQ[+##]:>1-Thread@a&,{5,5}]
алефальфа

4

Java, 550 540 508 504 байта

Это Java-апплет.

import java.awt.*;public class T extends java.applet.Applet{int a=98,b=49,x,y;public void paint(Graphics g){for(x=0;x<5;x++)for(y=0;y<5;y++)a(g.create(x*a,y*a,a,a),x%2^y%2);}void a(Graphics g,int c){if(c>0){g.translate(a,0);((Graphics2D)g).scale(-1,1);}g.setColor(Color.red);g.fillRect(0,0,b,b);g.fillRect(b,b,b,b);g.setColor(Color.blue);g.fillRect(b,0,b,b);g.fillRect(0,b,b,b);g.fillArc(0,-b,a,a,180,90);g.fillArc(0,b,a,a,0,90);g.setColor(Color.red);g.fillArc(-b,0,a,a,0,-90);g.fillArc(b,0,a,a,90,90);}}

Дополнено шаблоном:

import java.awt.*;
public class T extends java.applet.Applet{
    int a = 98, b = 49, x, y; //Make these larger for better quality pictures. a = b * 2
    public void paint(Graphics g) {
        for (x=0; x < 5; x++)      //Make these larger for more tiles.
            for (y=0; y < 5; y++)  //
                a(g.create(x * a, y * a, a, a), x % 2 ^ y % 2);
    }

    void a(Graphics g, int c) {
        if (c > 0) {
            g.translate(a, 0);
            ((Graphics2D) g).scale(-1, 1);
        }
        g.setColor(Color.red);            //Change colors for nicer looking colors.
        g.fillRect(0, 0, b, b);
        g.fillRect(b, b, b, b);
        g.setColor(Color.blue);
        g.fillRect(b, 0, b, b);
        g.fillRect(0, b, b, b);
        g.fillArc(0, -b, a, a, 180, 90);
        g.fillArc(0, b, a, a, 0, 90);
        g.setColor(Color.red);
        g.fillArc(-b, 0, a, a, 0, -90);
        g.fillArc(b, 0, a, a, 90, 90);
    }
}

Апплет: небольшая прикладная программа, которую можно вызывать для использования во время работы в другом приложении.

Пример изображения:

введите описание изображения здесь

Объяснение:

Это работает с использованием метода для печати каждой плитки. Перед созданием метода ему предоставляется графический объект, который использует систему координат с центром в верхнем левом углу каждой плитки:

Для создания плитки мы используем следующий метод:

void a(Graphics g, int c) {
    g.setColor(Color.red);
    g.fillRect(0, 0, b, b);
    g.fillRect(b, b, b, b);
    g.setColor(Color.blue);
    g.fillRect(b, 0, b, b);
    g.fillRect(0, b, b, b);
    g.fillArc(0, -b, a, a, 180, 90);
    g.fillArc(0, b, a, a, 0, 90);
    g.setColor(Color.red);
    g.fillArc(-b, 0, a, a, 270, 90);
    g.fillArc(b, 0, a, a, 90, 90);
}

Тем не менее, каждая другая плитка должна быть отражена горизонтально, чтобы получить правильное изображение.

Чтобы отразить плитку, мы просто модифицируем предоставленный graphicsобъект следующим кодом:

g.translate(a, 0);
((Graphics2D) g).scale(-1, 1);

Спасибо @CoolGuy за 4 байта.


1
Вы можете xyint a = 98, b = 49,x,y;
играть в

4

Mathematica 299 256

Словно, но это было приятно выяснить.

Базовая плитка - это r (показано ниже), которая является областью, отображаемой RegionPlot. Отражение плитки влево-вправо производится и соединяется с помощью r. Затем собранная фигура из двух плиток повторяется для разбиения пространства.

р

a_~f~b_ := (x + a)^2 + (y + b)^2 <= 1;
a = ImageAssemble;
r = RegionPlot[(0~f~0 && y <= 0 && ! f[-1, 1]) \[Or] (0~f~2 && 
      y >= -2 && ! f[1, 1]), {x, -1, 1}, {y, -2, 0}, Frame -> False,
    BoundaryStyle -> None];
s = ImageCrop@Rasterize@r;
t = s~ImageReflect~Right;
i = a@{s, t};
j = a@{t, s};
a@{k = {i, i, i, i}, m = {j, j, j, j}, k, m, k, m}

плитка


1

C 237 209 180 байт

180 байт Эта версия включает изменения, предложенные edc65 в комментарии. Это дает 9 предупреждений компилятора при сборке на Mac с clang и параметрами по умолчанию:

a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}

209 байт, используя некоторые предложения из комментариев Мартина. Компилируется без предупреждений с помощью clang:

#include <stdio.h>
int a,b,c,d,x,y;int main(){puts("P1 256 256");for(;b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c<256;++c)putchar(48+(x*x+y*y<962^b==d));puts("");}}

Оригинальная версия, 237 байт:

#include <stdio.h>
int main(){puts("P1 256 256");for(int a=0;a<256;++a){int b=a+32&64;for(int c=0;c<256;++c){int d=c+32&64;int x=(a&64)-d?31-a&31:a&31;int y=(c&64)-b?c&31:31-c&31;putchar(48+(x*x+y*y<962^b==d));}puts("");}}

Результат (256x256):

введите описание изображения здесь

Оригинальный код с пробелами для лучшей читаемости:

#include <stdio.h>
int main()
{
    puts("P1 256 256");
    for (int a = 0; a < 256; ++a)
    {
        int b = a + 32 & 64;
        for (int c = 0; c < 256; ++c)
        {
            int d = c + 32 & 64;
            int x = (a & 64) - d ? 31 - a & 31 : a & 31;
            int y = (c & 64) - b ? c & 31 : 31 - c & 31;
            putchar(48 + (x * x + y * y < 962 ^ b == d));
        }
        puts("");
    }
}

При этом не используется никакая графическая библиотека, рендеринг полностью содержится в коде.

Основная идея состоит в том, чтобы просто зациклить все 256x256 пикселей и посмотреть, находятся ли они внутри / снаружи дуги окружности квадрата 32x32, в котором они находятся. Нижние 5 битов общих координат пикселя определяют относительные координаты пикселя в пределах подкв. Внутренний / внешний тест (x, y)нахождения внутри дуги с радиусом rявляется стандартным:

x * x + y * y < r * r

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

Некоторые комментарии к решению:

  • Код генерирует изображение в формате PBM ASCII. Я загрузил результат в GIMP и скопировал и вставил в Paint, чтобы создать файл, который я разместил здесь. Таким образом, формат был преобразован, но содержимое точно соответствует исходному результату.
  • Если вы посмотрите внимательно, вы можете заметить, что качество не очень хорошее. Это связано с тем, что внутренний / внешний расчет выполняется для угла пикселя, а не для центра пикселя, в результате чего все это происходит на 1/2 пикселя. Я не думаю, что это будет очень трудно сделать лучше, но это сделает код несколько длиннее. И поскольку не было конкретных требований к качеству, я считаю, что этого достаточно.
  • Код был скомпилирован с использованием clang на Mac. Последняя версия выдает предупреждения, первоначальная версия - нет.
  • Это первый раз, когда я пробовал один из них, поэтому я пропустил несколько трюков, чтобы сохранить последний возможный байт.

3
Добро пожаловать в PPCG! Я не большой гольфист, но я думаю, что вижу некоторые улучшения: группируйте свои объявления как int a,b,c,d,x,y;... Я думаю, что вы даже можете просто сделать, main(a,b,c,d,x,y)я помню что-то, что тип по умолчанию - int. Как только вы избавитесь от этого, вы можете переместить назначения в d, x и y во внутреннюю forинструкцию приращения, например d=c+32&64,...,++c(возможно, даже переместить ++в другое место, где вы упомянули в cлюбом случае), и затем вы можете опустить скобки внутренний for. Хорошая работа, кстати! :)
Мартин Эндер

Благодарность! Я видел трюк с объявлением аргументов без типов в списке советов, но это казалось настолько грязным, что я не мог заставить себя пойти туда. ;) Я не думаю, что наличие нестандартных аргументов для main()стандартного соответствия. Я, безусловно, должен сгруппировать декларации. И перемещение приращений также сэкономит пару байтов. Символ puts()новой строки находится во внешнем цикле, поэтому я не уверен, смогу ли я избавиться от скобок.
Рето Коради

Обычно мы согласны с этим, если он компилируется в каком-то обычном компиляторе (поэтому он не должен быть полностью стандартным C). Также, да, я не думаю, что вы можете избавиться от внешних скобок, но вы должны быть в состоянии удалить внутренние.
Мартин Эндер

Получил до 210 байт. Спасибо за идеи.
Рето Коради

1
Подсказки: stdioне нужны, используйте объявление функции по умолчанию. intиспользуется по умолчанию для глобальных переменных и может быть опущено (переменные и основные). Сначала putsможно зайти внутрь. c var не используется во внутреннем цикле, поэтому приращение в условии. 180: a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}(компилируется со многими предупреждениями, но запускается)
edc65
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.