En Kısa Ek Zincir


23

Bir ilave zinciri, 1 ile başlayan bir tamsayı dizisidir; burada ilk 1 dışındaki her tamsayı, önceki iki tamsayının toplamıdır.

Örneğin, işte bir ek zinciri:

[1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

İşte onu bir ek zincir yapan miktarlar:

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
3 + 4 = 7
1 + 7 = 8
8 + 8 = 16
16 + 16 = 32
7 + 32 = 39
32 + 39 = 71

Bu zorlukta size pozitif bir tamsayı verilecek nve sonuçta en kısa ekleme zincirlerinden birini vermelisiniz n.

Örnekler - birçok olası çıktı bulunduğuna dikkat edin, bulmanız gereken tek şey, sadece kısa olan bir ekleme zinciridir:

1: [1]
2: [1, 2]
3: [1, 2, 3]
4: [1, 2, 4]
5: [1, 2, 3, 5]
6: [1, 2, 3, 6]
7: [1, 2, 3, 4, 7]
11: [1, 2, 3, 4, 7, 11]
15: [1, 2, 3, 5, 10, 15]
19: [1, 2, 3, 4, 8, 11, 19]
29: [1, 2, 3, 4, 7, 11, 18, 29]
47: [1, 2, 3, 4, 7, 10, 20, 27, 47]
71: [1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

Standart G / Ç kuralları vb. Standart Loopholes yasaklandı. Code golf: En az bayt kazanır.




1
Zinciri ters sırayla çıkarmamıza izin var mı?
Arnauld,

@Arnauld Hayır, bu özel sipariş.
isaacg

Yanıtlar:


6

Haskell , 57 bayt

c=[1]:[x++[a+b]|x<-c,a<-x,b<-x]
f n=[x|x<-c,last x==n]!!0

Bir kaba kuvvet çözümü. Çevrimiçi deneyin!

açıklama

Sonsuz liste c, uzunluğa göre sıralanmış tüm ekleme zincirlerini içerir. Bu liste alarak, kendi açısından indüktif tanımlandığı xgelen cve iki elemanları x, ve bunların toplamı ekleme x. Fonksiyon , istenen numara ile biten filk listeyi bulur c.

c=            -- c is the list of lists
 [1]:         -- containing [1] and
 [x           -- each list x
  ++[a+b]     -- extended with a+b
 |x<-c,       -- where x is drawn from c,
  a<-x,       -- a is drawn from x and
  b<-x]       -- b is drawn from x.
f n=          -- f on input n is:
 [x           -- take list of those lists x
 |x<-c,       -- where x is drawn from c and
  last x==n]  -- x ends with n,
 !!0          -- return its first element.

4

Brachylog , 14 bayt

∧≜;1{j⊇Ċ+}ᵃ⁽?∋

Çevrimiçi deneyin!

Doğru argümanı içeren bir zincir bulunduğunda durma, yinelemeli derinleştirme kullanarak tüm olası ekleme zincirlerini oluşturan bir kaba kuvvet başvurusu. Çoğu Brachylog gönderiminin aksine, bu, sağ argümanıyla giriş yapan (geleneksel olarak Çıktı olarak adlandırılır) ve sol argümanıyla (geleneksel olarak Giriş olarak adlandırılır) çıkan bir işlev sunumu; bunu yapmak biraz tartışmalıdır, ancak konuyla ilgili en yüksek oyu alan meta cevabı yasal olduğunu söylemektedir (ve bunu yapmak, fonksiyonlar için normal G / Ç varsayılan ayarlarımızla tutarlıdır). Girdi ve çıktıyı daha geleneksel bir şekilde kullanırsak, bu 16 bayt olacaktır (∧≜;1{j⊇Ċ+}ᵃ⁽.∋?∧çünkü programın sağ tarafı örtük kısıtlamayı kullanamayacaktı (bu nedenle, bu engellilere ve 2 bayt pahasına verilen yeni bir açık kısıtlamaya ihtiyaç duyacaktır).

açıklama

∧≜;1{j⊇Ċ+}ᵃ⁽?∋
∧               Disable implicit constraint to read the left argument
 ≜;        ⁽    Evaluation order hint: minimize number of iterations
    {    }ᵃ     Repeatedly run the following:
   1      ᵃ       From {1 on the first iteration, results seen so far otherwise}
     j            Make {two} copies of each list element
      ⊇           Find a subset of the elements
       Ċ          which has size 2
        +         and which sums to {the new result for the next iteration}
             ∋    If the list of results seen so far contains {the right argument}
            ?     Output it via the left argument {then terminate}

Buradaki ilginç bir incelik, ilk yinelemede olan, girişin diğer yinelemeler gibi bir listeden çok bir sayı olduğu; 1 rakamıyla başlıyoruz, her rakamın iki kopyasını çıkarıyoruz (11 rakamını alıyoruz), sonra 2 rakamlı bir sonucunu buluyoruz (ayrıca 11 rakamını). Sonra 2 olan rakam toplamını alırız ve bu şekilde sıra [1,2]bizim istediğimiz gibi başlar . Gelecekteki tekrarlamalar, biz böyle bir liste ile başlıyoruz [1,2]bunu iki katına [1,2,1,2](daha sonra iki eleman altdizisi alarak [1,1], [1,2], [2,1], veya [2,2]); açıkça, bunların her birinin toplamı, ekleme zincirinin sonraki unsurları geçerli olacaktır.

Burada değerlendirme sırası ipucuna ihtiyaç duyulması biraz sinir bozucu, özellikle de bileşen ( değerlendirme sırası ipucunu varsayılan olarak dışarıdan değil içeriden alır , dolayısıyla konuyu zorlamak için oldukça kaba kullanım gibi görünüyor ).


Bu zorluğun üstesinden gelmenin kısa bir yolunu bulmak için yaklaşık 30 dakika çalıştım. Benim çözümüm bundan daha uzundu.
17'de ölümle sonuçlandı

1
@Fatalize: nadiren ortaya çıkan yerleşiklerden biridir, ancak ihtiyaç duyduğunuzda, diğer kontrol yapılarını kullanarak uygulamanın uzaktan kısa ve öz bir yolu olmadığı için gerçekten ihtiyacınız vardır. Bunun bir meydan okuma olduğunu anladığımda , gerisi doğrudan oradan geldi.

2

Jöle , 17 bayt

’ŒP;€µ+þ;1Fḟ@µÐḟḢ

Üstel zamandaki sözlükbilimsel ilk çözümü çıkarır.

Çevrimiçi deneyin!

Nasıl çalışır

’ŒP;€µ+þ;1Fḟ@µÐḟḢ  Main link. Argument: n (integer)

’                  Decrement; n-1.
 ŒP                Powerset; generate all subarrays of [1, ..., n-1], sorted first
                   by length, then lexicographically.
   ;€              Append n to all generate subarrays.
     µ       µÐḟ   Filterfalse; keep only subarrays for which the chain between the
                   two chain separators (µ) returns a falsy value.
     µ             Monadic chain. Argument: A (array of integers)
      +þ               Add table; compute the sums of all pairs of elements in x,
                       grouping the results by the right addend.
        ;1             Append 1 to the resulting 2D array.
          F            Flatten the result.
           ḟ@          Filterfalse swapped; remove all elements of A that appear in
                       the result. This yields an empty list for addition chains.
                Ḣ  Head; select the first result.

2

JavaScript (ES6), 83 86 bayt

Düzenleme: Listeyi ters sırada yapmamak için düzeltildi.

n=>(g=(s,a=[1])=>s-n?s>n||a.map(v=>g(v+=s,a.concat(v))):r=1/r|r[a.length]?a:r)(r=1)&&r

gösteri


2

PHP, 195 Bayt

function p($a){global$argn,$r;if(!$r||$a<$r)if(end($a)==$argn)$r=$a;else foreach($a as$x)foreach($a as$y)in_array($w=$x+$y,$a)||$w>$argn||$w<=max($a)?:p(array_merge($a,[$w]));}p([1]);print_r($r);

Çevrimiçi deneyin!


Ne yazık ki bu algoritma, örneğin 15 için optimal cevaplar vermez.
Neil

@Neil şimdi daha uzun ama çalışıyor. Her iki yoldan hangisinin doğru olduğuna nasıl karar verileceğine dair bir fikrim yok. Belki asal sayısının bir rolü vardır
Jörg Hülsermann

bu kod 149 testi geçemez. Uzunluk 10, 11 değil
J42161217

@Jenny_mathy Düzeltildi
Jörg Hülsermann

1

Mathematica, 140 bayt

t={};s={1};(Do[While[Last@s!=#,s={1};While[Last@s<#,AppendTo[s,RandomChoice@s+Last@s]]];t~AppendTo~s;s={1},10^4];First@SortBy[t,Length@#&])&

.

Her çalıştırdığınızda farklı bir en kısa ekleme zinciri üretir

Çevrimiçi deneyin
, kodu ctrl + v ile yapıştırın, giriş kodunu sonuna yerleştiriniz, yani [71] ve shift + enter tuşlarına basınız.


Mathematica'ya erişimim olmadığından, bu giriş 15 için ne kadar zincir veriyor?
Neil,

doğru olanı {1, 2, 3, 5, 10, 15}
J42161217

3
149 girişi için programınızdan 11 uzunluğunda bir zincir aldım, ancak 10 ( [1,2,4,5,9,18,36,72,77,149]) uzunluğunda bir tane var . Programınız rasgele örnekleme kullanıyor gibi görünüyor ve en uygun çözümü bulmak için garanti edilmiyor.
Zgarb

sabit! ancak daha uzun sürer
J42161217

1

Pyth, 13 bayt

h-DsM^N2/#QyS

Test odası

Sözlükbilimsel olarak en kısa ilk zinciri verir. Oldukça yavaş, ama o kadar da kötü değil - 19pypy kullanarak yaklaşık 30 saniye içinde tamamlanıyor.

@ Dennis'in çözümünden bazı fikirler.

Bunu gerçekten sevdim - bir sürü temiz numara var.

Açıklama:

h-DsM^N2/#QyS
h-DsM^N2/#QySQ    Implicit variable introduction
            SQ    Inclusive range, 1 to input.
           y      Subsets - all subsets of the input, sorted by length then lexicographically
                  Only sorted subsets will be generated.
                  Our addition chain will be one of these.
        /#Q       Filter for presence of the input.
  D               Order by
 -                What's left after we remove
     ^N2          All pairs of numbers in the input
   sM             Summed
h                 Output the list that got sorted to the front.

Bunu anlamak biraz zor, ama biraz daha ayrıntılı olarak açıklamama izin ver.

ySQTüm muhtemel emir alt kümelerini [1, 2, ... Q], artan beden sırasına göre vererek başlıyoruz . En kısa ekleme zinciri kesinlikle bunlardan biri, ancak onu bulmamız gerekiyor.

Yapacağımız ilk şey, listeyi yalnızca a içeren listeleri tutmak için filtrelemek Q. Bunu birlikte yapıyoruz /#Q.

Sonra, belirli bir işlevin sonucunu çıkardıktan sonra kalanları listeye göre sıralarız. -Dbir şeyi çıkardıktan sonra kalanları sipariş eder.

Kaldırdığımız şey sM^N2, Nşeyleri çıkardığımız liste nerede . ^N2Kartezyen ürününü Niki elementin olası çiftleriyle birlikte verir N. sMsonra çiftlerin her birini toplar.

Bu kaldırma işlemini yaptıktan sonra mümkün olan en küçük sonuç nedir? Giriş listesindeki en küçük öğe kesinlikle kalacaktır, çünkü tüm sayılar pozitifdir, bu nedenle iki sayının toplamı en küçük sayıdan büyük olacaktır. Ve en az bir sayı olacak çünkü girişin listede bulunduğunu kontrol ettik. Bu nedenle, mümkün olan en küçük sonuç, en küçük sayı hariç her sayı listedeki diğer iki sayıların toplamı ve listedeki en küçük sayı 1 olduğunda olacaktır [1]. Bu durumda, sıralama anahtarı olacaktır . Bu gereklilikler listenin bir ek zincir olması gerektiği anlamına gelir.

Bu yüzden ekleme zincirlerini öne doğru sıralarız. yAltkümelerini, büyüklük sırasına göre verdiğini unutmayın , bu nedenle öne doğru sıralanan listenin en kısa ekleme zincirlerinden biri olması gerekir. ho listeyi seçer.

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.