Bir tamsayı bolluğu!


40

Bir bol sayıda kendi doğru bölenler toplamı başlangıçtaki sayıdan daha büyük olan herhangi bir sayıdır. Örneğin, 12'nin uygun bölenleri:

1, 2, 3, 4, 6

Ve bu sonuçları 16'da toplayın. 16'sı 12'den büyük olduğundan, 12'si bol miktarda bulunur. Bunun "Mükemmel sayılar" içermediğine dikkat edin , örneğin 6 ve 28 gibi uygun bölenlerin toplamına eşit sayılar .

Bugünkü göreviniz, bir sayının bol olup olmadığını belirleyen bir program veya işlev yazmaktır. Programınız giriş olarak tek bir tamsayı almalı ve bunun bol olup olmamasına bağlı olarak bir gerçeği / sahte değeri vermelidir. Girdinin her zaman geçerli ve 0'dan büyük olacağını varsayabilirsiniz; bu nedenle hatalı girdiler için tanımsız davranış iyi.

Girişinizi ve çıkışınızı herhangi bir makul formatta alabilirsiniz, örneğin STDIN / STDOUT, dosyalar veya argümanlar / dönüş değerleri kabul edilebilir.

Başvuru için, işte 100'e kadar sayısız sayı:

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

Ve daha fazlası A005101'de bulunabilir.

Bu , standart boşluklar reddedilir ve seçtiğiniz dilde mümkün olan en kısa kodu yazmaya çalışın!


11
"ilk garip bolluk 945 = 3 ^ 3 * 5 * 7, 232 bolluk sayı!"
mbomb007

Bol sayıların asimptotik yoğunluğu , aralık içinde bir yerdedir [0.24761748, 0.24764422]. Bu makalede bulunan kaynak kodu kullanılarak hesaplanmıştır .
Deadcode

1
Bunu Geometry Dash'da yapmaya çalışıyorum. Bu bir kabus
MilkyWay90 3

Yanıtlar:


41

ECMAScript Regex, 1085 855 597 536 511 508 504 bayt

ECMAScript regex'te bol sayıların eşleştirilmesi, pratikte diğer herhangi bir regex lezzetinde bunu yapmaktan tamamen farklı bir canavardır. Ileri / iç içe geçmiş referansların veya özyinelemelerin olmaması, toplam bir şeyi doğrudan saymanın veya sürdürmenin imkansız olduğu anlamına gelir. Bakış açısının eksikliği, çalışmak için yeterli alana sahip olmanın bile sıkıntı yaratmasını güçleştiriyor.

Pek çok sorun tamamen farklı bir bakış açısıyla ele alınmalı ve onların çözülebilir olup olmadığını merak edersiniz. Çalıştığınız sayıların hangi matematiksel özelliklerinin, belirli bir problemi çözülebilir hale getirmek için kullanılabileceğini bulmakta çok daha geniş bir ağ oluşturmaya zorlar.

Mart-Nisan 2014’te ECMAScript regex’te bu soruna bir çözüm yaptım. İlk başta sorunun tamamen imkansız olduğundan şüphelenmek için her türlü nedenim vardı, ama sonra matematikçi teukon , sonuçta çözülebilir görünmesi için teşvik edici bir dava açan bir fikir çizdi - ancak regex inşa etme niyetinde olmadığını açıkça belirtti. önceki regex'leri inşa etme / golf oynama konusundaki yarışmalarıyla işbirliği yaptım, ancak bu noktaya kadar sınırına ulaştım ve teorileştirmeye olan katkılarını sınırlamadan memnundu.

Bir kaç gün önce yayınlanan regex'imde olduğu gibi, bir uyarı vereceğim : ECMAScript regex'deki unary matematiksel problemlerin nasıl çözüleceğini öğrenmenizi tavsiye ederim. Benim için büyüleyici bir yolculuk oldu ve bunu denemek isteyebilecek herhangi biri için, özellikle de sayı teorisine ilgi duyanlar için onu mahvetmek istemiyorum. Birbiri ardına çözmek için art arda spoiler etiketli önerilen sorunların bir listesi için bu yazı bakın .

