Обилие целых чисел!


40

Обильный номер представляет собой любое число , где сумма его делителей больше , чем исходное число. Например, правильные делители 12:

1, 2, 3, 4, 6

И суммируя эти результаты в 16. Поскольку 16 больше, чем 12, 12 в изобилии. Обратите внимание, что это не включает «Совершенные числа», например, числа, которые равны сумме его собственных делителей, таких как 6 и 28.

Ваша задача на сегодня - написать программу или функцию, которая определяет, является ли число большим или нет. Ваша программа должна принимать одно целое число в качестве входных данных и выводить истинное / ложное значение в зависимости от того, является ли оно обильным или нет. Вы можете предположить, что входные данные всегда будут действительными и будут больше 0, поэтому для некорректных входных данных подходит неопределенное поведение.

Вы можете принимать входные и выходные данные в любом приемлемом формате, например, STDIN / STDOUT, файлы или аргументы / возвращаемые значения будут приемлемыми.

Для справки, вот многочисленные цифры до 100:

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

И еще можно найти на A005101

Поскольку это , стандартные лазейки запрещены, и постарайтесь написать как можно более короткий код на любом языке, который вы выберете!


11
«первое нечетное число - это 945 = 3 ^ 3 * 5 * 7, 232-е число с избытком!»
mbomb007

Асимптотическая плотность обильных чисел находится где-то в интервале [0.24761748, 0.24764422]. Рассчитано с использованием исходного кода, включенного в эту статью .
Deadcode

1
Я пытаюсь сделать это в Geometry Dash. Это кошмар
MilkyWay90

Ответы:


41

ECMAScript Regex, 1085 855 597 536 511 508 504 байта

Совпадение обильных чисел в регулярном выражении ECMAScript - это совершенно другой зверь, чем в любом другом варианте регулярного выражения. Отсутствие прямых / вложенных обратных ссылок или рекурсии означает, что невозможно напрямую подсчитать или сохранить промежуточный итог чего-либо. Отсутствие осмотрительности часто затрудняет работу даже при наличии достаточного пространства для работы.

Многие проблемы должны решаться с совершенно иной точки зрения, и вам будет интересно, решаются ли они вообще. Это заставляет вас создавать более широкую сеть, чтобы определить, какие математические свойства чисел, с которыми вы работаете, могут быть использованы для решения конкретной задачи.

Еще в марте-апреле 2014 года я построил решение этой проблемы в регулярном выражении ECMAScript. Сначала у меня были все основания подозревать, что проблема совершенно невозможна, но затем математик Теукон набросал идею, которая в конце концов обнадеживающе повлияла на то, чтобы она выглядела разрешимой, - но он дал понять, что не собирается строить регулярное выражение (он Я участвовал в соревнованиях / сотрудничал с моими в создании / игре предыдущих регулярных выражений, но к этому моменту достиг своего предела и был доволен, чтобы ограничить свой дальнейший вклад в теоретизирование).

Как и в случае с моим регулярным выражением, опубликованным пару дней назад, я дам предупреждение: я настоятельно рекомендую научиться решать унарные математические задачи в регулярном выражении ECMAScript. Для меня это было увлекательное путешествие, и я не хочу испортить его тем, кто потенциально может попробовать его сами, особенно тем, кто интересуется теорией чисел. См. Этот пост для списка последовательно рекомендованных спойлером проблем, решаемых один за другим.

Так что не читайте дальше, если вы не хотите, чтобы какая-то глубокая унарная магия испортилась для вас . Мой предыдущий пост был просто маленьким вкусом. Если вы действительно хотите сами разобраться в этой магии, я настоятельно рекомендую начать с решения некоторых проблем в регулярном выражении ECMAScript, как описано в этом посте, связанном выше.

Перед тем как разместить свое ECMAScript регулярное выражение, я думал , что это было бы интересно проанализировать Мартина Эндера решение .NET чисто регулярное выражение , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). Оказывается, очень просто понять это регулярное выражение, и оно элегантно в своей простоте. Чтобы продемонстрировать контраст между нашими решениями, вот закомментированная и довольно напечатанная (но не измененная) версия его регулярного выражения:

# 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.
)

Попробуйте регулярное выражение .NET онлайн

Теперь вернемся к моему регулярному выражению ECMAScript. Во-первых, вот он в необработанном формате без пробелов и комментариев:

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

(изменить , \14чтобы \14?для совместимости с PCRE, .NET, и практически любой другой регулярным выражением вкуса , который не ECMAScript)

Попробуйте онлайн!
Попробуйте онлайн! (быстрее, 537-байтовая версия регулярного выражения)

