Étant donné trois cercles mutuellement tangents, nous pouvons toujours trouver deux autres cercles qui sont tangents à tous les trois. Ces deux sont appelés cercles apolliniens . Notez que l'un des cercles apolliniens pourrait en fait être autour des trois cercles initiaux.
À partir de trois cercles tangents, nous pouvons créer une fractale appelée joint Apollonian , par le processus suivant:
- Appelez les 3 cercles initiaux les cercles parents
- Trouver les deux cercles apolliniens des cercles parents
- Pour chaque cercle apollinien:
- Pour chaque paire des trois paires de cercles parents:
- Appelez le cercle Apollonian et les deux cercles parents le nouvel ensemble de cercles parents et recommencez à partir de l'étape 2.
- Pour chaque paire des trois paires de cercles parents:
Par exemple, en commençant par des cercles de taille égale, nous obtenons:
Image trouvée sur Wikipédia
Il y a encore un peu de notation dont nous avons besoin. Si nous avons un cercle de rayon r de centre (x, y) , nous pouvons définir sa courbure comme k = ± 1 / r . Habituellement, k sera positif, mais nous pouvons utiliser k négatif pour désigner le cercle qui entoure tous les autres cercles dans le joint (c'est-à-dire que toutes les tangentes touchent ce cercle de l'intérieur). Ensuite, nous pouvons spécifier un cercle avec un triplet de nombres: (k, x * k, y * k) .
Aux fins de cette question, nous supposerons un entier positif k et rationnel x et y .
D'autres exemples de tels cercles peuvent être trouvés dans l'article Wikipedia .
Il y a aussi des trucs intéressants sur les joints intégraux dans cet article (entre autres choses amusantes avec des cercles).
Le défi
Vous recevrez 4 spécifications de cercle, dont chacune ressemblera (14, 28/35, -112/105)
. Vous pouvez utiliser n'importe quel format de liste et opérateur de division qui vous convient, de sorte que vous pouvez simplement eval
saisir les données si vous le souhaitez. Vous pouvez supposer que les 4 cercles sont en effet tangents les uns aux autres et que le premier a une courbure négative. Cela signifie que vous avez déjà reçu le cercle apollinien environnant des trois autres. Pour une liste d'exemples d'entrées valides, voir le bas du défi.
Écrivez un programme ou une fonction qui, compte tenu de cette entrée, dessine un joint apollinien.
Vous pouvez saisir des données via l'argument de fonction, ARGV ou STDIN et rendre la fractale à l'écran ou l'écrire dans un fichier image dans le format de votre choix.
Si l'image résultante est tramée, elle doit être d'au moins 400 pixels de chaque côté, avec moins de 20% de remplissage autour du plus grand cercle. Vous pouvez arrêter la récurrence lorsque vous atteignez des cercles dont le rayon est inférieur à un 400e du plus grand cercle d'entrée, ou des cercles plus petits qu'un pixel, selon la première éventualité.
Vous devez dessiner uniquement les contours des cercles, pas les disques pleins, mais les couleurs de l'arrière-plan et des lignes sont votre choix. Les contours ne doivent pas dépasser un 200e du diamètre des cercles extérieurs.
Il s'agit du code golf, donc la réponse la plus courte (en octets) l'emporte.
Exemples d'entrées
Voici tous les joints intégrés de l'article Wikipedia convertis au format d'entrée prescrit:
[[-1, 0, 0], [2, 1, 0], [2, -1, 0], [3, 0, 2]]
[[-2, 0, 0], [3, 1/2, 0], [6, -2, 0], [7, -3/2, 2]]
[[-3, 0, 0], [4, 1/3, 0], [12, -3, 0], [13, -8/3, 2]]
[[-3, 0, 0], [5, 2/3, 0], [8, -4/3, -1], [8, -4/3, 1]]
[[-4, 0, 0], [5, 1/4, 0], [20, -4, 0], [21, -15/4, 2]]
[[-4, 0, 0], [8, 1, 0], [9, -3/4, -1], [9, -3/4, 1]]
[[-5, 0, 0], [6, 1/5, 0], [30, -5, 0], [31, -24/5, 2]]
[[-5, 0, 0], [7, 2/5, 0], [18, -12/5, -1], [18, -12/5, 1]]
[[-6, 0, 0], [7, 1/6, 0], [42, -6, 0], [43, -35/6, 2]]
[[-6, 0, 0], [10, 2/3, 0], [15, -3/2, 0], [19, -5/6, 2]]
[[-6, 0, 0], [11, 5/6, 0], [14, -16/15, -4/5], [15, -9/10, 6/5]]
[[-7, 0, 0], [8, 1/7, 0], [56, -7, 0], [57, -48/7, 2]]
[[-7, 0, 0], [9, 2/7, 0], [32, -24/7, -1], [32, -24/7, 1]]
[[-7, 0, 0], [12, 5/7, 0], [17, -48/35, -2/5], [20, -33/35, 8/5]]
[[-8, 0, 0], [9, 1/8, 0], [72, -8, 0], [73, -63/8, 2]]
[[-8, 0, 0], [12, 1/2, 0], [25, -15/8, -1], [25, -15/8, 1]]
[[-8, 0, 0], [13, 5/8, 0], [21, -63/40, -2/5], [24, -6/5, 8/5]]
[[-9, 0, 0], [10, 1/9, 0], [90, -9, 0], [91, -80/9, 2]]
[[-9, 0, 0], [11, 2/9, 0], [50, -40/9, -1], [50, -40/9, 1]]
[[-9, 0, 0], [14, 5/9, 0], [26, -77/45, -4/5], [27, -8/5, 6/5]]
[[-9, 0, 0], [18, 1, 0], [19, -8/9, -2/3], [22, -5/9, 4/3]]
[[-10, 0, 0], [11, 1/10, 0], [110, -10, 0], [111, -99/10, 2]]
[[-10, 0, 0], [14, 2/5, 0], [35, -5/2, 0], [39, -21/10, 2]]
[[-10, 0, 0], [18, 4/5, 0], [23, -6/5, -1/2], [27, -4/5, 3/2]]
[[-11, 0, 0], [12, 1/11, 0], [132, -11, 0], [133, -120/11, 2]]
[[-11, 0, 0], [13, 2/11, 0], [72, -60/11, -1], [72, -60/11, 1]]
[[-11, 0, 0], [16, 5/11, 0], [36, -117/55, -4/5], [37, -112/55, 6/5]]
[[-11, 0, 0], [21, 10/11, 0], [24, -56/55, -3/5], [28, -36/55, 7/5]]
[[-12, 0, 0], [13, 1/12, 0], [156, -12, 0], [157, -143/12, 2]]
[[-12, 0, 0], [16, 1/3, 0], [49, -35/12, -1], [49, -35/12, 1]]
[[-12, 0, 0], [17, 5/12, 0], [41, -143/60, -2/5], [44, -32/15, 8/5]]
[[-12, 0, 0], [21, 3/4, 0], [28, -4/3, 0], [37, -7/12, 2]]
[[-12, 0, 0], [21, 3/4, 0], [29, -5/4, -2/3], [32, -1, 4/3]]
[[-12, 0, 0], [25, 13/12, 0], [25, -119/156, -10/13], [28, -20/39, 16/13]]
[[-13, 0, 0], [14, 1/13, 0], [182, -13, 0], [183, -168/13, 2]]
[[-13, 0, 0], [15, 2/13, 0], [98, -84/13, -1], [98, -84/13, 1]]
[[-13, 0, 0], [18, 5/13, 0], [47, -168/65, -2/5], [50, -153/65, 8/5]]
[[-13, 0, 0], [23, 10/13, 0], [30, -84/65, -1/5], [38, -44/65, 9/5]]
[[-14, 0, 0], [15, 1/14, 0], [210, -14, 0], [211, -195/14, 2]]
[[-14, 0, 0], [18, 2/7, 0], [63, -7/2, 0], [67, -45/14, 2]]
[[-14, 0, 0], [19, 5/14, 0], [54, -96/35, -4/5], [55, -187/70, 6/5]]
[[-14, 0, 0], [22, 4/7, 0], [39, -12/7, -1/2], [43, -10/7, 3/2]]
[[-14, 0, 0], [27, 13/14, 0], [31, -171/182, -10/13], [34, -66/91, 16/13]]
[[-15, 0, 0], [16, 1/15, 0], [240, -15, 0], [241, -224/15, 2]]
[[-15, 0, 0], [17, 2/15, 0], [128, -112/15, -1], [128, -112/15, 1]]
[[-15, 0, 0], [24, 3/5, 0], [40, -5/3, 0], [49, -16/15, 2]]
[[-15, 0, 0], [24, 3/5, 0], [41, -8/5, -2/3], [44, -7/5, 4/3]]
[[-15, 0, 0], [28, 13/15, 0], [33, -72/65, -6/13], [40, -25/39, 20/13]]
[[-15, 0, 0], [32, 17/15, 0], [32, -161/255, -16/17], [33, -48/85, 18/17]]