Un'abbondanza di numeri interi!


40

Un numero abbondante è qualsiasi numero in cui la somma dei propri divisori è maggiore del numero originale. Ad esempio, i divisori propri di 12 sono:

1, 2, 3, 4, 6

E sommando questi risultati in 16. Dato che 16 è maggiore di 12, 12 è abbondante. Si noti che ciò non include "Numeri perfetti", ad esempio numeri uguali alla somma dei propri divisori, come 6 e 28.

Il tuo compito per oggi è scrivere un programma o una funzione che determini se un numero è abbondante o meno. Il tuo programma dovrebbe prendere un singolo numero intero come input e produrre un valore di verità / falsità a seconda che sia abbondante o meno. Si può presumere che l'input sia sempre valido e maggiore di 0, quindi per input errati, il comportamento indefinito va bene.

È possibile accettare input e output in qualsiasi formato ragionevole, ad esempio STDIN / STDOUT, file o argomenti / valori di ritorno sarebbero tutti accettabili.

Per riferimento, ecco i numeri abbondanti fino a 100:

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

E altro ancora può essere trovato su A005101

Dato che si tratta di , le scappatoie standard vengono negate e provano a scrivere il codice più breve possibile nella lingua che ti capita di scegliere!


11
"la prima dispari in abbondanza è 945 = 3 ^ 3 * 5 * 7, il 232 ° numero abbondante!"
mbomb007,

La densità asintotica di numeri abbondanti è da qualche parte nell'intervallo [0.24761748, 0.24764422]. Calcolato utilizzando il codice sorgente incluso in questo documento .
Deadcode

1
Sto provando a farlo in Geometry Dash. È un incubo
MilkyWay90

Risposte:


41

ECMAScript Regex, 1085 855 597 536 511 508 504 byte

Abbinare numeri abbondanti in regex ECMAScript è una bestia completamente diversa rispetto a farlo praticamente in qualsiasi altro sapore regex. La mancanza di backreferenze o ricorsioni in avanti / nidificate significa che è impossibile contare direttamente o mantenere un totale parziale di qualsiasi cosa. La mancanza di lookbehind rende spesso una sfida anche avere abbastanza spazio per lavorare.

Molti problemi devono essere affrontati da una prospettiva completamente diversa e ti starai chiedendo se sono risolvibili. Ti costringe a lanciare una rete molto più ampia nel trovare quali proprietà matematiche dei numeri con cui stai lavorando potrebbero essere utilizzate per rendere risolvibile un particolare problema.

Nel marzo-aprile 2014 ho costruito una soluzione a questo problema nella regex di ECMAScript. All'inizio avevo tutte le ragioni per sospettare che il problema fosse completamente impossibile, ma poi il matematico Teukon ha delineato un'idea che ha reso un caso incoraggiante per renderlo risolvibile dopo tutto - ma ha chiarito che non aveva intenzione di costruire la regex (lui aveva gareggiato / collaborato con il mio per costruire / giocare a golf regex precedenti, ma a questo punto aveva raggiunto il suo limite ed era contento di limitare i suoi ulteriori contributi alla teoria).

Come con il mio regex pubblicato un paio di giorni fa, darò un avvertimento: consiglio vivamente di imparare a risolvere i problemi matematici unari in regex ECMAScript. È stato un viaggio affascinante per me e non voglio rovinarlo per nessuno che potrebbe potenzialmente provarlo da solo, in particolare quelli con un interesse per la teoria dei numeri. Vedi quel post per un elenco di problemi raccomandati consecutivamente con tag spoiler da risolvere uno per uno.

Quindi non leggere oltre se non vuoi rovinare qualche profonda magia regex unaria . Il mio precedente post era solo un piccolo assaggio. Se vuoi fare un tentativo per capire da solo questa magia, ti consiglio vivamente di iniziare risolvendo alcuni problemi nella regex di ECMAScript come indicato in quel post collegato sopra.

