Une abondance d'entiers!


40

Un nombre Abondant est un nombre où la somme de ses diviseurs appropriés est supérieure au nombre original. Par exemple, les diviseurs appropriés de 12 sont:

1, 2, 3, 4, 6

Et en sommant ces résultats dans 16. Puisque 16 est plus grand que 12, 12 est abondant. Notez que cela n'inclut pas les "nombres parfaits", par exemple les nombres qui sont égaux à la somme de ses diviseurs propres, tels que 6 et 28.

Votre tâche pour aujourd'hui est d'écrire un programme ou une fonction qui détermine si un nombre est abondant ou non. Votre programme doit prendre un seul entier en entrée et générer une valeur vérité / fausseté selon qu’il est abondant ou non. Vous pouvez supposer que l'entrée sera toujours valide et supérieure à 0. Par conséquent, pour les mauvaises entrées, le comportement non défini convient.

Vous pouvez utiliser vos entrées et sorties dans n’importe quel format raisonnable. Par exemple, STDIN / STDOUT, des fichiers ou des arguments / valeurs de retour seraient tous acceptables.

Pour référence, voici les nombres abondants jusqu’à 100:

12,
18,
20,
24,
30,
36,
40,
42,
48,
54,
56,
60,
66,
70,
72,
78,
80,
84,
88,
90,
96,
100

Et plus peut être trouvé sur A005101

Puisqu'il s'agit de , les échappatoires standard sont refusées et essayez d'écrire le code le plus court possible dans la langue de votre choix!


11
"le premier nombre impair est 945 = 3 ^ 3 * 5 * 7, le 232e nombre abondant!"
mbomb007

La densité asymptotique des nombres abondants se situe quelque part dans l'intervalle [0.24761748, 0.24764422]. Calculé à l'aide du code source inclus dans ce document .
Deadcode

1
J'essaie de faire cela dans Geometry Dash. C'est un cauchemar
MilkyWay90

Réponses:


41

ECMAScript Regex, 1085 855 597 536 511 508 504 octets

La correspondance de nombres abondants dans les expressions rationnelles ECMAScript est une bête totalement différente de celle utilisée dans pratiquement toute autre saveur de regex. L'absence de références arrière ou de récursion imbriquées / imbriquées signifie qu'il est impossible de compter directement ou de conserver un total cumulé. Le manque de repères rend souvent difficile le fait de disposer de suffisamment d’espace pour travailler.

De nombreux problèmes doivent être abordés sous un angle totalement différent, et vous vous demanderez s'ils sont résolus. Cela vous oblige à utiliser un réseau beaucoup plus large pour déterminer quelles propriétés mathématiques des nombres avec lesquels vous travaillez pourraient être utilisées pour résoudre un problème particulier.

En mars-avril 2014, j'ai construit une solution à ce problème dans les expressions rationnelles ECMAScript. Au début, j’avais toutes les raisons de penser que le problème était complètement impossible, mais le mathématicien Teukon a ensuite esquissé une idée encourageante, mais il a clairement indiqué qu’il n’avait pas l’intention de construire la regex (il avait concurrencé / coopéré avec mon sur la construction / le golfing regex précédents, mais a atteint sa limite à ce point et était content de restreindre ses contributions ultérieures à la théorisation).

Comme dans mon regex posté il y a quelques jours, je tiens à vous avertir: je vous recommande vivement d'apprendre à résoudre des problèmes mathématiques unaires dans ECMAScript regex. Ce voyage a été fascinant pour moi et je ne veux pas le gâter pour ceux qui voudraient éventuellement l'essayer eux-mêmes, en particulier ceux qui s'intéressent à la théorie des nombres. Voir ce post pour une liste de problèmes recommandés consécutivement étiquetés spoiler à résoudre un par un.

Donc , ne lisez pas plus loin si vous ne voulez pas que la magie des regex unaires profondes vous soit gâtée . Mon post précédent était juste un petit goût. Si vous voulez vraiment essayer de comprendre cette magie, je vous recommande vivement de commencer par résoudre certains problèmes de la regex ECMAScript, comme indiqué dans l'article ci-dessus.

Avant de poster mon ECMAScript regex, je pensais que ce serait intéressant d'analyser Martin Ender solution .NET regex pur , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). Il est très facile de comprendre cette expression rationnelle et elle est élégante dans sa simplicité. Pour démontrer le contraste entre nos solutions, voici une version commentée et joliment imprimée (mais non modifiée) de sa regex:

# For the purpose of these comments, the input number will be referred to as N.

