Створити послідовність SUDSI


15

Послідовність SUDSI ( su m, d ifference, s wap, i ncrement) є цікавою цілою послідовністю, яка, схоже, демонструє досить хаотичну поведінку. Його можна генерувати наступним чином:

Нехай S нескінченний список натуральних чисел: 1 2 3 4 5 6 .... Нехай S я позначаю один індексований я й елемент S . Отже, спочатку S 1 дорівнює 1, S 2 - 2 і т.д. (немає S 0 ).

Починаючи з S 1 і S 2 ...

  • Обчисліть їх суму: sum = S1 + S2
  • Обчисліть їх абсолютну різницю (більша мінус менша): diff = |S1 - S2|
  • Поміняйте два значення на S на показники суми та різниці:swap(Ssum, Sdiff)

  • Збільшення індексів S, з яким ви працюєте. Отже, наступного разу ви обчислите суму і різницю S 2 і S 3 , а час після цього буде S 3 і S 4 і т.д.

  • Повторіть цей процес нескінченно.

Ось перші кілька етапів S під час застосування цього процесу. Дужки []оточують два значення, які підлягають підсумовуванню та різниці.

Оригінальний S :

[1 2] 3 4 5 6 7 8 9 10 11 12 ...

Після того, як S 3 ( 3 = 1 + 2) і S 1 ( 1 = |1 - 2|) поміняються місцями:

3 [2 1] 4 5 6 7 8 9 10 11 12 ...

Після того, як S 3 і S 1 поміняються місцями:

1 2 [3 4] 5 6 7 8 9 10 11 12 ...

Після того, як S 7 і S 1 поміняються місцями:

7 2 3 [4 5] 6 1 8 9 10 11 12 ...

Після того як S 9 і S 1 поміняються місцями:

9 2 3 4 [5 6] 1 8 7 10 11 12 ...

Після того, як S 11 і S 1 поміняються місцями:

11 2 3 4 5 [6 1] 8 7 10 9 12 ...

Після того, як S 7 і S 5 будуть замінені:

11 2 3 4 1 6 [5 8] 7 10 9 12 ...

тощо.

Послідовність SUDSI визначається як послідовність перших елементів у кожному з цих списків. Отже, перші кілька термінів послідовності SUDSI є 1 3 1 7 9 11 11.

Ось перші 200 термінів послідовності SUDSI (20 на рядок):

1 3 1 7 9 11 11 11 15 15 19 19 19 19 19 19 19 19 19 19 
19 19 19 19 19 19 19 19 57 59 59 59 59 59 59 59 59 59 77 79 
81 83 85 87 89 91 91 91 91 91 91 91 91 91 91 91 91 91 115 115 
121 123 125 127 127 127 127 127 137 139 141 143 145 147 147 147 147 147 147 147 
147 147 147 147 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 
167 167 167 167 209 211 211 211 211 211 221 223 223 223 223 223 223 223 223 223 
223 223 243 243 243 243 243 243 257 259 261 263 263 263 263 263 263 263 263 263 
263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 
263 263 325 327 329 331 331 331 331 331 331 331 331 331 349 351 351 351 351 351 
361 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363

Незрозуміло (мені щонайменше), як можна прогнозувати майбутні терміни. Сміливо лише сказати, що терміни завжди непарні, не зменшуються (після другого терміну) і що деякі числа повторюються багато разів.

Виклик

Напишіть програму або функцію, яка приймає натуральне число n і друкує або повертає n- й член послідовності SUDSI. Наприклад, якщо n дорівнює 1, вихід є 1, якщо n дорівнює 2, вихід є 3, якщо n дорівнює 200, вихід є 363.

Візьміть введення будь-яким звичним способом (stdin / командний рядок / функція arg).
Виграє найкоротша відповідь у байтах .
(Цей сайт кодує речі в UTF-8, але ви можете використовувати будь-яке вже кодування, яке ви хочете.)

