11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)


35

Olumlu bir tamsayı N verildiğinde , göreviniz N'e ulaşmak için aşağıdaki algoritma için gereken adım sayısını döndürmektir :

  1. En küçük üçgen sayı bul T i öyle ki , T i  ≥ N . İlgili liste L = [1, 2, ..., i] oluşturun .

  2. L terimlerinin toplamı N'den büyük olsa da , ilk terimi listeden kaldırın.

  3. L terimlerinin toplamı şimdi N'den azsa , i değerini artırın ve listeye ekleyin. Adım 2 ile devam edin.

N'ye ulaşılır ulaşmaz dururuz . Sadece ilk adım sistematik olarak gerçekleştirilir. # 2 ve # 3 adımları hiç işlenmeyebilir.

Örnekler

Aşağıda N = 11 için bir örnek verilmiştir :

Örnek

Beklenen çıkış Böylece N = 11 olan 4 .

Diğer örnekler:

  • N = 5 - T 3 = 1 + 2 + 3 = 6 ile başlıyoruz, ardından 2 + 3 = 5 . Beklenen çıktı: 2 .
  • N = 10 - Sadece ilk adım gerekli, çünkü 10 üçgen bir sayıdır: T 4 = 1 + 2 + 3 + 4 = 10 . Beklenen çıktı: 1 .

İlk 100 değer

1 ≤ N ≤ 100 sonuçları aşağıdadır :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

kurallar

  • Tam bir program ya da sonucu yazdıran ya da veren bir fonksiyon yazabilirsiniz.
  • Sen ediyoruz gerekli herhangi işlemek için N ≤ 65536 orta sınıf donanım üzerinde az bir dakika içinde.
  • Biraz zaman verin, programınız / fonksiyon gerektiğini teorik olarak herhangi değeri için çalışmak N doğal olarak sizin dilinize tarafından desteklenmektedir. Olmazsa, lütfen cevabınızda neden olduğunu açıklayın.
  • Bu kod golf, yani bayt cinsinden en kısa cevap kazanır!

İlgili. (Bunu zaten bildiğinizden şüpheleniyorum, ama sadece gelecek için
gönderiyorsunuz

Ele almamız gereken maksimum N değeri nedir?
Luke,

@Luke Lütfen güncellenen kurallara bakın.
Arnauld,

Yanıtlar:


4

Jöle , 29 31 bayt

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

Sonucu döndüren bir monadik bağlantı (N = 65536 iki saniyeden az sürer).

Çevrimiçi deneyin!

Nasıl?

Algoritmanın ayrıntılı bir açıklaması için Martin Ender'in fantastik yazılarına bakınız .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

Tanımlanan algoritmadan oluşturduğum 29 baytlık tam program uygulaması dizüstü bilgisayarımda N = 65536 için 4 dk. 30 alıyor, sanırım sayılmaz.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

Her adım 3 için bir while döngüsü kullanmak ve onu adım 1 olarak tekrar kullanmak, listeyi başlatmakla başa çıkabileceğimin uzunluğuna eşittir, çünkü 3. adımdaki hiçbir kontrol, hiçbir şey kalana kadar bir liste oluşturmak ve daha sonra değerin ilk dizinini bulmak anlamına gelir:

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

Mathematica, 79 bayt

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

açıklama

Algoritmayı bu zorlukla uygulamak için canımı sıkmadı, bu yüzden çözüme giden bir kısayol aramak istedim. Bir tane bulurken maalesef algoritmayı uygulayan Mathematica cevabını geçmiyor. Bununla birlikte, bunun henüz en iyi şekilde golf oynamadığından eminim ve bu yaklaşımdan ya da süreçte edinilen bazı fikirlerden faydalanabilecek başka diller olabilir.

Bu yüzden hesaplamamız gereken dizinin:

f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)

Alternatif olarak, eğer n bir üçgen sayı ise f (n) = 1, aksi takdirde f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) olur .

