È all'interno del set Cantor?


20

La sfida

Per questa sfida, dovresti determinare se un determinato numero è nel set Cantor. Quindi, per prima cosa, definiamo il set Cantor.

Innanzitutto, inizia con i numeri compresi tra 0 e 1. Tutti i numeri al di fuori di questo intervallo non si trovano nel set Cantor. Ora, dividiamo i numeri in tre parti uguali: [0,1 / 3], [1 / 3,2 / 3], [2/3, 1]. Tutti i numeri non compresi negli intervalli della prima e dell'ultima parte non si trovano nel set Cantor. Ora, ripeti questo processo per i segmenti [0,1 / 3] e [2/3, 1]. Quindi ripeti su ciò che resta. Continui a farlo per sempre. Alla fine, tutti i numeri rimanenti si trovano nel set Cantor. Ecco un diagramma delle prime sei iterazioni:

Diagramma di Cantor


Ingresso

Due numeri interi xe y.
0 < y < 2^15
0 <= x <= y
Il massimo comune denominatore di xed yè 1, a meno che x == 0.


Produzione

Veramente se x/yè nel set Cantor.
Falsy se x/ynon è nel set Cantor.


Esempi

Ora, vediamo alcuni esempi di numeri che si trovano nel set Cantor.

1/3 -> true  

È su un confine e i confini non vengono mai rimossi.

1/4 -> true  

1/4non è mai nel terzo medio di un segmento, anche se non è mai al limite. Se segui il suo percorso, scoprirai che si alterna tra l'essere nel primo e l'ultimo terzo di una sezione.

1/13 -> true  

1/13 si alterna tra la prima, la prima e l'ultima sezione.

1/5 -> false

1/5 rientra nel primo blocco vuoto della terza riga nel diagramma sopra, tra 1/9 e 2/9.

Altri casi di test:

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

Puoi provare altri numeri con questo frammento:


Obbiettivo

Vince la persona con il minor numero di byte.


È garantito che l'ingresso non sia (0,0)? La frazione è data nella forma più semplice?
xnor

1
@xnor guarda l'intervallo indicato per y. Sto per dire che la frazione è nella forma più semplice a meno chex == 0
TheNumberOne

Alcuni casi di test in cui x! = 1 sarebbe buono. Inoltre, lo snippet dice che 1/3 non è nel set di cantor.
xnor

@xnor Aggiunto e risolto;)
TheNumberOne

6
Cantor può essere trovato?
mbomb007,

Risposte:


13

Mathematica, 54 byte

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

Funzione senza nome che prende una frazione x/ycome input, dove y > 0e 0 ≤ x ≤ y, e ritorno Trueo False.

Un numero reale compreso tra 0 e 1 è impostato nel Cantor proprio quando nessuna delle cifre nella sua espansione di base 3 è uguale a 1; l'eccezione è che una frazione il cui denominatore è una potenza di 3 (la cui espansione di base 3 termina quindi) può finire con un 1.

RealDigits[#,3][[1]]fornisce tutte le cifre dell'espansione base-3 dell'input frazionario #, in una forma simile {1, 0, 2, {0, 1, 0, 2}}: l'ultima lista è la parte periodica dell'espansione, mentre gli interi in precedenza sono le cifre prima che inizi la periodicità. Se l'espansione base-3 è periodica immediatamente, l'output è simile {{0, 1, 0, 2}}; se l'espansione base-3 termina, il modulo è simile {1, 0, 2}.

Quindi vogliamo verificare, usando ~FreeQ~1, se la lista è libera 1o meno. Tuttavia, a causa della cosa di espansione terminante, vogliamo eliminare l'ultimo elemento dell'elenco se è uguale 1; questo è ciò che If[Last@#===1,Most@#,#]compie. ( ===È necessario per confrontare un elenco potenziale con 1: ==da solo rimane non valutato in quella situazione.)


4
Sono sorpreso che Mathematica non abbia IsCantorNumberma abbia una funzione da determinare se qualcosa è una capra .
Brain Guider,

3
Beh, non so, che emergono di più nella vita reale: capre o frattali? ;)
Greg Martin,

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

Tale regola eliminerebbe anche i segni finali 1nella parte periodica, il che porta a risposte errate. Ad esempio, l'espansione base-3 di 7/8 è .21212121 ...., oppure {{2,1}}; ma la regola suggerita lo cambierebbe in {{2}}, che è privo di 1s ma non dovrebbe esserlo.
Greg Martin,

Touché. Che ne dici #==0||FreeQ[RealDigits[#,3]/.{{x___,1},_}:>{x},1]&? Se termina e zero RealDigits[#,3]sarà del modulo {{__Integer},-1}e se si ripete sarà del modulo {{___Integer,{__Integer}},-1}, giusto? Sono su cellulare, quindi è difficile testarlo adesso. Se funziona, anche l'uso della notazione infix per RealDigitspotrebbe funzionare.
ngenisi,

9

C (gcc) , 61 59 58 byte

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

Sfrutta la simmetria del set Cantor. Si interrompe dopo le yiterazioni per evitare un ciclo infinito.

Provalo online!


7

Gelatina , 22 17 16 15 byte

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

Stampa 3 per verità, niente per falsità.

Provalo online!

sfondo

Una proprietà ben nota dell'insieme Cantor è che contiene esattamente quei numeri tra 0 e 1 che possono essere scritti senza 1 nella loro espansione ternaria.

Si noti che alcuni numeri - precisamente i bordi giusti degli intervalli chiusi coinvolti nella costruzione dell'insieme - possono essere scritti con un singolo (finale) 1 o con una quantità infinita di 2 finali . Ad esempio, 1 = 1 3 = 0,22222… 3 e 1/3 = 0,1 3 = 0,022222… 3 , proprio come 0,5 10 = 0,499999… 10 .

Per evitare il caso speciale dei bordi giusti, possiamo verificare che 1 sia l'espansione decimale più breve sia in x / y che in 1 - x / y = (y - x) / y , dove x / y è un margine destro iff (y - x) / y è un bordo sinistro. Se almeno uno di essi non contiene 1 , x / y appartiene all'insieme Cantor.

Come funziona

,ạµ%⁹×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è il vero true+1.
Magic Octopus Urn

3

JavaScript (ES6), 65 67

Modifica 2 byte salvati grazie a @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

Meno golf

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
}

