Фрактальні точки на лінії


12

Іноді, коли мені дуже нудно ( дуже нудно), мені подобається малювати відрізок лінії і малювати на ній точки.

По-перше, я малюю відрізок рядка певного розміру, який становить 2 ^ N для деякого значення N. Рядок буде представлений рядом .символів.

................

Потім я накреслюю крапку в лівому кінці. Очки будуть представлені Xсимволами.

X...............

Потім я слідую за схемою. Починаючи з останньої наміченої точки (яку я зателефоную A), я переходжу до наступної накресленої точки (B) на лінії (обертаючись по мірі необхідності). Потім я переходжу до наступної наміченої точки на лінії (С). Потім я будую нову точку на півдорозі між цією третьою точкою (С) та наступною вже наміченою точкою (D).

Щоразу, коли ви обмотуєтеся навколо лінії, "середина" визначається в обгортальному порядку. Щойно намічена точка завжди знаходиться праворуч від C.

Скажімо, що наступний рядок був моїм поточним рядком. Ось як я побудував би наступні два моменти. У цьому прикладі я позначу кожну важливу точку листом.

X...A...X.X...X.
    ^

X...A...B.X...X.
        ^

X...A...B.C...X.
          ^

X...A...B.C...D.
            ^

X...X...X.X.A.X.
            ^

X...X...X.X.A.B.
              ^

C...X...X.X.A.B.
^

C...D...X.X.A.B.
  ^

X.A.X...X.X.X.X.
  ^

Повертаючись до попереднього прикладу, наступна точка буде побудована в середині рядка.

X.......X.......

Це, мабуть, трохи особливий випадок: перехід до наступної точки просто залишає вас там, де ви почали. Єдиною корисною точкою на півдорозі є "циклічна" точка на півдорозі (точка на півдорозі на лінії), на відміну від побудови точки над собою.

Нижче наводиться низка точок, які я побудував би на лінії звідси до кінця.

X.......X.......
X.......X...X...
X.......X.X.X...
X...X...X.X.X...
X...X...X.XXX...
X.X.X...X.XXX...
X.X.X...XXXXX...

Більше немає місця для побудови наступної точки, оскільки це повинно було би бути вклеєне між двома сусідніми точками, тому я досяг максимальної глибини для заданого значення N = 4. Останній рядок у наведеному вище списку "завершений . "

Змагання

Мета - написати найкоротшу програму / названу функцію, яка буде друкувати / повертати завершений рядок за заданим значенням N. Наведене вище показує N = 4.

Вхідні дані

Вхід буде одним невід’ємним цілим числом N. Довжина згенерованого рядка буде 2 ^ N.

Вихідні дані

Вихід буде завершена лінією довжиною 2 ^ N, утворена .і Xсимволи. Зворотний новий рядок не має значення.

Приклад вводу / виводу

0
X

1
XX

2
X.XX

3
X.X.XXX.

4
X.X.X...XXXXX...

5
X.X.X...X...X...X.XXX.XXX.......

Відповіді:


4

Пітон 2, 137

n=input()
l=[0]*2**n;i=0
while~i%2:i=i/2%2**n;l[i]=1;i=sum([k for k,v in enumerate(l*4)if(k>i)*v][1:3])
print''.join(['.X'[x]for x in l])

Досить прямо.

Піта, 49

Більш-менш переклад. Основна відмінність полягає в тому, що я не використовую список, що представляє рядок, я використовую рядок.

J*\.^2QW!%Z2K%/Z2lJ=JXJK\X=Zs<tf&q\X@JT>TKU*4J2)J

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

                         Q=input(); Z=0 #implicit
J*\.^2Q                  J = "."*(2^Q)
W!%Z2                    while !(Z%2):
  K%/Z2lJ                  K=(Z/2)%(len(J))
  =JXJK\X                  change J, the point at index K is changed to a "X"
       f          U*4J     filter all elements T in [0, 1, 2, ..., 4*len(J)-1]:
        &q\X@JT>TK           where J[T]=='X' and T>K
     <t               2    only us the second and third element
  =Zs                      and store the sum to Z
)J                       end while and print J


3

GolfScript (61 байт)