^(?!                  # Attempt to add up all the divisors. Since this is a regex and we
                      # can only work within the available space of the input, that means
                      # if the sum of the divisors is greater than N, the attempt to add
                      # all the divisors will fail at some point, causing this negative
                      # lookahead to succeed, showing that N is an abundant number.

  (1                  # Cycle through all values of tail that are less than N, testing
                      # each one to see if it is a divisor of N.

    (?<=              # Temporarily go back to the start so we can directly operate both
                      # on N and the potential divisor. This requires variable-length
                      # lookbehind, a .NET feature – even though this special case of
                      # going back to the start, if done left-to-right, would actually be
                      # very easy to implement even in a regex flavour that has no
                      # lookbehind to begin with. But .NET evaluates lookbehinds right
                      # to left, so please read these comments in the order indicated,
                      # from [Step 1] to [Step 7]. The comment applying to entering the
                      # lookahead group, [Step 2], is shown on its closing parenthesis.
      (?=             # [Step 3] Since we're now in a lookahead, evaluation is left to
                      #          right.
        (?(\3+$)      # [Step 4] If \3 is a divisor of N, then...
          (           # [Step 5] Add it to \2, the running total sum of divisors:
                      #          \2 = \2 + \3         
            (?>\2?)   # [Step 6] Since \2 is a nested backref, it will fail to match on
                      #          the first iteration. The "?" accounts for this, making
                      #          it add zero to itself on the first iteration. This must
                      #          be done before adding \3, to ensure there is enough room
                      #          for the "?" not to cause the match to become zero-length
                      #          even if \2 has a value.
            \3        # [Step 7] Iff we run out of space here, i.e. iff the sum would
                      #          exceed N at this point, the match will fail, making the
                      #          negative lookahead succeed, showing that we have an
                      #          abundant number.
          )

        )
      )               # [Step 2] Enter a lookahead that is anchored to the start due to
                      #          having a "^" immediately to its right. The regex would
                      #          still work if the "^" were moved to the left of the
                      #          lookahead, but would be slightly slower, because the
                      #          engine would do some spurious matching before hitting
                      #          the "^" and backtracking.
      ^(1+)           # [Step 1] \3 = number to test for being a potential divisor – its
                      #               right-side-end is at the point where the lookbehind
                      #               started, and thus \3 cycles through all values from
                      #               1 to N-1.
    )
  )*1$                # Exclude N itself from being considered as a potential divisor,
                      # because if we included it, the test for proper abundance would be
                      # the sum of divisors exceeding 2*N. We don't have enough space for
                      # that, so instead what would happen if we did not exclude N as a
                      # divisor would be testing for "half-abundance", i.e. the sum of
                      # all divisors other than N exceeding N/2. By excluding N as a
                      # divisor we can let our threshold for abundance be the sum of
                      # divisors exceeding N.
)

Essayez la regex .NET en ligne

Revenons maintenant à ma regex ECMAScript. Premièrement, le voici en format brut, sans espace ni commentaire:

^(?=(((?=(xx+?)\3+$)(x+)\4*(?=\4$))+(?!\3+$)(?=(xx(x*?))\5*$)x)(x+))(?=\1(x(x*))(?=\8*$)\6\9+$)(?=(.*)((?=\8*$)\5\9+$))(?=(x*?)(?=(x\11)+$)(?=\12\10|(x))(x(x*))(?=\15*$)(?=\11+$)\11\16+$)(?=(x(x*))(?=\17*$)\7\18+$)((?=(x*?(?=\17+$)(?=\17+?(?=((xx(x*))(?=\18+$)\22*$))(x+).*(?=\17$)\24*(?=\24$)(?!(xx+)\25*(?!\22+$)\25$)\22+$)((?=(x\7)+$)\15{2}\14|)))(?=.*(?=\24)x(x(x*))(?=\28*$)\23\29*$)(?=.*(x((?=\28*$)\22\29+$)))(.*(?!\30)\20|(?=.*?(?!x\20)(?=\30*$)(x(x*))(?=\33*$)(?=\31+$)\31\34+$).*(?=\33\21$)))+$

(remplacez \14par \14?pour la compatibilité avec PCRE, .NET et pratiquement tous les autres goûts de regex autres que ECMAScript)

Essayez-le en ligne!
Essayez-le en ligne! (version plus rapide de la regex avec 537 octets)

Et maintenant, un bref résumé de l'histoire derrière elle.

Au début, il était très peu évident, du moins pour moi, qu'il était même possible de faire correspondre des nombres premiers dans le cas général. Et après avoir résolu cela, la même chose s’appliquait aux puissances de 2. Et ensuite aux puissances des nombres composés. Et puis des carrés parfaits. Et même après avoir résolu ce problème, une multiplication généralisée semblait impossible au début.

Dans une boucle ECMAScript, vous ne pouvez suivre qu'un seul numéro qui change. ce nombre ne peut pas dépasser l'entrée et doit diminuer à chaque étape. Mon premier regex de travail pour faire correspondre les instructions de multiplication correctes A * B = C était de 913 octets et fonctionnait en factorisant A, B et C en leurs puissances principales - pour chaque facteur premier, diviser à plusieurs reprises la paire de facteurs de puissance premiers de A et C par leur base première jusqu'à ce que celui correspondant à A atteigne 1; celle qui correspond à C est ensuite comparée au facteur de puissance premier de B. Ces deux puissances du même nombre premier ont été "multiplexées" en un seul nombre en les additionnant; cela serait toujours séparable sans ambiguïté à chaque itération suivante de la boucle, pour la même raison que les systèmes de numération positionnelle fonctionnent.

La multiplication a été réduite à 50 octets en utilisant un algorithme complètement différent (auquel teukon et moi avons pu arriver indépendamment, bien que cela ne lui prenne que quelques heures et qu'il passe directement à cela, alors que cela m’a pris porté à mon attention qu’une méthode courte existait): pour A≥B, A * B = C le cas échéant uniquement si C est le plus petit nombre qui satisfait C≡0 mod A et CB mod A-1. (De manière pratique, l'exception de A = 1 ne nécessite aucune manipulation particulière dans regex, où 0% 0 = 0 donne une correspondance.) Je ne peux vraiment pas comprendre à quel point il est évident qu'une telle manière élégante de multiplier existe dans une telle saveur regex minimale. (Et l'exigence de A≥B peut être remplacée par une exigence voulant que A et B soient des puissances premières de même puissance. Pour le cas de A≥B, cela peut être prouvé à l'aide du théorème du reste chinois.)