Bu yüzden , eğer sizin için şımarık derin bir düzenli regex büyüsü istemiyorsanız, daha fazla okumayın . Benim önceki yazı sadece küçük bir tat oldu. Bu sihri kendiniz bulmaya bir göz atmak istiyorsanız, yukarıda belirtilen bağlantıda belirtildiği gibi ECMAScript regex'teki bazı sorunları çözerek başlamanızı şiddetle tavsiye ederim.

Benim ECMAScript regex yayınlamadan önce, ben Martin Ender'in analiz etmek ilginç olacağını düşündüm NET saf regex çözüm , ^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$). Bu regex'i anlamak oldukça kolay ve netliği açısından zarif. Çözümlerimiz arasındaki karşıtlığı göstermek için, işte regex'in yorumlanmış ve güzel basılmış (ancak değiştirilmemiş) bir versiyonudur:

# 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'i çevrimiçi olarak deneyin

Şimdi ECMAScript regex'ime döndüm. İlk olarak, burada ham, boşluk ve yorum içermeyen biçimde:

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

(değişim \14için \14?ECMAScript değil PCRE'nin, .NET ile uyumluluk için, ve pratik her regex lezzet)

Çevrimiçi deneyin!
Çevrimiçi deneyin! (daha hızlı, regex'in 537 bayt sürümü)

Ve şimdi arkasındaki hikayenin kısa bir özeti.

İlk başta, en azından bana göre, genel davada primerleri eşleştirmenin bile mümkün olduğu çok açık değildi. Ve bunu çözdükten sonra, aynısı 2'nin kuvvetlerine uygulanır. Ve sonra kompozit sayıların yetkileri. Ve sonra mükemmel kareler. Bunu çözdükten sonra bile, genelleştirilmiş çarpma işlemini yapmak ilk başta imkansız görünüyordu.

Bir ECMAScript döngüsünde, yalnızca bir değişen sayının kaydını tutabilirsiniz; bu sayı girişi aşamaz ve her adımda düşmek zorundadır. Doğru çarpım ifadelerini eşleştirmek için ilk çalışan regexim A * B = C 913 bayt idi ve A, B ve C'yi asal güçlerine faktoring ederek çalıştı - her asal faktör için, A ve C'nin asal güç faktörlerinin çiftini tekrar tekrar bölün. A 'ya karşılık gelen biri 1 olana kadar asal bazlarıyla; C'ye karşılık gelen bir daha sonra B'nin primer güç faktörü ile karşılaştırılır. Aynı prime ait bu iki güç, bir araya getirilerek tek bir sayıya "çarpılır"; bu, her zaman ilmeğin her bir yinelemesinde açıkça ayrılabilir, aynı nedenle konumsal sayı sistemleri çalışır.

Tamamen farklı bir algoritma kullanarak 50 bayta kadar çarpma yaptık (ki bu teukon ve ben bağımsız olarak ulaşabildik, sadece birkaç saat sürdü ve doğrudan gitti, oysa ki birkaç gün sürdü.) Kısa bir yöntemin var olduğuna dikkat çektim): A≥B için, A * B = C, eğer sadece C, C≡0 mod A ve C≡B mod A-1'i karşılayan en küçük sayı ise. (Uygun bir şekilde, A = 1 istisnasının regex'te özel bir işleme ihtiyacı yoktur, burada% 0 0 = 0 eşleşir.) Ben böyle zarif bir çarpma yapmanın böyle zarif bir şekilde var olmasının ne kadar düzenli olabileceğini bilemiyorum. minimal regex tadı. (Ve A≥B'nin gerekliliği, A ve B'nin aynı gücün ana güçleri olması şartıyla değiştirilebilir. A≥B için, bunun Çin geri kalanı teoremi kullanılarak kanıtlanması gerekir.)

