Uma abundância de números inteiros!

40

Um número abundante é qualquer número em que a soma de seus divisores adequados seja maior que o número original. Por exemplo, os divisores adequados de 12 são:

1, 2, 3, 4, 6

E somando esses resultados em 16. Como 16 é maior que 12, 12 é abundante. Observe que isso não inclui "Números perfeitos", por exemplo, números iguais à soma de seus divisores adequados, como 6 e 28.

Sua tarefa para hoje é escrever um programa ou função que determine se um número é abundante ou não. Seu programa deve usar um único inteiro como entrada e gerar um valor de verdade / falsidade, dependendo de ser abundante ou não. Você pode assumir que a entrada sempre será válida e maior que 0; portanto, para entradas ruins, o comportamento indefinido é bom.

Você pode levar sua entrada e saída em qualquer formato razoável, por exemplo, STDIN / STDOUT, arquivos ou argumentos / valores de retorno seriam aceitáveis.

Para referência, aqui estão os números abundantes de até 100:

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

E muito mais pode ser encontrado no A005101

Como se trata de , as brechas padrão são negadas e tente escrever o código mais curto possível no idioma que você escolher!

DJMcMayhem
fonte
11
"o primeiro abundante ímpar é 945 = 3 ^ 3 * 5 * 7, o 232º número abundante!"
mbomb007
A densidade assintótica de números abundantes está em algum lugar dentro do intervalo [0,24761748, 0,24764422]. Calculado usando o código fonte incluído neste documento .
Deadcode
11
Estou tentando fazer isso no Geometry Dash. É um pesadelo
MilkyWay90 29/01

Respostas:

41

ECMAScript Regex, 1085 855 597 536 511 508 504 bytes

Combinar números abundantes no regex ECMAScript é um animal totalmente diferente do que em praticamente qualquer outro sabor de regex. A falta de referências ou recursões avançadas / aninhadas significa que é impossível contar diretamente ou manter um total em execução de qualquer coisa. A falta de atenção faz com que muitas vezes seja um desafio ter espaço suficiente para trabalhar.

Muitos problemas devem ser abordados de uma perspectiva totalmente diferente, e você se perguntará se eles são solucionáveis. Obriga você a lançar uma rede muito mais ampla para descobrir quais propriedades matemáticas dos números com os quais você está trabalhando podem ser usadas para tornar um problema específico solucionável.

De março a abril de 2014, construí uma solução para esse problema no regex ECMAScript. No começo, eu tinha todos os motivos para suspeitar que o problema era completamente impossível, mas, em seguida, o matemático teukon esboçou uma idéia que fazia um argumento encorajador para torná-lo solucionável, afinal - mas ele deixou claro que não tinha intenção de construir o regex (ele havia competido / cooperado com o meu na construção / regexes anteriores de golfe, mas atingiu seu limite nesse ponto e estava contente em restringir suas contribuições adicionais à teorização).

Como no meu regex publicado há alguns dias, darei um aviso: eu recomendo aprender como resolver problemas matemáticos unários no regex ECMAScript. Foi uma jornada fascinante para mim, e não quero estragá-la para quem potencialmente queira experimentá-la, especialmente aqueles interessados ​​na teoria dos números. Consulte essa publicação para obter uma lista de problemas recomendados consecutivamente identificados por spoilers para resolver um por um.

Portanto , não leia mais se não quiser que você estrague uma mágica profunda e uniforme de regex . Meu post anterior foi apenas um gostinho. Se você quiser tentar descobrir essa mágica, eu recomendo começar resolvendo alguns problemas no regex ECMAScript, conforme descrito no post acima.

Antes de postar a minha regex ECMAScript, eu pensei que seria interessante analisar de Martin Ender solução pura regex .NET , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). É muito simples entender esse regex e é elegante em sua simplicidade. Para demonstrar o contraste entre nossas soluções, aqui está uma versão comentada e bem impressa (mas não modificada) de seu 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.
)

Experimente o regex .NET online

Agora, de volta ao meu regex ECMAScript. Primeiro, aqui está no formato bruto, sem espaço em branco e sem comentários:

