Фрактальные точки на линии


12

Иногда, когда мне очень скучно ( очень скучно), мне нравится рисовать отрезок линии и рисовать на нем точки.

Сначала я рисую отрезок линии определенного размера, который равен 2 ^ N для некоторого значения N. Линия будет представлена ​​серией .символов.

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

Затем я рисую точку на левом конце. Точки будут представлены Xсимволами.

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

Затем я следую шаблону. Начиная с самой последней нанесенной точки (которую я назову A), я перехожу к следующей нанесенной точке (B) на линии (при необходимости оборачиваясь). Затем я перехожу к следующей нанесенной точке на линии (С). Затем я строю новую точку на полпути между этой третьей точкой (C) и следующей уже нанесенной точкой (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

Python 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 короче, чем его вычисление. Divmod будет сохранять символ внутри цикла do. Часть, которая кажется наиболее расточительной, - это выходная конверсия, но я не вижу, как ее улучшить.



2

Ява, 209 207 195 191 байт

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

Это возвращает 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 байта благодаря ТНТ;)


(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 ( d) с новым, начинающимся с (c+d)/2и повторяюсь. Я останавливаюсь, когда (c+d)/2равняется c. Наконец, я добавляю a 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

Mathematica, 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.