Бонус Mathy: (потенційно придатний для винагороди)

  • Розкажіть мені більше про послідовність SUDSI. Яка основна закономірність того, які числа є частиною цього, і скільки їх є (і подібні речі)? ( До речі, я не зміг знайти SUDSI на OEIS .)

Як знову. Краще не посилатись, ніж створювати плутанину щодо кодування.
Оптимізатор

@Optimizer Я посилався на цей байтовий лічильник з тією ж фразою протягом століть . Чому це раптом спричинило б більше плутанини, ніж коли-небудь?
Хобі Кальвіна

1
@orlp Я думаю, що це буде приємною додатковою функцією, але я особисто покладаюся на можливість копіювати та вставляти, оскільки у мене рідко є вихідні файли для моїх публікацій.
Мартін Ендер

1
@orlp Але кому це все одно знадобиться? Вони можуть бачити розмір безпосередньо, якщо у них був файл. І видалити нову лінію в кінці кінців в деяких операційних системах не так просто.
jimmy23013

2
@ MartinBüttner Мені було нудно: meta.codegolf.stackexchange.com/questions/4944/…
orlp

Відповіді:


5

Pyth, 45 41 40 38 байт

MXGH_HhugGm@Gtd,s<>GH2.a-@GH@GhHtQr1yQ

Я помітив (як це робив Мартін Бюттнер), що максимальна кількість перебігу перестановки kє 2k + 1. Але оскільки у нас є лише n - 1кроки, нам потрібен лише список номерів до 2n - 1.

Спробуйте в Інтернеті: Демонстрація

M                       define a function g(G, H): return
                        (G is the list of numbers, H is a tuple)
 XGH_H                     a translation of G
                           (replaces the elements in H with the elements in reversed H)
                           in this application it swaps two values in the list G


                        implicit: Q = input()
 u     tQr1yQ           reduce, G = [1, 2, ..., 2*Q-1]
                        for each H in [0, 1, ..., Q - 2]:
                           G = 
  gG...                        g(G, ...)
h                       print the first element of the resulting list

And the second argument ... of the function call g is:

     ,                  create the tuple (
      s<>GH2               sum(G[H:][:2]), 
            .a-@GH@GhH     abs(G[H],G[H+1])
                        )
m@Gtd                   and map each value d to G[d - 1]

Чи є штраф за використання Pyth поза бібліотекою?
Алекс А.

1
@ Алекс А. Ха-ха, ні. Але є одна для неповернення книг.
Якубе

18

Математика, 88 байт

