Dans ce défi, vous recevrez une liste de points. Ces points se situent sur le périmètre d'un carré imaginaire . Votre objectif est de:
- Si possible, imprimez la rotation du carré, qui sera une valeur de [0, 90) où 0 représente un carré avec des lignes verticales et horizontales. La rotation doit être donnée en degrés comptés dans le sens antihoraire.
- Si la rotation du carré est ambiguë (par exemple ne recevoir que 2 points), imprimez "Inconnu"
- Si la création d'un carré étant donné les points est impossible, imprimez "Impossible"
Les points qui vous sont attribués sont garantis uniques et sans ordre particulier. Vous pouvez utiliser n'importe quel format pour entrer la liste, mais pour mes exemples, mes points seront au format x,y
et séparés par des espaces. Les nombres sont des nombres à virgule flottante, et vous pouvez supposer qu'ils se situent dans une plage que votre langue peut gérer. Votre sortie doit être précise à au moins 3 décimales et supposer que votre langue gère les nombres à virgule flottante avec une précision parfaite.
Voici quelques cas de test (j'ai fait la plupart de ceux-ci en utilisant des nombres entiers pour une visualisation facile, mais votre programme devrait gérer les virgules flottantes):
Inconnue:
0,0
0,0 1,0
0,0 1,0 0,1
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2
Impossible:
0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1
Possible (si non désigné, doit retourner 0):
0,0 1,0 2,0
0,0 0.3,0.3 0.6,0.6 (should return 45)
0,0 0.1,0.2 0.2,0.4 (should return appx 63.435 (the real value is arctan(2)))
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3
J'ai peut-être raté des cas de test intéressants. Si oui, veuillez commenter pour les ajouter.
C'est le code-golf, donc le code le plus court gagne!
Réponses:
Rév.1: Ruby, 354 octets
continuer à jouer au golf grâce à blutorange.
Rubis, 392 octets
L'algorithme est le suivant:
-Choisissez un point arbitraire (le premier) et déplacez-le à l'origine (soustrayez les coordonnées de ce point de tous les points de la liste.)
-Essayez toutes les rotations du carré autour de l'origine par incréments de 0,001 degré, jusqu'à 360 degrés.
-Pour une rotation donnée, si tous les points sont au-dessus de l'axe y, dessinez le plus petit carré possible autour de tous les points, en incorporant le point le plus bas et le plus à gauche.
-Vérifiez si tous les points sont sur le bord. Cela se fait avec un calcul doux qui prend chaque point, trouve les distances au carré de tous les bords et les multiplie ensemble. Cela donne un bon ajustement plutôt qu'une réponse oui / non. Il est interprété qu'une solution est trouvée si ce produit divisé par la longueur latérale ^ 8 est inférieur à 1E-9. En pratique, c'est moins qu'un degré de tolérance.
-Le meilleur ajustement est pris à 90 degrés et indiqué comme l'angle correct.
Actuellement, le code renvoie une valeur ambiguë si plus de 100 solutions sont trouvées (à une résolution de 0,001 degré. C'est 0,1 degré de tolérance.)
première fonction pleinement opérationnelle, dans le programme de test
J'ai laissé la résolution au 1 / 10e de la résolution requise pour rendre la vitesse raisonnable. Il y a une erreur de 0,01 dégressivité sur le tout dernier cas de test.
la version golfée, résolution conforme aux spécifications, prend environ une minute par appel, dans le programme de test.
Il y a toujours une erreur embêtante de 0,001 degrés sur le dernier cas de test. Augmenter encore la résolution l'éliminerait probablement.
Notez que pour environ 30% de code en plus, cet algorithme pourrait être adapté pour fonctionner rapidement: il est évident que dans les cas avec un nombre fini de solutions, l'un des bords se trouve à plat le long d'un cube, donc tout ce que nous devons vraiment essayer est ces angles qui correspondent à chaque paire de sommets. Il serait également nécessaire de faire un peu de tortillement pour vérifier qu'il n'y a pas une infinité de solutions.
la source
0,0 1,0 2,0 1,2
est toujours possible pour un carré de diagonale 0,0 ... 2,2. J'ai essayé cela, et aussi0,0 1,0 2,0 1,1
(ce dernier est en effet impossible.) Un autre point: considérez-vous acceptable ou inacceptable que mon code retourne impossible plutôt qu'inconnu quand un seul point est donné? J'apprécierais une réponse avant de commencer à jouer au golf.1,1
. Je ne sais pas comment1,2
on y est arrivé. Ce n'est pas acceptable.if..end
s car j'ai de gros problèmes avec les opérateurs ternaires imbriqués dans Ruby. Je vois que vous avez contourné cela en utilisant&&
.Perl
Bonjour, voici mon humble soution. Les cas de test sont placés dans le flux de données au bas du fichier. L'algorithme s'est développé grâce à une approche par erreur.
J'avoue que c'est une approche globalement heuristique, mais elle est vraiment rapide: elle résout tous les cas instantanément .
Je suis conscient qu'il y aura quelques bugs, mais jusqu'à présent, il donne des réponses correctes à tous les cas de test.
Je suis également conscient que le code le plus court l' emporte, mais je suis sûr que c'est l'un des plus courts au sens le plus rapide du terme.
Voici l'algorithme
examiner les points et pour chaque segment entre deux points enregistrer la pente, la longueur, l'ordonnée à l'origine, l'ordonnée à l'origine
trouver des lignes droites (c'est-à-dire trois points ou deux segments adjacents) et des pentes possibles distinctes (disons les rotations). Gardez une trace du segment le plus long disponible sur chaque ligne.
trouver toutes les distances entre un segment et un troisième point (cela devrait être utilisé pour le point 4). Gardez une trace de la distance minimale non nulle.
pour quatre points quelconques (grossièrement un rectangle) trouver des points intérieurs
Afficher les solutions:
A. Dites «impossible» s'il y a un ou plusieurs points intérieurs.
B. Une ligne:
Dans le cas de la plupart des points sur une seule ligne sans points intérieurs, dites "Possible"
En cas de points trop proches de la ligne, dites "Impossible"
C. Deux lignes:
Dites «Possible» lorsqu'il n'y a qu'une seule rotation possible
Dites «impossible» lorsqu'il y a plus d'une rotation
D. Pas de lignes: trouvez une rotation qui correspond à son segment de rotation à 90 °
Dites «Possible» si un seul ajustement ou autant de points conviennent.
Dites «impossible» si plus d'un correspond et pas autant que de points
Dites «inconnu» si le nombre de rotations convient.
Voici le code (tous les bugs connus sont résolus)
Et voici son ouptut
Cordialement.
Matteo.
la source