Eğer çarpma için daha basit bir algoritma olmadığı ortaya çıkarsa, bol sayı regex'i muhtemelen on bin bayt civarında olurdu (hatta 913 bayt algoritmasını 651 bayta düşürdüğümü dikkate alarak). Çok sayıda çarpma ve bölme yapar ve ECMAScript regex'in alt yordamları yoktur.

Çok sayıdaki problem üzerinde telaşlı bir şekilde, 23.03.2014 tarihinde, bunun bir alt problemi olarak görünen şeye bir çözüm üreterek telaşlı bir şekilde çalışmaya başladım: En yüksek çokluğun asal çarpanının belirlenmesi başlangıçta, gerekli bazı hesaplamaları yapmak için odadan çıkarak. O zamanlar bu almak için umut verici bir yol gibi görünüyordu. (İlk çözümüm 326 baytta oldukça büyük oldu, daha sonra 185 bayta kadar golf oynadı.) Ancak, teukon eskiz yönteminin geri kalanı oldukça karmaşık olurdu, bu yüzden ortaya çıktığımda, oldukça farklı bir rota izledim. N'deki en büyük primer faktöre karşılık gelen N'nin en büyük primer güç faktörünü bölmek için yeterli olduğu kanıtlanmıştır; bunu en yüksek çokluğun asallığı için yapmak, regex'e gereksiz karmaşıklık ve uzunluk eklerdi.

Geriye kalan, bölenlerin toplamını, doğrudan bir miktar yerine, toplamların bir ürünü olarak ele almaktı. As teukon ile açıklanabilir 2014 14 Mart'ta:

N = p 0 a 0 p 1 a 1 ... p k-1 a k-1 verilir . N faktörünün toplamını ele almak istiyoruz (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 ).

Bunu görmek aklımı başımdan aldı. Kısım toplamı bu şekilde çarpanlara ayırmayı hiç düşünmedim ve bu formül ECMAScript regex'teki bol sayı eşleşmesinin çözülebilirliğini makul görünmesine neden olan her şeyden daha fazladı.

Sonunda, N'yi aşan bir toplama veya çarpma sonucu test etmek ya da M'ye bölünerek böylesi bir sonucun N / M'yi aştığını test etmek yerine, bölme sonucu 1'den küçükse sınamaya girdim. 7 Nisan 2014 tarihinde ilk çalışan versiyon.

Bu regex'deki golf optimizasyonlarımın tam tarihi github'da. Belli bir noktada bir optimizasyon, regex'i çok daha yavaş hale getirdi, bu yüzden o noktadan itibaren iki versiyonu tuttum. Onlar:

bol numbers.txt eşleşen regex
bol sayılar eşleşen regex - shortest.txt

Bu regexes ECMAScript'e ve PCRE'nin ikisi ile tam uyumlu olduğunu, ancak son optimizasyon potansiyel katılımcı olmayan yakalama grubu kullanılarak dahil \14öylesine PCRE uyumluluğu bırakarak ve değiştirerek, \14?karşı \14her ikisi de 1 bayt ile azaltılabilir.