Prima di postare il mio regex ECMAScript, ho pensato che sarebbe stato interessante analizzare di Martin Ender NET soluzione pura espressione regolare , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). Risulta molto semplice capire quel regex, ed è elegante nella sua semplicità. Per dimostrare il contrasto tra le nostre soluzioni, ecco una versione commentata e piuttosto stampata (ma non modificata) del suo 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.
)

Prova la regex .NET online

Ora, torna al mio regex ECMAScript. Innanzitutto, eccolo in formato raw, spazi bianchi e senza commenti:

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

(passare \14a \14?per compatibilità con PCRE, .NET e praticamente ogni altro sapore regex che non sia ECMAScript)

Provalo online!
Provalo online! (più veloce, versione 537 byte del regex)

E ora un breve riassunto della storia dietro di essa.

All'inizio non era affatto ovvio, almeno per me, che fosse persino possibile abbinare i numeri primi nel caso generale. E dopo averlo risolto, lo stesso valeva per i poteri di 2. E poi i poteri di numeri composti. E poi quadrati perfetti. E anche dopo averlo risolto, inizialmente era impossibile fare una moltiplicazione generalizzata.

In un ciclo ECMAScript, è possibile tenere traccia di un solo numero variabile; quel numero non può superare l'input e deve diminuire ad ogni passo. Il mio primo regex funzionante per abbinare le corrette dichiarazioni di moltiplicazione A * B = C era di 913 byte e ha funzionato fattorizzando A, B e C nei loro poteri primi - per ogni fattore primo, dividere ripetutamente la coppia di fattori di potenza primi di A e C dalla loro base primaria fino a quando quella corrispondente ad A raggiunge 1; quello corrispondente a C viene quindi confrontato con il fattore di potenza primo di B. Queste due potenze dello stesso numero primo sono state "multiplexate" in un singolo numero sommandole; questo sarebbe sempre separabile in modo univoco su ogni successiva iterazione del ciclo, per lo stesso motivo per cui funzionano i sistemi numerici posizionali.

Abbiamo ottenuto una moltiplicazione fino a 50 byte usando un algoritmo completamente diverso (a cui teukon e io siamo riusciti ad arrivare in modo indipendente, anche se ci sono voluti solo poche ore e ci è andato dritto, mentre ci sono voluti un paio di giorni anche dopo che era portato alla mia attenzione che esisteva un metodo breve): per A≥B, A * B = C se presente solo se C è il numero più piccolo che soddisfa C≡0 mod A e C≡B mod A-1. (Convenientemente, l'eccezione di A = 1 non ha bisogno di una gestione speciale in regex, dove 0% 0 = 0 produce una corrispondenza.) Non riesco proprio a capire quanto sia bello che esista un modo così elegante di moltiplicare in sapore regex minimo. (E il requisito di A≥B può essere sostituito con un requisito che A e B sono potenze prime della stessa potenza. Nel caso di A≥B, questo può essere dimostrato usando il teorema del resto cinese.)

Se si fosse scoperto che non esisteva un algoritmo di moltiplicazione più semplice, l'abbondanza di regex numerici sarebbe probabilmente dell'ordine di diecimila byte o giù di lì (anche tenendo conto del fatto che ho golfato l'algoritmo da 913 byte fino a 651 byte). Fa molta moltiplicazione e divisione e il regex di ECMAScript non ha subroutine.

Ho iniziato a lavorare tangenzialmente sull'abbondante problema del numero nel 23 marzo 2014, costruendo una soluzione per quello che all'epoca sembrava essere un sotto-problema di questo: identificare il fattore primo di massima molteplicità, in modo che potesse essere diviso da N all'inizio, lasciando spazio per fare alcuni calcoli necessari. All'epoca sembrava essere una strada promettente da prendere. (La mia soluzione iniziale finì per essere piuttosto grande a 326 byte, poi passò a 185 byte.) Ma il resto del metodo disegnato da Teukon sarebbe stato estremamente complicato, quindi alla fine presi una strada piuttosto diversa. Si è rivelato sufficiente per dividere il più grande fattore di potenza principale di N corrispondente al più grande fattore primo su N; farlo per il massimo della massima molteplicità avrebbe aggiunto complessità e lunghezza inutili alla regex.

Ciò che restava era trattare la somma dei divisori come un prodotto di somme anziché una somma semplice. Come spiegato da Teukon il 14 marzo 2014:

Ci viene dato un numero n = p 0 a 0 p 1 a 1 ... p k-1 a k-1 . Vogliamo gestire la somma dei fattori di n, che è (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 ).

Mi è venuto in mente di vederlo. Non avevo mai pensato di fattorizzare la somma aliquota in quel modo, ed è stata questa formula più di ogni altra cosa a rendere plausibile la solvibilità di abbondanti corrispondenze numeriche nel regex di ECMAScript.

Alla fine, invece di testare un risultato di addizione o moltiplicazione superiore a N, o testare che tale risultato pre-diviso per M superi N / M, sono andato con i test se un risultato di divisione è inferiore a 1. Sono arrivato a la prima versione funzionante il 7 aprile 2014.

La storia completa delle mie ottimizzazioni golfistiche di questo regex è su github. A un certo punto un'ottimizzazione ha finito per rendere il regex molto più lento, quindi da quel momento ho mantenuto due versioni. Loro sono:

regex per l'abbinamento di numeri abbondanti.txt
regex per l'abbinamento di numeri abbondanti - shortest.txt

Queste regex sono pienamente compatibili sia con ECMAScript che con PCRE, ma una recente ottimizzazione ha comportato l'utilizzo di un gruppo di acquisizione potenzialmente non partecipante \14, pertanto la riduzione della compatibilità di PCRE e la modifica \14?ad \14esse possono essere entrambe ridotte di 1 byte.

Ecco la versione più piccola, con quell'ottimizzazione applicata (rendendola solo ECMAScript), riformattata per adattarsi a un blocco di codice StackExchange senza (per lo più) scorrimento orizzontale necessario:

# 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$)
  )
)+$

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
DJMcMayhem


