Чи це всередині набору Кантора?


20

Змагання

Для цього завдання ви повинні визначити, чи є вказане число в наборі Кантора. Отже, спочатку давайте визначимо набір Кантора.

Спочатку почніть з цифр від 0 до 1. Будь-які цифри поза цим діапазоном не містяться у наборі Кантора. Тепер поділимо числа на три рівні частини: [0,1 / 3], [1 / 3,2 / 3], [2/3, 1]. Будь-які числа, що не знаходяться у діапазоні першої та останньої частин, не містяться у наборі Кантора. Тепер ви повторите цей процес для сегментів [0,1 / 3] та [2/3, 1]. Потім ви повторите те, що залишається. Ви продовжуєте робити це назавжди. Зрештою, усі цифри, що залишилися, знаходяться у наборі Кантора. Ось схема перших шести ітерацій:

Кантора діаграма


Вхідні дані

Два цілих числа xі y.
0 < y < 2^15
0 <= x <= y
Найбільший спільний знаменник xі yдорівнює 1, якщо тільки немає x == 0.


Вихідні дані

Truthy якщо 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

Деякі тестові випадки, коли х! = 1 було б добре. Крім того, у вашому фрагменті сказано, що 1/3 відсутня в наборі кантора.
xnor

@xnor Додано та виправлено;)
TheNumberOne

6
Кантора його можна знайти?
mbomb007

Відповіді:


13

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

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

Безіменна функція, яка приймає дріб x/yяк вхід, де y > 0і 0 ≤ x ≤ y, і повертає Trueабо False.

Дійсне число між 0 і 1 знаходиться в наборі Кантора саме тоді, коли жодна цифра в його розширенні base-3 не дорівнює 1; виняток полягає в тому, що дробу, знаменником якої є сила 3 ​​(розширення бази-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

3
Що ж, я не знаю, чого в реальному житті більше придумують: кози чи фрактали? ;)
Грег Мартін

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

Таке правило також позбавлятиме від певного 1періоду періодичної частини, що призводить до неправильних відповідей. Наприклад, розширення 7/8 base-3 дорівнює .21212121 ...., або {{2,1}}; але запропоноване правило змінило би те {{2}}, що не містить 1s, але не повинно бути.
Грег Мартін

Touché. Як щодо #==0||FreeQ[RealDigits[#,3]/.{{x___,1},_}:>{x},1]&? Якщо він закінчується, а ненульовий RealDigits[#,3]буде форму, {{__Integer},-1}і якщо він повторюється, буде форму {{___Integer,{__Integer}},-1}, правда? Я на мобільному, тому зараз важко перевірити. Якщо це працює, також може бути використане позначення інфіксації RealDigits.
ngenisis


7

Желе , 22 17 16 15 байт

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

Друкує 3 для трюти, нічого для помилкового.

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

Фон

Добре відома властивість множини Кантора полягає в тому, що він містить саме ті числа між 0 і 1, які можна записати без 1 -х при їх потрійному розширенні.

Зауважимо, що деякі числа - саме праві краї закритих інтервалів, що беруть участь у побудові множини - можуть записуватися як з одиничним (заднім) 1, так і з нескінченною кількістю кінцевих 2 -х. Наприклад, 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 байти, збережені 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|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

Використовуйте, запиваючи в знаменнику перше, а числівник - друге. Стандартна форма - байт довше:

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|!qtrue якщо zfalse (ми не знайшли 1) або qfalse (поточна цифра дорівнює 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 для хибного, 1 для трибуна), як це дозволено методами PPCG вводу / виводу .

Я підозрюю, що регулярний вираз може бути додатково гольф, можливо, навіть усунення команди 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 як такий, що не знаходиться в наборі Кантора, тому що повторювана частина представлення бази-3 раціонального числа x / y може розглядатися як починається з цифри # y + 1 після потрійної точки , і становить максимум y цифр.


1

CJam (19 байт)

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

Інтернет-тестовий набір

Це анонімний блок (функція), який бере два аргументи на стеці та листі 0або 1на стеці. Він працює шляхом перетворення дробу x/yв yбазові 3цифри та повернення справжнього iff, якщо вони не містять, 1або є єдиною 1частиною суфікса 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

Піт , 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наступне значення x. jвірно, якщо nдосягає нуля (оскільки розширення припиняється) або ми перевірили y-1цифри, не знаходячи a 1. fє істинним, якщо jістинним, або якщо наступна цифра є a 1, в цей момент ми припиняємо циклічно та виводити j.

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