Sharkovskii的奇怪排序


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 pB = m·2 q,其中n,m≥1是奇数,而p,q≥0。然后,来之前的排序,如果满足下列条件之一成立:

  • n> 1m> 1p <q
  • 1 <n <mp = q
  • n> m = 1
  • n = m = 1并且p> q

这种排序出现在称为Sharkovskii定理的令人惊讶的数学结果中,该定理涉及动力学系统的周期点。我将不在这里详细介绍。

任务

您在此挑战中的任务是计算以上顺序。您的输入是两个正整数AB,它们可能相等。如果在排序中A排B之前,则输出为真实值,否则为假值。如果A = B,则您的输出应该是真实的。只要您保持一致,就可以按照任意顺序选择AB。

您不必担心整数溢出,但是从理论上讲,您的算法应该适用于任意大的输入。

测试用例

真实实例

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

Answers:


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

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,则a在b之前(或等于b)
  • 否则,如果a为1,则a不在b之前
  • 否则,如果a和b都为奇数,则使用常规的不等式检查
  • 否则,如果a为奇数,则它在b之前
  • 否则,如果b为奇数,则a不在b之前
  • 否则,将a和b除以2,然后重试。

编辑:由于@Arnauld,节省了2个字节。


真好 我没有考虑在这里使用递归。会a&1|~b&1&f(a/2,b/2)工作吗?
Arnauld

@Arnauld我不确定,我担心它会无限循环。
尼尔,

不能,因为b<2最终将是真的。现在,另一个问题是您将处理比所需更多的迭代,并获得浮点值。但是我找不到任何无法正常工作的反例。
Arnauld

@Arnauld啊,对,我原来没有用b<2,但是我想它现在可以工作了。
尼尔,

@Arnauld更妙的是,因为f(a/2,b/2)只有收益01falsetrue,我也不需要&1
尼尔

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会使用浮点除法将字节保存(n&n-1<1)/n为三元组中的第一个值,但缺少cmp


cmp(...)<=0等于cmp(...)<1吗?
mathmandan '16

@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 '16

@ XavCo7可以将内部的括号除去,但不能将其除去。所有现有的测试用例仍将通过,但是诸如这样的输入[1, 5]将被错误地标识为真实。
Arnauld

1
@Arnauld我将其添加为将来的新测试用例。
Zgarb

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]

类似于Neil的递归解决方案。


这似乎弄乱了一些测试用例。它说的f(158,158)是错误的,f(2,8)是正确的。
xnor

@xnor糟糕,应立即修复。
orlp 2016年

f(1,5)说错了。
xnor

不好,我的意思是f(1,5)应该为False,但是代码给出的是True。
xnor

@xnor啊,我发现了该错误,现已修复(希望如此)。我过分地遵循了尼尔的描述。
orlp 2016年

1

Mathematica,65个字节

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

未命名函数采用正整数列表,True如果该列表按Sharkovskii顺序形成升序,则返回该函数,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,143138字节

基本上是标准的相对简单的实现:

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

Python中,159个 158 153 144 142 141字节

感谢Kritixi Lithos,节省 2个字节!

这主要是为了练习Python。
使用OP给出的公式,而不是所有巧妙答案的方式

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.