Дивне впорядкування Шарковського


33

Вступ

У цьому виклику ми матимемо справу з певним упорядкуванням натуральних чисел. Упорядкування відбувається так:

   3,    5,    7,    9,    11, ...
 2*3,  2*5,  2*7,  2*9,  2*11, ...
 4*3,  4*5,  4*7,  4*9,  4*11, ...
 8*3,  8*5,  8*7,  8*9,  8*11, ...
16*3, 16*5, 16*7, 16*9, 16*11, ...
 ...
... 64, 32, 16, 8, 4, 2, 1

Спочатку перераховуємо всі непарні цілі числа, що перевищують 1, у порядку зростання. Потім ми перераховуємо два рази непарні цілі числа, що перевищують 1, потім 4 рази, потім 8 разів і так далі: для всіх k ми перераховуємо 2 k рази непарних цілих чисел, більших за 1, у порядку зростання. Нарешті, ми перераховуємо повноваження двох у порядку зменшення , що закінчується на 1. Кожне додатне ціле число трапляється в цьому "списку" рівно один раз.

Більш чітко розглянемо два виразних натуральних числа A = n · 2 p і B = m · 2 q , де n, m ≥ 1 непарні, а p, q ≥ 0 . Тоді A виходить перед B в порядку впорядкування, якщо виконується одна з наступних умов:

  • n> 1 , m> 1 і p <q
  • 1 <n <m і p = q
  • n> m = 1
  • n = m = 1 і p> q

Це впорядкування фігурує в дивовижному математичному результаті, відомому як теорема Шарковського , що стосується періодичних точок динамічних систем. Я тут не буду вникати в деталі.

Завдання

Ваше завдання в цьому виклику - обчислити вищезазначене замовлення. Ваші входи - це два натуральних числа A і B , які можуть бути рівними. Вихідний результат - це триєдна цінність, якщо A приходить до B при впорядкуванні, а хибне значення - в іншому випадку. Якщо A = B , вихід повинен бути надійним. Ви можете приймати A і B в будь-якому порядку, якщо ви послідовні.

Вам не доведеться турбуватися про цілісне переповнення, але ваш алгоритм повинен теоретично працювати для довільно великих входів.

Тестові справи

Екземпляри правди

3 11
9 6
48 112
49 112
158 158
36 24
14 28
144 32
32 32
32 8
3 1
1 1

Фальшиві екземпляри

1 2
1 5
11 5
20 25
2 8
256 255
256 257
72 52
2176 1216
2176 2496

Відповіді:


6

JavaScript (ES6), 53 49 байт

f=(a,b)=>b<2||a>1&&(a&b&1?a<=b:a&1|~b&f(a/2,b/2))

Пояснення:

  • Якщо b дорівнює 1, то передує (або дорівнює) b
  • В іншому випадку, якщо a дорівнює 1, то a не передує b
  • В іншому випадку, якщо і a, і b непарні, використовуйте регулярну перевірку нерівності
  • В іншому випадку, якщо a непарне, то воно передує b
  • В іншому випадку, якщо b непарне, то a не передує b
  • В іншому випадку розділіть і a, і b на 2 і повторіть спробу.

Редагувати: збережено 2 байти завдяки @Arnauld.


Приємно. Я не думав про використання рекурсії тут. Було б a&1|~b&1&f(a/2,b/2)працювати?
Арнольд

@Arnauld Я не впевнений, я побоювався, що це буде циклічно нескінченно.
Ніл

Це не може, тому що b<2зрештою буде правдою. Тепер ще одна проблема полягає в тому, що ви будете обробляти більше ітерацій, ніж потрібно, і отримуєте значення з плаваючою комою. Але я не можу знайти жодного контрприкладу, який би не працював так, як очікувалося.
Арнольд

@Arnauld Ага, правда, b<2спочатку я не використовував , але, мабуть, він буде працювати зараз.
Ніл

@Arnauld ще краще, так як f(a/2,b/2)тільки повертається 0, 1, falseабо true, я навіть не потрібен &1.
Ніл

5

Python 2, 87 71 байт

