L' arbre de Stern-Brocot est un arbre binaire de fractions où chaque fraction est acquise en ajoutant les numérateurs et les dénominateurs des deux fractions voisines dans les niveaux ci-dessus.
Il est généré en commençant par 0/1
et en 1/0
tant que "fractions de point final", et à partir de là, en itérant en plaçant une fraction entre chaque paire de fractions consécutives en ajoutant les numérateurs et les dénominateurs de ces fractions, comme ceci:
0. 0/1 1/0
1. 0/1 1/1 1/0
2. 0/1 1/2 1/1 2/1 1/0
3. 0/1 1/3 1/2 2/3 1/1 3/2 2/1 3/1 1/0
4. 0/1 1/4 1/3 2/5 1/2 3/5 2/3 3/4 1/1 4/3 3/2 5/3 2/1 5/2 3/1 4/1 1/0
Dans chaque itération de l'arbre Stern-Brocot (la n
ième itération), il y a des 2^n + 1
éléments dans la séquence, auxquels nous pouvons attribuer une fraction de 0/2^n
à 2^n/2^n
. Chaque nouvelle itération insère simplement une fraction "à mi-chemin" entre chaque paire de fractions consécutives.
Cela fait de l'arbre de Stern-Brocot une correspondance biunivoque entre les nombres rationnels positifs et les fractions binaires entre 0 et 1, ce qui sert également de preuve que les deux ensembles ont la même cardinalité.
Votre tâche consiste à écrire un programme ou une fonction qui, étant donné le numérateur et le dénominateur d'un nombre rationnel positif en termes les plus bas, détermine la fraction binaire qui correspond à la position de cette fraction dans l'arbre Stern-Brocot.
Des exemples d'entrées et de sorties sont fournis ci-dessous:
2/3 -> 3/8 (4th number in iteration 3)
4/7 -> 9/32 (between 1/2 and 3/5 in the chart above)
1/1 -> 1/2 (middle number in the first iteration)
Entrées que vous n'avez pas besoin de prendre en charge, mais qui sont incluses pour référence:
0/1 -> 0/1 (0/1 is considered the left number)
1/0 -> 1/1 (1/0 is considered the rightmost number)
Le programme le plus court dans n'importe quelle langue pour atteindre cet objectif gagne.
1/1 => 1
,1/2 => 2
,2/1 => 3
,1/3 => 4
, etc.). Si le nombre ainsi généré pour un nœud estn
, alors2^lg n
(journal binaire) est le bit le plus élevé définin
et la fraction binaire souhaitée est(2*(n - 2^lg n) + 1) / 2^(lg n + 1)
. (Quiconque tente une solution d'assembleur dans un jeu d'instructions avec un bit de jeu le plus élevé voudra probablement utiliser cette approche).Réponses:
GolfScript (
49 4846 caractères)ou
Les deux sont des fonctions qui prennent le numérateur et le dénominateur sur la pile et laissent le numérateur et le dénominateur sur la pile. Démo en ligne .
L'idée principale est exprimée en pseudocode dans la section 4.5 de Concrete Mathematics (p122 dans mon édition):
Si la chaîne de Ls et Rs est interprétée comme une valeur binaire avec L = 0 et R = 1, deux fois cette valeur plus un est le numérateur et le dénominateur est un peu plus long.
Comme point d'intérêt pour Golfscripters, c'est l'une de ces rares occasions où j'ai trouvé déplier utile. (Ok, je ne l'utilise que comme compteur de boucles, mais c'est mieux que rien).
la source
Mathematica,
130 114111 111 caractèresExemple:
la source
Rubis,
132125Rubied & Golfed la solution de référence de @JoeZ.
Exemples d'utilisation:
la source
Ruby (69 caractères)CoffeeScript (59 caractères)Il s'agit d'une fonction qui prend le numérateur et le dénominateur comme arguments et renvoie un tableau contenant le numérateur et le dénominateur après la bijection.
Démo en ligne
Il utilise la même approche que ma solution GolfScript ci-dessus, mais est beaucoup plus lisible car je peux utiliser 4 variables sans avoir à se soucier de la mise en boîte et du décompression dans un tableau. J'ai choisi CoffeeScript car il ne préfixe pas les variables
$
(20 caractères enregistrés sur PHP, par exemple), a une syntaxe de définition de fonction courte qui autorise les valeurs de paramètre par défaut (il n'est donc pas nécessaire d'envelopperf(a,b,x,y)
une fonctiong(a,b) = f(a,b,0,1)
), et me permet d'utiliser des booléens comme entiers dans expressions avec des valeurs utiles. Pour ceux qui ne le connaissent pas, CoffeeScript n'a pas l'opérateur ternaire standard de style C (C?P:Q
), mais je peux le remplacerC&&P||Q
ici carP
il ne sera jamais faux.Une alternative sans doute plus élégante, mais sans doute moins courte, est de remplacer la soustraction répétée par la division et le modulo:
(65 caractères; démo en ligne ). L'écrire de cette façon expose la relation avec l'algorithme d'Euclide.
la source
a<b
qui vous font économiser un caractère. L'inscription enc
donne deux autres. Vous pouvez également considérer la syntaxef=->a,b,x=0,y=1{...}
pour une définition encore plus courte.c=a<b ?
avec un espace supplémentaire aprèsb
. Sinon, le point d'interrogation est traité comme faisant partie dub
.Python - 531
Une solution non golfée en Python, pour servir de solution de référence en dernier lieu:
Il effectue simplement une recherche binaire entre les fractions, profitant du fait que le médian de deux fractions sera toujours entre les valeurs de ces deux fractions.
la source
GolfScript, 54 caractères
L'entrée doit être donnée sur STDIN sous la forme spécifiée dans la tâche. Vous pouvez essayer le code en ligne .
la source
Mathematica 138
Pas aussi rationalisé que la procédure d'alephalpha, mais c'était le meilleur que j'ai pu produire jusqu'à présent.
Essai
la source
JavaScript 186
pourrait être moins, mais j'aime le golf lisible
la source
Haskell , 125 octets
Essayez-le en ligne!
Entrée et sortie sous forme de paire
(n,d)
.Brève explication:
n
construit la ligne suivante à partir de la précédente en regardant chaque paire de fractions et en insérant la nouvelle entre la première et la récursion (ce qui placera la deuxième fraction juste là). Le cas de base est très simple car il s'agit essentiellement de la fonction d'identité. Lat
fonction itère cette fonction indéfiniment en fonction de l'état initial avec uniquement les deux fractions de frontière.t
indexe ensuite chaque ligne (i
) et chaque élément de la ligne (j
) et recherche la première fraction qui correspond à ce que nous recherchons. Quand il le trouve, il donnej
comme numérateur et2^i
comme dénominateur.la source