S'il s'était avéré qu'il n'existait pas d'algorithme plus simple pour la multiplication, le nombre abondant regex serait probablement de l'ordre de dix mille octets ou plus (même en tenant compte du fait que j'ai utilisé l'algorithme de 913 octets jusqu'à 651 octets). Il fait beaucoup de multiplication et de division, et la regex ECMAScript n'a pas de sous-programmes.

Le 23 mars 2014, j'ai commencé à travailler sur le problème de l'abondance de nombres de manière tangentielle, en élaborant une solution à ce qui semblait être à l'époque un sous-problème: Identifier le facteur premier de la multiplicité la plus élevée, afin de pouvoir le diviser en N au début, laisser de la place pour faire les calculs nécessaires. À l'époque, cela semblait être une voie prometteuse. (Ma solution initiale a finalement été assez importante, à 326 octets, puis à 185 octets.) Mais le reste de la méthode esquissée par Teukon aurait été extrêmement compliquée, de sorte que j’ai pris un chemin assez différent. Il s'est avéré suffisant de séparer le plus grand facteur de puissance N, correspondant au plus grand facteur premier de N; faire cela pour le nombre le plus élevé de multiplicité aurait ajouté une complexité et une longueur inutiles à la regex.

Il restait à traiter la somme des diviseurs comme un produit de sommes au lieu d’une somme simple. Comme expliqué par teukon le 14 mars 2014:

On nous donne un nombre n = p 0 a 0 p 1 a 1 ... p k-1 a k-1 . Nous voulons traiter la somme des facteurs de n, qui est (1 + p 0 + p 0 2 + ... + p 0 a 0 ) (1 + p 1 + p 1 2 + ... + p 1 a 1 ) ... (1 + p k-1 + p k-1 2 + ... + p k-1 a k-1 ).

Cela m'a coupé l'esprit de voir cela. Je n'avais jamais pensé à factoriser la somme aliquote de cette manière, et c'est cette formule plus que toute autre chose qui a rendu plausible la solvabilité de l'appariement de nombres abondants dans la regex ECMAScript.

En fin de compte, au lieu de rechercher un résultat d'addition ou de multiplication supérieur à N ou de vérifier qu'un résultat ainsi divisé par M est supérieur à N / M, je me suis tourné vers le test si le résultat de la division est inférieur à 1. Je suis arrivé à la première version de travail le 7 avril 2014.

L'historique complet de mes optimisations de golf de cette regex est sur github. À un moment donné, une optimisation a fini par ralentir considérablement la regex. À partir de ce moment, j'ai donc conservé deux versions. Elles sont:

regex pour faire correspondre les nombres abondants.txt
regex pour faire correspondre les nombres abondants - shortest.txt

Ces expressions rationnelles sont entièrement compatibles avec ECMAScript et PCRE, mais une optimisation récente impliquait l’utilisation d’un groupe de capture potentiellement non participant \14. Ainsi, en abandonnant la compatibilité PCRE et en passant \14?à la modification, \14elles peuvent toutes deux être réduites d’un octet.

Voici la plus petite version, avec cette optimisation appliquée (le rendant uniquement ECMAScript), reformatée pour tenir dans un bloc de code StackExchange avec (généralement) aucun défilement horizontal requis:

# Match abundant numbers in the domain ^x*$ using only the ECMAScript subset of regex
# functionality. For the purposes of these comments, the input number = N.
^
# Capture the largest prime factor of N, and the largest power of that factor that is
# also a factor of N. Note that the algorithm used will fail if N itself is a prime
# power, but that's fine, because prime powers are never abundant.
(?=
  (                      # \1 = tool to make tail = Z-1
    (                    # Repeatedly divide current number by its smallest factor
      (?=(xx+?)\3+$)
      (x+)\4*(?=\4$)
    )+                   # A "+" is intentionally used instead of a "*", to fail if N
                         #  is prime. This saves the rest of the regex from having to
                         #  do needless work, because prime numbers are never abundant.
    (?!\3+$)             # Require that the last factor divided out is a different prime.
    (?=(xx(x*?))\5*$)    # \5 = the largest prime factor of N; \6 = \5-2
    x                    # An extra 1 so that the tool \1 can make tail = Z-1 instead of just Z
  )
  (x+)                   # Z = the largest power of \5 that is a factor of N; \7 = Z-1
)
# We want to capture Z + Z/\5 + Z/\5^2 + ... + \5^2 + \5 + 1 = (Z * \5 - 1) / (\5 - 1),
# but in case Z * \5 > N we need to calculate it as (Z - 1) / (\5 - 1) * \5 + 1.
# The following division will fail if Z == N, but that's fine, because no prime power is
# abundant.
(?=
  \1                     # tail = (Z - 1)
  (x(x*))                # \8   = (Z - 1) / (\5 - 1); \9 = \8-1
  # It is guaranteed that either \8 > \5-1 or \8 == 1, which allows the following
  # division-by-multiplication to work.
  (?=\8*$)
  \6\9+$
)
(?=
  (.*)                   # \10 = tool to compare against \11
  (                      # \11 = \8 * \5  =  (Z - 1) / (\5 - 1) * \5; later, \13 = \11+1
    (?=\8*$)
    \5\9+$
  )
)
# Calculate Q = \15{2} + Q_R = floor(2 * N / \13). Since we don't have space for 2*N, we
# need to calculate N / \13 first, including the fractional part (i.e. the remainder),
# and then multiply the result, including the fractional part, by 2.
(?=
  (x*?)(?=(x\11)+$)      # \12 = N % \13; \13 = \11 + 1
  (?=\12\10|(x))         # \14 = Q_R = floor(\12 * 2 / \13)
                         #     = +1 carry if \12 * 2 > \11, or NPCG otherwise
  (x(x*))                # \15 = N / \13; \16 = \15-1
  (?=\15*$)
  (?=\11+$)              # must match if \15 <  \13; otherwise doesn't matter
  \11\16+$               # must match if \15 >= \13; otherwise doesn't matter
)
# Calculate \17 = N / Z. The division by Z can be done quite simply, because the divisor
# is a prime power.
(?=
  (x(x*))                # \17 = N / Z; \18 = \17-1
  (?=\17*$)
  \7\18+$
)
# Seed a loop which will start with Q and divide it by (P^(K+1)-1)/(P-1) for every P^K
# that is a factor of \17. The state is encoded as \17 * P + R, where the initial value
# of R is Q, and P is the last prime factor of N to have been already processed.
#
# However, since the initial R would be larger than \17 (and for that matter there would
# be no room for any nonzero R since with the initial value of P, it is possible for
# \17 * P to equal N), treat it as a special case, and let the initial value of R be 0,
# signalling the first iteration to pretend R=Q. This way we can avoid having to divide Q
# and \17 again outside the loop.
#
# While we're at it, there's really no reason to do anything to seed this loop. To seed
# it with an initial value of P=\5, we'd have to do some multiplication. If we don't do
# anything to seed it, it will decode P=Z. That is wrong, but harmless, since the next
# lower prime that \17 is divisible by will still be the same, as \5 cannot be a factor
# of \17.

# Start the loop.
(
  (?=
    (                    # \20 = actual value of R
      x*?(?=\17+$)       # move forward by directly decoded value of R, which can be zero
      # The division by \17 can be done quite simply, because it is known that
      # the quotient is prime.
      (?=
        \17+?            # tail = \17 * (a prime which divides into \17)
        (?=
          (              # \21 = encoded value for next loop iteration
            (xx(x*))     # \22 = decoded value of next smaller P; \23 = (\22-1)-1
            (?=\18+$)    # iff \22 > \17, this can have a false positive, but never a false negative
            \22*$        # iff \22 < \17, this can have a false positive, but never a false negative
          )
        )
        # Find the largest power of \22 that is a factor of \17, while also asserting
        # that \22 is prime.
        (x+)             # \24 = the largest power of \22 that is a factor of \17
        .*(?=\17$)
        \24*(?=\24$)
        (?!
          (xx+)\25*
          (?!\22+$)
          \25$
        )
        \22+$
      )
      (
        (?=(x\7)+$)      # True iff this is the first iteration of the loop.
        \15{2}\14        # Potentially unset capture, and thus dependent on ECMAScript
                         # behavior. Change "\14" to "\14?" for compatibility with non-
                         # ECMAScript engines, so that it will act as an empty capture
                         # with engines in which unset backrefs always fail to match.
      |
      )
    )
  )
  # Calculate \30 = (\24 - 1) / (\22 - 1) * \22 + 1
  (?=
    .*(?=\24)x           # tail = \24 - 1
    (x(x*))              # \28 = (\24 - 1) / (\22 - 1); \29 = \28-1
    (?=\28*$)
    \23\29*$
  )
  (?=
    .*(x(                # \30 = 1 + \28 * \22 = (\28 - 1) / (\22 - 1) * \22 + 1; \31 = \30-1
      (?=\28*$)
      \22\29+$
    ))
  )
  # Calculate \33 = floor(\20 / \30)
  (
    .*(?!\30)\20         # if dividing \20 / \30 would result in a number less than 1,
                         # then N is abundant and we can exit the loop successfully
  |
    (?=
      .*?(?!x\20)(?=\30*$)
      (x(x*))            # \33 = \20 / \30; \34 = \33-1
      (?=\33*$)
      (?=\31+$)          # must match if \33 <  \30; otherwise doesn't matter
      \31\34+$           # must match if \33 >= \30; otherwise doesn't matter
    )
    # Encode the state for the next iteration of the loop, as \17 * \22 + \33
    .*(?=\33\21$)
  )
)+$

Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacée pour discuter .
DJMcMayhem


27

Python 2 , 41 à 40 octets

n=k=j=input()
while~k<0:j-=1;k-=j>>n%j*n

La sortie s'effectue via le code de sortie , donc 0 est la vérité et 1 est la fausseté.

Essayez-le en ligne!

Comment ça marche

Après avoir réglé tous n , k et j à l'entrée de STDIN, nous entrons dans la en boucle. Ladite boucle se cassera dès que -k - 1 = ~ k ≥ 0 , c’est-à-dire que k ≤ -1 / k <0 .

Dans chaque itération, nous décrémentons d'abord j pour ne considérer que les diviseurs appropriés de n . Si j est un diviseur de n , on n%jobtient 0 et j >> n% j * n = j / 2 0 = j est soustrait de k . Cependant, si j ne divise pas n , il n%jest positif, il en n%j*nest de même pour n> log 2 j et j >> n% j * n = j / 2 n% j * n = 0 est soustrait de k .

Pour les nombres abondants, k atteindra une valeur négative avant ou lorsque j devient 1 , car la somme des diviseurs appropriés de n est strictement supérieure à n . Dans ce cas, nous sortir de la en boucle et le programme se termine normalement.

Cependant, si n n’est pas abondant, j finit par atteindre 0 . Dans ce cas, n%jgénère une erreur ZeroDivisionError et le programme se termine avec une erreur.


4
~k<0est chic, mais je pense -1<kaussi fait le tour;)
Martin Ender