k=lambda n:[n&~-n<1,(n&-n)*cmp(n&~-n,1),n/(n&-n)]
lambda a,b:k(a)<=k(b)

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

У читаному виразі кортеж для A = n · 2 p :

[n == 0, p * (1 - 2*(n == 0)), n]

5

Python 2, 50 байт

lambda*l:cmp(*[([-n][n&n-1:],n&-n,n)for n in l])<1

Кожне число відображається в трійку, відсортований порядок - бажаний порядок.

  • Первинним значенням є те [-n][n&n-1:], що обробляє сили 2 в кінці. Побітове значення "і" n&n-1дорівнює нулю саме тоді, коли nє потужність 2. Якщо так, ми отримуємо список [-n], а в іншому випадку порожній список []. Це ставить усі повноваження 2 в кінці замовлення, у порядку зменшення.
  • Вторинне значення n&-nвитягує коефіцієнт потужності 2 n.
  • Кінцеве значення nрозривів дорівнює потужності 2 на користь більшої кількості.

Відповідні кортежі передаються, cmpщоб побачити, чи це порівняння <=0. Python 3 врятував би байт з поділом float (n&n-1<1)/nдля першого значення в трійці, але його немає cmp.


Це не cmp(...)<=0рівнозначно cmp(...)<1?
математиканда

@mathmandan Так :)
xnor

Я думаю, що допустимо приймати цілі числа у зворотному порядку та використовувати ~замість<1
Мітч Шварц

4

JavaScript (ES6), 70 64 байт

Можливо, можна було б пограти ще трохи, але як перша спроба:

x=>y=>(a=x&-x,x/=a,b=y&-y,y/=b,y<2?x>1|b<=a:x>1&(b>a|b==a&y>=x))

Здійснює введення з синтаксисом currying (x)(y). Повернення 0/ 1.

Тестові справи


Ви можете вийняти дужки всередині і всередині b>a||(b==a&&y>=x), не вплинувши на виконання.
XavCo7

@ XavCo7 Добре знімати дужки всередині, а не навколо. Усі існуючі тестові випадки все-таки пройдуть, але такий матеріал, як [1, 5]би був неправильно ідентифікований як правда.
Арнольд

1
@Arnauld Додам це як новий тест на майбутнє.
Згарб

3

Perl 6 , 89 84 байт

->\a,\b{my \u=*>max a,b;a==first a|b,flat [1,2,4...u].&{(3*$_,5*$_...u for $_),.reverse}}

{my \u=*>@_.max;@_[0]==first @_.any,flat [1,2,4...u].&{.map(*X*(3,5...u)),.reverse}}

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

Не зовсім короткий, але я подумав, що було б цікаво написати рішення, яке фактично генерує послідовність упорядкування (до безпечної верхньої межі для кожної підпослідовності), а потім перевіряє, який вхід з’являється в ньому спочатку.

Наприклад:

  • Для введення 2, 3він генерує:

    3 5
    6
    12
    4 2 1
    ... і потім зауважує, що 3з'являється раніше 2.

  • Для введення 9, 6він генерує:

    3 5 7 9 11
    6 10
    12
    24
    48
    16 8 4 2 1
    ... і потім зауважує, що 9з'являється раніше 6.

Це може бути розумнішим і генерувати ще менше послідовності, але це займе більше байтів коду.


2

Python 2, 54 байти

f=lambda a,b:b<2or[f(a/2,b/2),a>1,0,1<a<=b][a%2+b%2*2]

Рекурсивне рішення, подібне до Ніла.


Це, здається, зіпсує деякі тестові випадки. У ньому йдеться про f(158,158)помилкове і f(2,8)правдиве.
xnor

@xnor На жаль, зараз слід виправити.
orlp

Це говорить f(1,5)помилково.
xnor

Моє погано, я мав на увазі, що це f(1,5)повинно бути помилковим, але код дає True.
xnor

@xnor Ах, я помітив помилку, виправлену зараз (на добро сподіваюся). Я пішов приблизно слідом за описом Ніла.
orlp

1

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

