是在康托集内吗?


20

挑战

对于这个挑战,您应该确定Cantor集中是否有给定的数字。首先,让我们定义Cantor集。

首先,从0到1之间的数字开始。超出此范围的任何数字均不在Cantor集中。现在,让我们将数字分为三个相等的部分:[0,1 / 3],[1 / 3,2 / 3],[2 / 3、1]。不在第一部分和最后一部分范围内的任何数字都不在Cantor集中。现在,对段[0,1 / 3]和[2/3,1]重复此过程。然后,您重复剩余的内容。您会永远这样做。最后,所有剩余的数字都在Cantor集中。这是前六个迭代的图表:

康托图


输入值

两个整数xy
0 < y < 2^15
0 <= x <= y
最大的共同点xy为1,除非x == 0


输出量

如果x/y在Cantor设置中,则为真。
如果x/y不在Cantor集合中,则为假。


例子

现在,让我们看一下Cantor集中的一些数字示例。

1/3 -> true  

它在边界上,并且边界永远不会删除。

1/4 -> true  

1/4永远不会位于细分的中间三分之一,尽管它也永远不会位于边界上。如果遵循它的路径,您实际上会发现它在节的前三分之一和后三分之一之间交替出现。

1/13 -> true  

1/13 在第一部分,第一部分和最后一部分之间切换。

1/5 -> false

1/5 落入上图中第三行的第一个空白块,介于1/9和2/9之间。

其他测试用例:

0/4 -> true
3/10 -> true
3/4 -> true
10/13 -> true
1/1 -> true
12/19 -> false
5/17 -> false
3/5 -> false
1/7 -> false
1/2 -> false

您可以使用此代码段尝试其他数字:


目的

字节数最少的人获胜。


我们保证输入不是(0,0)吗?分数是最简单的形式吗?
xnor

1
@xnor查看给定的y范围。我要说的是,该分数是最简单的形式,除非x == 0
TheNumberOne

x!= 1的一些测试用例会很好。另外,您的摘要显示1/3不在cantor集合中。
xnor

@xnor添加并修复;)
TheNumberOne '17

6
可以找到Cantor吗?
mbomb007 '17

Answers:


13

Mathematica,54个字节