^(?=(((?=(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$)))+$

(mudança \14para \14?a compatibilidade com PCRE, .NET, e praticamente todos os outros sabores regex que não é ECMAScript)

Experimente online!
Experimente online! (versão mais rápida, 537 bytes da regex)

E agora um breve resumo da história por trás disso.

No começo, era muito óbvio, pelo menos para mim, que era até possível igualar primos no caso geral. E depois de resolver isso, o mesmo se aplicava às potências de 2. E depois às potências dos números compostos. E depois quadrados perfeitos. E mesmo depois de resolver isso, fazer multiplicação generalizada parecia impossível a princípio.

Em um loop ECMAScript, você pode acompanhar apenas um número alterado; esse número não pode exceder a entrada e deve diminuir a cada passo. Meu primeiro regex de trabalho para combinar as instruções de multiplicação corretas A * B = C tinha 913 bytes e trabalhei fatorando A, B e C em suas potências primárias - para cada fator primo, divida repetidamente o par de fatores de potência primos de A e C por sua base principal até que a correspondente a A atinja 1; o correspondente a C é então comparado ao fator de potência principal de B. Essas duas potências do mesmo primo foram "multiplexadas" em um único número adicionando-as; isso sempre seria inequivocamente separável em cada iteração subsequente do loop, pela mesma razão que os sistemas numéricos posicionais funcionam.

Reduzimos a multiplicação para 50 bytes usando um algoritmo completamente diferente (que teukon e eu conseguimos chegar de forma independente, embora ele tenha levado apenas algumas horas e ele foi direto para ela, enquanto levei alguns dias mesmo depois de trouxe à minha atenção que existia um método curto): para A≥B, A * B = C, se houver, apenas se C for o menor número que satisfaça C0 mod A e C mod B A-1. (Convenientemente, a exceção de A = 1 não precisa de tratamento especial na regex, em que 0% 0 = 0 gera uma correspondência.) Simplesmente não consigo entender o quão interessante é que existe uma maneira tão elegante de fazer multiplicação em um sabor mínimo de regex. (E o requisito de A≥B pode ser substituído pelo requisito de que A e B sejam potências primárias da mesma potência. No caso de A≥B, isso pode ser comprovado usando o teorema do restante chinês.)

Se houvesse um algoritmo mais simples para multiplicação, o número abundante de regex provavelmente seria da ordem de dez mil bytes (mais ainda, considerando que eu joguei o algoritmo de 913 bytes em até 651 bytes). Ele faz muita multiplicação e divisão, e o regex ECMAScript não possui sub-rotinas.

Comecei a trabalhar tangencialmente no abundante número de problemas em 23 de março de 2014, construindo uma solução para o que parecia ser um subproblema: Identificar o fator primordial da maior multiplicidade, para que pudesse ser dividido entre N no início, deixando espaço para fazer alguns cálculos necessários. Naquele momento, parecia ser um caminho promissor a seguir. (Minha solução inicial acabou sendo bastante grande em 326 bytes, depois diminuiu para 185 bytes.) Mas o resto do método que o teukon esboçou teria sido extremamente complicado, então, como se viu, tomei uma rota bastante diferente. Provou ser suficiente dividir o maior fator de potência principal de N correspondente ao maior fator de potência primária de N; fazer isso para o primeiro da multiplicidade mais alta teria adicionado complexidade e comprimento desnecessários ao regex.

O que ficou foi tratar a soma dos divisores como um produto de somas, em vez de uma soma direta. Conforme explicado por teukon em 14 de março de 2014:

Recebemos um número n = p 0 a 0 p 1 a 1 ... p k-1 a k-1 . Queremos lidar com a soma dos fatores de n, que é (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 ).

Fiquei impressionado ao ver isso. Eu nunca tinha pensado em fatorar a soma da alíquota dessa maneira, e foi essa fórmula mais do que qualquer outra coisa que tornou plausível a resolubilidade da correspondência abundante de números no regex ECMAScript.

No final, em vez de testar um resultado de adição ou multiplicação superior a N ou testar se esse resultado pré-dividido por M excede N / M, fui testando se o resultado da divisão é menor que 1. Cheguei a a primeira versão de trabalho em 7 de abril de 2014.

A história completa das minhas otimizações de golfe desse regex está no github. Em um certo ponto, uma otimização acabou tornando o regex muito mais lento; portanto, a partir desse momento, mantive duas versões. Eles são:

regex para combinar números abundantes.txt
regex para combinar números abundantes - shortest.txt

Essas regexes são totalmente compatíveis com o ECMAScript e o PCRE, mas uma otimização recente envolveu o uso de um grupo de captura potencialmente não participante \14; portanto, ao abandonar a compatibilidade do PCRE e mudar \14?para \14ambos, é possível reduzir em 1 byte.

Aqui está a versão menor, com essa otimização aplicada (tornando-o apenas ECMAScript), reformatada para caber em um bloco de código StackExchange sem (principalmente) nenhuma rolagem horizontal necessária:

# 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$)
  )
)+$
Deadcode
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
DJMcMayhem
11
-98 bytes
Grimmy 5/03
27