10

Mathematica, 17 octets

Tr@Divisors@#>2#&

Explication

Tr@                 The sum of the main diagonal of
   Divisors@         the list of divisors of
            #         the first argument
             >      is greater than
              2#      twice the first argument.
                &   End of function.

1
Je suis surpris que Mathematica n'ait pas d'intégré pour cela ..
MrPaulch 21/02/2017

1
@MrPaulch Compte tenu de la durée du programme cependant, la fonction interne peut très bien être plus en nom>>.
Conor O'Brien

1
@ ConorO'Brien Si cela existait, ce serait probablement ainsi AbundantNumberQ, cela permettrait d'économiser quelques octets :)
ngenisis 22/02/2017


7

Retina , 50 à 45 octets

^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$)

Entrée unaire , sortie 1pour les nombres abondants, 0sinon.

Il n'y a rien de spécifique à Retina dans cette solution. Ce qui précède est une regex .NET pure qui ne correspond qu’à des nombres abondants.

Essayez-le en ligne! (Suite de tests filtrant les entrées décimales avec la regex ci-dessus.)


6

Retina , 34 octets

Le nombre d'octets suppose un codage ISO 8859-1.

M!&`(1+)$(?<=^\1+)
1>`¶

^(1+)¶1\1

Entrée unaire , sortie 1pour les nombres abondants, 0sinon.

