Sự phong phú của số nguyên!


40

Một số dồi dào là bất kỳ số mà tổng các ước thích hợp của nó là lớn hơn số ban đầu. Ví dụ: các ước số thích hợp của 12 là:

1, 2, 3, 4, 6

Và tổng hợp các kết quả này trong 16. Vì 16 lớn hơn 12, 12 là phong phú. Lưu ý rằng điều này không bao gồm "Số hoàn hảo", ví dụ: các số bằng tổng các ước số thích hợp của nó, chẳng hạn như 6 và 28.

Nhiệm vụ của bạn hôm nay là viết một chương trình hoặc hàm xác định xem một số có nhiều hay không. Chương trình của bạn nên lấy một số nguyên duy nhất làm đầu vào và xuất giá trị trung thực / giả mạo tùy thuộc vào việc nó có dồi dào hay không. Bạn có thể giả định rằng đầu vào sẽ luôn hợp lệ và lớn hơn 0, vì vậy đối với đầu vào xấu, hành vi không xác định là ổn.

Bạn có thể lấy đầu vào và đầu ra của mình ở bất kỳ định dạng hợp lý nào, ví dụ STDIN / STDOUT, các tệp hoặc các giá trị đối số / trả về đều có thể được chấp nhận.

Để tham khảo, đây là những con số phong phú lên tới 100:

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

Và nhiều hơn nữa có thể được tìm thấy trên A005101

Vì đây là , các sơ hở tiêu chuẩn bị từ chối và cố gắng viết mã ngắn nhất có thể theo bất kỳ ngôn ngữ nào bạn chọn!


11
"số dư lẻ đầu tiên là 945 = 3 ^ 3 * 5 * 7, số dồi dào thứ 232!"
mbomb007

Mật độ tiệm cận của số lượng dồi dào nằm ở đâu đó trong khoảng [0.24761748, 0.24764422]. Tính toán sử dụng mã nguồn bao gồm trong bài báo này .
Deadcode

1
Tôi đang cố gắng làm điều này trong Geometry Dash. Đó là một cơn ác mộng
MilkyWay90

Câu trả lời:


41

Regex ECMAScript, 1085 855 597 536 511 508 504 byte

Kết hợp số lượng dồi dào trong regex ECMAScript là một con thú hoàn toàn khác so với thực tế trong bất kỳ hương vị regex nào khác. Việc thiếu các phản hồi ngược hoặc lồng nhau hoặc đệ quy có nghĩa là không thể trực tiếp đếm hoặc giữ tổng cộng mọi thứ đang chạy. Việc thiếu cái nhìn khiến nó thường là một thách thức thậm chí để có đủ không gian để làm việc.

Nhiều vấn đề phải được tiếp cận từ một quan điểm hoàn toàn khác, và bạn sẽ tự hỏi liệu chúng có thể giải quyết được không. Nó buộc bạn phải tạo một mạng lưới rộng hơn nhiều trong việc tìm ra các thuộc tính toán học nào của các số bạn làm việc cùng có thể có thể được sử dụng để làm cho một vấn đề cụ thể có thể giải quyết được.

Trở lại vào tháng 3-tháng 4 năm 2014, tôi đã xây dựng một giải pháp cho vấn đề này trong biểu thức ECMAScript. Lúc đầu, tôi có mọi lý do để nghi ngờ vấn đề là hoàn toàn không thể, nhưng sau đó, nhà toán học teukon đã phác thảo một ý tưởng tạo ra một trường hợp đáng khích lệ để làm cho nó có thể giải quyết được - nhưng anh ta nói rõ rằng anh ta không có ý định xây dựng regex (anh ta đã cạnh tranh / hợp tác với tôi trong việc xây dựng / chơi golf trước đó, nhưng đã đạt đến giới hạn của anh ấy vào thời điểm này và là nội dung để hạn chế những đóng góp tiếp theo của anh ấy cho lý thuyết).

