J'ai trouvé cette séquence alors que je travaillais sur Evolution of OEIS , mais je n'ai jamais réussi à l'afficher comme réponse. Après avoir écrit une implémentation de référence dans Mathematica, j’ai pensé que c’était un exercice amusant à faire en tant que défi à part, alors nous y voilà.
Construisons un réacteur à fission numérique! Considérons un entier positif N
. À titre d'exemple, nous allons regarder 24
. Pour fissionner ce nombre, nous devons trouver le plus grand nombre d’ entiers positifs consécutifs à cette somme N
. Dans ce cas, c'est 7 + 8 + 9 = 24
. Nous avons donc divisé 24
en trois nouveaux numéros. Mais ce ne serait pas vraiment un réacteur à fission sans réactions en chaîne. Répétons donc le processus de manière récurrente pour ces composants:
24
/|\
/ | \
/ | \
7 8 9
/ \ /|\
3 4 / | \
/ \ / | \
1 2 2 3 4
/ \
1 2
Notez que nous arrêtons le processus chaque fois que le nombre ne peut pas être décomposé en entiers consécutifs plus petits. Notez également que nous aurions pu écrire en 9
tant que 4 + 5
, mais 2 + 3 + 4
a plus de composants. Le nombre de fission de N
est maintenant défini comme le nombre d'entiers obtenus dans ce processus, y compris N
lui-même. L'arbre ci-dessus a 13 nœuds, donc F(24) = 13
.
Cette séquence est l'entrée OEIS A256504 .
Les 40 premiers termes, à partir de N = 1
, sont
1, 1, 3, 1, 5, 6, 5, 1, 6, 7, 12, 10, 12, 11, 12, 1, 8, 16, 14, 17, 18, 18,
23, 13, 21, 18, 22, 23, 24, 19, 14, 1, 22, 20, 23, 24, 31, 27, 25, 26
Les 1000 premiers termes peuvent être trouvés dans cette pastebin .
Le défi
Étant donné un entier positif N
, déterminez son numéro de fission F(N)
. (Donc, vous n'avez pas besoin de couvrir le leader 0
énuméré sur OEIS.)
Vous pouvez écrire un programme ou une fonction en prenant l’entrée via STDIN (ou l’alternative la plus proche), un argument de ligne de commande ou une argumentation de fonction et en générant le résultat via STDOUT (ou l’alternative la plus proche), une valeur de retour de fonction ou un paramètre de fonction (out).
C'est le code de golf, donc la réponse la plus courte (en octets) gagne.
Question bonus: Pouvez-vous trouver des propriétés intéressantes de cette séquence?
la source
Réponses:
Pyth,
232221 octetsCeci définit une fonction récursive
y
. Essayez-le en ligne: démonstrationExplication:
la source
Fission ,
1328989887797 octetsCette réponse est un peu déraisonnablement longue (j'aimerais que nous ayons des régions réductibles ) ... s'il vous plaît, n'oubliez pas de faire défiler la page au-delà et de montrer aux autres réponses un peu d'amour!
Travailler sur ce code est ce qui a inspiré ce défi. Je voulais ajouter une réponse dans Fission à EOEIS, ce qui m'a amené à cette séquence. Cependant, pour apprendre réellement la fission et l’appliquer, il a fallu quelques semaines pour travailler dessus. Entre temps, la séquence avait vraiment pris de l'ampleur et j'ai donc décidé de poster un défi séparé pour elle (en plus, cela n'aurait pas été particulièrement long en bas de l'arbre sur EOEIS).
Je vous présente donc la monstruosité:
Il s'attend à ce qu'il n'y ait pas de fin de ligne sur l'entrée, vous pouvez donc l'appeler comme
echo -n 120 | ./Fission oeis256504.fis
.La mise en page pourrait probablement encore être plus efficace, alors je pense qu'il reste encore beaucoup à faire (par exemple, il contient
911581461374 espaces).Avant de passer à l'explication, une note sur le test: l' interprète officiel ne fonctionne pas entièrement tel quel. a)
Mirror.cpp
ne compile pas sur beaucoup de systèmes. Si vous rencontrez ce problème, commentez la ligne incriminée - le composant affecté (un miroir aléatoire) n'est pas utilisé dans ce code. b) Quelques bugs peuvent conduire à un comportement indéfini (et probablement pour un programme aussi complexe). Vous pouvez appliquer ce correctif pour les réparer. Une fois que vous avez fait cela, vous devriez pouvoir compiler l’interprète avecFait amusant: ce programme utilise presque tous les composants que la fission a à offrir, à l'exception de
#
(miroir aléatoire),:
(demi-miroir)-
ou|
(miroir simple) et"
(mode d'impression).Quoi sur Terre?
Attention: Ce sera assez long ... Je suppose que vous êtes vraiment intéressé par le fonctionnement de Fission et par la façon dont vous pourriez le programmer. Parce que si vous ne l'êtes pas, je ne sais pas comment je pourrais résumer ceci. (Le paragraphe suivant donne cependant une description générale de la langue.)
La fission est un langage de programmation bidimensionnel où les données et le flux de contrôle sont représentés par des atomes se déplaçant à travers une grille. Si vous avez déjà vu ou utilisé Marbelous auparavant, le concept devrait être vaguement familier. Chaque atome a deux propriétés entières: une masse non négative et une énergie arbitraire. Si la masse devient jamais négative, l'atome est retiré de la grille. Dans la plupart des cas, vous pouvez traiter la masse comme la "valeur" de l'atome et l'énergie comme une sorte de méta-propriété utilisée par plusieurs composants pour déterminer le flux des atomes (c'est-à-dire que la plupart des commutateurs dépendent du signe de l'énergie). Je vais désigner des atomes par
(m,E)
, si nécessaire. Au début du programme, la grille commence par un tas de(1,0)
des atomes où que vous vous trouviez sur l'un des quatre composantsUDLR
(où la lettre indique la direction dans laquelle l'atome se déplace initialement). Le tableau est ensuite peuplé de nombreux composants qui changent la masse et l’énergie des atomes, changent leur direction ou font d’autres choses plus sophistiquées. Pour une liste complète, voir la page esolangs , mais je vais en présenter la plupart dans cette explication. Un autre point important (que le programme utilise plusieurs fois) est que la grille est toroïdale: un atome qui frappe l'un des côtés réapparaît du côté opposé, se déplaçant dans la même direction.J'ai écrit le programme en plusieurs parties plus petites et les ai assemblées à la fin. C'est ainsi que je vais passer en revue les explications.
atoi
Ce composant peut sembler plutôt inintéressant, mais il est simple et agréable et me permet d’introduire un grand nombre des concepts importants de l’arithmétique et du flux de contrôle de Fission. Par conséquent, je vais passer en revue cette partie avec des détails assez minutieux afin de pouvoir réduire les autres parties à l'introduction de nouveaux mécanismes de fission et au fait de signaler des composants de niveau supérieur dont vous devez pouvoir suivre le flux de contrôle détaillé.
La fission peut uniquement lire les valeurs d'octet de caractères individuels, et non de nombres entiers. Bien que ce soit une pratique acceptable ici, je me suis dit que je pouvais le faire correctement et analyser les entiers réels sur STDIN. Voici le
atoi
code:Deux des composants les plus importants de la fission sont les réacteurs de fission et de fusion. Les réacteurs à fission sont l’un des types
V^<>
(le code ci-dessus utilise<
et>
). Un réacteur à fission peut stocker un atome (en l’envoyant dans le coin du personnage), la valeur par défaut(2,0)
. Si un atome frappe le sommet du personnage, deux nouveaux atomes seront envoyés aux côtés. Leur masse est déterminée en divisant la masse entrante par la masse stockée (c'est-à-dire divisant par deux en moitié) - l'atome de gauche obtient cette valeur et l'atome de droite reçoit le reste de la masse (c'est-à-dire que la masse est conservée dans la fission). . Les deux atomes sortants auront l'énergie entrante moinsl'énergie stockée. Cela signifie que nous pouvons utiliser des réacteurs de fission pour l'arithmétique, aussi bien pour la soustraction que pour la division. Si un réacteur de fission est touché depuis le site, l'atome est simplement réfléchi en diagonale et se dirigera ensuite vers le sommet du personnage.Les réacteurs de fusion sont l'un des
YA{}
(le code ci-dessus utiliseY
et{
). Leur fonction est similaire: ils peuvent stocker un atome (par défaut(1,0)
) et, lorsqu'ils sont touchés au sommet, deux nouveaux atomes sont envoyés aux côtés. Cependant, dans ce cas, les deux atomes seront identiques, conservant toujours l’énergie entrante et multipliant la masse entrante par la masse stockée. Autrement dit, par défaut, le réacteur à fusion duplique simplement tout atome atteignant son sommet. Quand ils touchent des côtés, les réacteurs à fusion sont un peu plus compliqués: l’atome est égalementstocké (indépendamment de l'autre mémoire) jusqu'à ce qu'un atome frappe le côté opposé. Lorsque cela se produit, un nouvel atome est libéré en direction du sommet dont la masse et l’énergie sont la somme des deux atomes anciens. Si un nouvel atome frappe le même côté avant qu'un atome correspondant n'atteigne le côté opposé, l'ancien atome sera simplement écrasé. Les réacteurs de fusion peuvent être utilisés pour mettre en œuvre l'addition et la multiplication.Une autre composante simple que je veux sortir de la voie est
[
et]
qui a simplement mis la direction de l'atome à droite et à gauche, respectivement (quelle que soit la direction entrante). Les équivalents verticaux sontM
(bas) etW
(haut) mais ils ne sont pas utilisés pour leatoi
code.UDLR
agissent également commeWM][
après avoir libéré leurs atomes initiaux.Quoi qu'il en soit, regardons le code là-haut. Le programme commence avec 5 atomes:
R
etL
au bas obtiennent simplement que leur incrément de masse (avec+
) devienne(10,0)
, puis stocké dans un réacteur à fission et dans un réacteur à fusion, respectivement. Nous allons utiliser ces réacteurs pour analyser l’entrée base 10.L
dans le coin supérieur droit obtient sa masse décrémentée (à_
) pour devenir(0,0)
et est stocké dans le côté d'un réacteur à fusionY
. C'est pour garder une trace du nombre que nous lisons - nous allons l'augmenter et le multiplier progressivement au fur et à mesure que nous lisons des chiffres.R
le coin supérieur gauche, la masse est réglée sur le code de caractère de0
(48)'0
, puis la masse et l’énergie sont échangées contre la dernière@
et enfin augmentées une fois avec+
pour donner(1,48)
. Il est ensuite redirigé avec des miroirs diagonaux\
et/
stocké dans un réacteur à fission. Nous allons utiliser la48
soustraction pour transformer l'entrée ASCII en valeurs réelles des chiffres. Nous avons également dû augmenter la masse1
pour éviter la division par0
.U
coin en bas à gauche est ce qui met tout en mouvement et est utilisé à l’origine uniquement pour le contrôle du flux.Après avoir été redirigé vers la droite, l'atome de contrôle frappe
?
. C'est le composant d'entrée. Il lit un caractère et définit la masse de l'atome sur la valeur ASCII lue et sur l'énergie0
. Si nous touchons EOF à la place, l'énergie sera réglée sur1
.L'atome continue et ensuite frappe
%
. Ceci est un commutateur de miroir. Pour les énergies non positives, cela agit comme un/
miroir. Mais pour l'énergie positive, il agit comme un\
(et diminue également l'énergie de 1). Ainsi, pendant que nous lisons les caractères, l'atome sera réfléchi vers le haut et nous pouvons traiter le personnage. Mais lorsque nous en aurons terminé avec l'entrée, l'atome sera réfléchi vers le bas et nous pouvons appliquer une logique différente pour extraire le résultat. Pour votre information, le composant opposé est&
.Nous avons donc un atome en mouvement pour le moment. Ce que nous voulons faire pour chaque caractère est de lire sa valeur numérique, de l'ajouter à notre total cumulé, puis de multiplier ce total cumulé par 10 pour préparer le prochain chiffre.
L'atome de caractère frappe d'abord un réacteur de fusion (par défaut)
Y
. Cela divise l'atome et nous utilisons la copie de gauche comme atome de contrôle pour revenir au composant d'entrée et lire le caractère suivant. La copie de droite sera traitée. Prenons le cas où nous avons lu le personnage3
. Notre atome sera(51,0)
. Nous échangeons de la masse et de l’énergie@
, de manière à pouvoir utiliser la soustraction du prochain réacteur à fission. Le réacteur soustrait48
l'énergie (sans changer la masse), donc il envoie deux copies de(0,3)
- l'énergie correspond maintenant au chiffre que nous avons lu. La copie montante est simplement supprimée avec;
(un composant qui détruit tous les atomes entrants). Nous continuerons à travailler avec la copie descendante. Vous devrez suivre son chemin à travers le/
et\
reflète un peu.Le
@
réacteur juste avant le réacteur de fusion échange à nouveau de la masse et de l’énergie, de sorte que nous ajouterons(3,0)
à notre total courant dans leY
. Notez que le total cumulé aura donc toujours de l'0
énergie.Maintenant
J
c'est un saut. Ce qu'il fait, c'est sauter tout atome entrant par son énergie. Si c'est le cas0
, l'atome continue à avancer tout droit. Si c'est le1
cas, une cellule sera ignorée, si c'est le cas,2
deux cellules, etc. L'énergie est dépensée dans le saut, de sorte que l'atome se termine toujours avec de l'énergie0
. Puisque le total en cours a une énergie nulle, le saut est ignoré pour le moment et l’atome est redirigé dans le réacteur de fusion{
qui multiplie sa masse par10
. La copie descendante est rejetée avec;
la copie montante qui est réinjectée dans leY
réacteur en tant que nouveau total courant.Ce qui précède continue à se répéter (d'une manière amusante, où les nouveaux chiffres sont traités avant les précédents) jusqu'à ce que nous atteignions EOF. Maintenant le
%
va envoyer l'atome vers le bas. L'idée est de transformer cet atome en(0,1)
maintenant avant de frapper le réacteur à total en marche de manière à ce que a) le total ne soit pas affecté (masse nulle) et b) nous obtenions une énergie de1
sursaut[
. Nous pouvons facilement prendre soin de l'énergie avec$
, ce qui augmente l'énergie.Le problème est que
?
cela ne réinitialise pas la masse lorsque vous appuyez sur EOF, la masse sera donc toujours celle du dernier caractère lu et l'énergie sera0
(parce que%
décrémenté le1
retour à0
). Nous voulons donc nous débarrasser de cette masse. Pour ce faire, nous échangeons masse et énergie avec à@
nouveau.Je dois introduire un élément supplémentaire avant de terminer cette section:
Z
. C'est essentiellement la même chose que%
ou&
. La différence est qu’elle laisse passer les atomes d’énergie positive (tout en décrémentant l’énergie) et fait dévier les atomes d’énergie non positive de 90 degrés vers la gauche. Nous pouvons utiliser ceci pour éliminer l'énergie d'un atome en l'enroulant àZ
plusieurs reprises - dès que l'énergie aura disparu, l'atome sera dévié et quittera la boucle. C'est ce motif:où l'atome se déplacera vers le haut une fois que l'énergie sera nulle. Je vais utiliser ce modèle sous une forme ou une autre plusieurs fois dans les autres parties du programme.
Ainsi , lorsque l'atome quitte cette petite boucle, il sera
(1,0)
et swappé(0,1)
par le@
avant de frapper le réacteur de fusion pour libérer le résultat final de l'entrée. Cependant, le total cumulé sera multiplié par 10, car nous l'avons déjà provisoirement multiplié pour un autre chiffre.Alors maintenant, avec l’énergie
1
, cet atome sautera le[
et sautera dans le/
. Cela le dévie dans un réacteur à fission que nous nous sommes préparés à diviser par 10 et à réparer notre multiplication superflue. Encore une fois, nous jetons une moitié avec;
et conservons l’autre en sortie (ici,O
nous affichons ici le caractère correspondant et la destruction de l’atome - dans le programme complet, nous continuons à utiliser l’atome à la place).itoa
Bien entendu, nous devons également reconvertir le résultat en chaîne et l’imprimer. C'est ce que cette partie est pour. Cela suppose que l’entrée n’arrive pas avant la case 10, mais dans le programme complet qui est facilement donné. Ce bit peut être trouvé au bas du programme complet.
Ce code introduit un nouveau composant très puissant dans la fission: la pile
K
. La pile est initialement vide. Lorsqu'un atome d'énergie non négative frappe la pile, l'atome est simplement poussé sur la pile. Lorsqu'un atome d'énergie négative frappe la pile, sa masse et son énergie sont remplacées par l'atome situé en haut de la pile (qui est ainsi éclaté). Si la pile est vide, le sens de l'atome est inversé et son énergie devient positive (c'est-à-dire multipliée par-1
).Ok, revenons au code actuel. L'idée de l'
itoa
extrait de code est de prendre à plusieurs reprises l'entrée modulo 10 pour trouver le prochain chiffre tout en divisant l'entier par 10 pour la prochaine itération. Cela donnera tous les chiffres dans l'ordre inverse (du moins significatif au plus significatif). Pour fixer cet ordre, nous plaçons tous les chiffres sur une pile et, à la fin, les supprimons un par un pour les imprimer.La moitié supérieure du code fait le calcul du chiffre: le
L
avec les plus donne un 10 que nous clonons et introduisons dans un réacteur à fission et un réacteur à fusion afin que nous puissions diviser et multiplier par 10. La boucle commence essentiellement après le[
dans le coin supérieur gauche . La valeur actuelle est divisée: une copie est divisée par 10, puis multipliée par 10 et stockée dans un réacteur de fission, qui est ensuite frappé par l'autre copie au sommet. Cela calculei % 10
commei - ((i/10) * 10)
. Notez également que laA
division du résultat intermédiaire après la division et avant la multiplication, de sorte que nous pouvons alimenteri / 10
à la prochaine itération.Il
%
abandonne la boucle une fois que la variable d'itération atteint 0. Puisqu'il s'agit plus ou moins d'une boucle do-while, ce code pourrait même fonctionner pour l'impression0
(sans créer de zéros non plus, sinon). Une fois que nous avons quitté la boucle, nous voulons vider la pile et imprimer les chiffres.S
est le contraire deZ
, c’est donc un commutateur qui va dévier un atome entrant avec une énergie non positive de 90 degrés vers la droite. Ainsi, l'atome se déplace réellement sur le bord duS
droit au premierK
pour faire apparaître un chiffre (notez le~
qui garantit que l'atome entrant a de l'énergie-1
). Ce chiffre est incrémenté de48
pour obtenir le code ASCII du caractère correspondant. LaA
fractionne le chiffre pour imprimer une copie avec!
et réintroduisez l'autre copie dans leY
réacteur pour le chiffre suivant. La copie imprimée est utilisée comme déclencheur suivant pour la pile (notez que les miroirs l’envoient également autour du bord pour la frapperM
de la gauche).Lorsque la pile est vide, la
K
volonté reflète l'atome et convertit son énergie en une+1
telle manière qu'il passe directement à travers leS
.N
affiche une nouvelle ligne (juste parce que c'est soigné :)). Et puis, l’atome passe deR'0
nouveau pour se retrouver dans le côté de laY
. Puisqu'il n'y a plus d'atomes autour, cela ne sera jamais publié et le programme se termine.Calcul du nombre de fission: le cadre
Passons à la viande du programme. Le code est essentiellement un portage de mon implémentation de référence Mathematica:
où
div
est le nombre d'entiers dans la partition maximale.Les principales différences sont que nous ne pouvons pas traiter les valeurs semi-entières dans Fission, je fais donc beaucoup de choses multipliées par deux et qu'il n'y a pas de récursivité dans Fission. Pour contourner ce problème, j'inspire tous les entiers d'une partition d'une file d'attente pour qu'ils soient traités ultérieurement. Pour chaque numéro que nous traitons, nous incrémentons un compteur de un et une fois la file d'attente vide, nous libérons le compteur et l'envoyons pour qu'il soit imprimé. (Une file d'attente
Q
fonctionne exactement commeK
dans l'ordre FIFO.)Voici un cadre pour ce concept:
Les nouveaux composants les plus importants sont les chiffres. Ce sont des téléporteurs. Tous les téléporteurs avec le même chiffre vont ensemble. Lorsqu'un atome frappe un téléporteur, il déplace immédiatement le téléporteur suivant dans le même groupe, où le prochain est déterminé dans l'ordre habituel de gauche à droite et de haut en bas. Celles-ci ne sont pas nécessaires, mais aident à la mise en page (et donc au golf un peu). Il y a aussi
X
qui duplique simplement un atome, en envoyant une copie tout droit et l’autre en arrière.À ce stade, vous pourrez peut-être régler vous-même la plupart des éléments du cadre. Le coin supérieur gauche contient la file de valeurs à traiter et en libère une
n
à la fois. Une copie den
est téléportée vers le bas parce que nous en avons besoin lors du calcul de la plage, l'autre copie va dans le bloc en haut qui calculediv
(c'est de loin la plus grande section du code). Une foisdiv
calculé, il est dupliqué - une copie incrémente un compteur dans le coin supérieur droit, qui est stocké dansK
. L'autre copie est téléportée au bas. Sidiv
c'était le cas1
, nous le renvoyons immédiatement vers le haut et l'utilisons comme déclencheur de la prochaine itération, sans mettre en attente de nouvelles valeurs. Sinon, nous utilisonsdiv
etn
dans la section du bas pour générer la nouvelle plage (c’est-à-dire un flux d’atomes avec les masses correspondantes qui sont ensuite placées dans la file d’attente), puis relâchez un nouveau déclencheur une fois la plage complétée.Une fois la file d'attente vide, le déclencheur sera reflété, passant directement à travers
S
et réapparaissant dans le coin supérieur droit, où il relâche le compteur (le résultat final)A
, qui est ensuite téléporté versitoa
via8
.Calcul du nombre de fission: le corps de boucle
Il ne reste donc que les deux sections pour calculer
div
et générer la plage. L'informatiquediv
est cette partie:Vous en avez probablement déjà vu assez pour résoudre ce problème vous-même avec un peu de patience. La décomposition en haut niveau est la suivante: Les 12 premières colonnes environ génèrent un flux de diviseurs de
2n
. Les 10 prochaines colonnes filtrent celles qui ne satisfont pasOddQ@# == IntegerQ[n/#]
. Les 8 prochaines colonnes filtrent celles qui ne satisfont pasn/# > (# - 1)/2)
. Enfin, nous plaçons tous les diviseurs valides sur une pile et une fois que nous avons terminé, nous viderons toute la pile dans un réacteur à fusion (en écrasant tout le dernier / le plus grand diviseur), puis nous relâcherons le résultat, puis nous éliminerons son énergie -zéro de vérifier l'inégalité).Il y a beaucoup de chemins fous là-dedans qui ne font rien vraiment. De manière prédominante, la
\/\/\/\/
folie au sommet (les5
s en font également partie) et un chemin autour du bas (qui passe par les7
s). Je devais les ajouter pour faire face à de mauvaises conditions de course. La fission pourrait utiliser un composant de retard ...Le code qui génère la nouvelle plage à partir de
n
etdiv
est-ce:Nous calculons d’abord
n/div - (div + 1)/2
(les deux termes pondérés, ce qui donne le même résultat) et enregistrons pour plus tard. Ensuite, nous générons une plage allant dediv
bas à1
et ajoutons la valeur stockée à chacun d’eux.Il y a deux nouveaux modèles communs dans ces deux, que je dois mentionner: l' un est
SX
ouZX
frappé par le bas (ou versions pivotés). C'est un bon moyen de dupliquer un atome si vous voulez qu'une copie aille droit devant vous (dans la mesure où rediriger les sorties d'un réacteur à fusion peut parfois être fastidieux). LeS
ouZ
fait pivoter l'atome dans leX
, puis fait pivoter la copie mise en miroir dans la direction de propagation d'origine.L'autre motif est
Si nous stockons une valeur,
K
nous pouvons la récupérer à plusieurs reprises en frappantK
avec une énergie négative du haut. LesA
doublons de la valeur qui nous intéresse et renvoient quelle copie sur la pile pour la prochaine fois que nous en avons besoin.Eh bien, c'était assez long ... mais si vous avez vraiment traversé cela, j'espère que vous avez eu l'idée que Fission est i̟nç̮̩red̙ibl̶̪̙̮̥̮y̶̠̠͎̺̪̙̮̥̮͍͍͍̱̦̰͍͜
la source
Now with 100% fewer scrollbars.
donc tu dis .. et c'est toujours à suivre ...CJam,
4241 octetsUne première traversée en largeur simple et une condition d'arrêt de niveau suivant vide.
Comment ça marche :
Essayez-le en ligne ici
la source
Python 3, 112 octets
4 octets enregistrés grâce à @FryAmTheEggman.
Explication à venir plus tard ...
En prime: chaque puissance de 2 a un nombre de fission de 1. Cela est dû au fait que la somme d'une séquence de longueur égale est toujours la somme des deux nombres du milieu, ce qui est impair, multiplié par la moitié de la longueur de la séquence, qui est un entier. . La somme d'une séquence de longueur impaire est le nombre du milieu multiplié par la longueur de la séquence, ce qui est impair. Ainsi, une puissance de 2 n'ayant pas de diviseur impair, elle ne peut être exprimée que par la somme de celle-ci.
la source
Python 2,
11110297 octetsUn peu lisible:
Pas si lisible:
Les deux 97 octets.
b
est len
moins le(a-1)th
nombre triangulaire. Sib % a == 0
, alorsn
est la somme desa
nombres consécutifs à partir deb
.la source
1else
. Seule la 2ème solution fonctionne. Ce n'est pas avant Python 3 que l'else
on peut immédiatement suivre un numéro.Python 2, 86
Moins joué au golf:
L'idée est de tester des suites potentielles d'entiers consécutifs qui totalisent
n
. L'exécution est stockée directement directement en tant qu'ensembleR
plutôt que via ses points d'extrémité.Nous vérifions comment la somme de la série en cours se compare à la somme souhaitée
n
via leur différence.f
sur l'exécution, la somme et ajoutons 1 pour le nœud actuel. Si la course est{n}
, nous avons essayé toutes les sommes possibles non triviales, arrêtez la récursion en supprimant d'n
abord.Merci à Sp3000 pour la sauvegarde de 3 caractères.
la source
Python 2, 85
Je suis très fier de cette réponse car cela prend déjà des dizaines de secondes pour n = 9 et 5-10 minutes pour n = 10. En code golf, ceci est considéré comme un attribut souhaitable d'un programme.
Il existe également une version en court-circuit qui prend moins de temps et utilise le même nombre d'octets:
Cela peut être plus rapide, mais au moins il dépasse la limite de récursion par défaut une fois que n dépasse légèrement 40.
L'idée est de faire une force brute de recherche de nombres
a
etd
telle quea + a+1 + ... + a+d == n
, sur des valeurs entre 1 etn
. Laf(n,a+d/n,d%n+1)
branche de la récursion passe en boucle par les(a, d)
paires. Dans le cas où l'égalité est satisfaite, je parviens à éviter unmap(range(...))
appel coûteux en scindant en deux branches, quelle que soit la durée de la séquence. Les nombres àa+1
traversd
sont regroupées en un seul appelf
en réglant lea
paramètre de sorte que ne peut pas être utilisé d' une manière différente de diviser la séquence.la source
Haskell,
7669 octetsUsage:
Comment ça fonctionne:
la source
Retina , 66 octets
Prend l’entrée et imprime la sortie unaire.
Vous pouvez mettre chaque ligne dans un seul fichier ou exécuter le code tel quel avec l'
-s
indicateur. Par exemple:Explication:
1
et convertissons le reste en1
.Les états de la chaîne tout au long du processus avec entrée
11111111111111 (unary 14)
:Merci beaucoup pour @MartinButtner pour l'aide dans le chat!
la source
CJam (43 bytes)
Démo en ligne
Je suis sûr que je manque quelques astuces avec les boucles avancées, mais cela exploite parfaitement la propriété CJam (qui m’avait déjà ennuyée),
%
les résultats restent dans la pile sur la pile et peuvent donc être consultés$
avec décalage négatif.la source
,
au début./
et%
quelques autres transforment implicitement les nombres en plages.,_m*
peut être remplacé par2m*
. La formule de progression arithmétique peut être remplacée par~,>:Y_,+:+
et~\,>0\
devient!Y
. Enfin, si vous utilisez{}#
au lieu de{}=
, vous n’avez pas besoin de l’)
aprèsX
. Rassembler tout cela:ri{):X2m*{~,>:Y_,+:+X=}#!Y{~$+}/)}%W=
Go, 133 octets
C'est mon premier code de golf, désolé si j'ai commis des erreurs.
Ceci utilise l'idée que la "composition" fissile peut également être vue comme une différence entre deux séquences d'entiers ordonnés. Par exemple, prenons la "composition" fissile pour le nombre 13. Il est 6,7. Mais cela peut être vu comme la somme des nombres entiers 1 ... 7 moins la somme des nombres entiers 1 ... 5
Rappelez-vous la formule des jours d'école de Gauss, somme 1 ... n = (n ^ 2 + n) / 2. Donc, pour trouver une composition de nombres entiers séquentiels pour un n donné, nous pourrions aussi dire que nous cherchons des «points finaux» p et q le long de la plage 1 ... n, de sorte que (p ^ 2 + p) / 2 - ( q ^ 2 + q) / 2 = n. Dans l'exemple ci-dessus, nous aurions recherché les «points finaux» 5 et 7 car 7 ^ 2 + 7 = 56/2, 5 ^ 2 + 5 = 30/2, 56 / 2-30 / 2 = 28-15 = 13.
Maintenant, il existe de nombreuses manières possibles de composer un nombre, comme l'a noté Martin 9 = 2 + 3 + 4 mais aussi 4 + 5. Mais il semble évident que la séquence de départ "la plus basse" sera aussi la plus longue, car elle prend plus de temps. petits nombres pour résumer à un grand nombre que les nombres de taille moyenne. (Je n'ai malheureusement aucune preuve)
Donc, pour trouver la composition de 9, testez chaque 'paire de points finaux', p et q, en effectuant une itération distincte de 0 à 9, et testez si p ^ p + p / 2 - q ^ 2 + q / 2 = 9. Ou, plus simplement, multipliez l'équation par 2 pour éviter les problèmes de division liés à l'arrondissement et conservez tous les calculs en nombres entiers. On cherche alors p et q tels que (p ^ p + p) - (q ^ q + q) = 9 * 2. La première correspondance que nous trouverons sera les critères de composition Fissile car, comme indiqué, le groupe de nombres le plus bas sera également le plus long, et nous recherchons des valeurs faibles à élevées (0 à 9). Nous sortons de la boucle dès que nous trouvons un match.
Maintenant, la fonction récursive trouve ces «points finaux fissiles» p et q pour le n donné, puis se rappelle elle-même pour chacun des «enfants» de l'arbre de p à q. Pour 9, il trouverait 1 et 4, (20-2 = 18), puis il se rappellera le 2, le 3 et le 4 en faisant la somme des résultats. Pour des nombres tels que 4, il ne trouve simplement jamais de correspondance et renvoie donc «1». C’est peut-être une solution, mais c’est comme mon troisième programme Go, et je ne suis pas un expert en récursivité.
Merci d'avoir lu.
la source
CJam,
403533 octetsMerci à @Optimizer pour avoir suggéré
few
, qui a sauvé 2 octets.Essayez-le en ligne dans l' interprète CJam .
Comment ça fonctionne
la source
ri{_,:)_few:+W%{1b1$=}=|{F}*}:F~],