Définissez la fonction f (n) pour un entier positif n comme suit:
- n / 2 , si n est pair
- 3 * n + 1 , si n est impair
Si vous appliquez à plusieurs reprises cette fonction à tout n supérieur à 0, le résultat semble toujours converger vers 1 (bien que personne n'ait encore pu le prouver). Cette propriété est connue sous le nom de conjecture de Collatz .
Définissez le temps d'arrêt d' un entier comme le nombre de fois que vous devez le passer par la fonction Collatz f avant qu'il n'atteigne 1. Voici les temps d'arrêt des 15 premiers entiers:
1 0
2 1
3 7
4 2
5 5
6 8
7 16
8 3
9 19
10 6
11 14
12 9
13 9
14 17
15 17
Appelons n'importe quel ensemble de numéros avec les mêmes cousins Collatz de temps d'arrêt . Par exemple, 5 et 32 sont des cousins Collatz, avec un temps d'arrêt de 5.
Votre tâche: écrire un programme ou une fonction qui prend un entier non négatif et génère l'ensemble des cousins Collatz dont le temps d'arrêt est égal à cet entier.
Contribution
Un entier non négatif S, donné via STDIN, ARGV ou un argument de fonction.
Production
Une liste de tous les numéros dont le temps d' arrêt est S, triée en ordre croissant ordre. La liste peut être sortie par votre programme, ou retournée ou sortie par votre fonction. Le format de sortie est flexible: séparé par des espaces, séparé par des sauts de ligne ou par tout autre format de liste standard de votre langue, tant que les chiffres sont facilement distinguables les uns des autres.
Exigences
Votre soumission doit donner des résultats corrects pour tout S ≤ 30. Elle doit se terminer en quelques secondes ou minutes, et non en heures ou jours.
Exemples
0 -> 1
1 -> 2
5 -> 5, 32
9 -> 12, 13, 80, 84, 85, 512
15 -> 22, 23, 136, 138, 140, 141, 150, 151, 768, 832, 848, 852, 853, 904, 906, 908, 909, 5120, 5376, 5440, 5456, 5460, 5461, 32768
Voici un résumé de la sortie pour S = 30 .
C'est le code-golf : le programme le plus court en octets gagne. Bonne chance!
Réponses:
Pyth,
262421 octetsCe code s'exécute instantanément pour
S=30
. Essayez-le vous-même: DémonstrationMerci à @isaacg pour avoir économisé 5 octets.
Explication
Mon code commence par
1
et annule la fonction Collatz. Il mappe tous les numérosd
de l'S-1
étape vers2*d
et(d-1)/3
. Le dernier n'est pas toujours valable cependant.la source
-F
.- ... 1
autour de la somme à l'intérieur de la réduction, vous n'avez pas besoin que la réduction soit un.u
, ni à l'-F
extérieur. Enregistre 2 caractères.q4%d6
est équivalent à!%hhd6
, mais 1 caractère plus court.Mathematica,
989289 octetsCette solution résout
S = 30
immédiatement:Il s'agit d'une fonction sans nom prenant
S
comme seul paramètre et renvoyant une liste des cousins Collatz.L'algorithme est une simple recherche en largeur. Les cousins Collatz pour une donnée
S
sont tous les entiers qui peuvent être atteints à partir des cousins Collatz pourS-1
via2*n
ou des nombres impairs qui peuvent être atteints via(n-1)/3
. Nous devons également nous assurer que nous ne produisons que les entiers qui ont été atteints pour la première fois après lesS
étapes, afin de garder une trace de tous les cousins précédentsp
et de les supprimer du résultat. Comme nous le faisons de toute façon, nous pouvons économiser quelques octets en calculant les étapes de tous les cousins précédents (pas seulement ceux deS-1
) pour enregistrer quelques octets (ce qui le rend légèrement plus lent, mais pas sensiblement pour le nécessaireS
).Voici une version légèrement plus lisible:
la source
Python 2,
8683757371 octetsAppelez comme
f(30)
.n = 30
est à peu près instantané.(Merci à @DLosc pour l'idée de récurrence en
k
étant un nombre plutôt qu'une liste de cousins, et quelques octets. Merci à @isaacg d'avoir abandonné~-
.)Cette variante est beaucoup plus courte, mais prend malheureusement trop de temps en raison d'une ramification exponentielle:
la source
f=lambda d,n=1:d and sorted(sum((c(d-1,x)for x in[n*2]+[~-n/3][:n>4==n%6]),[]))or[n]
. Il est moins efficace avec les appels de fonction mais le fait toujoursn = 30
en moins d'une seconde.f=lambda n,k=1:sorted([k][n:]or(k>4==k%6and f(n-1,~-k/3)or[])+f(n-1,k*2))
~-
n'est pas nécessaire parce que vous utilisez la division entière.CJam,
2926 octetsNous remercions @isaacg pour son idée de supprimer les 1 après chaque itération, ce qui m'a fait économiser deux octets directement et un autre indirectement.
Essayez-le en ligne dans l' interpréteur CJam (devrait se terminer en moins d'une seconde).
Comment ça marche
la source
CJam, 35 octets
Explication à venir. Il s'agit d'une version beaucoup plus rapide que l'approche "assez simple" (voir dans l'historique des modifications).
Essayez-le en ligne ici pour
N = 30
lequel s'exécute en quelques secondes sur la version en ligne et instantanément dans le compilateur Javala source
It should finish in seconds or minutes, not hours or days.
S=15
ne fonctionne pas.Java 8, 123
Quand
x
est 30, le programme prend 15 minutes et 29 secondes.Étendu
la source
javac 1.7.0_79
sur Ubuntu m'a donné beaucoup d'erreurs de syntaxe.i > 1 && ++n <= x
(vous pouvezn++
également la supprimer ) semble être encore plus rapide pour seulement 5 caractères de plus ... environ 3 minutes pour S = 30 pour moi. Cela se réduit en moins d'une minute en toute sécurité si.parallel()
Python 2, 118 octets
Eh bien, je me suis dit que je n'atteindrais pas le meilleur score Python après avoir vu la solution de @ Sp3000. Mais cela ressemblait à un petit problème amusant, donc je voulais quand même essayer une solution indépendante:
Même chose avant de supprimer les espaces:
Il s'agit d'une implémentation très directe d'une première recherche étendue. À chaque étape, nous avons l'ensemble avec le temps d'arrêt
k
, et dérivons l'ensemble avec le temps d'arrêtk + 1
en ajoutant les prédécesseurs possibles de chaque valeurt
dans l'ensemble de l'étapek
:2 * t
est toujours un prédécesseur possible.t
peut s'écrire3 * u + 1
, oùu
est un nombre impair qui n'est pas1
, alorsu
est également un prédécesseur.Il faut environ 0,02 secondes pour fonctionner
N = 30
sur mon MacBook Pro.la source
s.add(x)
n'est pas nécessaire dans un golf car vous pouvez généralement le faire à las|={x}
place. En outre, en utilisant~-x
au lieu d'(x+1)
enregistre sur les crochets. Mais sinon, bon travail :)s.add()
car elle devient une affectation et ne peut plus faire partie de l'expression. Cela fonctionne pour le premier. Lesfor
boucles basées sur des compteurs sont toujours aussi assez verbeuses. Je pensais que je pouvais le raccourcir en utilisant unewhile
boucle, mais il s'est avéré être exactement le même et la même longueur.for
boucle, puisque vous n'utilisez pas l'entrée d'une autre manière, vous pouvez probablement le faire à laexec"..."*input()
place :)PHP 5.4+, 178 octets
La fonction
Test et sortie
S (30) s'exécute en 0,24 seconde * , renvoie 732 éléments. Un couple sont
* Pour économiser sur les octets, j'ai dû ajouter
ksort
etarray_keys
à chaque étape. Le seul autre choix que j'avais était de faire une petite fonction wrapper qui appellec()
puis appellearray_keys
etksort
sur le résultat une fois. Mais en raison du temps encore décemment accrocheur, j'ai décidé de prendre le coup de performance pour un faible nombre d'octets. Sans un tri et un traitement appropriés, le temps est en moyenne de 0,07 seconde pour S (30).Si quelqu'un a des moyens intelligents d'obtenir le traitement approprié une seule fois sans trop d'octets supplémentaires, faites-le moi savoir! (Je stocke mes numéros sous forme de clés de tableau, d'où l'utilisation de
array_keys
etksort
)la source
Langage C
la source
{}
appuyer sur le bouton pour formater votre code, ce que j'ai fait pour vous. Mais comme le dit Alex, veuillez ajouter le nom de la langue (C?) Et essayez de jouer au golf :) Mais bienvenue!f
ne se comporte pas correctement. Avecs=5
, j'obtiens un tas de résultats incorrects.if (r == s)return true;
devrait êtrereturn (r==s)
, carf
ne reviendra pas de façon significative quand(r < s)
. En outre, je pense que vous devez déclareri
enf
tant quelong
, car il débordera assez rapidement pour certaines valeurs.return (r==s);