А теперь краткое изложение истории, стоящей за этим.

Сначала было очень неочевидно, по крайней мере для меня, что в общем случае можно было даже сопоставить простые числа. И после решения этого то же самое применимо к степеням 2. А затем к степеням составных чисел. А потом идеальные квадраты. И даже после решения этой задачи поначалу казалось, что обобщенное умножение невозможно.

В цикле ECMAScript вы можете отслеживать только один изменяющийся номер; это число не может превышать входное значение и должно уменьшаться на каждом шаге. Мое первое рабочее регулярное выражение для сопоставления правильных операторов умножения A * B = C было 913 байтов и работало путем деления A, B и C на их основные степени - для каждого простого множителя многократно делим пару простых коэффициентов мощности A и C по их первичной базе, пока та, которая соответствует А, не достигнет 1; затем значение, соответствующее C, сравнивается с основным коэффициентом мощности B. Эти две степени одного и того же простого числа были "мультиплексированы" в одно число путем сложения их вместе; это всегда будет однозначно отделимо на каждой последующей итерации цикла по той же причине, по которой работают позиционные системы счисления.

Мы получили умножение до 50 байт с использованием совершенно другого алгоритма (который мы с teukon смогли получить независимо, хотя ему потребовалось всего несколько часов, и он пошел прямо к нему, тогда как мне потребовалось несколько дней, даже после того, как привлек мое внимание к тому, что существовал короткий метод): для A≥B A * B = C, если есть, только если C - наименьшее число, которое удовлетворяет C≡0 mod A и C≡B mod A-1. (Удобно, что исключение A = 1 не требует специальной обработки в регулярном выражении, где 0% 0 = 0 дает совпадение.) Я просто не могу понять, насколько аккуратно, что такой элегантный способ выполнения умножения существует в таком минимальное регулярное выражение. (И требование A≥B может быть заменено требованием, чтобы A и B были простыми степенями одинаковой степени. Для случая A≥B это можно доказать с помощью китайской теоремы об остатках.)

Если бы оказалось, что не было более простого алгоритма для умножения, регулярное выражение с большим числом, вероятно, было бы порядка десяти тысяч байтов или около того (даже с учетом того, что я использовал алгоритм 913 байтов до 651 байта). Это делает много умножения и деления, и регулярное выражение ECMAScript не имеет подпрограмм.

Я начал работать над проблемой изобилия чисел тангенциально в 23 марта 2014 года, построив решение для того, что в то время казалось подзадачей: определить главный фактор наибольшей кратности, чтобы его можно было разделить на N в начале, оставляя место, чтобы сделать некоторые необходимые вычисления. В то время это казалось многообещающим маршрутом. (Мое первоначальное решение оказалось довольно большим - 326 байт, позднее - до 185 байт.) Но остальная часть набросанного teukon метода была бы чрезвычайно сложной, поэтому, как оказалось, я выбрал довольно другой маршрут. Этого оказалось достаточно, чтобы разделить наибольший простой коэффициент мощности N, соответствующий наибольшему простому коэффициенту на N; выполнение этого для простоты наибольшей кратности добавило бы ненужное сложность и длину к регулярному выражению.

То, что осталось, рассматривало сумму делителей как произведение сумм вместо прямой суммы. Как объяснил Теукон 14 марта 2014 года:

Нам дано число n = p 0 a 0 p 1 a 1 ... p k-1 a k-1 . Мы хотим обработать сумму факторов n, которая равна (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 ).

Это поразило меня, когда я увидел это. Я никогда не думал о факторизации суммы аликвот таким образом, и именно эта формула больше, чем что-либо еще, делала правдоподобной возможность сопоставления многочисленных чисел в регулярном выражении ECMAScript.

В конце концов, вместо того, чтобы проверять результат сложения или умножения, превышающего N, или проверять, что такой результат, предварительно разделенный на M, превышает N / M, я пошел с тестированием, если результат деления меньше 1. Я пришел к первая рабочая версия 7 апреля 2014 г.

Полная история моих оптимизаций в области гольфа для этого регулярного выражения находится на github. В определенный момент одна оптимизация закончилась тем, что регулярное выражение стало намного медленнее, поэтому с этого момента я сохранил две версии. Они есть:

регулярное выражение для сопоставления обильных чисел .txt
регулярное выражение для сопоставления обильных чисел - shorttest.txt

Эти регулярные выражения полностью совместимы как с ECMAScript, так и с PCRE, но недавняя оптимизация включала использование потенциально не участвующей группы \14перехвата, так что за счет снижения совместимости с PCRE и перехода \14?на \14них можно уменьшить их на 1 байт.