If[Last@#===1,Most@#,#]&@RealDigits[#,3][[1]]~FreeQ~1&

未命名函数,以小数x/y作为输入,其中y > 00 ≤ x ≤ y,并返回TrueFalse

当Cantor的base-3扩展中的所有数字都不等于1时,就会在Cantor中精确设置0到1之间的一个实数。唯一的例外是,其分母为3的幂的分数(其base-3扩展因此终止)被允许以1结尾。

RealDigits[#,3][[1]]给出小数输入的#以3为底的扩展的所有数字,格式如下{1, 0, 2, {0, 1, 0, 2}}:最后一个列表是扩展的周期部分,而预先的整数是周期开始之前的数字。如果base-3扩展立即为周期性,则输出为{{0, 1, 0, 2}}; 如果base-3扩展终止,则格式为{1, 0, 2}

因此,我们想使用来检查~FreeQ~1列表是否包含1s。但是,由于终止扩展的原因,如果列表的最后一个元素等于,我们要删除它1;那就是If[Last@#===1,Most@#,#]成就。(该===是比较具有潜在的名单需要1==。在这种情况下未计算的单独存在的)


4
我对Mathematica没有IsCantorNumber但具有确定某物是山羊的功能感到惊讶。
Brain Guider '02

3
好吧,我不知道,在现实生活中出现的更多:山羊还是分形?;)
格雷格·马丁

FreeQ[RealDigits[#,3][[1]]/.{{x___,1}}:>{x},1]&
ngenisis '02

这样的规则也将去除1周期部分中的尾随s,这将导致错误的答案。例如,7/8基3膨胀0.21212121 ....,或{{2,1}}; 但建议的规则会将其更改为{{2}},它不带1s,但不应这样做。
格雷格·马丁

触摸。怎么#==0||FreeQ[RealDigits[#,3]/.{{x___,1},_}:>{x},1]&样 如果它终止并且非零RealDigits[#,3]将是形式{{__Integer},-1},如果重复则将是形式{{___Integer,{__Integer}},-1},对吗?我正在使用手机,因此现在很难进行测试。如果RealDigits可行,则使用infix表示法也可能有效。
ngenisis'2


7

果冻22 17 16 15字节

,ạµ%⁹×3µÐĿ:⁹Ḅ3ḟ

打印3表示真相,不打印虚假。

在线尝试!

背景

Cantor集的一个众所周知的属性是,它精确地包含01之间的那些数字,这些数字可以在其三进制扩展中不加1的情况下写入。

请注意,某些数字(确切地说是集的构造所涉及的闭合区间的右边缘)可以用单个(尾部)1或无限数量的尾部2来写。例如,1 = 1 3 = 0.22222… 31/3 = 0.1 3 = 0.022222… 3,就像0.5 10 = 0.499999… 10一样

为了避免对右边缘进行特殊处理,我们可以检查1x / y1-x / y =(y-x)/ y的最短十进制扩展名,其中x / y是右边缘iff (y-x)/ y是左边缘。如果其中至少一个不包含1,则x / y属于Cantor集。

怎么运行的

,ạµ%⁹×3µÐĿ:⁹Ḅ3ḟ  Main link. Left argument: x. Right argument: y

 ạ               Absolute difference; yield y - x.
,                Pair; yield [x, y - x].
       µ         Begin a new, monadic chain with argument [a, b] := [x, y - x].
  µ     ÐĿ       Repeatedly execute the links in between until the results are no
                 longer unique, updating a and b after each execution. Return the
                 array of all unique results.
   %⁹              Compute [a % y, b % y].
     ×3            Compute [3(a % y), 3(b % y)].
                 This yields all unique dividends of the long division of x by y in
                 base 3.
          :⁹     Divide all dividends by y to get the corresponding ternary digits.
            Ḅ    Unbinary; turn [1, 1] into 3, other pairs into other numbers.
             3ḟ  Remove all occurrences of the resulting numbers from [3], leaving
                 an empty array if and only if one pair [a, b] is equal to [1, 1].

3是真正的true+1。
Magic Octopus Urn'1

3

JavaScript(ES6),65 67

编辑保存的2个字节thx @Luke

n=>d=>(z=>{for(q=0;~-q*n*!z[n];n=n%d*3)z[n]=1,q=n/d|0})([])|q!=1|!n

少打高尔夫球

n=>d=>{
  z = []; // to check for repeating partial result -> periodic number
  for(q = 0; q != 1 && n != 0 && !z[n]; )
    z[n] = 1,
    q = n / d | 0,
    n = n % d * 3
  return q!=1 | n==0
}

测试

f=
n=>d=>(z=>{for(q=0;~-q*n*!z[n=n%d*3];q=n/d|0)z[n]=1})([])|q!=1|!n
  

console.log(
'Truthy: 1/3 1/4 1/13 0/4 3/10 3/4 10/13 1/1\nFalsey: 1/5 12/19 5/17 3/5 1/7 1/2'.replace(/(\d+).(\d+)/g,(a,x,y)=>a+':'+f(x)(y))
)  


我认为您可以替换n=n%d*3为“ q=n/d|0z[n]z[n=n%d*3]
Luke”

2

JavaScript(ES6),55个字节

y=>f=(x,z,n=~y,q=x/y|0)=>n?!z|!q&&f(x%y*3,z|q==1,n+1):1

首先使用分母,然后使用分子。标准格式长一个字节:

f=(x,y,z,n=~y,q=x/y|0)=>n?!z|!q&&f(x%y*3,y,z|q==1,n+1):1

说明

如果分数不在Cantor集中,则它必须在某个时刻落入中间部分之一;因此,它在基数3中的表示形式必须包含1,并在某个点后跟一个非零数字。这是这样的:

  • z 跟踪我们是否找到了1。
  • q 是以3为底的当前数字。
  • !z|!q如果z为false(我们尚未找到1)或q为false(当前数字为0),则为true。

如果n在我们找到1之后某个地方的非零数字之前递减为零,则分数在Cantor集中,然后返回1


2

Bash + GNU实用程序,62字节

dc -e3o9d$2^$1*$2/p|tr -cd 012|grep -P "1(?!(0{$2,}|2{$2,})$)"

在线尝试!

向其传递两个整数参数,其中arg1 <= arg2和0 <arg2。

PPCG I / O方法所允许,输出以退出代码返回(0代表虚假,1代表真实)。

我怀疑正则表达式可以继续使用,甚至可以取消tr命令,而推荐使用grep -z,但这是我能想到的最短的命令。(不幸的是,grep -z与grep -P不兼容,并且!!语法要求使用-P选项来获取perl样式的正则表达式。)

测试平台程序和输出:

for x in '1 3' '1 4' '1 13' '1 5' '0 4' '3 10' '3 4' '10 13' '1 1' '12 19' '5 17' '3 5' '1 7' '1 2'
  do
    printf %-6s "$x "
    ./cantor $x >/dev/null && echo F || echo T
  done

1 3   T
1 4   T
1 13  T
1 5   F
0 4   T
3 10  T
3 4   T
10 13 T
1 1   T
12 19 F
5 17  F
3 5   F
1 7   F
1 2   F

说明

直流部分(参数为x和y):

3o     Set output base to 3.
9      Push 9 on the stack.
d      Duplicate the top of the stack. (The extra 9 on the stack isn't actually used, but I need some delimiter in the code here so that the 9 doesn't run into the number coming up next.  If I used a space as a no-op, then I'd need to quote it for the shell, adding an extra character.)
$2^    Raise 9 to the y power. This number in base 3 is 1 followed by 2y 0's.
$1*$2/ Multiply the base-3 number 10....0 (with 2y 0's in it) by x and then divide by y (truncating). This computes 2y digits (after an implied ternary point) of x/y.  That's enough digits so that the repeating part of the rational number is there at least twice.
p      Print the result, piping it to tr.

tr和grep部分:

一个较小的问题是,尽管dc处理任意大的整数,但是当dc打印大量数字时,它将分成69个字符的行,除最后一行以反斜杠结尾外,其余各行都换行。

tr命令删除所有反斜杠和换行符。这只剩下一行。

然后,grep命令使用perl样式的正则表达式(-P选项,它是GNU扩展名)。如果该行包含1,然后不包含至少y 0或至少y 2,则正则表达式匹配,然后结束该字符串。

这正是将x / y识别为不在Cantor集合中所需要的,因为有理数x / y的以3为基的表示的重复部分可以看作是从三元点后的数字#y + 1开始,最长为y位数。


1

CJam(19个字节)

{_@3@#*\/3b0-W<1&!}

在线测试套件

这是一个匿名块(函数),它在堆栈上有两个参数,在堆栈上离开0或离开1。它通过将小数x/y转换为y基数3并在它们不包含后缀1或仅包含1后缀的情况下返回true来工作1 0 0 0 ...

{            e# Begin a block
  _@3@#*\/3b e#   Base conversion
   0-W<      e#   Remove all zeros and the final non-zero digit
   1&!       e#   True iff no 1s are left
}

1

Pyth,14个字节

gu*3hS,G-QGQE0

基于我的C解决方案。y在第一条输入线上,x第二条上。

                Q = y
 u         QE   G = x
                loop y times
  *3                x = 3 *
    hS,G                min(x,
        -QG                 y-x)
g            0  return x >= 0

如果x/y在Cantor集合内,则x停留在0和之间y。否则,x变得大y于某一点,然后在其余迭代中发散到负无穷大。

在线尝试!


0

批处理,91字节

@set/ai=%3+1,n=%1*3%%%2,f=%1*3/%2%%2,f^|=j=!((%2-i)*n)
@if %f%==0 %0 %n% %2 %i%
@echo %j%

测试的前y-13个基数x/yi是测试的位数。n是的下一个值xj如果n达到零(因为扩展终止),则为true,或者我们已经测试了y-1数字而没有找到1f如果j为true或下一个数字为a 1,则为true ,此时我们停止循环并输出j

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.