Test

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))
)  


Penso che puoi sostituire n=n%d*3con q=n/d|0e poi sostituire z[n]conz[n=n%d*3]
Luca

2

JavaScript (ES6), 55 byte

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

Usalo indicando prima il denominatore e il secondo numeratore. Il modulo standard è un byte più lungo:

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

Spiegazione

Se una frazione non è nel set Cantor, ad un certo punto deve cadere in una delle sezioni centrali; pertanto, la sua rappresentazione nella base 3 deve contenere un 1 seguito a un certo punto da una cifra diversa da zero. Funziona così:

  • z tiene traccia del fatto che abbiamo trovato un 1.
  • q è la cifra corrente nella base 3.
  • !z|!qè vero se zè falso (non abbiamo trovato un 1) o qè falso (la cifra corrente è 0).

Se nscende a zero prima di trovare una cifra diversa da zero da qualche parte dopo un 1, la frazione è nel set di Cantor e torniamo 1.


2

Utilità Bash + GNU, 62 byte

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

Provalo online!

Passalo due argomenti interi con arg1 <= arg2 e 0 <arg2.

L'output viene restituito nel codice di uscita (0 per falsy, 1 per verità), come consentito dai metodi I / O PPCG .

Ho il sospetto che il regex possa essere ulteriormente approfondito, forse anche eliminando il comando tr in favore dell'uso di grep -z, ma questo è il più breve che sono stato in grado di trovare. (Sfortunatamente, grep -z non è compatibile con grep -P e l'opzione -P per ottenere regex in stile perl è richiesta per la sintassi?!).

Programma test e output:

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

Spiegazione

parte in cc (gli argomenti sono xey):

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.

parte tr e grep:

Un problema minore è che, sebbene dc gestisca numeri interi arbitrariamente grandi, quando dc stampa un numero elevato, lo spezzerà in righe di 69 caratteri, con ogni riga tranne l'ultima che termina con una barra rovesciata e con una nuova riga dopo ogni riga.

Il comando tr elimina eventuali barre rovesciate e newline. Questo lascia solo una riga.

Il comando grep usa quindi una regex in stile perl (opzione -P, che è un'estensione GNU). La regex corrisponde se la riga contiene un 1 non seguito da almeno y 0 o almeno y 2 che quindi termina la stringa.

Questo è esattamente ciò che è necessario per identificare x / y come non nel set Cantor, perché la parte ripetuta della rappresentazione base-3 del numero razionale x / y può essere vista come a partire dalla cifra # y + 1 dopo il punto ternario , ed è lungo al massimo y cifre.


1

CJam (19 byte)

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

Suite di test online

Questo è un blocco (funzione) anonimo che accetta due argomenti nello stack e lascia 0o 1nello stack. Funziona mediante la conversione di base della frazione x/yin cifre di ybase 3e la restituzione di iff veri e propri che contengono no 1o l'unica 1parte di un suffisso 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 byte

gu*3hS,G-QGQE0

Basato sulla mia soluzione C. ysulla prima riga di input, xsulla seconda.

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

Se si x/ytrova nel set Cantor, xrimane tra 0e y. Altrimenti, xdiventa maggiore rispetto ya un punto, quindi diverge all'infinito negativo nelle iterazioni rimanenti.

Provalo online!


0

Lotto, 91 byte

@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%

Verifica la prima y-1base di 3 cifre di x/y. iè il conteggio delle cifre testate. nè il prossimo valore di x. jè vero se nraggiunge lo zero (perché l'espansione termina) o abbiamo testato le y-1cifre senza trovare a 1. fè vero se jè vero o se la cifra successiva è a 1, a quel punto interrompiamo il looping e l'output j.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.