Last[f@n_:=n;(r=f@1;{f@a,f@b}={f[b=+##],f[a=Abs[#-#2]]};r)&@@f/@{#,#+1}&/@Range@Input[]]

Це повна програма, зчитуючи дані з підказки. Це дуже пряма реалізація визначення, де я відстежую поточну послідовність у f(значення яких f[n]за замовчуванням до n).

Ось трохи більш читабельна версія:

Last[
  f@n_ := n;
  (
    r = f@1;
    {f@a,f@b} = {f[b=+##],f[a=Abs[#-#2]]};
    r
  ) & @@ f /@ {#,#+1} & /@ Range @ Input[]
]

Деякий аналіз

Я побудував перші 2000 елементів послідовності (після цього вона не стає більш цікавою):

enter image description here

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

Ми можемо виправдати лінійний ріст досить легко (це трохи рухомо, але я думаю, що це було б до суворого доказу за допомогою індукції): спочатку максимальна кількість вплинутого кроку перестановки nстановить n + (n+1) = 2n + 1. Також зверніть увагу , що ці цифри будуть завжди бути переміщені 1, так як |n - (n+1)| = 1. Тож не дивно, що ми отримуємо числа, які приблизно знаходяться 2nв послідовності. Однак ми можемо також зазначити, що для кроків до n , S n + 1 завжди обмежений n + 1 , що означає, що жоден крок заміни не може змінювати два числа, які обидві більше, ніж n . Отже, числа, які ще потрібно обробити, будуть меншими або рівними їх початковому значенню. Отже,2n + 1 також є обмеженою для самої послідовності.

Я думаю, що знайти аргумент щодо тривалості кроків буде складніше.


3
+1 для гарного рішення, але в основному для дуже цікавого та інформативного аналізу!
Алекс А.

4

CJam, 45 40 39 байт

Просто наївний підхід. Можна додатково пограти в гольф. Занадто багато відсутньої функції заміни масиву.

ri_K*,\{\:L>2<L1$:+:S@:-z:DL=tDSL=t}/1=

Як це працює:

ri_                             "Read the input, convert to integer and copy it";
   K*,                          "Multiply the copy by 20 and get 0 to 20*input-1 array";
      \{ ... }/1=               "Swap and put input on stack and run the loop that many";
                                "times. After the loop, take the second element as";
                                "we have a 0 based array while series is 1 based";
{\:L>2<L1$:+:S@:-z:DL=tDSL=t}
 \:L                            "Swap to put iteration index behind the array";
                                "and store array in L";
    >2<                         "In each loop, the iteration index will be on stack";
                                "Get the two elements from the array starting at that";
       L1$                      "Put the array on stack and copy the tuple";
          :+:S                  "Get the sum and store it in S";
              @:-z:D            "Get the absolute difference of the tuple and store in D";
                    L=t         "Put the element at S diff at sum index";
                       DSL=t    "Put the element at S sum at diff index";

Спробуйте його онлайн тут


4

Haskell, 95 байт

f#n=let b=f$n+1;l=f n+b;r=abs$f n-b;y x|x==l=f r|x==r=f l|1<2=f x in y
p n=foldl(#)id[1..n-1]$1

Приклад використання: p 70->139

Я не зберігаю послідовність у списку чи масиві. Я неодноразово оновлюю функцію ідентичності на функцію з двома елементами поточного кроку, що поміняються. Після nкроків я викликаю отриману функцію з параметром 1.



1

Pyth, 55 53 51

Можливо, можна буде гольфу далі. Можливо, вийде дуже повільним для великих, nтому що я лінувався розібратися, як довгий масив мені знадобиться, і я просто використав його n^n.

Завдяки мінливості та Мартіну Бюттнеру за те, що вони зазначили, що я можу використовувати максимум 3n.

KU*3QFNr1QJ@KN=G@tKNAJG,+JG.a-JG=Y@KJ XXKJ@KGGY)@K1

Пояснення

                   Q = input (implicit)
KU*3Q              K = range(3 * Q)
FNr1Q              for N in range(1, Q):
 J@KN               J = K[N]
 =G@tKN             G = K[1:][N]
 AJG,+JG.a-JG       J, G = J + G, abs(J - G)
 =Y@KJ              Y = K[J]
 XXKJ@KGGY          K[J], K[G] = K[G], Y
)
@K1                print K[1]

Я провів кілька тестів, і здається, що потрібна довжина списку збігається до 2*nвеликої n, максимум 3*nдля n=1.
Нестабільність

@ Нестабільність По суті, максимум - це те 2n+1, що, як ви говорите, має максимум 3для n=1і (певним чином) сходиться 2n. Це не надто дивно, оскільки це максимум для неперевіреної послідовності, і жоден крок у процесі не може збільшити число, яке ще попереду. Я можу додати це до своєї відповіді.
Мартін Ендер

Я бачу, ви вже ставите моє .aпродовження до хорошої роботи! На шляху набагато більше ласощів, але isaac зараз спить: github.com/isaacg1/pyth/pull/32
orlp

@orlp, мені справді доводилося читати документи під час написання коду (я зазвичай використовую doc.txtна GitHub для посібника) і побачив оновлення. На щастя, як я міг просто пропустити це і написав користувальницьку реалізацію ...
PurkkaKoodari

1

Пітон 2, 117 106 101

j=input();a=range(3*j)
for i in range(1,j):b,c=a[i:i+2];d=abs(b-c);a[b+c],a[d]=a[d],a[b+c]
print a[1]

Використовує a dict(map) для збереження значень для використання довільних індексів. g(n)є функцією, що повертає nth елемент. Потім просто повторюється input-1час і виводиться перший елемент.

Виявляється, це коротше, використовуючи методи з моєї відповіді Pyth.

Завдяки xnor за збереження 5 байт.


Ви можете використовувати список розпакування: b,c=a[i:i+2]. Крім того, b+cвін досить короткий, що збереження його до змінної sвтрачає символи, ніж просто записати її двічі.
xnor

1

Ідіть 150

func f(j int){a:=make([]int,j*2);for i:=range a{a[i]=i};for i:=1;i<j;i++{b,c:=a[i],a[i+1];v:=b-c;if v<0{v*=-1};a[b+c],a[v]=a[v],a[b+c]};println(a[1])}

Безголовка, нічого хитрого, здебільшого викрадено у @ Pietu1998

func f(j int) {
    a := make([]int, j*2) // Build the array we will be working on
    for i := range a {
        a[i] = i
    }
    for i := 1; i < j; i++ {
        b, c := a[i], a[i+1]
        v := b - c
        if v < 0 {
            v *= -1
        }
        a[b+c], a[v] = a[v], a[b+c]
    }
    println(a[1])
}

http://play.golang.org/p/IWkT0c4Ev5


1

Ява, 162

int f(int n){int a[]=new int[2*n],s,d,x,t;for(x=0;x<2*n;)a[x]=++x;for(x=0;++x<n;){s=a[x]+a[x-1]-1;d=Math.abs(a[x]-a[x-1])-1;t=a[s];a[s]=a[d];a[d]=t;}return a[0];}

Пояснення

int f(int n) {
    int a[] = new int[2 * n], sum, diff, x, temp;
    for (x = 0; x < 2 * n;) {
        a[x] = ++x;  // set initial array
    }
    for (x = 0; ++x < n;) {
        sum = a[x] + a[x - 1] - 1;
        diff = Math.abs(a[x] - a[x - 1]) - 1;
        temp = a[sum];
        a[sum] = a[diff];
        a[diff] = temp;
    }
    return a[0];
}

Ви можете зберегти два байти, перемістивши тіло другого циклу в положення збільшення оператора for. (Розділіть висловлювання комами, а не крапкою.)
AJMansfield,

1

постійний струм, 134 132 131 байт

[_1*]sOdsn2*ddslsSsa[ladd:S1-dsa0<P]dsPx1d0rsN:N[la1+dsad;SdS@r1+;SdS@rL@L@r+Ss-d0>Od;SrLsdSsrLs;Sr:S:S1;SladsN:Nlaln>G]dsGxln1-;Nf

Використовуйте echo $n $code | dc, де $nце п і $codeє ... код ( задуха ). Цитата за смаком.

Редагувати: Якщо ви не докоряєте мені пояснення, я ніколи не обійдуся цим.


Чи потрібно мені додати три байти для `-e`?
Джо

@Sir, виявляється, ти цього не робиш! [ codegolf.stackexchange.com/questions/25670/…
Джо

Це була розмова з самим собою?
NoOneIsHere

@NoOneIsHere: Так, точно. Це питання було відкрите для будь-кого, але я знайшов відповідь.
Джо

0

Перл 5, 131

Наївне рішення (тобто пряме виконання визначення). Підпрограма, вона приймає введення як список1 s потрібної довжини.

{map$a[$_]=$_,1..3*@_;($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_;$a[1]}

Візуалізуйте його вихід, наприклад print sub...->(1,1,1,1,1).

Пояснення:

map$a[$_]=$_,1..3*@_ будує масив @a , індексуючи кожне ціле число від 1 до 3 разів більше розміру@_ (вхід).

($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_повторює комутатор неодноразово (в один раз менше, ніж розмір @_), перемикаючись $a[$a[$_-1]+$a[$_]]на$a[abs($a[$_-1]-$a[$_])] як$_ діапазоні від 2 до розміру @_.

А потім повертається підпрограма $a[1].


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.