Достаток цілих чисел!


40

Рясний номер представляє собою будь-яке число , де сума його дільників більше , ніж вихідне число. Наприклад, правильними дільниками 12 є:

1, 2, 3, 4, 6

І підсумовуючи ці результати за 16. Оскільки 16 більше, ніж 12, 12 є рясним. Зауважте, що це не включає "Ідеальні числа", наприклад числа, що дорівнюють сумі правильних дільників, таких як 6 і 28.

Ваше завдання на сьогодні - написати програму чи функцію, яка визначає, чисельна кількість чи ні. Ваша програма повинна приймати одне ціле число як вхідне та виводити величину truthy / falesy залежно від того, чи є вона рясною чи ні. Ви можете припустити, що вхід завжди буде дійсним та більшим за 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 regex в Інтернеті

Тепер повернемося до мого регулярного виразу 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; той, що відповідає С, порівнюється з коефіцієнтом основної потужності В. Ці дві сили одного і того ж простого "мультиплексуються" в одне число, додаючи їх разом; це завжди було б однозначно відокремлене на кожній наступній ітерації циклу з тієї ж причини, що працюють позиційні системи числення.

Ми отримали множення до 50 байт, використовуючи зовсім інший алгоритм (який і ми з Теуконом змогли прийти самостійно, хоча це знадобило йому лише кілька годин, і він пішов прямо до нього, тоді як мені знадобилося пару днів, навіть після того, як це було я звернув увагу, що існує короткий метод): для A≥B, A * B = C, якщо такий є лише, якщо C - найменше число, яке задовольняє C≡0 mod A і C andB 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; Якщо це зробити для найвищої кратності, це додало би непотрібної складності та тривалості виразці.

Залишилося трактувати суму дільників як добуток сум замість прямої суми. Як пояснив Teukon 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
регекс для відповідності великої кількості - найкоротший.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

Математика, 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 Однак, враховуючи тривалість програми, вбудований може бути дуже довгим у назві>.>
Conor O'Brien

1
@ ConorO'Brien Якби воно існувало, це, мабуть, було б AbundantNumberQ, тому це врятувало б пару байтів :)
ngenisis


7

Сітківка , 50 45 байт

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

Введіть уніар , виведіть 1для великої кількості, 0інакше.

У цьому рішенні немає нічого конкретного для сітківки. Наведене вище є чистим регулярним виразом .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на другому рядку, ніж у нас на першому рядку. Якщо це так, сума правильних дільників перевищує вхідну. Сітківка підраховує кількість збігів цього регулярного виразу, що буде 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 мав на увазі хибність. Оновлено також виправлення.
640 Кб

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

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

1
Дуже дякую за всю вашу допомогу та ваші коментарі. Я оновив вбудовану документацію та вилучив термін ungolfed. Чесно кажучи, я ніколи не задумувався над цим, але я бачу вашу думку щодо цього, оскільки це не відрізняється за винятком вбудованих коментарів. Також домовтеся про те, щоб зробити чіткішими і зворотні прапори. Попрацюємо над цим трохи. Дякуємо за увагу та допомогу!
640 Кб


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()>n65 байт (якщо припустити, що я отримав пакет прямо вгорі голови)
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

Ви можете зберегти два байти, порахувавши найбільшу величину та перевіривши, чи не перевищує вона в 2 рази вхід -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 байт завдяки обаракону.

Спробуйте в Інтернеті!


9 символів, 10 байт.
Metoniem

@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 виходить з циклу
%?- 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

Пакет, 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це єдиний спосіб Batch робити арифметику, тому я не можу легко регулювати цикл.)


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

2

Perl 6, 72 24 байти

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

Завдяки @ b2gills.


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

@ BradGilbertb2gills Дякую! :)
Вен

2

J, 19 байт

Дякуємо Conor O'Brien за скорочення його до 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.
Conor O'Brien

Дякую за пораду! Однак ви можете, будь ласка, пояснити дієслово шапки ([:) та дієслово перемикання (~). Я дійсно не розумію, що вони повинні робити в цьому мовчазному дієслові.
Блоки

~ перемикає, так що це є # 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

У ланцюзі fork #~оцінюється після виконання дієслів праворуч, тому його лівий аргумент стає результатом справа
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


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.