Như với regex của tôi được đăng cách đây vài ngày, tôi sẽ đưa ra một cảnh báo: Tôi đặc biệt khuyên bạn nên học cách giải các bài toán đơn phương trong biểu thức chính của ECMAScript. Đó là một hành trình hấp dẫn đối với tôi và tôi không muốn làm hỏng nó cho bất kỳ ai có khả năng muốn thử nó, đặc biệt là những người quan tâm đến lý thuyết số. Xem bài đăng đó để biết danh sách các vấn đề được đề xuất liên quan đến spoiler để giải quyết từng vấn đề một.

Vì vậy, đừng đọc thêm nữa nếu bạn không muốn một số ma thuật regex unary sâu sắc hư hỏng cho bạn . Bài viết trước của tôi chỉ là một hương vị nhỏ. Nếu bạn thực sự muốn tự mình tìm ra phép thuật này, tôi khuyên bạn nên bắt đầu bằng cách giải quyết một số vấn đề trong biểu thức ECMAScript như được nêu trong bài đăng được liên kết ở trên.

Trước khi đăng regex ECMAScript của tôi, tôi nghĩ sẽ rất thú vị khi phân tích giải pháp regex thuần .NET của Martin Ender , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). Hóa ra rất đơn giản để hiểu regex đó, và nó thanh lịch trong sự đơn giản của nó. Để chứng minh sự tương phản giữa các giải pháp của chúng tôi, đây là một phiên bản được bình luận và in đẹp (nhưng chưa được sửa đổi) của regex của anh ấy:

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

Hãy thử .NET regex trực tuyến

Bây giờ, trở lại biểu thức ECMAScript của tôi. Đầu tiên, ở đây là định dạng thô, không có khoảng trắng và bình luận:

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

(thay đổi \14để \14?tương thích với PCRE, .NET và thực tế là mọi hương vị regex khác không phải là ECMAScript)

Hãy thử trực tuyến!
Hãy thử trực tuyến! (nhanh hơn, phiên bản 537 byte của regex)

Và bây giờ là một bản tóm tắt ngắn gọn về câu chuyện đằng sau nó.

Lúc đầu, điều đó rất không rõ ràng, đối với tôi, ít nhất là nó thậm chí có thể khớp với các số nguyên tố trong trường hợp chung. Và sau khi giải quyết điều đó, áp dụng tương tự cho các lũy thừa của 2. Và sau đó là các lũy thừa của các số tổng hợp. Và sau đó là hình vuông hoàn hảo. Và ngay cả sau khi giải quyết điều đó, việc nhân rộng tổng quát ban đầu dường như là không thể.

Trong vòng lặp ECMAScript, bạn chỉ có thể theo dõi một số thay đổi; con số đó không thể vượt quá đầu vào và phải giảm ở mỗi bước. Regex hoạt động đầu tiên của tôi để khớp các câu lệnh nhân chính xác A * B = C là 913 byte và hoạt động bằng cách bao gồm A, B và C thành các lũy thừa chính của chúng - cho mỗi thừa số nguyên tố, liên tục chia cặp nhân tố công suất chính của A và C bởi cơ sở nguyên tố của chúng cho đến khi một tương ứng với A đạt 1; một công suất tương ứng với C sau đó được so sánh với hệ số công suất nguyên tố của B. Hai công suất này của cùng một số nguyên tố được "ghép" thành một số duy nhất bằng cách cộng chúng lại với nhau; điều này sẽ luôn luôn được phân tách rõ ràng trên mỗi lần lặp tiếp theo của vòng lặp, với cùng lý do là các hệ thống số vị trí hoạt động.

Chúng tôi đã nhân lên tới 50 byte bằng một thuật toán hoàn toàn khác nhau (mà teukon và tôi có thể đến một cách độc lập, mặc dù anh ấy chỉ mất vài giờ và anh ấy đã đi thẳng vào nó, trong khi tôi phải mất vài ngày ngay cả sau khi làm tôi chú ý rằng đã tồn tại một phương thức ngắn): đối với A≥B, A * B = C nếu có nếu C là số nhỏ nhất thỏa mãn C≡0 mod A và C≡B mod A-1. (Thuận tiện, ngoại trừ A = 1 không cần xử lý đặc biệt trong regex, trong đó 0% 0 = 0 mang lại kết quả khớp.) Tôi không thể hiểu được sự gọn gàng của cách thức nhân lên như vậy tồn tại trong một cách đơn giản như vậy tồn tại hương vị regex tối thiểu. (Và yêu cầu của A≥B có thể được thay thế bằng yêu cầu A và B là các quyền lực chính có cùng sức mạnh. Đối với trường hợp của A≥B, điều này có thể được chứng minh bằng định lý còn lại của Trung Quốc.)