OrderedQ[{1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}/.{a_,1}->{∞,-a}]&

Безіменна функція, яка приймає список натуральних чисел і повертається, Trueякщо список утворює висхідну послідовність у порядку Шарковського, в Falseіншому випадку. (Зокрема, у вхідному списку не повинно бути лише два елементи - ми отримуємо додаткову функціональність безкоштовно.)

Серцем алгоритму є функція {1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}, яка неодноразово переміщує коефіцієнти 2 навколо, щоб перетворити ціле число форми m*2^kз mнепарною в упорядковану пару {2^k,m}(і робить це для кожного елемента вхідного списку). OrderedQпотім вирішує, чи вже впорядкований список упорядкованих пар; за замовчуванням це означає збільшення порядку за першим елементом, потім збільшення порядку за другим елементом.

Це саме те, що ми хочемо, за винятком цифр, які мають повноваження 2, дотримуються різних правил. Тому перед тим, як зареєструватися в OrderingQ, ми застосовуємо останнє правило /.{a_,1}->{∞,-a}, яке перетворює (наприклад) {64,1}на {∞,-64}; що ставить сили 2 у правильному місці в упорядкуванні.


0

Haskell, 143 138 байт

В основному відносно просто реалізація критеріїв:

e n=head[k-1|k<-[0..],n`mod`(2^k)>0]   -- exponent of 2
f n=n`div`2^e n                        -- odd part
a#b|n<-f a,p<-e a,m<-f b,q<-e b=n>1&&(m>1&&p<q||n<m&&p==q||m<2)||n<2&&m<2&&p>q||a==b  

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


0

Пітон, 159 158 153 144 142 141 байт

Збережено 2 байта завдяки Kritixi Lithos!

Це в основному лише для того, щоб займатися гольфу на моєму пітоні!
Використовували формулу, подану ОП, а не способи всіх розумніших відповідей

f=lambda a,p=0:(a&1)*(a,p)or f(a>>1,p+1)
t=lambda(n,p),(m,q):(n==1)*(m==1)&(p>=q)or (m>1)&(p<=q)|(n<=m)&(p==q)or m==1
lambda a,b:t(f(a),f(b))

Ви можете грати в гольф, видаляючи зайві пробіли: наприклад, у (a, b)другому рядку, де ви можете видалити пробіл між комою та b.
Kritixi Lithos

0

APL (Dyalog Extended) , 27 байт

1⊃∘⍋⍮⍥{p⍵⍮⍨-⍵⍴⍨⍵=2*p←⊥⍨~⊤⍵}

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

Мовчазна діадійна функція, лівий аргумент якої є, aа права b.

Підхід майже ідентичний рішенню Python 2 xnor , оскільки ми перетворюємо кожне число у вкладений масив і проводимо лексикографічне порівняння між ними.

Частина 1: Перетворити номер в вкладений масив

{p⍵⍮⍨-⍵⍴⍨⍵=2*p←⊥⍨~⊤⍵}   Input: positive integer N
                  ⊤⍵    Convert N to binary digits
                 ~      Flip all the bits (1 to 0, 0 to 1)
             p←⊥⍨       Count trailing ones and assign it to p
                        (maximum power of 2 that divides N)
         ⍵=2*           Test if N itself is equal to 2^p
     -⍵⍴⍨               If true, create 1-element array containing -N;
                        otherwise, an empty array
 p⍵⍮⍨                   Form a 2-element nested array;
                        1st element is the above, 2nd is [p, N]

Частина 2: Порівняйте два вкладені масиви

1⊃∘⍋⍮⍥f   Input: A (left) and B (right)
     f   Evaluate f A and f B
         Create a 2-element nested array [f A, f B]
         Grade up; indexes of array elements to make it sorted
          Here, the result is [0 1] if A  B, [1 0] otherwise
1⊃∘       Take the element at index 1 (0-based)

Синтаксис dfn підтримує умовні висловлювання, наприклад, {a:x ⋄ b:y ⋄ z}значення if a then x else if b then y else z, але це занадто багатослівний для використання в цьому випадку.


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