มันอยู่ในชุดคันทอร์หรือไม่?


20

ความท้าทาย

สำหรับความท้าทายนี้คุณควรตรวจสอบว่าตัวเลขที่กำหนดอยู่ในชุดคันทอร์หรือไม่ ก่อนอื่นเรามากำหนดชุดคันทอร์กันก่อน

ก่อนอื่นให้เริ่มด้วยตัวเลขระหว่าง 0 ถึง 1 หมายเลขใด ๆ ที่อยู่นอกช่วงนี้ไม่ได้อยู่ในชุดคันทอร์ ทีนี้ลองแบ่งตัวเลขออกเป็นสามส่วนเท่า ๆ กัน: [0,1 / 3], [1 / 3,2 / 3], [2/3, 1] หมายเลขใด ๆ ที่ไม่อยู่ในช่วงของส่วนแรกและส่วนสุดท้ายไม่อยู่ในชุดคันทอร์ ตอนนี้คุณทำขั้นตอนนี้ซ้ำสำหรับกลุ่ม [0,1 / 3] และ [2/3, 1] จากนั้นคุณทำซ้ำในสิ่งที่เหลืออยู่ คุณทำเช่นนี้ตลอดไป ในท้ายที่สุดตัวเลขทั้งหมดที่เหลืออยู่จะอยู่ในชุดคันทอร์ นี่คือไดอะแกรมของการทำซ้ำหกครั้งแรก:

แผนภาพต้นเสียง


อินพุต

สองจำนวนเต็มและx ตัวหารร่วมที่ยิ่งใหญ่ที่สุดของและเป็น 1 เว้นแต่y
0 < y < 2^15
0 <= x <= y
xyx == 0


เอาท์พุต

ความจริงถ้าx/yอยู่ในชุดคันทอร์
เป็นเท็จหากx/yไม่ได้อยู่ในชุดคันทอร์


ตัวอย่าง

ตอนนี้เรามาดูตัวอย่างของตัวเลขที่อยู่ในชุดคันทอร์

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 ไม่อยู่ในชุดคันทอร์
xnor

@xnor เพิ่มและแก้ไข;)
TheNumberOne

6
คันทอร์สามารถพบได้หรือไม่
mbomb007

คำตอบ:


13

Mathematica, 54 ไบต์

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

ฟังก์ชั่นที่ไม่มีชื่อการเศษส่วนx/yเป็น input ที่y > 0และ0 ≤ x ≤ yและกลับมาหรือTrueFalse

จำนวนจริงระหว่าง 0 ถึง 1 อยู่ในชุดคันทอร์ได้อย่างแม่นยำเมื่อไม่มีตัวเลขใด ๆ ในการขยายฐาน -3 เท่ากับ 1; ข้อยกเว้นคือเศษส่วนที่ตัวส่วนเป็นพลังของ 3 (ซึ่งการขยายฐาน -3 สิ้นสุดลง) จึงได้รับอนุญาตให้สิ้นสุดใน 1