27

Python 2 , 41 40 byte

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

L'output è tramite il codice di uscita , quindi 0 è verità e 1 è falsa.

Provalo online!

Come funziona

Dopo aver impostato n , k e j sull'input da STDIN, entriamo nel ciclo while . Detto loop si interromperà non appena -k - 1 = ~ k ≥ 0 , ovvero k ≤ -1 / k <0 .

In ogni iterazione, prima diminuiamo j per considerare solo i divisori propri di n . Se j è un divisore di n , n%jproduce 0 e j >> n% j * n = j / 2 0 = j viene sottratto da k . Tuttavia, se j non non divide n , n%jè positivo, quindi n%j*nè almeno n> log 2 j e j >> n% j * n = j / 2 n% j * n = 0 è sottratto da k .

Per numeri abbondanti, k raggiungerà un valore negativo prima o quando j diventa 1 , poiché la somma dei divisori propri di n è strettamente maggiore di n . In questo caso, usciamo dal ciclo while e il programma termina normalmente.

Tuttavia, se n non è abbondante, j alla fine raggiunge 0 . In questo caso, n%jgenera ZeroDivisionError e il programma si chiude con un errore.


4
~k<0è elegante, ma penso che -1<kfaccia anche il trucco;)
Martin Ender,


10

Gelatina , 3 byte

Æṣ>

Provalo online!

Come funziona

Æṣ>  Main link. Argument: n

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


10

Mathematica, 17 byte

Tr@Divisors@#>2#&

Spiegazione

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
Sono sorpreso che Mathematica non abbia incorporato questo ...
MrPaulch,

1
@MrPaulch Considerando la durata del programma, tuttavia, il file incorporato potrebbe essere molto più lungo nel nome>.>
Conor O'Brien

1
@ ConorO'Brien Se esistesse, probabilmente lo sarebbe AbundantNumberQ, quindi risparmierebbe un paio di byte :)
ngenesi


7

Retina , 50 45 byte

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

Input in unario , output 1per numeri abbondanti, 0altrimenti.

Non c'è nulla di specifico di Retina in questa soluzione. Quanto sopra è una regex .NET pura che corrisponde solo a numeri abbondanti.

