Pemesanan aneh Sharkovskii

33

pengantar

Dalam tantangan ini, kita akan berhadapan dengan pemesanan tertentu dari bilangan bulat positif. Pemesanannya seperti ini:

   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

Kami pertama-tama mendaftar semua bilangan bulat ganjil yang lebih besar dari 1 dalam urutan naik. Kemudian kami mendaftar dua kali bilangan bulat ganjil lebih besar dari 1, kemudian 4 kali, kemudian 8 kali, dan seterusnya: untuk semua k , kami mencantumkan 2 k kali bilangan bulat ganjil lebih besar dari 1 dalam urutan naik. Akhirnya, kami daftar kekuatan dua dalam urutan menurun , berakhir pada 1. Setiap bilangan bulat positif terjadi dalam "daftar" ini tepat sekali.

Lebih eksplisit, pertimbangkan dua bilangan bulat positif A = n · 2 p dan B = m · 2 q , di mana n, m ≥ 1 ganjil, dan p, q ≥ 0 . Kemudian A muncul sebelum B dalam pemesanan, jika salah satu dari kondisi berikut berlaku:

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

Urutan ini muncul dalam hasil matematika mengejutkan yang dikenal sebagai teorema Sharkovskii , yang menyangkut poin periodik sistem dinamik. Saya tidak akan membahas detailnya di sini.

Tugas

Tugas Anda dalam tantangan ini adalah untuk menghitung pemesanan di atas. Input Anda adalah dua bilangan bulat positif A dan B , yang mungkin sama. Output Anda adalah nilai kebenaran jika A datang sebelum B dalam pemesanan, dan nilai palsu sebaliknya. Jika A = B , output Anda harus benar. Anda dapat mengambil A dan B dalam urutan mana pun, selama Anda konsisten.

Anda tidak perlu khawatir tentang integer overflow, tetapi algoritme Anda secara teoritis harus bekerja untuk input besar yang sewenang-wenang.

Uji kasus

Contoh yang benar

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

Contoh palsu

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

Jawaban:

6

JavaScript (ES6), 53 49 byte

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

Penjelasan:

  • Jika b adalah 1, maka sebuah mendahului (atau sama dengan) b
  • Kalau tidak, jika a adalah 1, maka a tidak mendahului b
  • Kalau tidak, jika a dan b aneh, gunakan pemeriksaan ketimpangan reguler
  • Kalau tidak, jika a aneh, maka mendahului b
  • Kalau tidak, jika b ganjil, maka a tidak mendahului b
  • Jika tidak, bagi a dan b dengan 2 dan coba lagi.

Sunting: Disimpan 2 byte berkat @Arnauld.

Neil
sumber
Bagus. Saya tidak berpikir tentang menggunakan rekursi di sini. Akan a&1|~b&1&f(a/2,b/2)bekerja
Arnauld
@Arnauld Saya tidak yakin, saya khawatir itu akan berulang tanpa batas.
Neil
Tidak bisa karena b<2pada akhirnya akan benar. Sekarang, masalah lain adalah Anda akan memproses lebih banyak iterasi daripada yang dibutuhkan dan mendapatkan nilai floating point. Tetapi saya tidak dapat menemukan contoh tandingan yang tidak akan berfungsi seperti yang diharapkan.
Arnauld
@Arnauld Ah, benar, saya tidak menggunakan b<2awalnya, tapi saya kira itu akan berfungsi sekarang.
Neil
@Arnauld Lebih baik lagi, karena f(a/2,b/2)hanya kembali 0, 1, falseatau true, aku bahkan tidak perlu &1.
Neil
5

Python 2, 87 71 byte

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

Ini mungkin tidak akan memenangkan penghargaan ukuran apa pun, tetapi jawaban ini berfungsi dengan membuat 3-tupel menggunakan 3 ekspresi dari integer yang bila dipesan secara leksikografis akan menghasilkan urutan yang benar.

Dalam istilah yang dapat dibaca, tupel untuk A = n · 2 p :

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

Python 2, 50 byte

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

Setiap nomor dipetakan ke triple yang urutannya diurutkan adalah urutan yang diinginkan.

  • Nilai primernya adalah [-n][n&n-1:], yang menangani kekuatan 2 pada akhirnya. Bitwise "dan" n&n-1adalah nol kapan tepatnya nkekuatan dari 2. Jika demikian, kami mendapatkan daftar [-n], dan sebaliknya daftar kosong []. Ini menempatkan semua kekuatan 2 di akhir perintah, dalam urutan menurun.
  • Nilai sekunder n&-nmengekstrak faktor kekuatan-of-2 dari n.
  • Nilai akhir ntiebreak sama dengan kekuatan 2 yang mendukung jumlah yang lebih besar.

Tupel masing-masing dilewatkan cmpuntuk melihat apakah perbandingan itu <=0. Python 3 akan menyimpan byte dengan divisi float (n&n-1<1)/nuntuk nilai pertama dalam triple, tetapi tidak memiliki cmp.

Tidak
sumber
Tidak cmp(...)<=0setara dengan cmp(...)<1?
mathmandan
@mathmandan Ya :)
xnor
Saya pikir itu diperbolehkan untuk mengambil bilangan bulat dalam urutan terbalik dan menggunakan ~bukan<1
Mitch Schwartz
4

