J'ai lu quelque chose sur les cercles quelque part, et je viens d'apprendre les disques ( c'est en fait un concept assez courant ) et j'ai pensé au codegolf.
Votre tâche consiste à randomiser un point / plusieurs points sur un disque avec le rayon 1.
Règles:
- Tous les points doivent avoir une probabilité égale pour être générés
- Des coordonnées en virgule flottante doivent être utilisées; l'exigence minimale est de deux décimales (par exemple, les points
(0.12, -0.45)
ou(0.00, -1.00)
sont valides) - Vous obtenez -20 octets si votre programme affiche réellement le cercle de délimitation et le ou les points générés dans celui-ci. Les coordonnées doivent toujours être valides mais ne sont pas affichées, et l'image générée doit avoir une taille d'au moins 201 x 201 pixels
- Vous obtenez -5 octets si votre programme prend le nombre de points à générer en entrée sur stdin
- Si vous décidez de ne pas tracer le cercle de délimitation et le (s) point (s), votre programme doit sortir le (s) point (s) généré (s) sur le format
(x, y)
ou(x,y)
sur stdout - Si vous décidez de prendre le nombre de points générés en entrée, mais pas de le tracer - votre programme doit sortir tous les points aléatoires au format indiqué ci-dessus avec ou sans un espace entre les deux.
La soumission la plus courte en octets gagne!
code-golf
math
graphical-output
random
patate douce
la source
la source
0.3503082505747327+0.13499221288682994j
.Réponses:
Pyth, 26 - 5 = 21 octets
Prend le nombre de coordonnées à générer sur stdin et les affiche sur stdout comme ceci:
Utilise une stratégie similaire à @ MartinBüttner, générant des coordonnées polaires et des rayons, sauf qu'il le fait en utilisant une exponentiation complexe.
la source
p
, n'est-ce pas? Il modifie simplement la sortie sur des lignes distinctes.CJam,
2827 octetsCette solution n'est pas basée sur le rejet. Je génère les points en coordonnées polaires, mais avec une distribution non uniforme des rayons pour obtenir une densité uniforme des points.
Testez-le ici.
Explication
Pourquoi ça marche? Considérons un espace étroit de rayon
r
et de (petite) largeurdr
. La zone est approximativement2π*r*dr
(si l'espace annulaire est étroit, la circonférence intérieure et extérieure sont presque identiques, et la courbure peut être ignorée, de sorte que la zone peut être traitée comme celle d'un rectangle avec des longueurs latérales de la circonférence et la largeur de la anneau). La zone augmente donc linéairement avec le rayon. Cela signifie que nous voulons également une distribution linéaire des rayons aléatoires, afin d'atteindre une densité constante (à deux fois le rayon, il y a deux fois plus de surface à remplir, donc nous voulons deux fois plus de points là-bas).Comment générer une distribution aléatoire linéaire de 0 à 1? Regardons d'abord le cas discret. Disons, nous avons une distribution souhaitée de 4 valeurs, comme
{0.1, 0.4, 0.2, 0.3}
(c'est-à-dire que nous voulons1
être 4 fois plus communs que0
, et deux fois plus communs que2
; nous voulons3
trois fois plus communs que0
):Comment choisir l'une des quatre valeurs avec la distribution souhaitée? Nous pouvons les empiler, choisir une valeur uniformément aléatoire entre 0 et 1 sur l'axe des y et choisir le segment à ce point:
Il existe cependant une manière différente de visualiser cette cueillette. On pourrait plutôt remplacer chaque valeur de la distribution par l'accumulation des valeurs jusqu'à ce point:
Et maintenant, nous traitons la ligne supérieure de ce graphique comme une fonction
f(x) = y
et l'inversons pour obtenir une fonction , que nous pouvons appliquer à une valeur uniformément aléatoire dans :g(y) = f-1(y) = x
y ∈ [0,1]
Cool, alors comment utiliser cela pour générer une distribution linéaire des rayons? Voici la distribution que nous voulons:
La première étape consiste à accumuler les valeurs de la distribution. Mais la distribution est continue, donc au lieu de résumer toutes les valeurs précédentes, nous prenons une intégrale de
0
àr
. On peut facilement résoudre ce analytiquement: . Cependant, nous voulons que cela soit normalisé, c'est-à-dire le multiplier par une constante telle que cela donne la valeur maximale de , donc ce que nous voulons vraiment, c'est :∫0r r dr = 1/2 r2
1
r
r2
Et enfin, nous inversons cela pour obtenir une fonction que nous pouvons appliquer à une valeur uniforme
[0,1]
, que nous pouvons à nouveau faire analytiquement: c'est juster = √y
, oùy
est la valeur aléatoire:Il s'agit d'une technique assez utile qui peut souvent être utilisée pour générer exactement des distributions simples (elle fonctionne pour n'importe quelle distribution, mais pour les plus compliquées, les deux dernières étapes peuvent devoir être résolues numériquement). Cependant, je ne l'utiliserais pas dans ce cas particulier dans le code de production, car la racine carrée, le sinus et le cosinus sont d'un coût prohibitif: l'utilisation d'un algorithme basé sur le rejet est en moyenne beaucoup plus rapide, car il n'a besoin que d'addition et de multiplication.
la source
Mathematica,
6844-20 = 24 octetsMerci beaucoup à David Carraher de m'avoir informé
RandomPoint
, qui a économisé 24 (!) Octets. Mathematica ne possède un pour tout intégré.Cela trace le point et le cercle de délimitation pour se qualifier pour le bonus:
Le résultat est une image vectorielle, donc la spécification de taille de 201x201 pixels n'a pas vraiment de sens, mais par défaut, elle est plus grande que cela.
la source
Graphics[{Circle[], Point@RandomPoint@Disk[]}]
?Graphics@{Circle[], Point@RandomPoint@Disk[]}
,
?CJam,
3126 octetsCela fonctionne en générant à plusieurs reprises des points aléatoires dans un carré de longueur de côté 2 et en conservant le premier qui tombe à l'intérieur du disque de l'unité.
Merci à @ MartinBüttner pour avoir joué au golf sur 3 octets!
Essayez-le en ligne dans l' interpréteur CJam .
Comment ça fonctionne
la source
iKe ,
5351 octetsRien de particulièrement spécial, mais je suppose que nous devrions avoir au moins une solution graphique:
Essayez-le dans votre navigateur .
Edit: je peux raser deux octets en appliquant l'approche de @ MartinBüttner pour modifier la distribution des coordonnées polaires. Je pense que c'est aussi un peu plus direct:
la source
Perl, 59 octets
C'est juste une solution simple, générer des points dans un carré et rejeter ceux trop loin. Mon astuce de golf singulière consiste à inclure les affectations à l'intérieur de la condition.
Edit: En cours de golf, j'ai trouvé un moyen intéressant d'imprimer des points aléatoires sur un cercle .
la source
Octave,
2453-20 = 33 octetsGénère 501 valeurs thêta également espacées plus un nombre aléatoire et les met à l'échelle à [0..2π]. Génère ensuite 501 1 pour le rayon du cercle, plus un rayon aléatoire pour le point et prend la racine carrée pour assurer une distribution uniforme sur le disque. Trace ensuite tous les points sous forme de coordonnées polaires.
Voici une rapide démonstration de la distribution (sans le cercle unitaire):
la source
Octave / Matlab,
7464 octetsMéthode de rejet , 64 octets:
Méthode directe , 74 octets (merci à Martin Büttner de m'avoir aidé à corriger deux erreurs):
la source
R,
999581-20 =797561 octetsUtilisez la construction de nombres complexes pour construire les x / y à partir des coordonnées polaires. Prendre l'entrée était un peu cher et il y a probablement une meilleure façon de le faire. Le
ylim
et permetde s'assurer que l'ensemble du cercle est tracé et lexlim
asp
assure que les points sont affichés sous le symbole du cercle.Merci à @jbaums et @flodel pour les économies
Essayez-le ici
la source
runif(9,0,1)
peut être simplifié enrunif(9)
symbols(0,0,1,i=F,asp=1,ylim=c(-1,1));points(complex(,,,runif(9),runif(9,-1)*pi))
yli
travaille à la place deylim
.Traitement / Java 141 octets-20 = 121
l'exigence de 201 * 201 étant la taille minimale m'oblige à mettre dans la
setup
méthode depuis Processing.org par défaut à 200x200 :(la source
QBasic, 138 octets - 20 - 5 = 113
Prend l'entrée de l'utilisateur et dessine le disque et les points. Testé sur QB64 .
C'est une stratégie assez simple de "lancer sur le jeu de fléchettes et de garder ce qui colle". Le hic, c'est que "ce qui colle" n'est pas déterminé mathématiquement mais graphiquement: un disque blanc est tracé sur un fond noir, puis les points générés aléatoirement sont rejetés jusqu'à ce qu'ils ne soient pas noirs. Les points eux-mêmes sont dessinés en bleu (bien qu'il soit difficile de dire quand ce sont des pixels uniques - cliquez sur l'image pour l'agrandir).
la source
awk - 95 - 5 = 90
Comme je n'étais pas tout à fait sûr de la partie rand () <. 5, j'ai fait quelques tests de distribution avec cela, en utilisant ce script:
qui pour une entrée de 1e7 me donne ce résultat, après avoir bu une ou deux fois à mon café:
qui je pense est tout à fait bien.
Une petite explication:
après avoir griffonné pendant un certain temps, il s'est avéré que si vous voulez diviser le disque en quatre anneaux de surface égale, les rayons où vous devriez couper sont sqrt (1/4), sqrt (1/2 ) et sqrt (3/4). Comme le rayon réel du point que je teste serait sqrt (x ^ 2 + y ^ 2), je peux ignorer l'enracinement carré. La "coïncidence" 1/4, 2/4, 3/4 pourrait être liée à ce que M. Buettner a souligné plus tôt.
la source
HPPPL , 146 (171-20-5) octets
Exemple pour 10000 points (y compris le chronométrage en secondes pour le vrai appareil):
La fonction elle-même est appelée par
r(n)
. Le reste de l'image ci-dessus est uniquement à des fins de synchronisation.Résultat (le diamètre du disque est de 236 pixels):
La version ci-dessus ne stocke pas les coordonnées du point, j'ai donc écrit une version qui prend deux paramètres
r(n,p)
.n
est le nombre de points etp=0
renvoie les points au terminal,p=1
trace les points et le disque), dans le cas où le stockage des coordonnées est obligatoire. Cette version fait 283 (308-20-5) octets de long:La version non golfée:
Sortie borne pour
r(10,0)
:r(10,1)
montre le disque avec les points, comme indiqué ci-dessus.la source
JavaScript, 75 octets
Basé sur le rejet:
Méthode directe (80 octets):
la source
Python,
135130 octetsSuppression des
**0.5
remerciements à la suggestion de @ jimmy23013 (car il s'agit d'un cercle unité, je vérifie maintenant si la distance au carré entre (x, y) et (0, 0) est égale à 1 2. C'est la même chose).Cela m'a également libéré pour supprimer les parenthèses.
la source
**0.5
.