Вот наименьшая версия с примененной оптимизацией (сделав ее только для ECMAScript), переформатированная, чтобы уместиться в блок кода StackExchange без (в основном) горизонтальной прокрутки (не требуется):

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

Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
DJMcMayhem


27

Python 2 , 41 40 байт

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

Вывод осуществляется через код выхода , поэтому 0 соответствует действительности, а 1 - неверно.

Попробуйте онлайн!

Как это работает

После установки всех п , к , и J на вход из STDIN, мы вводим в то время как цикл. Упомянутый цикл обрывается, как только -k - 1 = ~ k ≥ 0 , т. Е. K ≤ -1 / k <0 .

На каждой итерации мы сначала уменьшаем j, чтобы рассмотреть только собственные делители n . Если j - делитель n , то n%jполучается 0 и j >> n% j * n = j / 2 0 = j вычитается из k . Однако, если J вовсе не делит п , n%jявляется положительным, так n%j*n, по крайней мере п> войти 2 J и J >> п% J * п = у / 2 п% J * п = 0 вычитают из к .

Для больших чисел k достигнет отрицательного значения до или когда j станет 1 , так как сумма n делителей строго больше, чем n . В этом случае, мы нарушаем из в то время как петли и программа нормально завершается.

Однако, если п является не обильным, J в конце концов достигает 0 . В этом случае, n%jбросает ZeroDivisionError и программа завершается с ошибкой.


4
~k<0это модно, но я думаю, что -1<kтоже делает
Мартин Эндер




10

Mathematica, 17 байт

Tr@Divisors@#>2#&

объяснение

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
Я удивлен, что у Mathematica нет встроенного для этого ..
MrPaulch

1
@MrPaulch Несмотря на длину программы, встроенное имя вполне может быть более длинным по имени>.>
Конор О'Брайен

1
@ ConorO'Brien Если бы он существовал, он, вероятно, был бы AbundantNumberQ, поэтому он бы сэкономил пару байтов :)
ngenisis


7

Сетчатка , 50- 45 байт

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

Ввод в унарном порядке , вывод 1для больших чисел, в 0противном случае.

В этом решении нет ничего специфичного для Retina. Выше приведено чистое регулярное выражение .NET, которое соответствует только многочисленным числам.

Попробуйте онлайн! (Набор тестов, который фильтрует десятичный ввод с помощью приведенного выше регулярного выражения.)


6

Сетчатка , 34 байта

Число байтов предполагает кодировку ISO 8859-1.

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

^(1+)¶1\1

Ввод в унарном порядке , вывод 1для больших чисел, в 0противном случае.

Попробуйте онлайн!

объяснение

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

Мы начнем с получения всех делителей ввода. Для этого мы возвращаем ( !) все совпадения ( &) совпадений ()M ) регулярного выражения (1+)$(?<=^\1+). Регулярное выражение соответствует некоторому суффиксу входных данных, при условии, что весь ввод кратен этому суффиксу (что мы обеспечиваем, пытаясь достичь начала строки, используя только копии суффикса). Из-за того, как механизм регулярных выражений ищет совпадения, это приведет к появлению списка делителей в порядке убывания (разделенных переводами строк).