Provalo online! (Test suite che filtra l'input decimale con la regex sopra.)


6

Retina , 34 byte

Il conteggio dei byte presuppone la codifica ISO 8859-1.

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

^(1+)¶1\1

Input in unario , output 1per numeri abbondanti, 0altrimenti.

Provalo online!

Spiegazione

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

Iniziamo ottenendo tutti i divisori dell'input. Per fare ciò, restituiamo ( !) tutte le sovrapposizioni ( &) corrispondenze ( M) del regex (1+)$(?<=^\1+). La regex corrisponde ad alcuni suffissi dell'input, a condizione che l'intero input sia un multiplo di quel suffisso (che assicuriamo cercando di raggiungere l'inizio della stringa usando solo copie del suffisso). A causa del modo in cui il motore regex cerca le corrispondenze, ciò comporterà un elenco di divisori in ordine decrescente (separati da avanzamenti di riga).

1>`¶

Lo stage stesso abbina semplicemente i feed di linea ( ) e li rimuove. Tuttavia, 1>è un limite che salta la prima partita. Quindi questo aggiunge efficacemente tutti i divisori tranne l'input stesso. Finiamo con l'input sulla prima riga e la somma di tutti i divisori propri sulla seconda riga.

^(1+)¶1\1

Infine, cerchiamo di abbinare almeno un altro 1sulla seconda riga rispetto a quello che abbiamo sulla prima riga. In tal caso, la somma dei divisori propri supera l'input. Retina conta il numero di partite di questa regex, che sarà 1per numeri abbondanti e in 0altro modo.


1
Mi ha sempre stupito come puoi fare matematica in retina. Mi piacerebbe vedere una spiegazione! :)
DJMcMayhem

1
@DJMcMayhem Siamo spiacenti di averlo aggiunto prima. Fatto.
Martin Ender,

6

8086 Assembly, 23 28 25 24 byte

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

smontato:

; 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

Esempio di programma di 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

Uscita [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

Uscita [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

Uscita [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

aggiornamenti:

  • Risolto per overflow a 16 bit (+5 byte). Grazie @deadcode per i suggerimenti!
  • Logica di ritorno semplificata (-3 byte). Grazie ancora per l'aiuto di @deadcode.
  • Utilizzare TEST anziché CMP (-1 byte). Grazie a @ l4m2!

1
Vorrei suggerire di sostituire JLEcon JBEdi raddoppiare l'intervallo di numeri questo test può prima di iniziare overflow inducendolo a dare falsi negativi. Quindi invece di iniziare a fallire a 12600 (somma aliquota 35760), inizierà a fallire a 25200 (somma aliquota 74744). Ancora meglio sarebbe rilevare anche il flag carry e trattarlo come un numero abbondante senza dover calcolare la somma effettiva> 16 bit.
Deadcode

1
Buona cattura @Deadcode. Ho aggiornato il codice per saltare sotto invece di saltare meno. Capisco cosa intendi, facendo un JC dopo ADD BX, CX catturerà lì l'overflow senza segno e lo correggerà fino a N = 65535. Complica il test dei flag e restituisce un po 'lo stato, poiché in precedenza CF implicava false. Aggiornato anche con correzione.
640 KB

1
È possibile salvare 3 byte invertendo la specifica del valore restituito, con CF impostato se abbondante e chiaro in caso contrario. Ma raccomanderei di fare la modifica per correggere prima la documentazione di output, quindi sembra bello nella cronologia delle modifiche.
Deadcode

1
Inoltre, per semplificare le cose, la specifica dovrebbe essere che il valore di ritorno è nella bandiera carry e nessuno di questi problemi con le altre flag. Il chiamante dovrebbe usare JCo JNCagire sul fatto che il numero sia abbondante o meno.
Deadcode

1
Grazie mille per tutto il tuo aiuto e i tuoi commenti. Ho aggiornato la documentazione in linea e rimosso il termine non golfato. Onestamente non ci ho mai pensato molto, ma vedo il tuo punto a riguardo, in quanto non è diverso con l'eccezione dei commenti in linea. Anche d'accordo sul rendere più chiare anche le bandiere di ritorno. Ci lavoreremo un po '. Grazie per l'attenzione e l'assistenza!
640 KB


5

05AB1E , 4 byte

ѨO‹

Provalo online!

Come funziona

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

Mi dispiace pubblicare nella vecchia domanda, stavo solo esaminando i vecchi post per la pratica e ho notato che la mia soluzione era più corta della migliore soluzione 05AB1E successiva.


4
Sorry to post in old questionNon ti preoccupare! Sono sempre felice di vedere le risposte alle mie vecchie sfide, ed è in realtà incoraggiato da queste parti . :)
DJMcMayhem


4

Java 8, 53 byte (molto di più se includi il codice cerimoniale)

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

Provalo online

Spiegazione :

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
Ottima risposta, ma con Java 8 è necessario includere la funzione nel conteggio dei byte. Poi di nuovo, puoi rilasciare il messaggio returnse non sbaglio, quindi sarà ancora più breve: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(non al 100% se questo è corretto, non ho quasi mai programmato in Java 8). Benvenuti in PPCG!
Kevin Cruijssen,

1
Il conteggio corretto tramite il conteggio standard sarebbe n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>nper 65 byte (supponendo che ho ricevuto il pacchetto dalla parte superiore della mia testa)
CAD97

4

Powershell, 51 49 byte

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

Vorrei poter rimuovere alcune parentesi.

-2 grazie ad AdmBorkBork, invece di non contare l'input nell'intervallo iniziale, lo prendiamo semplicemente in considerazione nel controllo finale.

Loop attraverso la gamma di 1..al $input, meno 1, trovare dove ( ?) il modulo inverso di ingresso per il numero attuale è $true(alias solo 0) - allora -jointutti quei numeri insieme con +e iexla stringa risultante per calcolarlo, poi vedere se la la somma di queste parti è maggiore dell'input.

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

Puoi salvare due byte contando il valore più alto e controllando che sia maggiore del param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
doppio

3

MATL, 6 byte

Z\sGE>

Emette 1 per numeri abbondanti, 0 altrimenti.

Come funziona

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 byte

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

Questo è un adattamento al test di primalità QBIC . Invece di contare i divisori e verificare se è inferiore a tre, questo somma i divisori appropriati. Questo funziona solo per metà 1 to n, dove il test di primalità si 1 to ncompleta completamente.

Spiegazione:

:       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 byte

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>


Ero sicuro che una risposta ricorsiva sarebbe stata la migliore, ma non pensavo che sarebbe stata così buona.
Neil,

3

Japt , 9 7 6 byte

<Uâ1 x

Risparmiato 2 byte grazie a ETHproductions. Salvato 1 byte grazie a obarakon.

Provalo online!


9 caratteri, 10 byte.
Metoniem,

@Metoniem Sono sicuro che âsia 1 byte, almeno in Unicode (0xE2).
Tom,

1
@Metoniem Japt utilizza la codifica ISO-8859-1 , in cui âè un singolo byte.
ETHproductions

Se âviene fornito un argomento vero, rimuoverà il numero effettivo dall'elenco rimanente, quindi puoi fare â1 x >Uper salvare un paio di byte :-)
ETHproductions

@TomDevs Nice! Puoi fare <Uâ1 xper salvare un byte. Japt aggiunge il Udavanti al programma.
Oliver,

3

Cubix , 38 byte

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

Provalo qui

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

0I:- imposta lo stack con 0, n, n (s, n, d)
^- inizio del ciclo )?- decremento d e test per 0. 0 esce dal ciclo
%?- mod contro n e test. 0 causa la ;rrw+s;rUrotazione di s verso l'alto e l'aggiunta di d, la rotazione di s verso il basso e la ricongiungimento del ciclo
;<- Pulizia e ricollegamento del ciclo.
All'uscita dal loop
;<- Rimuovi d dallo stack e reindirizza
-?- Rimuovi n da se testa, 0 LOU@gira a sinistra, uscite ed uscite, i negativi 0O@spingono zero, uscite ed uscite. i positivi ;Orimuovono la differenza e gli output n. Il percorso passa quindi alla svolta a sinistra che reindirizza verso l' @uscita


3

Pure Bash, 37 byte

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

Grazie a @Dennis per aver riorganizzato il codice, salvando 6 byte ed eliminando l'output accidentale su stderr.

L'input viene passato come argomento.

L'output viene restituito nel codice di uscita: 0 per abbondante, 1 per non abbondante.

L'output su stderr dovrebbe essere ignorato.

Esecuzioni di test:

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

È possibile salvare 6 byte evitando l'output vagante su STDERR. tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/…
Dennis

2

RProgN , 8 byte

~_]k+2/<

spiegato

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

Provalo online!


2

Lotto, 84 byte

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

Uscite -1per un numero abbondante, 0altrimenti. Funziona sottraendo tutti i fattori 2ne spostando il risultato di 31 posizioni per estrarre il bit del segno. Formulazione alternativa, anche 84 byte:

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

Uscite 1per un numero abbondante. Funziona sottraendo tutti i fattori ne quindi confrontando il risultato con -n. ( set/aè l'unico modo di Batch di fare l'aritmetica, quindi non posso facilmente regolare il ciclo.)


1
"(% 1 %%%% j)" oh, batch :)
Bryan Boettcher,

2

Perl 6, 72 24 byte

{$_ <sum grep $_%%*,^$_}
  • Argomento del programma: a.
  • Genera un elenco da 1..a.
  • Prendi tutti i numeri che sono divisori di a.
  • Sommarli.
  • Controlla se tale somma è maggiore di a.

Grazie a @ b2gills.


Ogni ricorrenza di $^adopo il primo può essere abbreviata in giusto $a. ma è ancora più breve se lo scrivi come {$_ <sum grep $_%%*,^$_}Anche guardando una versione precedente, [+](LIST)funziona (senza spazi)
Brad Gilbert b2gills

@ BradGilbertb2gills Grazie! :)
Ven

2

J, 19 byte

Grazie a Conor O'Brien per averlo ridotto a 19 byte!

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

Precedente: (34 byte)

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

Restituisce 1 se è abbondante e 0 se non lo è.

Produzione:

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

Benvenuti in PPCG! Sono consentite funzioni anonime, pertanto è possibile rimuovere il lead f=:come parte del conteggio dei byte. Inoltre, puoi arrivare a 19 convertendoli in un verbo tacito:<[:+/i.#~i.e.]%2+i.
Conor O'Brien,

Grazie per il consiglio! Tuttavia, potresti spiegare il verbo cap ([:) e il verbo switch (~). Non capisco davvero cosa dovrebbero fare in questo verbo tacito.
Blocca il

~ cambia quindi è # i. ma qual è lo scopo di [:?
Blocca il

quindi sai delle forcelle, vero? (f g h) y' is the same as (fy) g (hy) . When f` è un berretto, ([: g h) yè approssimativamente lo stesso di g h y. Per quanto riguarda ~, questo cambia gli argomenti sinistro e destro. È importante sapere che ~non è un verbo ma in realtà è un avverbio. Modifica un verbo. Ad esempio, potremmo avere qualcosa di simile 2 %~ 8. Qui, ~modifica %per cambiare i suoi argomenti, quindi l'espressione è equivalente a8 % 2 .
Conor O'Brien,

Nella catena della forcella, #~viene valutato dopo l'esecuzione dei verbi alla sua destra, quindi l'argomento sinistro diventa il risultato a destra
Conor O'Brien,

2

Pyth, 11 byte

>sPf!%QTS

Vecchio:

L!%Qb>sPy#S

Non posso usare !%come un pfn per #, perché sono due funzioni. Mi rende 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

Non definire una funzione sembra essere più breve:>sPf!%QTS
FryAmTheEggman,

2

K , 19 16 15 byte

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

Restituisce 1per vero e 0per falso.

Provalo 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



2

F #, 51 byte

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

Provalo online!

Filtra tutti i numeri che non si dividono uniformemente in n, quindi li somma e li confronta con n.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.