Tüm Farklı Gozinta Zincirlerini Bul


36

Gozinta Zincirleri

( Project Euler # 606'dan ilham alındı )

N için bir gozinta zinciri, {1,a,b,...,n}her elemanın bir sonrakini uygun şekilde böldüğü bir sekanstır . Örneğin, 12 için sekiz ayrı gozinta zinciri vardır:

{1,12}, {1,2,12}, {1,2,4,12}, {1,2,6,12}, {1,3,12}, {1,3,6,12}, {1,4,12} and {1,6,12}.

Meydan okuma

Pozitif bir tamsayı ( n > 1) kabul eden ve verilen sayı için tüm farklı gozinta zincirlerini çıkaran veya veren bir program veya işlev yazın .

  1. Zincirlerdeki düzen önemlidir (artan), zincirlerin sırası olmaz.
  2. Var olma ihtimali üzerine, sorunu çözen bir yerleşik kullanamazsınız.
  3. Bu .

Düzenleme: 1Potansiyel bir giriş olarak kaldırma .


4
PPCG'ye Hoşgeldiniz. Güzel ilk soru!
AdmBorkBork

5
"Off-
Chance'de

3
Yalnızca bir sebebi istiyorsanız - AdmBorkBork dediği gibi, kenar kılıfı genellikle zorluk çekirdek için önemli olan yalnızca eklenir [[1]]ı eğer söyleyebilirim [1,1]bir gozinta olan 1o [1,1,12]bir gozinta olduğu 12gibi [1,1,1,12]ve şimdi biz artık "hepsini geri al ..."
Jonathan Allan

4
Sorunu, bilmeyenler için netleştirmelisiniz. 2|4"iki dördüncü" aka "iki gozinta dördüncü" olarak okunur.
mbomb007

1
Sanal alanın çalışması için iki buçuk saat yeterli değildir. Sandbox SSS bölümüne bakın .
Peter Taylor

Yanıtlar:


10

Python 3 , 68 65 bayt

Düzenleme: @notjagan sayesinde -3 bayt

f=lambda x:[y+[x]for k in range(1,x)if x%k<1for y in f(k)]or[[x]]

Çevrimiçi deneyin!

açıklama

Her bir gozinta zinciri , zincirin sonundaki sayıdan oluşur xve solunda en az bir bölen bulunur. Her bölen için kbir xzincir [1,...,k,x]farklıdır. Bu nedenle her bölen için olabilir konun ayrı tamamı gozinta zincirleri ve ekleme yapılması xtüm farklı olsun, onlara sonuna kadar gozinta zincirleri ile kdoğrudan solunda x. Kadar bu yinelemeli yapılır x = 1nerede [[1]]döndürülen tüm olarak, gozinta zincirleri 1 ile başlar tekrarlama dibe yani.

Çift yinelemeye izin veren Python listesinin anlaşılması nedeniyle kod çok kısa oluyor. Bu, bulunan değerlerin f(k), tüm farklı bölenler için aynı listeye eklenebileceği anlamına gelir k.


bunu yapmaya çalışıyordu, şimdi çok geç = /
Rod,

3
Bu cevap şimdiye kadar diğerlerine kıyasla inanılmaz derecede hızlı.
ajc2000

-3 gereksiz bayt paketini kaldırarak kaldırarak.
notjagan,

7

Kabuğu , 13 bayt

ufo=ḣ⁰…ġ¦ΣṖḣ⁰

H.PWiz'inkine biraz farklı bir yaklaşım olsa da, yine de kaba bir güçle. Çevrimiçi deneyin!

açıklama

Temel fikir, tüm alt dizilerini birleştirmek [1,...,n]ve sonucu, her bir öğenin bir diğerini böldüğü alt listelere bölmektir. Bunlardan başlıyor 1, bitiyor nve kopya içermeyenleri saklıyoruz. Bu yerleşik "rangify" ile yapılır . Daha sonra kopyaları atmak için kalır.

ufo=ḣ⁰…ġ¦ΣṖḣ⁰  Input is n=12.
           ḣ⁰  Range from 1: [1,2,..,12]
          Ṗ    Powerset: [[],[1],[2],[1,2],[3],..,[1,2,..,12]]
         Σ     Concatenate: [1,2,1,2,3,..,1,2,..,12]
       ġ¦      Split into slices where each number divides next: [[1,2],[1,2],[3],..,[12]]
 fo            Filter by
      …        rangified
   =ḣ⁰         equals [1,...,n].
u              Remove duplicates.

Her sayının diğerini böldüğü güç kümesindeki dizilere filtre uygulamanın daha kısa olmadığını tahmin ediyorum?
ETHProductions

@ETHproductions Hayır, bu bir bayt daha uzun .
Zgarb

5

Jöle , 9 8 bayt

ÆḌ߀Ẏ;€ȯ

Çevrimiçi deneyin!

Japt cevabına benzer bir teknik kullanır ve bu nedenle daha büyük test durumlarında çok hızlı bir şekilde çalışır.

Nasıl çalışır

ÆḌ߀Ẏ;€ȯ    Main link. Argument: n (integer)
ÆḌ          Yield the proper divisors of n.
       ȯ    If there are no divisors, return n. Only happens when n is 1.
  ߀        Otherwise, run each divisor through this link again. Yields
            a list of lists of Gozinta chains.
    Ẏ       Tighten; bring each chain into the main list.
     ;€     Append n to each chain.

4

Mathematica, 77 bayt

FindPath[Graph@Cases[Divisors@#~Subsets~{2},{m_,n_}/;m∣n:>m->n],1,#,#,All]&

GraphKöşelerin Divisorsgirişin #olduğu ve kenarların uygun bölünebilirliği temsil ettiği formlar , daha sonra Alltepe 1noktasından tepe noktasına giden yolları bulur #.


1
Woah, bu çok zekice!
JungHwan Min

3

Jöle , 12 bayt

ŒPµḍ2\×ISµÐṀ

Bir tamsayıyı kabul eden ve tamsayı listelerinin bir listesini döndüren monadik bir bağlantı.

Çevrimiçi deneyin!

Nasıl?

Bir ile N arasındaki tüm dizilmiş benzersiz tamsayı listelerini istiyoruz, öyle ki ilki birincisi, sonuncusu N'dir ve tüm çiftler bölünür. Kod, bu bilgiyi çiftli bölme ölçütlerinin, söz konusu aralığın güç setine göre karşılandığını kontrol ederek elde eder, ancak yalnızca maksimum artışlı fark toplamına sahip olanları seçerek (hem bir ile başlayan hem de N ile olacak artan N-1 farklılıklarının toplamı, diğerleri daha az olacaktır).

ŒPµḍ2\×ISµÐṀ - Link: number N
ŒP           - power-set (implicit range of input) = [[1],[2],...,[N],[1,2],[1,3],...,[1,N],[1,2,3],...]
          ÐṀ - filter keep those for which the result of the link to the left is maximal:
  µ      µ   - (a monadic chain)
    2\       -   pairwise overlapping reduce with:
   ḍ         -     divides? (1 if so, 0 otherwise)
       I     -   increments  e.g. for [1,2,4,12] -> [2-1,4-2,12-4] = [1,2,8]
      ×      -   multiply (vectorises) (no effect if all divide,
             -                          otherwise at least one gets set to 0)
        S    -   sum         e.g. for [1,2,4,12] -> 1+2+8 = 11 (=12-1)

Akıllıca örtüşen azalma azaltmak bekleyin? : o nasıl görmemiştim: PI kullanıyordu <slice>2<divisible>\<each>: P
HyperNeutrino 15:17 '

Jelly'in hızlılarındaki en yeni değişikliği kullanarak, 11 baytƝ için `2` yerine kullanabilirsiniz .
Bay Xcoder

3

Japt , 17 bayt

⬣ßX m+S+UR÷ª'1

Çevrimiçi test edin!

Tuhaf bir şekilde, çıktının bir dizge olarak üretilmesi, dizilerin dizisi olarak oluşturulmasından çok daha kolaydı ...

açıklama

 ⬠£  ßX m+S+URà ·  ª '1
Uâq mX{ßX m+S+UR} qR ||'1   Ungolfed
                            Implicit: U = input number, R = newline, S = space
Uâ                          Find all divisors of U,
  q                           leaving out U itself.
    mX{         }           Map each divisor X to
       ßX                     The divisor chains of X (literally "run the program on X")
          m    R              with each chain mapped to
           +S+U                 the chain, plus a space, plus U.
                  qR        Join on newlines.
                     ||     If the result is empty (only happens when there are no factors, i.e. U == 1)
                       '1     return the string "1".
                            Otherwise, return the generated string.
                            Implicit: output result of last expression

Öyleyse yaklaşımınız geçersiz zincirler üretmekten kaçınıyor, sonra diğer yaklaşımlar gibi onları filtreliyor mu?
Şemsiye

@ Şemsiye Hayır, sadece geçerli olanları, bir seferde bir bölen üretir, bu nedenle neden 12000 :-) gibi durumlarda bile yıldırım hızında çalıştığını
öğrenir

Özyinelemenin çok güzel kullanımı :) Ve ben bu ¬numarayı kullanıyorum! : p
Shaggy

@Shaggy ¬, temelde "X, hiçbir argüman vermeyen veya Y'nin bir gerçeğe aykırı argüman verdiği" işlevlerini yerine getirme nedenlerimden biri: P
ETHproductions

3

Mathematica, 60 bayt

Cases[Subsets@Divisors@#,x:{1,___,#}/;Divisible@@Reverse@{x}]&

Kullanımları belgesiz çok arg formu Divisible, Divisible[n1,n2,...]döner Trueeğer n2∣n1, n3∣n2vb, ve Falseaksi. Hepimiz almak Subsetslistesinin Divisorsgirişinin #ardından dönüş Casesformun {1,___,#}böyle Divisibleverir Trueiçin Reversebölenler d dizisi.


Peki, Divisibletemelde bir gozinta zincirini doğrulamak için bir yerleşik mi?
Şemsiye

@ Şemsiye Uygun bölünme olup olmadığını kontrol etmez.
ngenis

3

Haskell, 51 bayt

f 1=[[1]]
f n=[g++[n]|k<-[1..n-1],n`mod`k<1,g<-f k]

Özyinelemeyle uygun bölenlerin gozinta zincirlerini bulun ve ekleyin n.

Çevrimiçi deneyin!


Doğru işlem için ekstra kredi olması gerektiğini düşünüyorum 1. Toplu olarak muaf tutulduğumuza göre 1, bu davayı kaldırarak 10 bayt tasarruf edebilir misiniz?
Şemsiye

@Şemsiye 1bu algoritma için özel bir durum değildir, özyineleme için temel durum olarak gereklidir. Kendi başına, ikinci tanımlayıcı denklem yalnızca boş listeye geri dönebilir.
Christian Sievers

Anlıyorum. Benim çözümüm (henüz gönderilmemiş) [[1]]bir üs olarak da kullanır .
Şemsiye

3

Haskell (Lambdabot), 92 85 bayt

x#y|x==y=[[x]]|1>0=(guard(mod x y<1)>>(y:).map(y*)<$>div x y#2)++x#(y+1)
map(1:).(#2)

İhtiyaç duyulması guardgereken Lambdabot Haskell'e ihtiyacı var Control.Monad. Ana işlev, bana izin verilen ve birkaç baytlık tıraş ettiğim anonim bir işlevdir.

Yedi byte tasarruf için Laikoni'ye teşekkürler.

Açıklama:

Monadlar çok kullanışlı.

x # y

Bu, asıl işi yapan özyinelemeli fonksiyonumuzdur. xbiriktirdiğimiz sayı (değerde kalan bölenlerin ürünü) ve ybuna ayırmayı denememiz gereken bir sonraki sayıdır.

 | x == y = [[x]]

Eğer xeşittir yo zaman bitti recursing konum. Sadece xmevcut gozinta zincirinin sonu olarak kullanın ve iade edin.

 | 1 > 0 =

"True" için Haskell golf sahası. Yani, bu varsayılan durumdur.

(guard (mod x y < 1) >>

Şimdi liste monadında çalışıyoruz. Liste monad içinde, aynı anda birden fazla seçim yapma yeteneğine sahibiz. Bu, yorgunluktan bir şeyin "mümkün olan" hepsini bulurken çok yararlıdır. guardİfadesi "bir koşul doğruysa yalnızca aşağıdaki seçim olarak" diyor. Bu durumda, yalnızca aşağıdaki seçim olarak yböler x.

(y:) . map (y *) <$> div x y#2)

Eğer ybölünmeyi yapar x, biz ekleme seçeneğine sahip ygozinta zincirine. Bu durumda, tekrar tekrar çağırıp (#), eşittir y = 2ile başlayarak , zincire yeni eklediğimiz "çarpanı" bulmak istedik. Daha sonra, bu özyinelemeli çağrının sonucu ne olursa olsun, bizim değerlerimizi sadece çarpanlara katlayın ve gozinta zincirine resmi olarak ekleyin .xx / yyyy

++

Aşağıdaki seçimi de göz önünde bulundurun. Bu sadece iki listeyi bir araya getirir, ancak tek taraflı olarak "bu şeyi yapmaktan başka bir şey arasında seçim yapmak" diyerek düşünebiliriz.

x # (y + 1)

Diğer seçenek ise sadece özyinelemeye devam etmek ve değeri kullanmamaktır y. Eğer ybölmek yok xo zaman bu tek seçenektir. Eğer ybölme yaparsa , xbu seçenek diğer seçeneklerin yanı sıra alınacak ve sonuçlar birleştirilecektir.

map (1 :) . (# 2)

Bu ana gozinta işlevidir. (#)Argümanını arayarak özyinelemeye başlar . A 1, her gozinta zincirine hazırlanmıştır, çünkü (#)fonksiyon hiçbir zaman zincirleri içine koyar.


1
Harika bir açıklama! Desen korumalarını hepsini bir satıra yerleştirerek bazı baytları kaydedebilirsiniz. mod x y==0kısaltılabilir mod x y<1. İsimsiz fonksiyonlara izin verildiğinden, ana fonksiyonunuz olarak işaretsiz olarak yazılabilir map(1:).(#2).
Laikoni

3

Haskell, 107 100 95 bayt

f n=until(all(<2).map head)(>>=h)[[n]]
h l@(x:_)|x<2=[l]|1<2=map(:l)$filter((<1).mod x)[1..x-1]

Belki daha iyi bir fesih koşulu vardır

f n=i[[n]]
i x|g x==x=x|1<2=i$g x
g=(>>=h)

ama daha uzun). 1Fırçalama tekrarı 1veya kopyaları ( içeri nubgirmiyor Prelude) daha fazla bayt olduğu için kontrol daha mantıklı görünüyor .

Çevrimiçi deneyin.


3
(>>=h)için(concatMap h)
Michael Klein


Vay canına, benim için aptal u...
Leif Willerts

3

JavaScript (Firefox 30-57), 73 bayt

f=n=>n>1?[for(i of Array(n).keys())if(n%i<1)for(j of f(i))[...j,n]]:[[1]]

Uygun n%0<1şekilde yanlıştır.


2

Jöle , 17 bayt

ḊṖŒP1ppWF€ḍ2\Ạ$Ðf

Çevrimiçi deneyin!


Bu etkileyici hızlıydı. 1Yine de sonucun beklenmedik. İçin kesin bir sonuç bulamadım 1, ancak olduğunu sandım [[1]]. [1,1]Diğer tüm sonuçların sekansları arttırması dışında bunun yanlış olduğunu kesin olarak söyleyemem . Düşünceler?
Şemsiye

@Şemsiye Cevapların 1 için bir şey yapmasına izin vermek isteyebilirsin
Bay Xcoder

@Umbrella bir sorun varsa ben (replace +2 doğru yolu gösterir ;€ile ;Q¥€).
Outgolfer Erik,

2

Mathematica, 104 bayt

(S=Select)[Rest@S[Subsets@Divisors[t=#],FreeQ[#∣#2&@@@Partition[#,2,1],1>2]&],First@#==1&&Last@#==t&]&

FreeQ[...]olabilirAnd@@BlockMap[#∣#2&@@#&,#,2,1]
JungHwan Min

çok hoş! ama ben ekstra bir mesaj alıyorum DeveloperPartitionMap :: nlen: - Mesaj metni bulunamadı - >> `neden bu?
J42161217

BlockMapDeveloper`PartitionMapişlevi dahili olarak kullanır , ancak bir geliştirici işlevi olduğundan, hiçbir hata mesajı yoktur. Hata, 2 bölümleme yapamayacağınız 1 veya 0 öğelere sahip listelerden kaynaklanır.
JungHwan Min

2

Mathematica, 72 bayt

Cases[Subsets@Divisors@#,{1,___,#}?(And@@BlockMap[#∣#2&@@#&,#,2,1]&)]&

açıklama

Divisors@#

Girişin tüm bölenlerini bulun.

Subsets@ ...

Bu listenin tüm alt kümelerini oluşturun.

Cases[ ... ]

Desene uyan tüm davaları seçin ...

{1,___,#}

1 ile başlayıp <input>... ile bitecek ...

?( ... )

ve durumu tatmin ediyor ...

And@@BlockMap[#∣#2&@@#&,#,2,1]&

Soldaki öğe, listedeki tüm 2 bölümler için sağdaki öğeyi ayırır, ofset 1.


2

TI-BASIC, 76 bayt

Input N
1→L1(1
Repeat Ans=2
While Ans<N
2Ans→L1(1+dim(L1
End
If Ans=N:Disp L1
dim(L1)-1→dim(L1
L1(Ans)+L1(Ans-(Ans>1→L1(Ans
End

açıklama

Input N                       Prompt user for N.
1→L1(1                        Initialize L1 to {1}, and also set Ans to 1.

Repeat Ans=2                  Loop until Ans is 2.
                              At this point in the loop, Ans holds the
                              last element of L1.

While Ans<N                   While the last element is less than N,
2Ans→L1(1+dim(L1              extend the list with twice that value.
End

If Ans=N:Disp L1              If the last element is N, display the list.

dim(L1)-1→dim(L1              Remove the last element, and place the new
                              list size in Ans.

L1(Ans)+L1(Ans-(Ans>1→L1(Ans  Add the second-to-last element to the last
                              element, thereby advancing to the next
                              multiple of the second-to-last element.
                              Avoid erroring when only one element remains
                              by adding the last element to itself.

End                           When the 1 is added to itself, stop looping.

Ans> 1 onayını ve döngü koşulunu kaldırarak, incelikle yerine bir hatayla çıkmasına izin verilirse, 5 bayt daha kaydedebilirim. Ama buna izin verildiğinden emin değilim.


Bunu hesap makinene yazdın mı? Çünkü bu beklenmedik ve biraz etkileyici.
Şemsiye

Evet! TI-BASIC ile ilgili en zor kısım yalnızca global değişkenler olduğudur, bu yüzden listeyi kendimi özyineleme yığını olarak kullanmak zorunda kaldım.
calc84maniac

2

Mathematica 86 77 Bayt

Select[Subsets@Divisors@#~Cases~{1,___,#},And@@BlockMap[#∣#2&@@#&,#,2,1]&]&

Tanım tarafından kaba kuvvet.

Bir listenin ikili sıralı eleman karşılaştırmasını yapmanın daha kısa bir yolu olsaydı.

9 bayt tasarruf önerileri için @Jenny_mathy ve @JungHwanMin için teşekkürler


1
FreeQ[#∣#2&@@@Partition[#,2,1],1>2]&]82 bayta gitmek için (ikinci argüman olarak kullanabilirsiniz )
J42161217

@Jenny_mathy Ya da daha iyisi,And@@BlockMap[#∣#2&@@#&,#,2,1]
JungHwan Min


0

PHP 147 141

Yedekli bir testi kaldırmak için düzenlendi

function g($i){$r=[[1]];for($j=2;$j<=$i;$j++)foreach($r as$c)if($j%end($c)<1&&$c[]=$j)$r[]=$c;foreach($r as$c)end($c)<$i?0:$R[]=$c;return$R;}

Açıklaması:

function g($i) {

15 adet kazan plakası :(

    $r = [[1]];

[[1]]Her zincir 1 ile başlayan sonucu ayarlanan sonucu girin . Bu aynı zamanda bir giriş olarak 1 için destek sağlar.

    for ($j = 2; $j <= $i; $j++) {
        foreach ($r as $c) {
            if ($j % end($c) < 1) {
                $c[] = $j;
                $r[] = $c;
            }
        }
    }

2'ye kadar her numara için $i, mevcut sayısına göre bizim sette her zincirini genişletmek için gidiyoruz eğer o gozinta , o zaman, bizim sonuç grubuyla genişletilmiş zincir ekleyin.

    foreach ($r as $c) {
        end($c) < $i ? 0 : $R[] = $c;
    }

Başaramayan zincirlerimizi filtreleyin $i

    return $R;
}

10 adet kazan plakası :(


-1

Mathematica

f[1] = {{1}};
f[n_] := f[n] = Append[n] /@ Apply[Join, Map[f, Most@Divisors@n]]

Ek aramalar için cevap önbelleğe alınır.


1
Siteye Hoşgeldiniz! Bu bir kod golfüdür, bu nedenle bayt sayınızı da eklemelisiniz ve ek olarak bazı boş alanlarınızı kaldırmaya çalışmalısınız.
Buğday Sihirbazı
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.