Essayez-le en ligne!

Explication

M!&`(1+)$(?<=^\1+)

Nous commençons par obtenir tous les diviseurs de l’entrée. Pour ce faire, nous revenons ( !) tout chevauchement ( &correspondances) ( M) de l'expression rationnelle (1+)$(?<=^\1+). L'expression régulière correspond à un suffixe de l'entrée, à condition que toute l'entrée soit un multiple de ce suffixe (ce que nous garantissons en essayant d'atteindre le début de la chaîne en utilisant uniquement des copies du suffixe). En raison de la façon dont le moteur des expressions rationnelles recherche les correspondances, une liste de diviseurs par ordre décroissant (séparés par des sauts de ligne) apparaîtra.

1>`¶

La scène elle-même correspond simplement à linefeeds ( ) et les supprime. Cependant, le 1>est une limite, qui saute le premier match. Cela ajoute donc efficacement tous les diviseurs, à l'exception de l'entrée elle-même. Nous nous retrouvons avec l'entrée sur la première ligne et la somme de tous les diviseurs appropriés sur la deuxième ligne.

^(1+)¶1\1

Enfin, nous essayons d’aligner au moins un de plus 1sur la deuxième ligne que sur la première. Si c'est le cas, la somme des diviseurs appropriés dépasse l'entrée. Retina compte le nombre de correspondances de cette expression rationnelle, qui seront 1pour des nombres abondants et 0autres.


1
Je suis toujours étonné de voir comment on peut faire des mathématiques en rétine. J'aimerais voir une explication! :)
DJMcMayhem

1
@DJMcMayhem Désolé d'avoir oublié de l'ajouter plus tôt. Terminé.
Martin Ender

6

8086 Assemblée, 23 28 25 24 octets

8bc8 d1e9 33db 33d2 50f7 f158 85d2 7502 03d9 7204 e2f0 3bc3

Non assemblé:

; calculate if N (1 < N <= 65535) is abundant
; input: N (mem16/r16)
; output: CF=1 -> abundant, CF=0 -> not abundant
ABUND   MACRO   N 
        LOCAL DIV_LOOP, CONT_LOOP, END_ABUND
        IFDIFI <N>,<AX> ; skip if N is already AX
    MOV  AX, N          ; AX is dividend
        ENDIF
    MOV  CX, AX         ; counter starts at N / 2
    SHR  CX, 1          ; divide by 2
    XOR  BX, BX         ; clear BX (running sum of factors)
DIV_LOOP:
    XOR  DX, DX         ; clear DX (high word for dividend)
    PUSH AX             ; save original dividend
    DIV  CX             ; DX = DX:AX MOD CX, AX = DX:AX / CX
    POP  AX             ; restore dividend (AX was changed by DIV)
    TEST DX, DX         ; if remainder (DX) = 0, it divides evenly so CX is a divisor
    JNZ  CONT_LOOP      ; if not, continue loop to next
    ADD  BX, CX         ; add number to sum
    JC   END_ABUND      ; if CF=1, BX has unsigned overflow it is abundant (when CX < 65536)
CONT_LOOP:
    LOOP DIV_LOOP
    CMP  AX, BX         ; BX<=AX -> CF=0 (non-abund), BX>AX -> CF=1 (abund)
END_ABUND:
        ENDM

Exemple de programme de test, test N = [12..1000]:

    MOV  AX, 12         ; start tests at 12
LOOP_START:
    ABUND AX            ; call ABUND MACRO for N (in AX)
    JNC  LOOP_END       ; if not abundant, display nothing
    CALL OUTDECCSV      ; display AX as decimal (generic decimal output routine)