Python 2 , 41 40 bytes

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

A saída é via código de saída , então 0 é verdadeiro e 1 é falso.

Experimente online!

Como funciona

Após o ajuste de todos n , k , e j para a entrada de STDIN, que introduza o enquanto loop. O referido loop quebrará assim que -k - 1 = ~ k ≥ 0 , ou seja, k ≤ -1 / k <0 .

Em cada iteração, primeiro decrementamos j para considerar apenas os divisores apropriados de n . Se j é um divisor de n , n%jproduz 0 e j >> n% j * n = j / 2 0 = j é subtraído de k . No entanto, se j se não dividir n , n%jé positiva, então n%j*né, pelo menos, n> log 2 j e j >> n% j * n = j / 2 n% j * n = 0 é subtraído a partir de k .

Para números abundantes, k atingirá um valor negativo antes ou quando j se tornar 1 , uma vez que a soma dos divisores adequados de n é estritamente maior que n . Neste caso, nós sair da enquanto loop e o programa termina normalmente.

No entanto, se n não for abundante, j chegará a 0 . Nesse caso, n%jlança um ZeroDivisionError e o programa sai com um erro.

Dennis
fonte
4
~k<0é chique, mas acho que -1<ktambém faz o truque;)
Martin Ender
12

Braquilog , 5 bytes

fk+>?

Experimente online!

Explicação

f           Factors
 k          Knife: remove the last one (the input itself)
  +         Sum
   >?       Stricly greater than the Input
Fatalizar
fonte
10

Gelatina , 3 bytes

Æṣ>

Experimente online!

Como funciona

Æṣ>  Main link. Argument: n

Æs   Get the proper divisor sum of n.
  >  Test if the result is greater than n.
Dennis
fonte
10

Python , 44 bytes

lambda n:sum(i*(n%i<1)for i in range(1,n))>n

Experimente online!

Jonathan Allan
fonte
É uma pena que você não pode fazer range(n). Esse módulo irritante por zero
DJMcMayhem
10

Mathematica, 17 bytes

Tr@Divisors@#>2#&

Explicação

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.
ngenisis
fonte
11
Estou surpreso Mathematica não tem construído em para este ..
MrPaulch
11
@MrPaulch Considerando a duração do programa, porém, o embutida pode muito bem ser mais no name>>.
Conor O'Brien
11
@ ConorO'Brien Se existisse, seria provavelmente AbundantNumberQ, por isso seria salvar um casal bytes :)
ngenisis
7

Retina , 50 45 bytes

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

Entrada unária , saída 1para números abundantes, 0caso contrário.

Não há nada específico da Retina sobre esta solução. O acima é um regex .NET puro que corresponde apenas a números abundantes.

Experimente online! (Conjunto de testes que filtra a entrada decimal com o regex acima.)

Martin Ender
fonte
6

Retina , 34 bytes

A contagem de bytes assume a codificação ISO 8859-1.

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

^(1+)¶1\1