JavaScript (ES6), 70 64 byte

Mungkin bisa bermain golf lagi, tetapi sebagai upaya pertama:

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))

Mengambil input dengan sintaks currying (x)(y). Pengembalian 0/ 1.

Uji kasus

Arnauld
sumber
Anda dapat mengambil tanda kurung di dalam dan di dalam b>a||(b==a&&y>=x), tidak akan membuat perbedaan untuk eksekusi.
XavCo7
@ XavCo7 Tidak apa-apa untuk menghapus tanda kurung di dalam tetapi tidak ada. Semua kasus uji yang ada masih akan lulus, tetapi input seperti [1, 5]itu akan salah diidentifikasi sebagai kebenaran.
Arnauld
1
@Arnauld saya akan menambahkan itu sebagai test case baru untuk masa depan.
Zgarb
3

Perl 6 , 89 84 byte

->\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}}

( Cobalah online. )

Tidak terlalu pendek, tapi saya pikir akan menarik untuk menulis solusi yang benar-benar menghasilkan urutan pemesanan (hingga batas atas yang aman untuk setiap sub-urutan), dan kemudian memeriksa input mana yang muncul terlebih dahulu.

Sebagai contoh:

  • Untuk input 2, 3yang dihasilkannya:

    3 5
    6
    12
    4 2 1
    ... dan kemudian mengamati yang 3muncul sebelumnya 2.

  • Untuk input 9, 6yang dihasilkannya:

    3 5 7 9 11
    6 10
    12
    24
    48
    16 8 4 2 1
    ... dan kemudian mengamati yang 9muncul sebelumnya 6.

Itu bisa lebih pintar dan menghasilkan urutan yang lebih sedikit, tetapi itu akan membutuhkan lebih banyak byte kode.

seseorang
sumber
2

Python 2, 54 byte

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

Solusi rekursif mirip dengan Neil.

orlp
sumber
Ini tampaknya mengacaukan beberapa kasus uji. Dikatakan f(158,158)Salah dan f(2,8)Benar.
xnor
@xnor Ups, harus diperbaiki sekarang.
orlp
Ini mengatakan f(1,5)salah.
xnor
Buruk saya, saya maksudkan itu f(1,5)harus Salah, tetapi kode memberikan Benar.
xnor
@ xnor Ah, saya melihat bug, diperbaiki sekarang (semoga saya berharap). Saya pergi tentang mengikuti deskripsi Neil sedikit terlalu longgar.
orlp
1

Mathematica, 65 byte

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

Fungsi yang tidak disebutkan namanya mengambil daftar bilangan bulat positif dan kembali Truejika daftar membentuk urutan naik dalam urutan Sharkovskii, Falsejika tidak. (Khususnya, daftar input tidak harus hanya memiliki dua elemen — kami mendapatkan fungsionalitas tambahan secara gratis.)

Inti dari algoritma adalah fungsi {1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}, yang secara berulang-ulang menggerakkan faktor 2 untuk mengkonversi bilangan bulat dari bentuk m*2^k, dengan mganjil, ke pasangan terurut {2^k,m}(dan melakukannya untuk setiap elemen dari daftar input). OrderedQkemudian memutuskan apakah daftar pasangan yang dihasilkan sudah diurutkan; secara default, itu berarti meningkatkan urutan elemen pertama, kemudian meningkatkan urutan elemen kedua.

Itulah tepatnya yang kita inginkan, kecuali angka yang merupakan kekuatan 2 mengikuti aturan yang berbeda. Jadi sebelum memeriksa OrderingQ, kami menerapkan satu aturan terakhir /.{a_,1}->{∞,-a}, yang mengubah (misalnya) {64,1}menjadi {∞,-64}; yang menempatkan kekuatan 2 di tempat yang benar dalam pemesanan.

Greg Martin
sumber
0

Haskell, 143 138 byte

Pada dasarnya implementasi kriteria yang relatif mudah:

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  

Cobalah online!

cacat
sumber
0

Python, 159 158 153 144 142 141 byte

Disimpan sebuah 2 byte berkat Kritixi Lithos!

Ini terutama hanya untuk berlatih bermain golf Python saya!
Menggunakan formula yang diberikan oleh OP daripada cara semua jawaban yang lebih pintar

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))
Mie9
sumber
Anda dapat golf dengan menghapus spasi yang tidak perlu: misalnya di (a, b)pada baris kedua di mana Anda dapat menghapus ruang antara koma dan b.
Kritixi Lithos
0

APL (Dyalog Extended) , 27 byte

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

Cobalah online!

Fungsi diad diam-diam yang argumen kirinya adalah adan kanan adalah b.

Pendekatan ini hampir identik dengan solusi Python 2 dari xnor , di mana kami mengonversi setiap angka menjadi array bersarang dan melakukan perbandingan leksikografis di antara mereka.

Bagian 1: Konversi angka menjadi array bersarang

{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]

Bagian 2: Bandingkan dua array bersarang

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)

Sintaks DFF memang mendukung pernyataan bersyarat misalnya {a:x ⋄ b:y ⋄ z}makna if a then x else if b then y else z, tetapi terlalu verbose untuk digunakan dalam kasus ini.

Bubbler
sumber