Nếu nó chỉ ra rằng không có thuật toán đơn giản nào để nhân, thì regex số dồi dào có thể sẽ ở mức mười nghìn byte hoặc hơn (thậm chí có tính đến việc tôi đánh gôn thuật toán 913 byte xuống còn 651 byte). Nó thực hiện nhiều phép nhân và chia, và biểu thức chính của ECMAScript không có chương trình con.

Tôi đã bắt đầu giải quyết vấn đề số lượng dồi dào một cách hữu hình vào ngày 23 tháng 3 năm 2014, bằng cách xây dựng một giải pháp cho vấn đề dường như là vấn đề phụ của vấn đề này: Xác định hệ số nguyên tố của bội số cao nhất, để có thể chia ra N khi bắt đầu, rời khỏi phòng để làm một số tính toán cần thiết. Tại thời điểm này dường như là một tuyến đường đầy hứa hẹn để đi. (Giải pháp ban đầu của tôi đã kết thúc khá lớn ở mức 326 byte, sau đó được giảm xuống còn 185 byte.) Nhưng phần còn lại của phương pháp mà teukon đã phác thảo sẽ cực kỳ phức tạp, vì vậy hóa ra, tôi đã đi một con đường khá khác. Nó được chứng minh là đủ để phân chia hệ số công suất nguyên tố lớn nhất của N tương ứng với hệ số nguyên tố lớn nhất trên N; làm điều này cho số nguyên tố cao nhất sẽ có thêm độ phức tạp và độ dài không cần thiết cho biểu thức chính quy.

Những gì còn lại là coi tổng của các ước là một sản phẩm của tổng thay vì một tổng thẳng. Theo giải thích của teukon vào ngày 14 tháng 3 năm 2014:

Chúng tôi đã cho một số n = p 0 a 0 p 1 a 1 ... p k - 1 a k - 1 . Chúng tôi muốn xử lý tổng các thừa số của n, đó là (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 ).

Nó làm tôi suy nghĩ khi thấy điều này. Tôi chưa bao giờ nghĩ đến việc bao thanh toán tổng số theo cách đó, và chính công thức này hơn bất kỳ thứ gì khác làm cho khả năng thanh toán của số lượng lớn phù hợp trong biểu thức chính của ECMAScript trông có vẻ hợp lý.

Cuối cùng, thay vì kiểm tra kết quả cộng hoặc nhân vượt quá N, hoặc kiểm tra kết quả như vậy được chia trước M vượt quá N / M, tôi đã đi kiểm tra nếu kết quả của phép chia nhỏ hơn 1. Tôi đã đến phiên bản làm việc đầu tiên vào ngày 7 tháng 4 năm 2014.

Lịch sử đầy đủ về tối ưu hóa golf của tôi về regex này là trên github. Tại một thời điểm nhất định, một tối ưu hóa đã kết thúc làm cho regex chậm hơn nhiều, vì vậy kể từ thời điểm đó, tôi đã duy trì hai phiên bản. Họ đang:

regex để khớp số lượng dồi dào
regex regex để khớp với số lượng dồi dào - shortest.txt

Những regexes là hoàn toàn tương thích với cả hai ECMAScript và PCRE, nhưng một tối ưu hóa gần đây liên quan đến sử dụng một nhóm chụp có khả năng không tham gia \14, vì vậy bằng cách thả tương thích PCRE và thay đổi \14?để \14cả hai đều có thể được giảm thiểu bằng 1 byte.

Đây là phiên bản nhỏ nhất, với tối ưu hóa được áp dụng (chỉ ở dạng ECMAScript), được định dạng lại để phù hợp với khối mã StackExchange với (hầu hết) không cần cuộn ngang:

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

Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
DJMcMayhem


27

Python 2 , 41 40 byte

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