Entrada unária , saída 1para números abundantes, 0caso contrário.

Experimente online!

Explicação

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

Começamos obtendo todos os divisores da entrada. Para fazer isso, retornamos ( !) todas as correspondências sobrepostas ( &) ( M) da expressão regular (1+)$(?<=^\1+). A regex corresponde a algum sufixo da entrada, desde que toda a entrada seja um múltiplo desse sufixo (o que garantimos ao tentar chegar ao início da string usando apenas cópias do sufixo). Devido à maneira como o mecanismo regex procura correspondências, isso resultará em uma lista de divisores em ordem decrescente (separados por feeds de linha).

1>`¶

O estágio em si simplesmente corresponde a linefeeds ( ) e os remove. No entanto, 1>é um limite, que pula a primeira partida. Portanto, isso efetivamente adiciona todos os divisores, exceto a entrada em si. Terminamos com a entrada na primeira linha e a soma de todos os divisores apropriados na segunda linha.

^(1+)¶1\1

Finalmente, tentamos igualar pelo menos mais um 1na segunda linha do que na primeira linha. Se for esse o caso, a soma dos divisores apropriados excede a entrada. A retina conta o número de correspondências desse regex, que será 1para números abundantes e 0outros fatores.

Martin Ender
fonte
11
Sempre me surpreendeu como você pode fazer matemática na retina. Eu adoraria ver uma explicação! :)
DJMcMayhem
11
@DJMcMayhem Desculpe esqueci de adicionar isso antes. Feito.
Martin Ender
6

8086 Assembly, 23 28. 25 24 bytes

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

Desmontado:

; 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

Exemplo de programa de teste, testando 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

Saída [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

Saída [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

Saída [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

Atualizações:

  • Corrigido o estouro de 16 bits (+5 bytes). Obrigado @deadcode pelas sugestões!
  • Lógica de retorno simplificada (-3 bytes). Agradecemos a ajuda do @deadcode mais uma vez.
  • Use TEST em vez de CMP (-1 byte). Thx para @ l4m2!
640KB
fonte
11
Eu sugeriria substituir JLEpor JBEpara dobrar o intervalo de números que isso pode testar antes que os estouros comecem a causar falsos negativos. Em vez de começar a falhar em 12600 (soma da alíquota 35760), começará a falhar em 25200 (soma da alíquota 74744). Melhor ainda seria detectar também o sinalizador de transporte e tratá-lo como um número abundante sem precisar calcular a soma real> 16 bits.
Deadcode
11
Boa captura @Deadcode. Atualizei o código para pular abaixo em vez de pular menos. Entendo o que você quer dizer, ao fazer um JC após o ADD BX, o CX capturará o estouro não assinado lá e o corrigirá até N = 65535. Complica o teste do sinalizador e retorna um pouco o estado, pois anteriormente o CF implicava falso. Atualizado com correção também.
640KB 23/01
11
Você pode salvar 3 bytes invertendo a especificação do seu valor de retorno, com CF sendo definido se abundante e claro se não. Mas eu recomendo fazer a edição para corrigir a documentação de saída primeiro, para que fique bem no histórico de edições.
Deadcode
11
Além disso, para manter as coisas simples, a especificação deve ser que o valor de retorno esteja no sinalizador de transporte e nada disso perturbe os outros sinalizadores. O chamador deve usar JCou JNCagir sobre se o número é abundante ou não.
Deadcode
11
Muito obrigado por toda a sua ajuda e seus comentários. Atualizei a documentação embutida e removi o termo não destruído. Honestamente, nunca pensei muito nisso, mas entendo o seu ponto de vista, pois não é diferente, com exceção dos comentários embutidos. Também concorde em fazer as sinalizações de retorno também. Irá trabalhar nisso daqui a pouco. Obrigado pela atenção e assistência!
640KB 25/01
5

05AB1E , 4 bytes

ѨO‹

Experimente online!

Como funciona

Ñ        #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? 

Desculpe postar em uma pergunta antiga, eu estava apenas passando por postagens antigas para praticar e percebi que minha solução era mais curta que a próxima melhor solução 05AB1E.

lixo espacial
fonte
4
Sorry to post in old questionNão se preocupe com isso! Sempre fico feliz em ver respostas sobre meus velhos desafios, e isso é realmente incentivado por aqui . :)
DJMcMayhem
4

PARI / GP , 15 bytes

n->sigma(n)>2*n

n->sigma(n,-1)>2Infelizmente, a variante é mais longa.

Charles
fonte
4

Java 8, 53 bytes (muito mais se você incluir o código cerimonial)

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

Experimente online

Explicação:

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
Gautam D
fonte
4
Ótima resposta, mas com o Java 8 você deve incluir a função na sua contagem de bytes. Então, novamente, você pode largar o arquivo returnse não me engano, por isso será ainda mais curto: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(não 100% se isso estiver correto, eu quase nunca programa no Java 8). Bem-vindo ao PPCG!
Kevin Cruijssen 21/02
11
A contagem correta via contagem padrão seria n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>nde 65 bytes (supondo que eu tenha tirado o pacote da cabeça)
CAD97
4

Powershell, 51 49 bytes

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

Eu gostaria de poder remover alguns suportes.

-2 graças ao AdmBorkBork, em vez de não contar a entrada no intervalo inicial, apenas a levamos em consideração na verificação final.

Loop através de gama de 1..ao $input, menos 1, encontrar onde ( ?) o modulo inverso da entrada pelo número atual é $true(aka apenas 0) - então -jointodos os números com a +e iexa cadeia resultante para calculá-lo, em seguida, ver se o A soma dessas partes é maior que a entrada.

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
colsw
fonte
Você pode salvar dois bytes contando o valor superior e verificar se é maior do que 2x a entrada -param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
AdmBorkBork
3

MATL, 6 bytes

Z\sGE>

Saídas 1 para números abundantes, 0 caso contrário.

Como funciona

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

QBIC , 22 bytes

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

Esta é uma adaptação ao teste de primalidade QBIC . Em vez de contar os divisores e verificar se é menor que três, isso soma os divisores apropriados. Isso é executado apenas em metade 1 to n, onde o teste de primalidade é executado 1 to ncompletamente.

Explicação:

:       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.
steenbergh
fonte
3

JavaScript (ES6), 33 bytes

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>

ETHproductions
fonte
Eu tinha certeza de que uma resposta recursiva seria melhor, mas não achei que seria tão bom.
Neil
3

Japonês , 9 7 6 bytes

<Uâ1 x

Economizou 2 bytes graças ao ETHproductions. Guardado 1 byte graças a obarakon.

Experimente online!

Tom
fonte
9 caracteres, 10 bytes.
Metoniem 21/02
@ Metoniem Tenho certeza de que âé 1 byte, em pelo menos unicode (0xE2).
Tom
11
@Metoniem Japt usa a codificação ISO-8859-1 , na qual âhá um único byte.
ETHproductions
Se âfor fornecido um argumento de verdade, ele removerá o número real da lista restante, para que você possa â1 x >Usalvar alguns bytes :-)
ETHproductions
@TomDevs Nice! Você pode fazer <Uâ1 xpara salvar um byte. Japt adiciona o Una frente do programa.
21417 Oliver
3

Cubix , 38 bytes

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

Experimente aqui

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

0I:- configura a pilha com 0, n, n (s, n, d)
^- início do loop )?- diminui de 0 para 0. 0 sai do loop
%?- mod contra ne test. 0 causa ;rrw+s;rUque gira s para cima e adiciona d, gira s para baixo e volta ao loop
;<- Limpe e volte ao loop.
Ao sair do loop
;<- Remova d da pilha e redirecione
-?- Remova n de se teste, 0 LOU@vira à esquerda, sai e sai, negativos 0O@pressiona zero, sai e sai. positivos ;Oremovem diferença e resultados n. O caminho passa à esquerda, que redireciona para a @saída

MickyT
fonte
3

Pure Bash, 37 bytes

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

Agradecemos ao @Dennis por reorganizar o código - economizando 6 bytes e eliminando a saída incidental para o stderr.

A entrada é passada como argumento.

A saída é retornada no código de saída: 0 para abundante, 1 para não abundante.

A saída para stderr deve ser ignorada.

Execuções de teste:

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
Mitchell Spector
fonte
Você pode salvar 6 bytes, evitando a saída dispersa para STDERR. tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/…
Dennis
2

RProgN , 8 bytes

~_]k+2/<

Explicado

~_]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.

Experimente online!

ATaco
fonte
2

Lote, 84 bytes

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

Saídas -1para um número abundante, 0caso contrário. Funciona subtraindo todos os fatores de 2ne depois deslocando o resultado 31 lugares para extrair o bit do sinal. Formulação alternativa, também 84 bytes:

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

Saídas 1para um número abundante. Funciona subtraindo todos os fatores de ne comparando o resultado a para -n. ( set/aé a única maneira do Batch fazer aritmética, então não posso ajustar facilmente o loop.)

Neil
fonte
11
"(% 1 %%%% j)" oh, lote :)
Bryan Boettcher
2

Perl 6, 72 24 bytes

{$_ <sum grep $_%%*,^$_}
  • Argumento do programa: a.
  • Gere uma lista de 1..a.
  • Pegue todos os números que são divisores de a.
  • Soma-os.
  • Verifique se essa soma é maior que a.

Graças a @ b2gills.

Ven
fonte
Toda ocorrência $^aapós a primeira pode ser reduzida para apenas $a. mas é ainda mais curto se você escrevê-lo como {$_ <sum grep $_%%*,^$_}também a olhar para uma versão anterior, [+](LIST)obras (sem espaços)
Brad Gilbert b2gills
@ BradGilbertb2gills Thanks! :)
Ven
2

J, 19 bytes

Agradecimentos a Conor O'Brien por reduzi-lo a 19 bytes!

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

Anterior: (34 bytes)

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

Retorna 1 se for abundante e 0 se não for.

Saída:

   f 3
0
   f 12
1
   f 11
0
   f 20
1
Blocos
fonte
Bem-vindo ao PPCG! Permitimos funções anônimas, para que você possa remover a liderança f=:como parte da sua contagem de bytes. Além disso, você pode chegar a 19 convertendo para um verbo tácito:<[:+/i.#~i.e.]%2+i.
Conor O'Brien
Obrigado pelo conselho! No entanto, você poderia explicar o verbo cap ([:) e o verbo switch (~). Eu realmente não entendo o que eles deveriam fazer neste verbo tácito.
Bloqueia
~ alterna, portanto é # i. mas qual é o propósito de [:?
Bloqueia
então você sabe sobre garfos, certo? (f g h) y' is the same as (fy) g (hy) . When f` é um limite, ([: g h) yé aproximadamente o mesmo que g h y. Quanto a ~isso, alterna os argumentos esquerdo e direito. É importante saber que ~não é um verbo, mas na verdade é um advérbio. Modifica um verbo. Por exemplo, poderíamos ter algo parecido 2 %~ 8. Aqui, ~modifica %para alternar seus argumentos, para que a expressão seja equivalente a 8 % 2.
Conor O'Brien
Na cadeia de garfo, #~é avaliada após os verbos à sua direita são executados, por isso é argumento esquerda torna-se o resultado à direita
Conor O'Brien
2

Pitão, 11 bytes

>sPf!%QTS

Velho:

L!%Qb>sPy#S

Não posso usar !%como pfn para #, porque são duas funções. Deixa-me 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
Ven
fonte
Não definir uma função parece ser mais curto:>sPf!%QTS
FryAmTheEggman
2

k , 19 16 15 bytes

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

Retorna 1para true e 0para false.

Experimente online!

{             } /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
zgrep
fonte
2

Lisp comum, 63 bytes

(lambda(n)(>(loop for i from 1 below n if(=(mod n i)0)sum i)n))

Experimente online!

Renzo
fonte
2

F #, 51 bytes

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

Experimente online!

Filtra todos os números que não se dividem uniformemente ne depois os soma e os compara n.

Ciaran_McCarthy
fonte