~2\?,[]0{.@|$4*.@?2+1$>2<.+~<!4$,*++.2/\1&!}do;`{&!'X.'1/=}+%

Кількість необхідних ітерацій циклу, здається, становить A061419 , але цикл do-циклу коротший, ніж для обчислення. Дивмод врятував би діаграму всередині циклу do. Частина, яка вважає себе найбільш марною, - це конверсія на виході, але я не бачу, як її покращити.



2

Java, 209 207 195 191 байт

Я здивований, що мені вдалося розібратися в цьому стислі. Напевно, ще є можливість для вдосконалення. Як завжди, пропозиції будуть оцінені :)

Це повертає a char[]. Дзвінок за допомогою a(n).

char[]a;int b,c,d,e=2;char[]a(int f){java.util.Arrays.fill(a=new char[b=1<<f],'.');for(a[0]=88;d+1<e;c=(d+e)/2,a[c%b]=88)e=b(d=b(b(c)));return a;}int b(int f){for(;;)if(a[++f%b]>87)return f;}

Відступ:

char[] a;
int b, c, d, e = 2;

char[] a(int f){
    java.util.Arrays.fill(
            a = new char[
                    b = 1 << f
                    ]
            , '.'
    );
    for(
            a[0] = 88;
            d + 1 < e;
                c = (d + e) / 2,
                a[c % b] = 88
        )
        e = b(
                d = b(
                        b(c)
                )
        );
    return a;
}

int b(int f){
    for (;;)
        if (a[++f % b] > 87)
            return f;
}

12 байт завдяки Петру :)
4 байти завдяки TNT;)


(c%b+b)%b? Чи очікуєте ви cнегативу?
Пітер Тейлор

c=0і d=0може бути скорочений до справедливого cі d. intтипи, визначені на рівні класу, автоматично ініціалізуються до 0.
TNT

1

Haskell, 182 байт

(a:b)%(c:d)|a<c=a:b%(c:d)|1<2=c:(a:b)%d
f i=putStr$map(!(0:g[0,n..]))[0..n-1]where n=2^i;e!l|e`elem`l='X'|1<2='.';g(_:_:c:d:r)|m==c=[]|1<2=mod m n:g((d:r)%[m,m+n..])where m=div(c+d)2

Використання: f 5. Вихід: X.X.X...X...X...X.XXX.XXX........

На жаль, Haskell не має функції злиття в стандартних бібліотеках, тому я повинен надати свій власний (-> %). На щастя, мені доводиться об'єднувати лише нескінченні списки, тому мені не доведеться висвітлювати базові випадки, тобто порожні списки. Він досі коштує 40 байт.

Як це працює: замість того, щоб встановлювати Xs безпосередньо в масиві, я зберігаю список позицій, де вони знаходяться. Більше того, я не обертаюсь, 2^Nале продовжую збільшувати позиції до нескінченності (наприклад, для N = 2 з Xфронтом, список позицій виглядає так [0,4,8,12,16,20,…]). Я беру 3-й і 4-й елемент ( cі d), обчислюю нову позицію (c+d)/2, зберігаю її для списку вихідних даних, об'єдную старий список позицій з позиції 4 (the d) на нову, починаючи з (c+d)/2і повторюючись. Я зупиняюся, коли (c+d)/2дорівнює c. Нарешті я додаю а 0до списку вихідних даних і друкую Xs на заданих позиціях та .інших місцях.

step by step example, N=2

step  position list       (c+d)/2  output     lists to merge (pos. list for next round)
                                   list       old list from d on / new list from (c+d)/2

  #1  [0,4,8,12,16,…]       10     [10]          [12,16,20,24,…] / [10,14,18,22,…]
  #2  [10,12,14,16,18,…]    15     [10,15]       [16,18,20,22,…] / [15,19,23,27,…]
  #3  [15,16,18,19,20,…]    18

stop here, because c equals (c+d)/2

add 0 to the output list: [0,10,15]
take all elements modulo 2^N: [0,2,3]
print X at position 0, 2 and 3 

1

Математика, 110 102 112 108

a=Array["."&,n=2^Input[]];a[[Mod[Round@{n/2,n}//.{x_,y_,z___}/;y-x>1:>{z,x+n,(x+y)/2+n,y+n},n]+1]]="X";""<>a
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.