Đầu ra là thông qua mã thoát , vì vậy 0 là trung thực và 1 là sai.

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Sau khi thiết lập tất cả các n , kj để đầu vào từ STDIN, chúng ta bước vào trong khi vòng lặp. Vòng lặp đã nói sẽ ngắt ngay khi -k - 1 = ~ k 0 , tức là k ≤ -1 / k <0 .

Trong mỗi lần lặp, trước tiên chúng ta giảm j để chỉ xem xét các ước số thích hợp của n . Nếu j là ước của n , n%jmang lại 0j >> n% j * n = j / 2 0 = j bị trừ khỏi k . Tuy nhiên, nếu k thì không chia n , n%jlà tích cực, vì vậy n%j*nít nhất là n> log 2 jk >> n% j * n = k / 2 n% j * n = 0 được trừ vào k .

Đối với số lượng dồi dào, k sẽ đạt giá trị âm trước hoặc khi j trở thành 1 , vì tổng các ước số thích hợp của n là lớn hơn n . Trong trường hợp này, chúng ta thoát ra khỏi trong khi vòng lặp và kết thúc chương trình bình thường.

Tuy nhiên, nếu nkhông dồi dào, j cuối cùng đạt đến 0 . Trong trường hợp này, n%jném ZeroDivisionError và chương trình thoát với một lỗi.


4
~k<0là lạ mắt, nhưng tôi nghĩ -1<kcũng có mẹo;)
Martin Ender




10

Toán học, 17 byte

Tr@Divisors@#>2#&

Giải trình

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
Tôi ngạc nhiên khi
Mathicala

1
@MrPaulch Xem xét độ dài của chương trình, phần dựng sẵn rất có thể dài hơn về tên>.>
Conor O'Brien

1
@ ConorO'Brien Nếu nó tồn tại, có lẽ nó sẽ tồn tại, AbundantNumberQvì vậy nó sẽ tiết kiệm được một vài byte :)
ngenisis


7

Võng mạc , 50 45 byte

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

Đầu vào trong unary , đầu ra 1cho số lượng phong phú, 0nếu không.

Không có gì cụ thể của Retina về giải pháp này. Trên đây là một regex .NET thuần túy chỉ phù hợp với số lượng dồi dào.

Hãy thử trực tuyến! (Bộ kiểm tra lọc đầu vào thập phân với biểu thức chính quy ở trên.)


6

Võng mạc , 34 byte

Số lượng byte giả định mã hóa ISO 8859-1.

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

^(1+)¶1\1

Đầu vào trong unary , đầu ra 1cho số lượng phong phú, 0nếu không.

Hãy thử trực tuyến!

Giải trình

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

Chúng tôi bắt đầu bằng cách nhận tất cả các ước của đầu vào. Để làm điều này, chúng tôi quay trở lại ( !) tất cả các chồng chéo ( &) matches ( M) của regex (1+)$(?<=^\1+). Regex khớp với một số hậu tố của đầu vào, với điều kiện là toàn bộ đầu vào là bội số của hậu tố đó (mà chúng tôi đảm bảo bằng cách cố gắng bắt đầu chuỗi cho chỉ sử dụng các bản sao của hậu tố). Do cách công cụ regex tìm kiếm kết quả khớp, điều này sẽ dẫn đến một danh sách các ước số theo thứ tự giảm dần (cách nhau bởi các đường dẫn).