RealDigits[#,3][[1]]ให้ตัวเลขทั้งหมดในการขยายฐาน -3 ของอินพุตแบบเศษส่วน#ในรูปแบบ{1, 0, 2, {0, 1, 0, 2}}ดังนี้: รายการสุดท้ายคือส่วนที่เป็นระยะของการขยายตัวในขณะที่จำนวนเต็มล่วงหน้าเป็นหลักก่อนเริ่มต้นช่วงเวลา หากการขยายฐาน 3 เป็นระยะในทันทีผลลัพธ์จะเป็น{{0, 1, 0, 2}}ดังนี้ หากการขยายฐาน -3 สิ้นสุดลงแบบฟอร์มจะเป็นเช่น{1, 0, 2}นั้น

ดังนั้นเราต้องการตรวจสอบโดยใช้~FreeQ~1ไม่ว่ารายการนั้นจะว่าง1หรือไม่ อย่างไรก็ตามเนื่องจากการยกเลิกการขยายตัวเราต้องการลบองค์ประกอบสุดท้ายของรายการถ้ามันเท่ากับ1; นั่นคือสิ่งที่If[Last@#===1,Most@#,#]สำเร็จ ( ===สิ่งที่จำเป็นในการเปรียบเทียบรายการที่มีศักยภาพด้วย1: ==เพียงอย่างเดียวยังไม่ได้รับการประเมินในสถานการณ์นั้น)


4
อิ่มประหลาดใจที่ Mathematica ไม่ได้IsCantorNumberแต่มีฟังก์ชั่นเพื่อตรวจสอบเป็นสิ่งที่เป็นแพะ
Brain Guider

3
เอาล่ะฉันไม่รู้แล้วในชีวิตจริงมีอะไรมากขึ้น: แพะหรือเศษส่วน? ;)
Greg Martin

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

กฎดังกล่าวจะตัดการต่อท้าย1ในส่วนที่เป็นระยะซึ่งนำไปสู่คำตอบที่ไม่ถูกต้อง ตัวอย่างเช่นการขยายฐาน -3 จาก 7/8 คือ. 21212121 .... หรือ{{2,1}}; แต่กฎที่แนะนำจะเปลี่ยนสิ่ง{{2}}นั้นเป็นซึ่งเป็นอิสระ1แต่ไม่ควรเป็น
เกร็กมาร์ติน

Touch? แล้วไง#==0||FreeQ[RealDigits[#,3]/.{{x___,1},_}:>{x},1]&ล่ะ ถ้ามันถูกยกเลิกและไม่ใช่ศูนย์RealDigits[#,3]จะเป็นของแบบฟอร์ม{{__Integer},-1}และถ้ามันเป็นการทำซ้ำมันจะเป็นของแบบฟอร์ม{{___Integer,{__Integer}},-1}ใช่ไหม? ฉันอยู่บนมือถือดังนั้นจึงยากที่จะทดสอบในตอนนี้ หากใช้งานได้ให้ใช้สัญกรณ์มัดสำหรับRealDigitsอาจทำงานได้เช่นกัน
ngenisis

9

C (gcc) , 61 59 58 ไบต์

f(x,y,i){for(i=y;i--&&x<y;)x=(y-x<x?y-x:x)*3;return x<=y;}

ใช้ประโยชน์จากความสมมาตรของชุดคันทอร์ แบ่งตามyการวนซ้ำเพื่อหลีกเลี่ยงการวนซ้ำไม่สิ้นสุด

ลองออนไลน์!


7

เยลลี่ , 22 17 16 15 ไบต์

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

พิมพ์3เพื่อความจริงไม่มีอะไรที่ผิดพลาด

ลองออนไลน์!

พื้นหลัง

คุณสมบัติที่รู้จักกันดีของชุดคันทอร์คือมันมีตัวเลขเหล่านั้นอย่างแม่นยำระหว่าง0ถึง1ที่สามารถเขียนได้โดยไม่ต้อง1ในการขยายตัวที่สามของพวกเขา

โปรดทราบว่าตัวเลขบาง - แม่นยำขอบขวาของช่วงเวลาปิดมีส่วนร่วมในการก่อสร้างของตลาดหลักทรัพย์ฯ - สามารถเขียนได้ทั้งที่มีเพียงครั้งเดียว (ต่อท้าย) 1หรือมีจำนวนอนันต์ของท้าย2 's ยกตัวอย่างเช่น1 = 1 3 = 0.22222 ... 3และ1/3 = 0.1 3 = 0.022222 ... 3เช่นเดียวกับ0.5 10 = 0.499999 ... 10

เพื่อหลีกเลี่ยงการใส่ขอบพิเศษด้านขวาเราสามารถตรวจสอบว่า1คือการขยายทศนิยมที่สั้นที่สุดในทั้งx / yและ1 - x / y = (y - x) / yโดยที่x / yเป็นขอบขวา iff (y - x) / yเป็นขอบซ้าย หากอย่างน้อยหนึ่งในนั้นไม่มี1 , x / yอยู่ในชุดคันทอร์

มันทำงานอย่างไร

,ạµ%⁹×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

3

JavaScript (ES6), 65 67

แก้ไข 2 ไบต์ที่บันทึกไว้ขอบคุณ @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

น้อย golfed

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|0แล้วแทนที่z[n]ด้วยz[n=n%d*3]
ลุค

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

ใช้โดย currying ในตัวส่วนแรกและตัวเศษที่สอง รูปแบบมาตรฐานคือไบต์ที่ยาวนานกว่า:

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

คำอธิบาย

หากเศษส่วนไม่อยู่ในชุดคันทอร์จะต้องตกอยู่ในส่วนตรงกลางของจุดใดจุดหนึ่ง ดังนั้นการเป็นตัวแทนในฐาน 3 จะต้องมี 1 ตามมาในบางจุดด้วยตัวเลขที่ไม่เป็นศูนย์ นั่นเป็นวิธีการทำงาน:

  • z ติดตามว่าเราได้พบ 1
  • q คือตัวเลขปัจจุบันในฐาน 3
  • !z|!qเป็นจริงถ้าzเป็นเท็จ (เราไม่พบ 1) หรือqเป็นเท็จ (ตัวเลขปัจจุบันคือ 0)

ถ้าnวิ่งลงไปที่ศูนย์ก่อนที่เราจะพบว่าไม่เป็นศูนย์หลักอยู่ที่ไหนสักแห่งหลังจากที่ 1 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

เอาท์พุทจะถูกส่งกลับในรหัสทางออก (0 สำหรับ falsy, 1 สำหรับ truthy) เช่นได้รับอนุญาตจากPPCG I / O วิธี

ฉันสงสัยว่า regex สามารถเล่นกอล์ฟต่อไปได้หรืออาจกำจัดคำสั่ง tr เพื่อใช้ grep -z แต่นี่เป็นเวลาที่สั้นที่สุดที่ฉันสามารถทำได้ (น่าเสียดายที่ grep -z ไม่สามารถใช้ร่วมกับ grep -P ได้และต้องใช้ตัวเลือก -P เพื่อรับ regex-perl-style สำหรับไวยากรณ์?!)

โปรแกรมและผลลัพธ์ที่ทดสอบแล้ว:

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

คำอธิบาย

ส่วน dc (อาร์กิวเมนต์คือ 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 จะใช้ regex สไตล์ perl (ตัวเลือก -P ซึ่งเป็นนามสกุล GNU) regex ตรงกันถ้าบรรทัดมี 1 ไม่ตามด้วยอย่างน้อย y 0 หรืออย่างน้อย y 2 ซึ่งสิ้นสุดสตริง

ตรงนี้เป็นสิ่งที่จำเป็นในการระบุ x / y ที่ไม่ได้อยู่ในชุดคันทอร์เพราะส่วนที่ซ้ำกันของการแสดงฐาน 3 ของจำนวนตรรกยะ x / y สามารถดูได้โดยเริ่มต้นที่หลัก # y + 1 หลังจากจุดที่ประกอบไปด้วยสาม และมีความยาวไม่เกิน y หลัก


1

CJam (19 ไบต์)

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

ชุดทดสอบออนไลน์

นี่คือบล็อกที่ไม่ระบุชื่อ (ฟังก์ชัน) ซึ่งรับสองอาร์กิวเมนต์บนสแต็กและใบไม้0หรือ1บนสแต็ก มันทำงานโดยการแปลงฐานเศษx/yเข้าไปในyฐาน3ตัวเลขและกลับมาที่แท้จริงของพวกเขามี IFF ไม่มี1หรือเพียงเป็นส่วนหนึ่งของคำต่อท้าย11 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อยู่ในชุดต้นเสียง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-1ฐาน 3 x/yหลักของ iคือการนับจำนวนของการทดสอบ เป็นค่าต่อไปของn เป็นจริงถ้าถึงศูนย์ (เพราะยุติการขยายตัว) หรือที่เราได้ทดสอบตัวเลขโดยไม่หา เป็นจริงถ้าเป็นความจริงหรือถ้าหลักถัดไปคือตรงจุดนี้เราจะหยุดการวนลูปและเอาท์พุทxjny-11fj1j

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.