1>`¶

Сама сцена просто соответствует linefeeds ( ) и удаляет их. Однако1> это предел, который пропускает первый матч. Таким образом, это эффективно складывает все делители, кроме самого ввода. В итоге мы получим ввод в первой строке и сумму всех правильных делителей во второй строке.

^(1+)¶1\1

Наконец, мы пытаемся сопоставить по крайней мере еще одно значение 1во второй строке, чем у нас в первой строке. Если это так, сумма правильных делителей превышает входные. Retina подсчитывает количество совпадений этого регулярного выражения, которое будет 1для многочисленных чисел и в 0противном случае.


1
Меня всегда удивляло, как ты можешь делать математику в сетчатке. Я хотел бы увидеть объяснение! :)
DJMcMayhem

1
@DJMcMayhem К сожалению забыл добавить это ранее. Выполнено.
Мартин Эндер

6

8086 Ассамблея, 23 28 25 24 байта

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

разобранное:

; 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

Пример тестовой программы, тестирование 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

Выход [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

Выход [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

Выход [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

Обновления:

  • Исправлено 16-битное переполнение (+5 байт). Спасибо @deadcode за предложения!
  • Упрощенная логика возврата (-3 байта). Спасибо еще раз от @deadcode.
  • Используйте TEST вместо CMP (-1 байт). Спасибо @ l4m2!

1
Я хотел бы предложить замену JLEс JBEдвойной диапазон номеров этого теста , прежде чем начать переполняется , заставляя его давать ложные негативы. Тогда вместо того, чтобы начать терпеть неудачу в 12600 (аликвотная сумма 35760), он начнет терпеть неудачу в 25200 (аликвотная сумма 74744). Еще лучше было бы также обнаружить флаг переноса и рассматривать его как избыточное число без необходимости вычислять фактическую сумму> 16 бит.
Deadcode

1
Хороший улов @Deadcode. Я обновил код для перехода ниже, а не меньше. Я понимаю, что вы имеете в виду, выполняя JC после ADD BX, CX обнаружит переполнение без знака и исправит его до N = 65535. Немного усложняет тестирование флага и возвращает состояние, так как ранее CF подразумевал false. Обновлен с исправлением также.
640KB

1
Вы можете сэкономить 3 байта, инвертировав спецификацию вашего возвращаемого значения, при этом CF устанавливается, если он имеется, и очищается, если нет. Но я бы рекомендовал сначала выполнить редактирование, чтобы исправить выходную документацию, чтобы она выглядела хорошо в истории редактирования.
Deadcode

1
Кроме того, для простоты в спецификации должно быть указано, что возвращаемое значение находится в флаге переноса, и ни один из этих сует не связан с другими флагами. Вызывающий абонент должен использовать JCили JNCдействовать в зависимости от того, является ли номер обильным или нет.
Deadcode

1
Большое спасибо за вашу помощь и ваши комментарии. Я обновил встроенную документацию и удалил термин ungolfed. Честно говоря, никогда не задумывался об этом, но я понимаю вашу точку зрения по этому поводу, поскольку она ничем не отличается, за исключением встроенных комментариев. Также договорились о том, что флаги возврата более понятны. Будет работать над этим немного позже. Спасибо за внимание и помощь!
640KB


5

05AB1E , 4 байта

ѨO‹

Попробуйте онлайн!

Как это работает

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

Извините, что опубликовал старый вопрос, я просто просматривал старые сообщения для практики и заметил, что мое решение короче, чем следующее лучшее решение 05AB1E.


4
Sorry to post in old questionНе беспокойся об этом! Я всегда рад видеть ответы на мои старые проблемы, и это на самом деле поощряется здесь . :)
DJMcMayhem


4

Java 8, 53 байта (намного больше, если включить церемониальный код)

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

Попробуйте онлайн

Пояснение:

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
Отличный ответ, но с Java 8 вы должны включить функцию в подсчет байтов. Опять же, вы можете отказаться, returnесли я не ошибаюсь, так что это будет еще короче: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(не 100%, если это правильно, я почти никогда не программирую на Java 8). Добро пожаловать в PPCG!
Кевин Круйссен,

1
Правильный счет по стандартному счету был бы n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>nдля 65 байтов (при условии, что я получил пакет прямо с головы)
CAD97

4

Powershell, 51 49 байт

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

Я хотел бы снять некоторые скобки.

-2 благодаря AdmBorkBork, вместо того, чтобы не считать входные данные в начальном диапазоне, мы просто учитываем их при окончательной проверке.

Пролистать диапазон 1..до $input, минус 1, найти где ( ?) обратный модуль ввода текущего значения равен $true(иначе всего 0) - затем -joinвсе эти числа вместе +и iexрезультирующая строка для его вычисления, а затем посмотреть, если сумма этих частей больше, чем вход.

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

Вы можете сохранить два байта, посчитав верхнее значение и проверив, что оно больше, чем двукратный ввод -param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
AdmBorkBork

3

MATL, 6 байтов

Z\sGE>

Выходы 1 для обильных чисел, 0 в противном случае.

Как это работает

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 байта

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

Это адаптация к тесту первичности QBIC . Вместо того, чтобы подсчитывать делители и проверять, меньше ли это трех, это суммирует правильные делители. Это выполняется только вдоль половины 1 to n, где тест на первичность проходит 1 to nполностью.

Объяснение:

:       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 байта

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>


Я был уверен, что рекурсивный ответ будет лучшим, но я не думал, что это будет так хорошо.
Нил

3

Japt , 9 7 6 байт

<Uâ1 x

Сохранено 2 байта благодаря ETHproductions. Сохранено 1 байт благодаря obarakon.

Попробуйте онлайн!


9 символов, 10 байтов.
Метония

@Metoniem Я уверен, что âэто 1 байт, по крайней мере, в Unicode (0xE2).
Том

1
@Metoniem Japt использует кодировку ISO-8859-1 , в которой âиспользуется один байт.
ETHproductions

Если âзадан верный аргумент, фактическое число будет удалено из оставшегося списка, так что вы можете â1 x >Uсохранить пару байтов :-)
ETHproductions

@TomDevs Отлично! Вы можете сделать, <Uâ1 xчтобы сохранить байт. Japt добавляет Uперед программой.
Оливер

3

Cubix , 38 байт

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

Попробуй здесь

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

0I:- устанавливает стек с 0, n, n (s, n, d)
^- начало цикла )?- декремент d и проверка на 0. 0 выходит из цикла loop
%?- mod против n и проверяет. 0 вызывает ;rrw+s;rUвращение s в верхнюю часть и добавление d, вращение s в нижнюю часть и воссоединение с циклом
;<- Очистить и восстановить цикл.
В выходящем цикле
;<- Удалить d из стека и перенаправить
-?- Удалить n из s и проверить, 0 LOU@оборотов влево, выходы и выходы, отрицательные значения - 0O@ноль, выход и выход. положительные ;Oубрать разницу и выходы n. Затем путь проходит до левого поворота, который перенаправляет на @выход


3

Чистый Баш, 37 байт

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

Спасибо @Dennis за перестановку кода - сохранение 6 байтов и исключение побочного вывода в stderr.

Ввод передается в качестве аргумента.

Выход возвращается в коде выхода: 0 для обильного, 1 для не обильного.

Вывод в stderr должен игнорироваться.

Тестовые прогоны:

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

Вы можете сохранить 6 байтов, избегая паразитного вывода в STDERR tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/…
Деннис

2

RProgN , 8 байт

~_]k+2/<

Разъяснения

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

Попробуйте онлайн!


2

Пакетная, 84 байта

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

Выходы -1для обильного числа, в 0противном случае. Работает, вычитая все факторы 2nи затем сдвигая результат на 31 позицию, чтобы извлечь знаковый бит. Альтернативная формулировка, также 84 байта:

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

Выходы 1на обильное количество. Работает, вычитая все факторы из, nа затем сравнивая результат с -n. ( set/aэто единственный способ выполнения арифметики в пакетном режиме, поэтому я не могу легко настроить цикл.)


1
"(% 1 %%%% j)" о, партия :)
Брайан

2

Perl 6, 72 24 байта

{$_ <sum grep $_%%*,^$_}
  • Программный аргумент: а.
  • Создайте список из 1..a.
  • Возьмите все числа, которые являются делителями a.
  • Суммируйте их.
  • Проверьте, больше ли эта сумма, чем a.

Благодаря @ b2gills.


Каждое вхождение $^aпосле первого можно сократить до всего $a. но это еще короче, если вы напишите его как « {$_ <sum grep $_%%*,^$_}Также, глядя на более раннюю версию, [+](LIST)работает (без пробелов)»
Брэд Гилберт b2gills

@ BradGilbertb2gills Спасибо! :)
Ven

2

J, 19 байт

Спасибо Конору О'Брайену за сокращение его до 19 байт!

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

Предыдущая: (34 байта)

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

Возвращает 1, если его много, и 0, если его нет.

Выход:

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

Добро пожаловать в PPCG! Мы разрешаем анонимные функции, поэтому вы можете удалить ведущий f=:как часть вашего количества байтов. Кроме того, вы можете получить до 19, превратив в молчаливый глагол:<[:+/i.#~i.e.]%2+i.
Конор О'Брайен

Спасибо за совет! Тем не менее, не могли бы вы объяснить заглавный глагол ([:) и глагол переключателя (~). Я действительно не понимаю, что они должны делать в этом молчаливом глаголе.
Блокирует

~ переключается так что то есть # я. но какова цель [:?
Блокирует

так что вы знаете о вилках, верно? (f g h) y' is the same as (fy) g (hy) . When f` - шапка, ([: g h) yпримерно такая же, как g h y. Что касается ~, это переключает левый и правый аргументы. Важно знать, что ~это не глагол, а на самом деле наречие. Это изменяет глагол. Например, мы могли бы иметь что-то вроде 2 %~ 8. Здесь ~модифицирует, %чтобы переключать свои аргументы, поэтому выражение эквивалентно 8 % 2.
Конор О'Брайен

В цепочке #~
Conor O'Brien

2

Pyth, 11 байт

>sPf!%QTS

Старый:

L!%Qb>sPy#S

Я не могу использовать !%как PFN для #, потому что это две функции. Заставляет меня грустить :(.


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

Не определение функции кажется короче:>sPf!%QTS
FryAmTheEggman

2

k , 19 16 15 байт

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

Возвращает 1как истинное, так и 0ложное.

Попробуйте онлайн!

{             } /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



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.