Это в пределах набора Кантора?

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.


Выход

Правда, если 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

Mathematica, 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]]дает все цифры в расширении base-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
Такое правило также удаляет конечные 1s в периодической части, что приводит к неправильным ответам. Например, расширение base-3 7/8 равно .21212121 .... или {{2,1}}; но предлагаемое правило изменит это на {{2}}, которое свободно от 1s, но не должно быть.
Грег Мартин
Туш. Как насчет #==0||FreeQ[RealDigits[#,3]/.{{x___,1},_}:>{x},1]&? Если оно завершается и ненулевое значение RealDigits[#,3]будет иметь форму, {{__Integer},-1}а если оно повторяется, оно будет иметь форму {{___Integer,{__Integer}},-1}, верно? Я на мобильном, так что сейчас сложно проверить. Если это работает, использование инфиксной нотации для RealDigitsможет также работать.
ngenisis
9

С (ССЗ) , 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итераций, чтобы избежать бесконечного цикла.

Попробуйте онлайн!

nwellnhof
источник
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 «S является кратчайшим расширение десятичной как в х / у и 1 - х / у = (у - х) / у , где х / у является правым краем тогда и только тогда (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.
Волшебная урна осьминога
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))
)  

edc65
источник
Я думаю , вы можете заменить 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.

ETHproductions
источник
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

объяснение

часть 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 использует регулярное выражение в стиле perl (опция -P, которая является расширением GNU). Регулярное выражение совпадает, если строка содержит 1, за которым не следует, по крайней мере, y 0 или, по крайней мере, y 2, которые затем заканчивают строку.

Это именно то, что необходимо для определения x / y как не входящего в набор Кантора, потому что повторяющаяся часть представления base-3 рационального числа x / y может рассматриваться как начинающаяся с цифры # y + 1 после троичной точки и длиной не более y цифр.

Митчелл Спектор
источник
1

CJam (19 байт)

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

Набор онлайн-тестов

Это анонимный блок (функция), который принимает два аргумента в стеке и оставляет 0или 1в стеке. Он работает путем базового преобразования дроби x/yв yбазовые 3цифры и возврата истины, если они не содержат 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

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в одной точке, затем расходится до отрицательной бесконечности на оставшихся итерациях.

Попробуйте онлайн!

nwellnhof
источник
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Значение true, если nдостигает нуля (поскольку расширение прекращается) или мы проверили y-1цифры, не найдя a 1. ftrue, если jtrue или если следующая цифра a 1, в этот момент мы прекращаем цикл и выводим j.

Нил
источник