İşte en küçük sürüm, bu optimizasyon uygulanmış (yalnızca ECMAScript'i yapar), (çoğunlukla) yatay kaydırma gerektirmeyen bir StackExchange kod bloğuna uyacak şekilde yeniden biçimlendirilmiş:

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

Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
DJMcMayhem


27

Python 2 , 41 40 bayt

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

Çıkış, çıkış koduyla yapılır , bu nedenle 0 , truthy ve 1 ise sahtedir.

Çevrimiçi deneyin!

Nasıl çalışır

N , k ve j'nin tümünü STDIN'den girişe ayarladıktan sonra while döngüsüne giriyoruz . Bahsedilen döngü -k - 1 = ~ k≥0 , yani k ≤ -1 / k <0 olur olmaz kırılır .

Her yineleme, biz ilk eksiltme j sadece uygun bölenler dikkate n . Eğer j , n'nin böleni ise , n%jverim 0 ve j >> n% j * n = j / 2 0 = j , k'dan çıkarılır . Ancak, j gelmez değil bölmek n , n%jbu yüzden, pozitif n%j*nen az olduğu n> log 2 j ve j >> n% j * n = j / 2 n% j * n = 0 çıkarılır k .

Bol numaralar için k zaman ya önüne eksi değere ulaşacaktır j olur 1 toplamı beri, n 'in uygun bölenler daha sıkı büyüktür n . Bu durumda, while döngüsünden ayrılırız ve program normal şekilde tamamlanır.

Ancak, n ise değil bol, j sonunda ulaştığı 0 . Bu durumda, n%jbir ZeroDivisionError atar ve program bir hatayla çıkar.


4
~k<0fantezi, ama -1<kaynı zamanda hile yapar;)
Martin Ender




10

Mathematica, 17 bayt

Tr@Divisors@#>2#&

açıklama

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’da bunun için hiçbir şey yapılmadığı için şaşırdım ..
MrPaulch

1
@MrPaulch Programın uzunluğu dikkate alındığında, yapının adı çok daha uzun olabilir>.>
Conor O'Brien

1
@ ConorO'Brien Var olsaydı, muhtemelen olurdu AbundantNumberQ, bu yüzden birkaç bayt kurtarır :)
ngenisis


7

Retina , 50 45 bayt

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

Unary girişi , 1bol sayılar için çıkışı , 0aksi takdirde.

Bu çözümle ilgili Retina'ya özgü hiçbir şey yok. Yukarıdakiler, yalnızca bol sayılarla eşleşen saf bir .NET regex'idir.

Çevrimiçi deneyin! (Ondalık girişi yukarıdaki regex ile filtreleyen test takımı.)


6

Retina , 34 bayt

Bayt sayısı, ISO 8859-1 kodlamasını varsayar.

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

^(1+)¶1\1

Unary girişi , 1bol sayılar için çıkışı , 0aksi takdirde.

Çevrimiçi deneyin!

açıklama

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

Girişin tüm bölümlerini alarak başlıyoruz. Bunu yapmak için, regex'in üst üste gelen ( ) !tüm ( ) eşleşmelerine ( ) döneriz . Regex, girişin tamamının, bir son ekin katı olması koşuluyla (ekin sadece kopyalarını kullanarak dizgenin başlangıcına ulaşmaya çalıştığımızdan emin olduğumuz sürece) girdi ekleriyle eşleşir. Regex motorunun eşleşmeleri arama biçimi nedeniyle, bu azalan sırada bölenlerin bir listesini (satır beslemeleri ile ayrılmış) sağlayacaktır.&M(1+)$(?<=^\1+)