1>`¶

Bản thân giai đoạn chỉ đơn giản khớp với nguồn cấp dữ liệu ( ) và loại bỏ chúng. Tuy nhiên, đó 1>là một giới hạn, bỏ qua trận đấu đầu tiên. Vì vậy, điều này có hiệu quả cộng tất cả các ước số trừ đầu vào chính nó. Chúng tôi kết thúc với đầu vào trên dòng đầu tiên và tổng của tất cả các ước số thích hợp trên dòng thứ hai.

^(1+)¶1\1

Cuối cùng, chúng tôi cố gắng khớp ít nhất một lần nữa 1trên dòng thứ hai so với chúng tôi có trên dòng đầu tiên. Nếu đó là trường hợp, tổng các ước số thích hợp vượt quá đầu vào. Retina đếm số lượng trận đấu của regex này, sẽ 1dành cho số lượng phong phú và mặt 0khác.


1
Nó luôn làm tôi ngạc nhiên về cách bạn có thể làm toán ở võng mạc. Tôi muốn thấy một lời giải thích! :)
DJMcMayhem

1
@DJMcMayhem Xin lỗi đã quên thêm điều đó sớm hơn. Làm xong.
Martin Ender

6

8086 hội, 23 28 25 24 byte

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

Chưa được lắp ráp:

; 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

Ví dụ chương trình kiểm tra, kiểm tra 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

Đầu ra [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

Đầu ra [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

Đầu ra [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

Cập nhật:

  • Đã sửa lỗi tràn 16 bit (+5 byte). Cảm ơn @deadcode vì những gợi ý!
  • Logic trả về đơn giản hóa (-3 byte). Thx để giúp đỡ từ @deadcode một lần nữa.
  • Sử dụng TEST thay vì CMP (-1 byte). Thx đến @ l4m2!

1
Tôi sẽ đề nghị thay thế JLEbằng JBEđể nhân đôi phạm vi các con số mà điều này có thể kiểm tra trước khi tràn ra bắt đầu khiến nó đưa ra âm tính giả. Sau đó, thay vì bắt đầu thất bại ở 12600 (aliquot sum 35760), nó sẽ bắt đầu thất bại ở 25200 (aliquot sum 74744). Thậm chí tốt hơn là cũng phát hiện cờ mang và coi đó là một số lượng dồi dào mà không cần tính tổng tiền thực> 16 bit.
Deadcode

1
Bắt tốt @Deadcode. Tôi đã cập nhật mã để nhảy bên dưới thay vì nhảy ít hơn. Tôi hiểu ý của bạn, thực hiện một JC sau ADD BX, CX sẽ bắt được tràn không dấu ở đó và làm cho nó chính xác cho đến khi N = 65535. Biến chứng kiểm tra cờ và trả về trạng thái một chút, vì CF trước đó ngụ ý sai. Cập nhật với sửa chữa cũng.
640KB

1
Bạn có thể lưu 3 byte bằng cách đảo ngược đặc tả của giá trị trả về của bạn, với CF được đặt nếu dồi dào và rõ ràng nếu không. Nhưng tôi khuyên bạn nên thực hiện chỉnh sửa để sửa tài liệu đầu ra trước, để nó trông đẹp trong lịch sử chỉnh sửa.
Deadcode

1
Ngoài ra, để giữ cho mọi thứ đơn giản, thông số kỹ thuật phải là giá trị trả về nằm trong cờ mang và không có gì khó hiểu với các cờ khác. Người gọi nên sử dụng JChoặc JNChành động xem số đó có phong phú hay không.
Deadcode

1
Cảm ơn rất nhiều cho tất cả sự giúp đỡ và ý kiến ​​của bạn. Tôi đã cập nhật các tài liệu nội tuyến và loại bỏ thuật ngữ vô căn cứ. Thành thật không bao giờ cho nó nhiều suy nghĩ nhưng tôi thấy quan điểm của bạn về nó, vì nó không có gì khác biệt ngoại trừ các bình luận nội tuyến. Cũng đồng ý về makint cờ trở lại rõ ràng hơn là tốt. Sẽ làm việc trên đó một chút. Cảm ơn sự quan tâm và giúp đỡ!
640KB


5

05AB1E , 4 byte

ѨO‹

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Xin lỗi để đăng trong câu hỏi cũ, tôi chỉ xem qua các bài viết cũ để thực hành và nhận thấy giải pháp của tôi ngắn hơn giải pháp 05AB1E tốt nhất tiếp theo.


4
Sorry to post in old questionĐừng lo lắng về điều đó! Tôi luôn vui mừng khi thấy câu trả lời về những thách thức cũ của tôi, và nó thực sự khuyến khích quanh đây . :)
DJMcMayhem


4

Java 8, 53 byte (nhiều hơn nữa nếu bạn bao gồm mã nghi lễ)

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

Dùng thử trực tuyến

Giải trình :

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
Câu trả lời tuyệt vời, nhưng với Java 8, bạn phải bao gồm hàm trong số byte của mình. Sau đó, một lần nữa, bạn có thể bỏ qua returnnếu tôi không nhầm, vì vậy nó sẽ còn ngắn hơn: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(không phải 100% nếu điều này là chính xác, tôi gần như không bao giờ lập trình trong Java 8). Chào mừng đến với PPCG!
Kevin Cruijssen

1
Số đếm chính xác thông qua số lượng tiêu chuẩn sẽ là n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>n65 byte (giả sử tôi đã nhận được gói ngay trên đỉnh đầu)
CAD97

4

Powershell, 51 49 byte

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

Tôi ước tôi có thể loại bỏ một số dấu ngoặc.

-2 cảm ơn admBorkBork, thay vì không tính đầu vào trong phạm vi ban đầu, chúng tôi chỉ đưa nó vào tài khoản trong lần kiểm tra cuối cùng.

Lặp lại phạm vi của 1..đối số $i, trừ 1, tìm vị trí ( ?) modulo nghịch đảo của đầu vào theo số hiện tại là $true(còn gọi là 0) - sau đó -jointất cả các số đó cùng với +iexchuỗi kết quả để tính toán, sau đó xem nếu tổng của các phần này lớn hơn đầu vào.

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

Bạn có thể lưu hai byte bằng cách đếm giá trị hàng đầu và kiểm tra xem nó có lớn hơn gấp 2 lần đầu vào không -param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
admBorkBork

3

MATL, 6 byte

Z\sGE>

Đầu ra 1 cho số lượng dồi dào, 0 khác.

Làm thế nào nó hoạt động

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

Đây là một sự thích ứng với bài kiểm tra tính nguyên thủy của QBIC . Thay vì đếm các ước số và kiểm tra xem nó có nhỏ hơn ba hay không, điều này tổng hợp các ước số thích hợp. Điều này chỉ chạy dọc theo một nửa 1 to n, trong đó bài kiểm tra nguyên thủy chạy qua 1 to nhoàn toàn.

Giải trình:

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


Tôi chắc chắn rằng một câu trả lời đệ quy sẽ là tốt nhất nhưng tôi không nghĩ nó sẽ tốt như vậy.
Neil

3

Japt , 9 7 6 byte

<Uâ1 x

Đã lưu 2 byte nhờ vào ETHproductions. Đã lưu 1 byte nhờ obarakon.

Hãy thử trực tuyến!


9 ký tự, 10 byte.
Metoniem

@Metoniem Tôi chắc chắn âlà 1 byte, trong unicode ít nhất (0xE2).
Tom

1
@Metoniem Japt sử dụng mã hóa ISO-8859-1 , trong đó âlà một byte đơn.
Sản phẩm ETH

Nếu âđược đưa ra một đối số trung thực, nó sẽ xóa số thực tế khỏi danh sách còn lại, vì vậy bạn có thể làm gì â1 x >Uđể lưu một vài byte :-)
ETHproductions

@TomDevs Đẹp quá! Bạn có thể làm <Uâ1 xđể lưu một byte. Japt thêm Uvào trước chương trình.
Oliver

3

Khối , 38 byte

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

Hãy thử nó ở đây

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

0I:- thiết lập ngăn xếp với 0, n, n (s, n, d)
^- bắt đầu vòng lặp )?- giảm d và kiểm tra 0. 0 thoát vòng lặp
%?- mod chống lại n và kiểm tra. 0 nguyên nhân làm ;rrw+s;rUquay s lên đỉnh và thêm d, xoay s xuống đáy và nối lại vòng lặp
;<- Dọn dẹp và nối lại vòng lặp.
Trên vòng lặp thoát
;<- Xóa d khỏi ngăn xếp và chuyển hướng
-?- Xóa n khỏi s và kiểm tra, 0 LOU@rẽ trái, đầu ra và thoát, phủ định 0O@đẩy số không, đầu ra và thoát. tích cực ;Oloại bỏ sự khác biệt và đầu ra n. Con đường sau đó đi qua rẽ trái để chuyển hướng đến @lối ra


3

Bash thuần túy, 37 byte

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

Cảm ơn @Dennis vì đã sắp xếp lại mã - tiết kiệm 6 byte và loại bỏ đầu ra ngẫu nhiên thành stderr.

Các đầu vào được thông qua như là một đối số.

Đầu ra được trả về trong mã thoát: 0 cho dồi dào, 1 cho không dồi dào.

Đầu ra cho stderr nên được bỏ qua.

Chạy thử:

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

Bạn có thể lưu 6 byte trong khi tránh đầu ra đi lạc vào STDERR. tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/
Dennis

2

RProgN , 8 byte

~_]k+2/<

Giải thích

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

Hãy thử trực tuyến!


2

Mẻ, 84 byte

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

Đầu ra -1cho một số lượng lớn, 0nếu không. Hoạt động bằng cách trừ tất cả các yếu tố từ 2nvà sau đó dịch chuyển kết quả 31 vị trí để trích xuất bit dấu. Công thức thay thế, cũng 84 byte:

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

Đầu ra 1cho một số lượng phong phú. Hoạt động bằng cách trừ tất cả các yếu tố từ nvà sau đó so sánh kết quả với -n. ( set/alà cách duy nhất để làm số học của Batch nên tôi không thể dễ dàng điều chỉnh vòng lặp.)


1
"(% 1 %%%% j)" oh, đợt :)
Bryan Boettcher

2

Perl 6, 72 24 byte

{$_ <sum grep $_%%*,^$_}
  • Đối số chương trình: a.
  • Tạo một danh sách từ 1..a.
  • Lấy tất cả các số là ước của a.
  • Tính tổng chúng.
  • Kiểm tra xem tổng đó có lớn hơn không a.

Cảm ơn @ b2gills.


Mỗi lần xuất hiện $^asau lần đầu tiên có thể rút ngắn lại $a. nhưng nó thậm chí còn ngắn hơn nếu bạn viết nó như {$_ <sum grep $_%%*,^$_}Nhìn vào một phiên bản trước đó, [+](LIST)hoạt động (không có dấu cách)
Brad Gilbert b2gills

@ BradGilbertb2gills Cảm ơn! :)
Ven

2

J, 19 byte

Cảm ơn Conor O'Brien vì đã cắt nó thành 19 byte!

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

Trước đó: (34 byte)

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

Trả về 1 nếu nó dồi dào và 0 nếu không.

Đầu ra:

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

Chào mừng đến với PPCG! Chúng tôi cho phép các hàm ẩn danh, vì vậy bạn có thể loại bỏ phần đầu f=:như một phần của số byte của mình. Ngoài ra, bạn có thể giảm xuống 19 bằng cách chuyển đổi thành động từ ngầm:<[:+/i.#~i.e.]%2+i.
Conor O'Brien

Cảm ơn vì lời khuyên! Tuy nhiên, bạn có thể vui lòng giải thích động từ cap ([:) và động từ chuyển đổi (~). Tôi thực sự không hiểu những gì họ phải làm trong động từ ngầm này.
Khối

~ chuyển đổi vì vậy đó là # i. nhưng mục đích của [: là gì?
Khối

bạn biết gì về dĩa phải không? (f g h) y' is the same as (fy) g (hy) . When f` là một cái mũ, ([: g h) ygần giống như g h y. Đối với ~, điều này chuyển đổi các đối số trái và phải. Điều quan trọng là phải biết rằng đó ~không phải là một động từ mà thực sự là một trạng từ. Nó sửa đổi một động từ. Ví dụ, chúng ta có thể có một cái gì đó như 2 %~ 8. Ở đây, ~sửa đổi %để chuyển đổi các đối số của nó, vì vậy biểu thức tương đương với 8 % 2.
Conor O'Brien

Trong chuỗi ngã ba, #~được đánh giá sau khi các động từ bên phải được thực thi, do đó, đối số bên trái sẽ trở thành kết quả ở bên phải
Conor O'Brien

2

Bình thường, 11 byte

>sPf!%QTS

Cũ:

L!%Qb>sPy#S

Tôi không thể sử dụng !%như một pfn cho #, bởi vì đó là hai chức năng. Làm tôi buồn :(.


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

Không xác định chức năng dường như ngắn hơn:>sPf!%QTS
FryAmTheEggman

2

k , 19 16 15 byte

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

Trả về 1đúng và 0sai.

Hãy thử trực tuyến!

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



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.