LOOP_END:
    INC  AX             ; increment loop counter
    CMP  AX, 1000       ; if less than 1000...
    JBE  LOOP_START     ; continue loop
    RET                 ; return to DOS

Sortie [2..1000]

12, 18, 20, 24, 30, 36, 40, 42, 48, 54, 56, 60, 66, 70, 72, 78, 80, 84, 88, 90, 96, 100, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 144, 150, 156, 160, 162, 168, 174, 176, 180, 186, 192, 196, 198, 200, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 288, 294, 300, 304, 306, 308, 312, 318, 320, 324, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 392, 396, 400, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 450, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 576, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 648, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 738, 740, 744, 748, 750, 756, 760, 762, 768, 770, 774, 780, 784, 786, 792, 798, 800, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 846, 852, 858, 860, 864, 868, 870, 876, 880, 882, 888, 894, 896, 900, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 954, 960, 966, 968, 972, 978, 980, 984, 990, 992, 996, 1000

Sortie [12500..12700]

12500, 12504, 12510, 12512, 12516, 12520, 12522, 12528, 12530, 12534, 12540, 12544, 12546, 12552, 12558, 12560, 12564, 12570, 12572, 12576, 12580, 12582, 12584, 12588, 12594, 12600, 12606, 12612, 12618, 12620, 12624, 12628, 12630, 12636, 12640, 12642, 12648, 12650, 12654, 12656, 12660, 12666, 12670, 12672, 12678, 12680, 12684, 12688, 12690, 12696, 12700

Sortie [25100..25300]

25100, 25104, 25110, 25116, 25120, 25122, 25128, 25130, 25134, 25140, 25144, 25146, 25152, 25158, 25160, 25164, 25168, 25170, 25172, 25176, 25180, 25182, 25188, 25194, 25200, 25206, 25212, 25216, 25218, 25220, 25224, 25228, 25230, 25232, 25236, 25240, 25242, 25245, 25248, 25254, 25256, 25260, 25266, 25270, 25272, 25278, 25280, 25284, 25290, 25296, 25300

Mises à jour:

  • Correction du débordement de 16 bits (+5 octets). Merci @deadcode pour les suggestions!
  • Logique de retour simplifiée (-3 octets). Merci de l'aide de @deadcode encore une fois.
  • Utilisez TEST au lieu de CMP (-1 octet). Merci à l4m2!

1
Je suggérerais de remplacer JLEpar JBEdoubler la plage de nombres que ceci peut tester avant que les débordements ne commencent à le faire donner des faux négatifs. Ensuite, au lieu de commencer à échouer à 12600 (somme aliquot 35760), il échouera à 25200 (somme aliquot 74744). Mieux encore, il faudrait également détecter l'indicateur de portage et le traiter comme un nombre abondant sans avoir à calculer la somme réelle> 16 bits.
Deadcode

1
Bonne prise @Deadcode. J'ai mis à jour le code pour sauter ci-dessous au lieu de sauter moins. Je vois ce que vous voulez dire, faire un JC après ADD BX, CX attrapera le débordement non signé et le corrigera jusqu’à N = 65535. Complique les tests d’indicateur et renvoie un peu l’état, car auparavant, CF impliquait faux. Mis à jour avec correct aussi.
640KB le

1
Vous pouvez économiser 3 octets en inversant la spécification de votre valeur de retour, avec CF défini si abondant et clair sinon. Mais je vous recommanderais de modifier d'abord la documentation de sortie afin qu'elle soit belle dans l'historique des modifications.
Deadcode

1
De plus, pour que les choses restent simples, la spécification doit être que la valeur de retour est dans l'indicateur de report, et que rien de tout cela ne se mêle aux autres indicateurs. L'appelant doit utiliser JCou JNCpour déterminer si le nombre est abondant ou non.
Deadcode

1
Merci beaucoup pour toute votre aide et vos commentaires. J'ai mis à jour la documentation en ligne et supprimé le terme non golfé. Honnêtement, je n'y ai jamais vraiment pensé, mais je vois ce que vous voulez dire, car ce n'est pas différent, à l'exception des commentaires en ligne. Également d’accord pour que les drapeaux de retour soient clarifiés. Travaillera sur cela dans un peu. Merci pour l'attention et l'assistance!
640 Ko


5

05AB1E , 4 octets

ѨO‹

Essayez-le en ligne!

Comment ça marche

Ñ        #list of divisors
 ¨       #remove last element (i.e the input from the list of factors)
  O      #sum the list 
   ‹     #is this sum less than the input? 

Désolé de poster dans l'ancienne question, je parcourais simplement d'anciens posts pour m'entraîner et j'ai remarqué que ma solution était plus courte que la meilleure solution suivante 05AB1E.


4
Sorry to post in old questionNe t'inquiète pas pour ça! Je suis toujours heureux de voir des réponses à mes anciens défis, et c'est vraiment encourageant ici . :)
DJMcMayhem

4

PARI / GP , 15 octets

n->sigma(n)>2*n

La variante n->sigma(n,-1)>2est malheureusement plus longue.


4

Java 8, 53 octets (beaucoup plus si vous incluez le code de cérémonie)

return IntStream.range(1,n).filter(e->n%e<1).sum()>n;

Essayez-le en ligne

Explication:

IntStream.range(1,n) \\ numbers from 1 to n-1
filter(e->n%e<1)     \\ filter in numbers that perfectly divide the number n
sum()>n              \\ sum and compare to original number

4
Excellente réponse, mais avec Java 8, vous devez inclure la fonction dans votre nombre d'octets. Là encore, vous pouvez laisser tomber le returnsi je ne me trompe pas, alors ce sera encore plus court: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(pas à 100% si cela est correct, je ne programme presque jamais en Java 8). Bienvenue chez PPCG!
Kevin Cruijssen le

1
Le nombre correct via le nombre standard serait n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>nde 65 octets (en supposant que le paquet me soit
parvenu de mémoire

4

Powershell, 51 à 49 octets

param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i

J'aimerais pouvoir enlever quelques crochets.

-2 grâce à AdmBorkBork, au lieu de ne pas compter l'entrée dans la plage initiale, nous en tenons compte lors de la vérification finale.

Boucle à travers gamme de 1..la $input, moins 1, trouver où ( ?) modulo inverse de l' entrée par le nombre actuel est $true(alias seulement 0) - alors -jointous ces chiffres ensemble avec +et iexla chaîne résultante pour le calculer, puis voir si le la somme de ces parties est supérieure à l'entrée.

PS C:\++> 1..100 | ? {.\abundance.ps1 $_}
12
18
20
24
30
36
40
42
48
54
56
60
66
70
72
78
80
84
88
90
96
100

Vous pouvez économiser deux octets en comptant la valeur supérieure et en vérifiant qu'elle est supérieure à 2x l'entrée -param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
AdmBorkBork

3

MATL, 6 octets

Z\sGE>

Sorties 1 pour les nombres abondants, 0 sinon.

Comment ça marche

Z\      % list the divisors of the implicit input
s       % add them
G       % push the input again
E       % double it
>       % compare
        % implicitly display result

3

QBIC , 22 octets

:[a/2|~a%b|\p=p+b}?p>a

Ceci est une adaptation au test de primalité QBIC . Au lieu de compter les diviseurs et de vérifier s’il s’agit de moins de trois, cela fait la somme des diviseurs appropriés. Cela ne concerne que la moitié des cas 1 to n, où le test de primalité est 1 to ncomplètement effectué.

Explication:

:       Get the input number, 'a'
[a/2|   FOR(b=1, b<=(a/2), b++)
~a%b    IF a MOD b != 0  --> QBasic registers a clean division  (0) as false. 
        The IF-branch ('|') therefor is empty, the code is in the ELSE branch ('\')
|\p=p+b THEN add b to runnning total p
}       Close all language constructs: IF/END IF, FOR/NEXT
?p>a    Print '-1' for abundant numbers, 0 otherwise.

3

JavaScript (ES6), 33 octets

let g =
x=>(f=n=>--n&&n*!(x%n)+f(n))(x)>x
<input type=number min=1 value=1 step=1 oninput="O.innerHTML=g(+value)"><br>
<pre id=O>false</pre>


J'étais sûr qu'une réponse récursive serait la meilleure mais je ne pensais pas que ce serait aussi bien.
Neil

3

Japt , 9 7 6 octets

<Uâ1 x

2 octets sauvés grâce à ETHproductions. Sauvé 1 octet grâce à obarakon.

Essayez-le en ligne!


9 caractères, 10 octets.
Metoniem

@ Metoniem, je suis sûr, âest de 1 octet, au moins en Unicode (0xE2).
Tom

1
@ Metoniem Japt utilise le codage ISO-8859-1 , qui âconsiste en un seul octet.
ETHproductions

Si âun argument de vérité est donné, cela supprimera le nombre réel de la liste restante, vous pourrez â1 x >Udonc sauvegarder quelques octets :-)
ETHproductions

@TomDevs Nice! Vous pouvez faire <Uâ1 xpour sauvegarder un octet. Japt ajoute le Udevant du programme.
Oliver

3

Cubix , 38 octets

/..?%?(O;0I:^.<.>;rrw+s;rUO?-<...O0L.@

Essayez-le ici

      / . .
      ? % ?
      ( O ;
0 I : ^ . < . > ; r r w
+ s ; r U O ? - < . . .
O 0 L . @ . . . . . . .
      . . .
      . . .
      . . .

0I:- établit la pile avec 0, n, n (s, n, d)
^- commence la boucle )?- décrémente d et teste pour 0. 0 quitte la boucle
%?- mod contre n et teste. 0 provoque la ;rrw+s;rUrotation de s vers le haut et l'ajout de d, la rotation de s vers le bas et rejoint la boucle
;<- Nettoyez et rejoignez la boucle.
En boucle de sortie
;<- Enlevez d de la pile et redirigez
-?- Enlevez n de s et testez, LOU@tournez à gauche, sorties et sorties, les négatifs 0O@poussent à zéro, sortez et sortez . les positifs ;Oéliminent la différence et sortent n. Le chemin passe ensuite à gauche et mène à la @sortie.


3

Pure Bash, 37 octets

for((;k++<$1;s+=$1%k?0:k)){((s>$1));}

Merci à @Dennis d’avoir réorganisé le code, ce qui a permis d’économiser 6 octets et d’éliminer toute sortie accessoire vers stderr.

L'entrée est passée en argument.

La sortie est renvoyée dans le code de sortie: 0 pour abondant, 1 pour non abondant.

La sortie vers stderr doit être ignorée.

Tests effectués:

for n in {1..100}; do if ./abundant "$n"; then echo $n; fi; done 2>/dev/null
12
18
20
24
30
36
40
42
48
54
56
60
66
70
72
78
80
84
88
90
96
100

Vous pouvez enregistrer 6 octets tout en évitant une sortie parasite vers STDERR. tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/…
Dennis

2

RProgN , 8 octets

~_]k+2/<

A expliqué

~_]k+2/<
~           # Zero Space Segment
 _          # Convert the input to an integer
  ]         # Duplicate the input on the stack
   k+       # Get the sum of the divisors of the top of the stack
     2/     # Divded by 2
       <    # Is the Input less than the sum of its divisors/2.