1>`¶

Sahnenin kendisi sadece satır besleyicileri ( ) ile eşleşir ve bunları kaldırır. Ancak, 1>ilk eşleşmeyi atlayan bir sınırdır. Dolayısıyla bu, girdi dışındaki tüm bölenleri etkin bir şekilde bir araya getirir. İlk satırdaki girdiler ve ikinci satırdaki tüm uygun bölenlerin toplamı ile son buluruz.

^(1+)¶1\1

Son olarak, 1ikinci hatta, ilk sıradakinden en az bir tane daha eşleştirmeye çalışırız . Bu durumda uygun bölenlerin toplamı girdiyi aşıyor. Retina olacak bu regex maçları, sayar 1bol numaraları ve için 0başka türlü.


1
Retinada matematik yapmayı hep şaşırttım. Bir açıklama görmek isterdim! :)
DJMcMayhem

1
@DJMcMayhem Üzgünüz, daha önce eklemeyi unuttum. Bitti.
Martin Ender

6

8086 Meclisi, 23 28 25 24 bayt

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

unassembled:

; 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

Örnek test programı, N = [12..1000] testi:

    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

Çıktı [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

Çıktı [12500.1.100]

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

Çıktı [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

Güncellemeler:

  • 16-bit taşma (+5 bayt) için düzeltildi. Önerileriniz için teşekkürler @deadcode!
  • Basitleştirilmiş dönüş mantığı (-3 bayt). Thx @deadcode bir kez daha yardımcı olmak için.
  • CMP (-1 byte) yerine TEST kullanın. Thx ila @ l4m2!

1
Ben değiştirmenizi öneririz JLEile JBEtaşmaları yanlış negatifleri vermek neden başlamadan önce sayıların alanını bu kutu testi iki katına çıkarmak. Daha sonra, 12600'de başarısızlık yapmak yerine (toplam 35760 kısım), 25200'de başarısızlıkla başlar (kısım toplam 74744). Daha da iyisi, taşıma bayrağını tespit etmek ve gerçek> 16 bit toplamı hesaplamak zorunda kalmadan, bol sayı olarak kabul etmek olacaktır.
Deadcode

1
@Deadcode iyi yakalamak. Daha az atlama yerine aşağıdaki atlama kodunu güncelledim. Ne demek istediğinizi anlıyorum, ADD BX’ten sonra bir JC yaparak, CX orada imzasız taşma olayını yakalayacak ve N = 65535'e kadar düzeltecektir. Bayrak testini ve geri dönüş durumunu biraz daha karmaşık hale getiriyor, çünkü önceden CF yanlış. Ayrıca düzeltme ile güncellendi.
640KB

1
Geri dönüş değerinizin spesifikasyonunu tersine çevirerek 3 bayt tasarruf edebilirsiniz, CF bolsa ve net değilse ayarlanmıştır. Ancak önce çıktı belgelerini düzeltmek için düzenlemeyi yapmanızı öneririm, bu nedenle düzenleme geçmişinde hoş görünüyor.
Deadcode

1
Ayrıca, her şeyi basit tutmak için, şartname, geri dönüş değerinin taşıma bayrağı içinde olması ve hiçbirinin diğer bayraklarla karışması olmamalıdır. Arayan kişi , sayının bol olup olmadığına bakmak için kullanmalı JCveya kullanmalıdır JNC.
Deadcode

1
Tüm yardımlarınız ve yorumlarınız için çok teşekkürler. Satır içi belgelerini güncelledim ve ungolfed terimini kaldırdım. Dürüst olmak gerekirse, hiçbir zaman çok düşünmedim, ancak satır içi yorumlar dışında hiçbir farkı olmadığı için bu konudaki amacınızı anlıyorum. Ayrıca dönüş bayraklarının daha net anlaşılması konusunda da hemfikir olun. Biraz bunun üzerinde çalışacak. Dikkatiniz ve yardımınız için teşekkürler!
640KB,


5

05AB1E , 4 bayt

ѨO‹

Çevrimiçi deneyin!

Nasıl çalışır

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

Eski soruyu gönderdiğim için özür dilerim, eski pratik çalışmalarımdan geçiyordum ve çözümümün bir sonraki en iyi 05AB1E çözümünden daha kısa olduğunu fark ettim.


4
Sorry to post in old questionEndişelenme! Eski zorluklarımın yanıtlarını gördüğüm için her zaman mutlu oluyorum ve bu gerçekten buralarda teşvik ediliyor . :)
DJMcMayhem


4

Java 8, 53 bayt (tören kodunu eklerseniz çok daha fazlası)

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

Çevrimiçi deneyin

Açıklama:

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
Harika cevap, ancak Java 8 ile byte-count içindeki işlevi eklemelisiniz. Sonra tekrar, returneğer yanılmıyorsam bırakabilirsiniz , bu yüzden daha kısa olacaktır: n->IntStream.range(1,n).filter(e->n%e<1).sum()>n(bu doğruysa% 100 değil, neredeyse hiç Java 8 programlamam). PPCG'ye Hoşgeldiniz!
Kevin Cruijssen,

1
Standart sayımla yapılan doğru sayım n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>n65 bayt olacaktır (sanırım paketi başımın üstünden aldım)
CAD97

4

Powershell, 51 49 Bayt

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

Keşke bazı braketleri çıkarabilseydim.

-2 AdmBorkBork sayesinde, ilk aralıktaki girişi saymamak yerine, son kontrolde dikkate alıyoruz.

Aralığında döngü 1..için $input, eksi 1, (burada bulabilirsiniz ?anki sayısına göre girişin ters modülo olan) $truedaha sonra - (aka sadece 0) -joinhep birlikte bu sayılar ile arasında +ve iexbunu hesaplamak için elde edilen dize, daha sonra görmek bu parçaların toplamı girdiden büyük.

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

En yüksek değeri sayarak ve girişin 2 katından büyük olup olmadığını kontrol ederek iki bayttan tasarruf edebilirsiniz -param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
AdmBorkBork

3

MATL, 6 bayt

Z\sGE>

Bol sayılar için 1, aksi takdirde 0 çıkışlar.

Nasıl çalışır

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 bayt

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

Bu, QBIC primallik testine bir adaptasyondur . Bölenleri saymak ve üçten az olup olmadığını kontrol etmek yerine, bu uygun bölenleri toplar. Bu 1 to n, ilkellik testinin 1 to ntamamen geçtiği yerin sadece yarısı boyunca çalışır .

Açıklama:

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

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>


Özyinelemeli bir cevabın en iyi olacağından emindim ama bu kadar iyi olacağını düşünmedim.
Neil

3

Japt , 9 7 6 bayt

<Uâ1 x

ETHproductions sayesinde 2 bayt kurtardı. Obarakon sayesinde 1 bayt kaydedildi.

Çevrimiçi deneyin!


9 karakter, 10 bayt.
Metoniem

@Metoniem âEn az 1 numaralı bayt, unicode'da (0xE2).
Tom,

1
@Metoniem Japt , içinde tek bir bayt olan ISO-8859-1 kodlamasını kullanır â.
ETHProductions

Eğer âbir truthy argüman verilir bunu yapabilirsiniz, o kalan listeden gerçek sayısını kaldıracak â1 x >Ubir çift bayt :-) kaydetmek
ETHproductions

@ TomDevs Güzel! <Uâ1 xBir bayt kaydetmek için yapabilirsiniz . Japt Uprogramın önüne ekler .
Oliver,

3

Cubix , 38 bayt

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

Burada dene

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

0I:- yığını 0, n, n (s, n, d) ile ayarlar
^- döngünün başlangıcı )?- azalış d ve 0 için test edin. 0
%?n'ye karşı döngü - moddan çıkın ve test edin. 0 ;rrw+s;rUs'yi en üste döndüren ve d ekleyen, s'yi alttan döndüren ve döngüye
;<yeniden katılan - nedenleri temizler ve döngüye yeniden katılır .
Çıkış döngüsünde
;<- d'yi istiften çıkarın ve yönlendirin
-?- n'i s ve testten çıkarın, 0 LOU@sola döner, çıkışlar ve çıkışlar, negatifler 0O@sıfıra basar, çıkış ve çıkar. pozitifler ;Ofarkı ve çıktıları ortadan kaldırır Yol daha sonra @çıkışa yönlendiren sola döner.


3

Saf Bash, 37 bayt

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

Kodu yeniden düzenlemek için @Dennis 'e teşekkürler - 6 bayt tasarrufu ve arızalı çıkışın stderr'ye kaldırılması.

Giriş bir argüman olarak iletilir.

Çıkış çıkış kodunda döndürülür: 0 için bol, 1 için bol değil.

Stderr'e çıkış ihmal edilmelidir.

Test çalıştırması:

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

STDERR'ye yolsuzluktan kaçınırken 6 bayt tasarruf edebilirsiniz. tio.run/nexus/bash#S04sUbBTSEwqzUtJzCtRsLFRUHf1d1P/…
Dennis

2

RProgN , 8 Bayt

~_]k+2/<

Açıklaması

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

Çevrimiçi deneyin!


2

Toplu iş, 84 bayt

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

Çıkışlar -1bol numarası, 0aksi. 2nİşaret faktörünü çıkarmak için tüm faktörleri çıkararak ve sonucu değiştirerek 31 yerden geçirerek çalışır. Alternatif formülasyon, ayrıca 84 bayt:

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

1Bol bir sayı için çıktılar . Tüm faktörleri nçıkardıktan sonra sonucu ile karşılaştırarak çalışır -n. ( set/aBatch'in aritmetik yapmanın tek yolu budur, bu yüzden döngüyü kolayca ayarlayamıyorum.)


1
"(% 1 %%%% j)" oh, toplu iş :)
Bryan Boettcher

2

Perl 6, 72 24 bayt

{$_ <sum grep $_%%*,^$_}
  • Program argümanı: a.
  • Listesinden bir liste oluşturun 1..a.
  • Bölenlerin tüm numaralarını al a.
  • Topla onları.
  • Bu toplamın büyük olup olmadığını kontrol edin a.

@ B2gills'e teşekkür ederiz.


İlkinden $^asonraki her olay sadece kısaltılabilir $a. Eğer olarak yazarsanız ama bile kısadır {$_ <sum grep $_%%*,^$_}Ayrıca önceki bir sürümüne bakarak, [+](LIST)eserleri (boşluksuz)
Brad Gilbert b2gills

@ BradGilbertb2gills Teşekkürler! :)
Ven,

2

J, 19 bayt

Conor O'Brien'a 19 byte'a böldüğü için teşekkürler!

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

Önceki: (34 bayt)

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

Bolsa 1, değilse 0 döndürür.

Çıktı:

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

PPCG'ye Hoşgeldiniz! Anonim işlevlere izin veriyoruz, böylece f=:önceliği bayt sayınızın bir parçası olarak kaldırabilirsiniz . Ayrıca, tam bir fiili dönüştürerek 19'a kadar alabilirsiniz:<[:+/i.#~i.e.]%2+i.
Conor O'Brien

Tavsiye için teşekkürler! Ancak, başlık fiilini ([:) ve anahtar fiilini (~) açıklar mısınız? Gerçekten bu zımni fiilde yapmaları gerekenleri anlamıyorum.
Bloklar

~ anahtarlar yani # i. ama [:? 'in amacı nedir?
Bloklar

çatalları biliyorsun, değil mi? (f g h) y' is the same as (fy) g (hy) . When f` bir kapaktır, ([: g h) ykabaca aynıdır g h y. Gelince ~, bu sol ve sağ argümanları değiştirir. Bunun ~bir fiil olmadığını, aslında bir zarf olduğunu bilmek önemlidir . Bir fiili değiştirir. Örneğin, bunun gibi bir şey olabilir 2 %~ 8. Burada, argümanlarını ~değiştirmek %için değişiklikler yapar, yani ifade eşdeğerdir 8 % 2.
Conor O'Brien,

Çatal zincirinde, #~sağdaki fiiller yerine getirildikten sonra değerlendirilir, bu nedenle sol argümanı sağdaki sonuç olur
Conor O'Brien,

2

Pyth, 11 bayt

>sPf!%QTS

Eski:

L!%Qb>sPy#S

!%Pfn olarak kullanamıyorum #, çünkü bu iki fonksiyon. Beni üzüyor :(.


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

Bir fonksiyon tanımlamaması daha kısa gibi görünüyor:>sPf!%QTS
FryAmTheEggman

2

k , 19 16 15 bayt

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

İade 1gerçek için ve 0yanlış için.

Çevrimiçi deneyin!

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



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.