İlk ifadede, A023532 basitçe bu iki farklı durumu kodlar. Diğer iki dizi (artı 1) en büyük tam sayıyı arasında fark vardır k en uzun ayrışma n ardışık tamsayılar (k-i + 1) + (k-i + 2) + ... + k = n ve en büyük tamsayı j, böylece 1 + 2 + ... + j <n .

Biraz daha basit bir ifadeyle, burada olmayan üçgen sayılar için cevap bulmak nasıl: Birincisi, büyük üçgen sayı bulmak T j olduğunu az daha n . Daha sonra j , 1. adımda eklenen sondan fazla tamsayıdır (çünkü j + 1 ekledikten sonra n'yi geçeceğiz ). Ardından n'yi mümkün olduğu kadar çok sayıda (veya küçük) ardışık tamsayıya ayırın ve bu sayılar arasında en fazla k'yi çağırın . Sonuç sadece 2 * (kj) . Bunun sezgisel nedeni, ayrıştırmadaki maksimum değerin diğer her adımda 1 oranında artması ve ulaştığımızda durmamızdır.k .

Bunun işe yaradığını ispatlamak için dört şey göstermemiz gerekiyor:

  1. Üçgen sayılar için f (n) = 1 . Bu esasen böyledir, çünkü ilk adım basitçe tüm üçgen sayıları boyunca yinelenir. Biz vurursanız n bu süreçte tam bitti ve hesaplamak için sadece bir adım yoktu.
  2. Diğer tüm numaralar için, bir ekleme adımından sonra asla bir silme adımından sonra sonlanır. Bu, diğer tüm f (n) ' nin eşit olduğu anlamına gelir .
  3. Birinciden sonraki her ekleme adımında, yalnızca tek bir sayı ekleriz. Bu, kj çift ​​basamaklarından sonra k dahil bir ayrışmaya ulaşacağımızı garanti eder .
  4. Elde ettiğimiz n'in nihai ayrışması , her zaman n'nin ardışık tam sayılara mümkün olan en uzun ayrışması veya başka bir deyişle, her zaman n'nin toplam sayılar arasında en düşük azami dağılışıdır. Başka bir deyişle, toplamı eklediğimiz son sayı her zaman A212652 (n) 'dir .

Neden (1) doğru olduğunu zaten gösterdik. Sonra, ilk adım hariç (üçgen olmayan sayılar için gerçekleşmeyen) bir ekleme adımına son veremeyeceğimizi kanıtlıyoruz.

Bir ekleme adımında sona erdiğimizi , toplama p değerini ekledikten sonra n'ye ulaşdığımızı varsayalım . Bu, bu ekleme adımından önce, değerin np olduğu ( veya bir kerede birden fazla değer eklediğimizde daha az olduğu) anlamına gelir . Ancak bu ekleme adımından önce bir silme adımından önce geldik (çünkü 1. adımda n'ye vuramadık ). Bu silme adımı sırasında çıkardığımız son q , algoritmanın çalışmasından dolayı mutlaka p'den daha azdı . Çıkarılmış önce Ama bu araçlar q biz , n-p + q ( daha az ya da daha az olan) n. Ancak bu bir çelişkidir, çünkü başka bir q'yu çıkarmak yerine n-p + q'ya bastığımızda tamsayıları kaldırmak zorunda kalmazdık . Bu, yukarıdaki (2) noktasını kanıtlar. Şimdi her zaman bir silme adımına son verdiğimizi ve bu nedenle tüm üçgen olmayan sayıların bile çıktıları olduğunu biliyoruz.