Essayez-le en ligne!


2

Lot, 84 octets

@set/ak=%1*2
@for /l %%j in (1,1,%1)do @set/ak-=%%j*!(%1%%%%j)
@cmd/cset/a"%k%>>31

Sorties -1pour un nombre abondant, 0sinon. Fonctionne en soustrayant tous les facteurs de 2n, puis en décalant le résultat 31 endroits pour extraire le bit de signe. Formulation alternative, également 84 octets:

@set k=%1
@for /l %%j in (1,1,%1)do @set/ak-=%%j*!(%1%%%%j)
@if %k% lss -%1 echo 1

Sorties 1pour un nombre abondant. Fonctionne en soustrayant tous les facteurs de n, puis en comparant le résultat à -n. ( set/aC’est la seule façon pour Batch de faire de l’arithmétique, je ne peux donc pas régler facilement la boucle.)


1
"(% 1 %%%% j)" oh, lot :)
Bryan Boettcher le

2

Perl 6, 72 24 octets

{$_ <sum grep $_%%*,^$_}
  • Argument du programme: a.
  • Générez une liste à partir de 1..a.
  • Prenez tous les nombres diviseurs de a.
  • Somme eux.
  • Vérifiez si cette somme est supérieure à a.

Merci à @ b2gills.


Chaque occurrence d’ $^aaprès le premier peut être réduite à juste $a. mais il est même plus court si vous l'écrivez ainsi: {$_ <sum grep $_%%*,^$_}[+](LIST)
Voir

@ BradGilbertb2gills Merci! :)
Ven

2

J, 19 octets

Merci à Conor O'Brien de l'avoir coupé à 19 octets!

<[:+/i.#~i.e.]%2+i.

Précédent: (34 octets)

f=:3 :'(+/((i.y)e.y%2+i.y)#i.y)>y'

Retourne 1 s'il est abondant et 0 s'il ne l'est pas.

Sortie:

   f 3
0
   f 12
1
   f 11
0
   f 20
1

Bienvenue chez PPCG! Nous autorisons les fonctions anonymes afin que vous puissiez supprimer le début f=:dans le nombre d'octets. En outre, vous pouvez descendre à 19 en convertissant en un verbe tacite:<[:+/i.#~i.e.]%2+i.
Conor O'Brien le

Merci pour le conseil! Cependant, pourriez-vous expliquer le verbe ([:) et le verbe switch (~). Je ne comprends pas vraiment ce qu'ils sont censés faire dans ce verbe tacite.
Blocs

~ commutateurs donc c'est-à-dire # i. mais quel est le but de [:?
Blocs

donc vous savez sur les fourches, non? (f g h) y' is the same as (fy) g (hy) . When f` est une casquette, ([: g h) yest à peu près la même chose que g h y. En ce qui concerne ~, cela change les arguments gauche et droit. Il est important de savoir qu’il ~ne s’agit pas d’un verbe mais bien d’un adverbe. Cela modifie un verbe. Par exemple, nous pourrions avoir quelque chose comme 2 %~ 8. Ici, ~modifie %pour changer ses arguments, donc l'expression est équivalente à 8 % 2.
Conor O'Brien

Dans la chaîne de fourche, #~ est évalué après que les verbes à sa droite sont exécutés, donc l'argument de gauche devient le résultat à droite
Conor O'Brien

2

Pyth, 11 octets

>sPf!%QTS

Vieux:

L!%Qb>sPy#S

Je ne peux pas l'utiliser !%comme un pfn #, parce que c'est deux fonctions. Me rend triste :(.


L!%Qb>sPy#SQ    Program's argument: Q
L!%Qb           Define a lambda y, that takes b as an argument
 !%Qb           Return true if Q is divisible by b
          S     Make a range 1..Q
        y#      Filter that range with the lambda (y)
       P        Remove the last element (Q itself)
      s         Sum them
     >     Q    Check if that sum is greater than the program's argument

Ne pas définir une fonction semble être plus court:>sPf!%QTS
FryAmTheEggman le

2

k , 19 16 15 octets

{x<+/&~(!x)!'x}

Retourne 1pour vrai et 0pour faux.

Essayez-le en ligne!

{             } /function(x)
       (!x)     /{0, 1, ..., x-1}
            '   /for each n in {0, 1, ..., x-1}:
           ! x  /    do (x mod n)
      ~         /for each, turn 0 -> 1, * -> 0 (map not)
     &          /get indices of 1's
   +/           /sum (fold add)
 x<             /check if x < the sum



2

F #, 51 octets

let f n=Seq.filter(fun x->n%x=0){1..n-1}|>Seq.sum>n

Essayez-le en ligne!

Filtre tous les nombres qui ne se divisent pas de manière égale n, puis les additionne et les compare n.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.