Обкладіть площину цим модифікованим колом


22

Візьміть одиничне коло з центром походження. У будь-яких двох сусідніх квадрантах віддзеркалюйте криву кола по лініях, що з'єднують перехоплення кола x і y.

Отриманою формою можна плитку викласти:

коло теселяції

Я зробив це зображення з дивовижною двовимірною пісочницею з фізики 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}

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

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
Чи не будуть краї трохи спотворені завдяки 3d-перспективі?
orlp

6
З висотою 0.1та зміщенням 0.001диска нахиляється $ \ phi = \ arctan (0,01) = 0,57 ° $, дивлячись зверху диски здаються стисненими на коефіцієнт $ \ cos (\ phi) = 0,99995 $, це набагато менше пікселя.
DenDenDo

@DenDenDo поп-промінь не може поставити камеру в нескінченність?
Випадково832

@ Random832 може, з camera{orthographic location -9z}. Але оскільки сцена в основному 2D, це не має ніякої різниці, ви можете навіть відтворити її при перегляді 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на кривій , отримані з зчеплених quartercircle-дуг і повернути її на 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

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



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; Я зробив знімок екрана нижче.

EDIT: завдяки @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

Математика: 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@#символ супер-сценарію-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

Ява, 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

Wordy, але це було приємно зрозуміти.

Основна плитка - r (показано нижче), що є регіоном, відображеним RegionPlot. Ліво-праве відбиття плитки робиться і з'єднується з r. Потім дві фігури, зібрані плиткою, повторюються, щоб укласти плитку в простір.

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 із параметрами кланг та типовими параметрами:

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 байт, використовуючи деякі пропозиції з коментарів Мартіна. Компілюється без попереджень з клангом:

#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("");
    }
}

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

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

x * x + y * y < r * r

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

Деякі коментарі до рішення:

  • Код формує зображення у форматі PBM ASCII. Я завантажив результат у GIMP і зробив копію та вставлення в Paint, щоб генерувати фактичний файл, який я розмістив тут. Тож формат був перетворений, але вміст точно такий, як вихідний вихід.
  • Якщо ви придивитесь уважніше, ви можете помітити, що якість не велика. Це пояснюється тим, що обчислення внутрішньої та зовнішньої сторони робиться для кута пікселя, а не піксельного центру, і це спричиняє вимкнення 1/2 пікселя. Я не думаю, що зробити це краще, але це зробить код дещо довшим. А оскільки конкретних вимог до якості не було, я вважаю, що цього достатньо.
  • Код був складений за допомогою clang на Mac. Остання версія дає попередження, початкова версія - ні.
  • Це перший раз, коли я робив спробу одного з них, тому, мабуть, пропустив кілька хитрощів, щоб зберегти останній можливий байт.

3
Ласкаво просимо до PPCG! Я не великий гольфіст на C, але, думаю, я можу побачити декілька вдосконалень: згрупуйте свої декларації на кшталт 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. Гарна робота, btw! :)
Мартін Ендер

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

З нами зазвичай це нормально, поки він збирається в якомусь звичайному компіляторі (тому це не повинно бути повністю стандартним С). Також так, я не думаю, що ви можете позбутися від зовнішніх брекетів, але ви повинні вміти видаляти внутрішні.
Мартін Ендер

Знизив його до 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.