Daha sonra kanıtlıyoruz (3), her ekleme adımının sadece bir değer ekleyebileceğini kanıtlıyoruz. Bu aslında (2) nin bir sonucudur. Bir değer ekledikten sonra tam olarak n'e vuramayacağımızı ve ispatın bir eşitsizlik kullandığından beri, n'in altına da çıkamayacağımızı gösterdik (o zamandan beri n-p + q hala n'den az olurdu ve kaldırmamalıydık) ilk etapta bu kadar değer). Bu yüzden ne zaman tek bir değer eklesek, n'i geçmemiz garantilidir, çünkü daha küçük bir değeri kaldırarak n altına indik. Dolayısıyla, toplamın üst kısmının diğer her adımda 1 arttığını biliyoruz . Biz (o en küçük olan bu üst ucunun başlangıç değerini bilmek m böyleT m > n ). Şimdi son toplamı bulduktan sonra bu üst ucu bulmamız gerekiyor. O zaman adım sayısı farkın iki katıdır (artı 1).

Bunu yapmak için, (4), son toplamın her zaman n'nin mümkün olduğu kadar çok sayıda tamsayıya ayrıştırılması olduğunu veya bu ayrıştırmadaki maksimum değerin en az olduğu yerde ayrıştırma olduğunu (yani, mümkün olan en eski ayrıştırma) kanıtlıyoruz. Bunu yine çelişki ile yaparız (bu kısımdaki ifadeler biraz daha titiz olabilirdi, ama ben zaten bunun için çok fazla zaman harcadım ...).

N'nin mümkün olan en erken / en uzun ayrışmanın bazı a + (a + 1) + ... (b-1) + b , a ≤ b olduğunu ve algoritmanın atladığını söyleyin. O zaman bu araçlar b ilave alır, bir zorunluluk artık toplamı bir parçası olabilir. Eğer bir toplamı bir parçasıydı lar , o zaman olurdu n ≤ s o anda. Yani ya toplamı sadece gelen değerleri içeren bir karşı b eşittir, n ve biz (dolayısıyla biz bu ayrışma atlamak değildi) durdurmak veya daha az en az bir değer yoktur bir hangi durumda toplamında, kazanmak n <sve biz kesin toplamı elde edinceye kadar bu değer ortadan kalkacaktı (yine, ayrışma atlanmadı). Bu yüzden kurtulmak olurdu bir eklemeden önce b . Ama biz olurdu demek olduğunu bir durum ulaşmak için bir toplamının en küçük bileşenidir ve büyük değildir b henüz. Ancak, bu noktada biz kaldıramazsınız bir toplamı açıkça daha az olduğu için, n (çünkü b eksik), biz eklemek kadar ilk değerlerini eklemek için gerekli konum böylece b ve isabet n tam olarak. Bu kanıtlar (4).

Öyleyse bunları birlikte almak: İlk adım çiftinin bize maksimum A002024 (n) değeri verdiğini biliyoruz . Son ayrışmanın maksimum değerinin A212652 (n) olduğunu biliyoruz . Ve bu maksimumın her adımda bir artırıldığını biliyoruz. Dolayısıyla, son ifade 2 * ( A212652 (n) - A002024 (n) + 1) 'dir . Bu formül neredeyse üçgensel sayılar için işe yarar, bunun dışında 2 yerine sadece 1 adım gerekli olanların dışında, bu nedenle sonucu üçgensel sayıların (veya tersi, hangisi daha uygunsa) gösterge işlevi ile düzeltiriz.

Son olarak, uygulamaya gelince. Önceki dizi için OEIS'den MIN (tek d | n; n / d + (d-1) / 2) formülünü kullanıyorum . MIN ifadesini almak için 2 faktörünü bu ifadeye alırsak, birkaç bayttan tasarruf edersek ortaya çıkıyor , çünkü -1 , ilk sürümümde +1 ile iptal ettiğinden ve f (n) ile doğrudan üçgen şeklinde olan ve üçgen sayılar için iki olgu kodlar. Kodda, bu:

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

İkinci sıra için ( 1, 2, 2, 3, 3, 3, ...) basit bir kapalı form kullanabiliriz:

⌊(2#)^.5+.5⌋

Ve son olarak, 8n + 1 mükemmel bir kare olduğunda üçgen sayıların ters gösterge işlevi 0'dır . Bu, Mathematica’da şu şekilde ifade edilebilir:

⌈Sqrt[8#+1]~Mod~1⌉

Bu son iki diziyi ifade etmenin ve aralarındaki bazı sabit dengeleri kaydırmanın birçok yolu var, bu yüzden bunun henüz en uygun bir uygulama olmadığından eminim, ancak umarım bu, başkalarına yeni yaklaşımlara bakmak için bir başlangıç ​​noktası verebilir. kendi dilleri

Tüm bu sıkıntılara gittiğimden, işte n = 1000'e kadar olan dizilerin bir grafiği: ( Birkaç saniye içinde 100k'yi de hesaplayabilirim, ancak ek bir içgörü göstermiyor):

görüntü tanımını buraya girin

Bu çok düz çizgilerle ilgili varyasyonlara bakmak ilginç olabilir, ama bunu başkasına bırakacağım ...


Sonunda cevabınızı iyice okumak için zaman ayırdım. Bu mükemmel. Algoritmada (3) zaten varsayıldığına dikkat edin (adım # 3, eğer bir süre değil , ancak) ispat elbette - memnuniyetle karşılandı.
Arnauld,

@Arnauld Teşekkürler. :) Eğer if / while bölümünü gözden kaçırmalı / yanlış anlamış olmalıyım. İyi ki o zaman bir fark yaratmaz.
Martin Ender

7

Mathematica, 72 bayt

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

Tamsayı argüman alarak saf işlevi.

Nasıl çalışır

For[ ... ]

Bir Fordöngü.

l=u=c=k=0

Başlatma; grubu l(daha düşük), u(üst), c(karşı) ve k0 (toplam).

k!=#

Şart; tekrarlayın kgirişe eşit değil.

c++

Artış; sayacı artırmak c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

Vücut

If[#>k, ... ]

Girdi şundan büyükse k:

While[#>k,k+=++u]

Giriş katından daha fazla iken k, artım uve artım kile u.

Giriş aşağıdakilerden büyük değilse k:

While[#<k,k-=l++]

Giriş az iken kazalma, kile lve artım l.

( ... ;c)

Döngüden csonra dön .


1
For[,...]yener While[...].
Martin Ender

5

Python 2 , 104 bayt

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

Çevrimiçi deneyin!

Listenin sonuna terim ekleme ve terimleri baştan kaldırma arasında geçiş yapar.


5

Haskell , 70 63 68 64 bayt

DÜZENLE:

  • -7 bayt: Bir anlamdan, iki işaretten ve bazı parantezlerden kurtulma duygusunu yok ederek a. Açıklamadaki tek tek hatalar düzeltildi.
  • 5 bayt: Ahh, tamamen 65536 gereklilik ve çıkıyor 2 (1) güçler, özellikle pahalı olduğunu cevapsız sen (sayı kendisi (2) çok uzun aralıklar toplanmasıdır olsun o zaman onlar sadece hit almak çünkü sarma etrafında sıfır) her zaman. Toplamı matematiksel bir formülle değiştirdim.
  • -4 bayt: Düzeltmek için toplama formülündeki terimleri almak için ayarlandı ave bdoğrusal olarak.

1#1 bir tamsayı alıp döndüren adsız bir işlevdir.

Olarak kullanın (1#1) 100.

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

Çevrimiçi deneyin!

Nasıl çalışır

  • (a#b)nGeçerli hesaplama adımını temsil eder. a, brakamlar ise 1, 3, 5, .., nbasamağa bağlı olarak pozitif veya negatif olabilir.
    • 1. veya 3. adımda, liste [(a+1)/2,(a+3)/2..(b-1)/2]ve hedef numaralarını temsil eder -n.
    • 2. adımda, liste [(b+1)/2,(b+3)/2..(a-1)/2]ve hedef numarasını gösterir n.
  • a, bListeler arasında garip yazışmalar , kısa ifadeyle toplamayı yapabilmektir s=a*a-b*b.
    • Adım 1 ve 3'te, bu aynıdır s= -8*sum[(a+1)/2..(b-1)/2].
    • 2. adımda, bu aynıdır s=8*sum[(b+1)/2..(a-1)/2].
  • Dallanma, her birinde sadece bir durumda eleman üreten unsurların listelenmesi ve sonuçların toplanması ile yapılır.
    • Eğer s>8*nöyleyse b, tekrarlamadan önce 2 ile artırılır.
      • 1. ve 3. adımda, bu liste büyürken, 2. adımda bu küçülür.
    • Eğer s<8*nöyleyse, özyineleme takas değiştirerek ave bve olumsuzlayarak adım değiştirir ve nsonuca 1 eklenir.
    • Öyleyse s==8*n, iki liste kavrayışından hiçbiri herhangi bir öğe vermezse , toplamı öyledir 0.
  • (1#1) nBaşlamadan önce kukla bir "aşama 2" yi temsil eder, bu hemen listeyi oluşturarak 1. adıma değiştirilir [1..0]=[].

4

PHP> = 7.0, 74 Bayt

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

kullanmak uzay operatörünü

Çevrimiçi deneyin!

Expanded

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

Nedir $argn?
chx

@chx PHP'yi -R Seçeneği ile komut satırından açtığınızda kullanabileceğiniz bir değişken php.net/manual/en/features.commandline.options.php
Jörg Hülsermann

Vay. Hiç -Rdaha azını duymamıştım argvya da argi. Elbette argüman ve argüman biliyordum. Çok ilginç, teşekkürler.
chx

4

C, 94 91 bayt

Çevrimiçi dene

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

Başlatılmamış değişkenlerde yoğun kullanım oO
YSC

C'deki @YSC, başlatılmamış global olarak bildirilen tam sayılar derleme zamanında sıfıra ayarlanır. devamını oku
Khaled.K

Bunu unuttum. Bu hatırlatma için teşekkürler.
YSC

Bilginize, başka bir C cevabı gönderdim . Kullandığım numaralardan en az biri diğer derleyicilerle (eksik returnolanlarla) çalışmayacak, fakat bunu yapanlar için bunları cevabınıza dahil etmekten çekinmeyin.
hvd

3

JavaScript (ES6), 82 bayt

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

Test Parçacığı


Bunu söylediğim için üzgünüm ama her biri 3 bayt olarak sayılıyor. Önemsizce değiştirilebildiği için önemli değil sanırım.
Ørjan Johansen

@ ØrjanJohansen Beni hatırlattığın için teşekkürler. Kodumu uzunluğundan ziyade bayt ile puanlamayı gerçekten hatırlamalıyım. "Kolayca değiştirilebilen [değişkenler]" konulu bir topluluk görüş birliği olduğunu sanmıyorum, bu yüzden yazıyı düzenledim. Oh iyi.
R. Kap,

3
Snippet 6553'te “Çok fazla özyineleme” ile başarısız oluyor. 6553 yerel olarak Düğümde (6.9.1) çalışıyor, ancak 65536 yok (“Maksimum çağrı yığını boyutu aşıldı”).
eush77

3

dc , 61 bayt

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

Çevrimiçi deneyin!

açıklama

Ana özyinelemeli makro:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

Bu makro:

  1. Yığındaki geçerli sayıyı aşan minimum üçgen sayıyı bulur (değiştirilmiş üçgen kök formülünü kullanarak ).
  2. Üçgen toplamın Sgeçerli sayıyı tam olarak gösterip göstermediğini kontrol eder. Varsa çıkar.
  3. S+N(Aşırı yaklaşım) veya S-N(az yaklaşma) ile adım 1'e ilerler , seçim yinelemeler arasında değişir.

Çıktığında, yığında bırakılan iz ana programa kaç tane yineleme yaptığını söyler.


3

Python 3, 150 138 bayt

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

Değişiklikler:

  • + = Olarak değiştirildi, başkası kaldırıldı (teşekkürler musicman523, Loovjo; -12 bytes)

1
2. Adım, bir veya birkaç terimi listeden bir kerede kaldırabilir (N = 11 örneğindeki örnekte 1, 2 ve 3 gibi) ancak her iki şekilde de tek adım olarak sayılır.
Arnauld,

@Arnauld, bunu göz ardı etti; sabit.
L3viathan

1
Neden elsegerekli olduğunu açıklayabilir misiniz ? elseHer seferinde koşuya inanıyorum , çünkü döngü her zaman normal olarak sonlandırılıyor (onsuz break) ve onsuz iyi çalışıyor gibi görünüyor .
musicman523

Parçayı atlayıp yerine A=l.appendkullanabilirsiniz l+=[x].
Loovjo

3

Toplu iş, 126 bayt

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

Açıklama: l2. adım hiç çalışmadıysa sıfırdır. Bu, n3. adımdaki yinelemelerin sayısını izlemenizi sağlar . Algoritma 3. adımda hiç durmadığından, bu nedenle n+1toplam n+n+2adımlar için 1. adımı bir kez ve 2. adımı çalıştırması gerekir . Bununla birlikte, eğer parametre üçgen bir sayı ise, o zaman 2. adım asla çalışmaz, bu yüzden bir adımı çıkarmamız gerekir.


3

Python 2, 86 81 bayt

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

Çevrimiçi deneyin!

65536 test durumunu TIO'da hesaplar 0.183s.


Bu 84 byte özyinelemeli sürüm 65536 kadar tüm değerleri hesaplamak mümkün değil:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

Çevrimiçi deneyin!


2

Mathematica, 92 bayt

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

Bir tamsayı argümanı alıp bir tamsayı döndüren salt işlev.

Değişkenler ave bayakta, incelenmekte olan toplamında başlangıç ve bitiş numaraları (sürekli değişen) ise q(sayı koşarak toplam standları a+1için b); şimdiye kadar karşılaşılan ttüm değerlerin kaydını tutar q. Bu değişkenleri başlattıktan sonra, Fordöngü If[q<#,q+=++b,q-=++a], sonuna yeni bir sayı ekleyen veya qgirdiye eşit olana kadar spec tarafından belirtildiği şekilde öndeki sayıyı çıkaran yürütmeye devam eder .

Şimdi adım adım sayısını , yol boyunca karşılaşılan değerlerin tlistesini çıkarmak zorundayız q. Girişi olduğunda Örneğin 11, Fordöngü ile çıkar teşit {0,1,3,6,10,15,14,12,9,15,11}. Bundan atılan adım sayısını hesaplamak için bulduğum en iyi yol, farklılıkların aşağıdan aşağıya doğru kaç kez değiştiğini saymak; Ayrıntılı komutun Length@Split@Sign@Differences@tyaptığı budur, ancak geliştirilebileceğinden şüpheleniyorum.


2

C (tcc), 71 bayt (61 + 10)

Komut satırı argümanları (boşluk dahil):

-Dw=while

Kaynak:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

Nasıl çalışır:

cadım sayısını sayar. mve Maralığın minimum ve maksimumunu s, toplamı saklayın . Başlangıçta, hepsi sıfır.

Sürekli colarak artmakta ve skarşılaştırılmaktadır n. Eşit olmadıkları sürece:

  • Eğer ctek, sonra sürece s<n, aralığının sonuna kadar bir tamsayıyı ekleyin: artış Mbiri tarafından sgöre M.

  • Eğer csürece bile, daha sonra s>n, aralık başından itibaren bir tamsayı kaldırın: azalma sile m, ve artırmak mbirer.

Döngü çıktığında, cçok fazla artmıştır. Bunun azaltılması doğru sonucu verir ve dönüş değeri olarak hareket etmek için doğru kayıtta hesaplanır.

Eğlenceliydi, Khaled.K'nın C cevabı ile aynı değişken isimleri kullanıyor . Kopyalanmadılar.


1

Perl 6 , 114 bayt

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(daha önceki bir Haskell uygulamasından ilham aldı )

Deneyin
Bilgisayarımda 45 saniyenin altında bir 65536 girişiyle çalışıyor, ancak TIO.run ile 60 saniyenin altında çalışmasını sağlayamadım.
Rakudo v2017.04 + var, burada v2017.01 var .
Rakudo / NQP / MoarVM neredeyse her gün optimizasyonlar alıyor, bu nedenle aradan zaman içinde almak için gereken herhangi bir sayı olabilir.


Expanded

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Rakudo'nun, Range.sumtüm değerleri tekrar etmesi gerekmeyecek bir optimizasyona sahip olduğunu unutmayın .

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.