Considérons un triangle ABC où chaque côté a une longueur entière (un triangle intégral ). Définissez une médiane de ABC comme étant un segment de ligne allant d'un sommet au milieu du côté opposé. Dans la figure ci-dessous, les segments de ligne rouge représentent les médianes. Notez que tout triangle donné a trois médianes.
Soit n un entier positif. Combien de triangles intégraux non dégénérés dont la longueur de chaque côté est inférieure ou égale à n ont au moins une médiane intégrale?
Défi
Écrivez un programme pour calculer le nombre de triangles intégraux avec au moins une médiane intégrale pour une longueur de côté maximale donnée n . L'ordre des longueurs des côtés n'a pas d'importance, c'est-à-dire que <6,6,5> représente le même triangle que <5,6,6> et ne doit être compté qu'une seule fois. Exclure les triangles dégénérés tels que <1,2,3>.
Notation
Le plus grand n pour lequel votre programme peut générer le nombre de triangles en 60 secondes sur ma machine est votre score. Le programme avec le score le plus élevé gagne. Ma machine est une Sony Vaio SVF14A16CLB, Intel Core i5, 8 Go de RAM.
Exemples
Que T ( N ) soit le programme avec l' entrée N .
T(1) = 0
T(6) = 1
T(20) = 27
T(22) = 34
Notez que T (1) = T (2) = T (3) = T (4) = T (5) = 0 car aucune combinaison de côtés intégraux ne donnera une médiane intégrale. Cependant, une fois que nous arrivons à 6, nous pouvons voir que l'une des médianes du triangle <5,5,6> est 4, donc T (6) = 1.
Notez également que T (22) est la première valeur à laquelle le double comptage devient un problème: le triangle <16,18,22> a des médianes 13 et 17 (et 2sqrt (85)).
Calcul des médianes
Les médianes d'un triangle peuvent être calculées par les formules suivantes:
Current top score: Sp3000 - 7000 points - C
la source
Réponses:
C, force brute - n = 6080
C'est plus une référence qu'un concurrent sérieux, mais au moins cela devrait faire démarrer les choses.
n = 6080 est aussi élevé que je l'ai obtenu en une minute d'exécution sur ma propre machine, qui est un MacBook Pro avec un Intel Core i5. Le résultat que j'ai obtenu pour cette valeur est:
Le code est purement brutal. Il énumère tous les triangles dans la limite de taille et teste la condition:
la source
lrintf()
ou(int)roundf()
au lieu d'ajouter 0.5f et d'utiliser la troncature par défaut. Parfois, vous devez cependant l'utiliser-ffast-math
pour le compiler en une seulecvtss2si
instruction. gcc en lignelrintf()
etsqrtf
avec seulement-fno-math-errno
, donc vous obtenez un asm efficace: godbolt.org/g/E3hncQ . (J'ai utilisé-march=ivybridge
parce que c'est le CPU de l'OP). Avec-ffast-math
, clang transforme le sqrt en une itération rsqrt + Newton; IDK si c'est une victoire.roundf
. Utiliser(int)nearbyintf()
silrintf()
n'est pas en ligne, car il utilise le mode d'arrondi actuel au lieu d'un mode bizarre spécifique. stackoverflow.com/questions/37620659/…C, environ
66506900Je n'utilise pas vraiment C souvent, mais avec la quantité d'arithmétique en cours, cela semblait être un bon choix de langage. L'algorithme de base est une force brute comme la réponse de @ RetoKoradi , mais avec quelques optimisations simples. Je ne suis pas sûr que nos valeurs soient comparables, car l'ordinateur de @ RetoKoradi semble être plus rapide que le mien.
L'optimisation majeure contourne
% 4
complètement le contrôle. Un carré entiern*n
vaut 0 ou 1 modulo 4, selon qu'iln
est lui-même 0 ou 1 modulo 2. Ainsi, nous pouvons examiner toutes les possibilités pour(x, y, z) % 2
:Idéalement, il n'y a que deux cas à considérer:
(0, 0, 0)
et(1, 1, 0)
qui, étant donné les deux premiers côtésa, b
, équivaut au troisième côtéc
ayant la paritéa^b
:a^b
est la même parité quea-b
, donc plutôt que de chercher à partirc = a-b+1
de 1s et de remonter, cela nous permet de rechercherc = a-b+2
et de monter de 2s.Une autre optimisation vient du fait que, pour le
(1, 1, 0)
cas, nous n'avons besoin d'appeler is_square qu'une seule fois car une seule permutation fonctionne. Ceci est spécial dans le code en déroulant la recherche.L'autre optimisation incluse est simplement un échec rapide dans la
is_square
fonction.La compilation a été faite avec
-std=c99 -O3
.(Merci à @RetoKoradi d'avoir souligné que le
0.5
in is_square devait être0.5f
pour éviter une double conversion.)la source
0.5f
place de0.5
inis_square()
.0.5
est une constante de typedouble
, donc l'expression produira une valeur double lorsque vous l'ajoutez0.5
, y compris la conversion de type defloat
àdouble
pour l'autre terme.f
.Felix, inconnu
Fondamentalement, un port de la réponse C, mais c'est plus rapide que cela, testé avec
clang -O3
eticc -O3
. Felix et Nim sont littéralement les deux seuls langages que je connais qui peuvent battre C et C ++ aux benchmarks. Je travaille sur une version parallèle, mais ce sera un peu jusqu'à ce qu'elle soit finie, j'ai donc décidé de poster ceci à l'avance.J'ai aussi mis "inconnu" car mon ordinateur n'est pas forcément le plus rapide du monde ...
Commande utilisée pour construire:
Le C ++ généré est assez intéressant à regarder:
la source
C # (environ 11000?)
n
est considéré comme un argument de ligne de commande.Explication
la source
n=5000
sont de 67 secondes pour la réponse de Reto Koradi, 48 secondes pour la réponse de Sp3000 et 13 secondes pour ma réponse.C, n = 3030 ici
résultats:
le code ci-dessus serait la traduction en C de la réponse Axiom (si l'on ne compte pas la fonction isq ()).
Mon compilateur ne lie pas une fonction que d'autres utilisent sqrtf () ... ici il n'y a pas de fonction sqrt pour float ... Sont-ils sûrs que sqrtf est une fonction standard C?
la source
APL NARS, n =
239282 en 59 secondes(je traduis la réponse Axiom à un, en APL) test:
la source
Axiome, n = 269 en 59 sec
Si a, b, cx sont la longueur des côtés d'un triangle de longueur maximale côté n ...
Nous saurions que m: = sqrt ((2 * (a ^ 2 + b ^ 2) -cx ^ 2) / 4)
Comme l'a dit Peter Taylor, 4 | (2 * (a ^ 2 + b ^ 2) -cx ^ 2) et parce que 2 | 2 * (a ^ 2 + b ^ 2) que 2 | cx ^ 2 => cx = 2 * c. Donc à partir de 1 sera
a, et b doit avoir la même parité, donc on pourrait écrire b en fonction de a
que nous avons ça
de sorte que le (1) peut être réécrit, voir (2) (3) (4) comme:
où
résultats
la source
VBA 15 000 en DIX secondes!
Je m'attendais à beaucoup moins après ces autres articles. Sur un Intel 7 avec 16 Go de RAM, j'obtiens 13-15 000 en DIX secondes. Sur un Pentium avec 4 Go de RAM, j'obtiens 5-7 000 en DIX secondes. Le code est ci-dessous. Voici le dernier résultat sur le Pentium
Il a atteint un triangle avec les côtés 240, 239, 31 et un milieu de 121. Le nombre de médiums est de 7 371.
la source