N'nin tüm çarpımsal bölümlerini listele


28

Pozitif bir sayı Verilen n tüm farklı çarpımsal bölümleri, çıkış n herhangi uygun bir biçimde.

Bir çarpımsal bölümü n kendi ürünü olduğunu bir tamsayılar kümesi, birden bütün büyüktür, şekildedir n . Örneğin, 20 aşağıdaki farklı çarpma bölümlerine sahiptir:

2 * 2 * 5
2 * 10
4 * 5
20

Düzen önemli değil 2 * 2 * 5, aynı bölümdür 2 * 5 * 2.


Örnekler:

1 -> {}
2 -> {2}
4 -> {2, 2}, {4}
20 -> {2, 2, 5}, {2, 10}, {4, 5}, {20}
84 -> {2, 2, 3, 7}, {2, 2, 21}, {2, 14, 3}, {2, 6, 7}, {2, 42}, {4, 3, 7}, {28, 3}, {4, 21}, {6, 14}, {12, 7}, {84}


Yanıtlar:


6

Brachylog , 16 bayt

>~l:{1<}a.*?,.=o

Bu, girdi olarak pozitif bir sayı alan ve onun tüm çarpımsal bölümlerini üreten bir işlevdir (tam bir program değil) . (Ayrıca, bu çözümde herhangi bir ana çarpanlaştırma yerleşikini kullanmaktan da kaçınıldım, çünkü çoğunlukla yardım edeceklerinden emin değildim; bir noktada da daha yoğun bir çözüm deneyebilirim.)

Çevrimiçi deneyin! (Tam bir program haline getirmek için buradaki fonksiyonun etrafına ekstra kod eklenmiştir; yukarıda gösterilen fonksiyonu doğrudan TIO'ya verirseniz, işlevi çalıştıracak ancak çıktısını herhangi bir yere basmayacak, bu da bir gösteri olarak işe yaramaz .)

Bu program beni gerçekten hayal kırıklığına uğratıyor, çünkü çoğu Brachylog yorumlayıcısındaki hatalar üzerinde çalışıyor ve spesifikasyondaki problemleri gerçekten çözüyor; ama tercüman budur. (Böyle bir programla bile, tercüman mantıklı olması gerekenden çok daha fazla hafıza kullanır ve hafıza tükenmesi nedeniyle çöker, ancak neyse ki ilk önce istenen çıktıyı üretmeyi başardığı küçük problemler üzerine.) Varsayımsal bir "mükemmel Brachylog sürümü" sadece ~*.o.:{>1}a,4 byte daha kısa olan bir yazı yazabilirsiniz , ancak tercümana biraz yardımcı olmak için ekstra kısıtlamalar eklemeliydim. (Brachylog’dan pek hoşlanmıyorum ve Prolog’a sadık kalmayı tercih ediyorum, ancak programın çalışması için benzer ipuçlarına ihtiyaç vardı ve yazmaları çok daha uzun sürdü. Öyleyse Brachylog öyle.)

Açıklama:

Her zamanki gibi, bir Brachylog programı bir dizi kısıtlamadır; Varsayılan olarak, ilk kısıtlama girişi bir bilinmeyen ( A olarak adlandırırım ), ancak ikinci kısıtlama A'yı ikinci bir bilinmeyen B'ye karşı vb. sınırlar. Gibi bazı karakterler {}bu genel akışı değiştirebilir, bu yüzden bilinmeyenleri iç içe yüklemlerde göstermek için farklı bir harf kümesi (örneğin X / Y ) kullanırım.

>       A is smaller than the input
~l      B has length A
  1<    X is 1, Y is larger
:{1<}a  For each element X of B, it corresponds to an element Y of C
.       C, the output, and D are all identical
*       E is the product of D's elements
?       E, the input, and F are all identical
,       There's no constraint between F and G
.       G, the output, and H are all identical
=       H and I are identical, and need to be evaluated early
o       The output can be produced by sorting I

Programın nasıl çalıştığı hala belli değil, bu yüzden kısıtlamaları biraz basitleştirmeyi deneyelim. C , D , G , H ve I hepsi aynı (ve çıktıya eşit). E ve F da aynıdır (ve girişe eşittir). Yani kısıtlamalarımız buna bağlı olarak:

  • A , B'nin ve çıkışın uzunluğu ve girişten daha küçük.
  • B , tüm 1'lerden oluşur ve özellikle kullanışlı değildir (sadece mevcut Brachylog yorumlayıcısında :{1<}asınırlı bir uzunluğa sahip olmak için sol argümanına ihtiyaç duyması nedeniyle programın bir parçasıdır , ya da yorumlayıcı sonsuz bir döngüye girer).
  • Çıktı tamamen 1'den büyük sayılardan (yani karşılık gelen B öğesinden büyük ) oluşur.
  • Çıktı elemanlarının çarpımı girişe eşittir.
  • Çıkış, sıralama yaparak değişmez (yani, sıralı sıradadır).

Bu arada, açıkça çıktının tüm öğelerinin tamsayı olduğunu, gerekli görünebilecek bir şey olduğunu belirtmedim; Bununla birlikte, Brachylog'un kısıtlayıcı çözücüsü tamsayı olmayanları işleyemez, bu nedenle yalnızca tam sayıları içeren çözümleri rahatlıkla üretir.

Açıkçası, çıkış girişinin çarpımsal bölüm olduğunda gerçek olacak "çıkışının uzunluğu girişi daha küçüktür" (çünkü 2 x > x tüm negatif olmayan için x , yani pozitif 2 x ). Böylece bu kısıtlamayı göz ardı edebiliriz; Brachylog tercümanına programı değerlendirmek için çalışma stratejisi vermek yalnızca oradadır. Diğer kısıtlamalar (çıktının sıralandığı, ürününün girdi olduğu ve öğelerinin hepsinin 1'den büyük olduğu) çarpımsal bir bölümün tanımıdır ve bu nedenle bu işlev temelde sorunun doğrudan bir uygulamasıdır.


6

Brachylog 1, 14 bayt

:{$pp~c:*ao}fd

Çevrimiçi deneyin!

Brachylog 2, 11 10 bayt, dil son kullanma tarihi zorluğu

{ḋp~c×ᵐo}ᵘ

Çevrimiçi deneyin!

Maltysen, bu soruyu Pyt'un 17 baytında cevapladı, ben de soruyu tanımlamayı Brachylog'a çevirerek çalışan 16 baytlık bir Brachylog çözümü buldum. Bunu yaparken, Dennis 15 baytlık bir Jelly çözümü yazdı. Bu yüzden 14 bayta inmek zorunda kaldım. Bu, girdiyi argüman olarak alan ve tüm bölümlerin bir listesini (diğer çözümümde olduğu gibi bir jeneratör yerine) döndüren bir işlevdir .

Bu cevabı yazdıktan bir süre sonra, Dennis ve ben birlikte Jelly çözümünü 11 bayta indirmeyi başardık. Yeni bir Brachylog sürümü çıktı, terser sözdizimi; meydan okumayı yayınladı, aslında saymıyor, ancak 11 baytlık toplamı, yayınlandığı anda çok fazla yönetebiliyordu; Dilin daha sonra yapılan revizyonları (diğer zorluklardan esinlenerek) burada görüldüğü gibi 10'a kadar düşebilir. İki program aynıdır, tek fark sözdizimidir.

"Golf ilkellerini" çok fazla kullanmayan, ancak doğrudan sorunu belirttiğim diğer çözümümden farklı olarak, bu, Brachylog kısıtlamalarının tüm gücünü görmezden geliyor ve bunun yerine en iyi Jelly izlenimini yapıyor; Sol argüman zaten bilinir (ve bu nedenle kısıtlamalar, tamamen şişirilmiş kısıtlamalardan ziyade Jelly monads gibi davranır). Bu nedenle @ Maltysen'in Pyth çözümü ile aynı algoritmayı kullanır, bu muhtemelen tipik golf ilkellerini kullanarak bunu çözmenin en kolay yoludur. (İlginçtir, diğer cevabımdaki "sadece sorunu belirtin" çözümü, golf ilkellerini kullanmamasına rağmen, Brachylog tercümanındaki hatalar / eksiklikler için olmasaydı daha kısa olurdu. Bir gün "gelişmiş bir Brachylog" yazmam gerekiyor. bu tür sorunlara iyi bir çözüm bulmak için; Golf dilleri giderken, Brachylog aslında gerçekten ayrıntılı.

Program bir jeneratör ve etrafındaki bir paketleyiciden oluşur. Öncelikle, burada jeneratörün açıklaması:

$pp~c:*ao  ḋp~c×ᵐo
$p         ḋ        Prime factor decomposition of the input
  p         p       Generate all permutations
   ~c        ~c     Generate all inverse concatenations (i.e. partitions)
     :*a       ×ᵐ   Take the product of each list element in each partition
        o        o  Sort each partition

Bu neredeyse problemi çözüyor, fakat çoğu kez birçok bölüm üretiyoruz. Bu yüzden çözümleri tekilleştirmek için bir sargıya ihtiyacımız var:

:{…}fd
:{…}f     Convert generator to list
     d    Remove duplicate elements

{…}ᵘ      Convert generator to list of unique elements

Neden mevcut cevabınızı düzenlemiyorsunuz?
Downgoat

3
@Downgoat: İki cevap tamamen farklı yaklaşımlar kullanır; algoritmalar farklıdır, kullanılan dil özellikleri çoğunlukla bağımsızdır ve benzerleridir. Büyük olanı yenisiyle değiştirmek mantıklı olmaz (ve yenisini daha uzun süre olsa bile yayınlamış olabilirdim). Bu meta gönderisi , bu tür durumlarda ayrı cevaplar göndermenin tercih edildiğini gösterir.

1
Bunu biliyor musunuz bilmiyorum ama çıktıyı TIO'da bir değişken (örneğin bir büyük harf) olacak şekilde ayarlayarak çıktıyı alabilirsiniz. Örneğin .
17'de ölüm

5

Mathematica, 61 bayt

±1={{}}
±n_:=Union@@(Sort/@Append[n/#]/@±#&/@Most@Divisors@n)

(Özyinelemeli) bir tekli işleç tanımlar. ±Bölüm listesini döndüren .


Matematiğin sonunda noktalı virgül gerekmiyor mu?
Pavel,

@Pavel no, noktalı virgül yalnızca etkileşimli not defterindeki çıktıları bastırır. Buna dikkat çektiğiniz için teşekkürler, btw, sonunda yanlışlıkla bir noktalı virgül bıraktım.
Martin Ender

4

Pyth - 17 bayt

Asal çarpanlara ayırmanın tüm izinlerini alır, daha sonra her birini bölümlere ayırır ve sonra tüm bölümleri ürünlere ayırır, sonra yalnızca ayrı bölümleri korur.

{mS-*Md1s./M.p+1P

Test Takımı .


4

Python 2,70 bayt

f=lambda n,k=2,l=[]:n/k and(n%k<1)*f(n/k,k,l+[k])+f(n,k+1,l)or 1/n*[l]

Sıralanmış listelerin bir listesini çıkarır. Örneğin f(20)bir [[2, 2, 5], [2, 10], [4, 5], [20]].


Python'un yerleşik tamsayı tipinin sınırları olmadığı için, kayan nokta yanlışlıklar çok büyük girdiler için cevabı kıracağından kabul edilebilir bir çözüm değildir.
orlp

@ orlp Tamam, sonra Python 2'ye dönün.
xnor

TL; DR 998'in çok büyük bir giriş olmadığını düşünüyorum ;-) IMO daha çok gecikme süresi gibi gerçek bir kod O(n) ve Python 2 rakiplerine kıyasla daha O(n^4)stilli olabilir - f (998) bellek ya da donanımın çalışma sırasında ölmesine neden olabilir diğer algoritma ile yaklaşık 80 gün süre ile bu süre burada yakl. Sonucu elde etmek için makinemde 7 mili saniye [[2, 499], [998]]. IMO sorun daha fazla olabilir bunun için Python yukarıdaki 3 kod ... mutlu golf :-) dururN > 998RecursionError: maximum recursion depth exceeded in comparison
Dilettant

@Dilettant O(n^4)Python2 gönderimim için bile yeterli olup olmadığından emin değilim: D Test durumum 998 göz önüne alındığında, kodum 9 kez çalıştırılacak ve (n+r-1)! / r! / (n-1)!her seferinde r2'den doğrusal olarak büyüyecek olan tuple miktarını hesaplayacak ve n9 - 2 . Ama hey, en azından özyineleme sınırını değiştirmek zorunda değilsiniz ...
Yytsi

@TuukkaX Caveat: Şifreyi analiz etmedim, sadece birkaç kişi için iki aday arasında çalışma sürelerinin gelişimini inceledim ve karşılaştırdım, sonra 41'e kadar N'ye kadar yorum yaptım; tatsız durumlarda ne kadar derin sorular sorduğumu sorduğumda ... içeriye giren araştırmaların miktarı için yeterince bulanık olduğunu umarım.
Dilettant

3

Jöle , 14 13 11 bayt

Ḋx³ŒPQP=¥Ðf

Çevrimiçi deneyin!

@ Dennis'in Jelly çözümünün geliştirilebileceğinden oldukça emindim. Ne yazık ki, Brachylog rekorunu kıramadım ama bağlamayı başardım. Güncelleme : @Dennis 'yardımı ile şimdi geliştirildi; Sanırım Jelly tacı geri alıyor.

Bu program inanılmaz derecede verimsizdir, O (2 n 2 ) performansa sahiptir (bu nedenle yukarıdaki test durumu giriş 4 için gösterilmektedir). Hızlı bir şekilde 4'te tamamlanır, 5'te çok yavaş gerçekleşir ve daha büyük sayılar için pratik olarak mümkün olmayabilir.

İlginç bir şekilde, Brachylog, sorunu tanımlayan bir çözümden (hangi Brachylog'da iyidir) girdiyi faktörleştirmeye dayanan bir algoritmayı kullanan bir çözüme (Jelly'in iyi olduğu); Bu arada, jöle çözümü uzaklaşan ile iyileştirildi onun güçlü ve sadece sorunu açıklayan bir çözüme arkasını gidiyor.

Açıklama:

Ḋx³ŒPQP=¥Ðf
Ḋ              List of integers from 2 to the input (apparently undocumented)
 x³            Make a number of copies of each that's equal to the input
   ŒP          Take all (possibly noncontiguous) subsequences of that list (!)
     Q         Remove duplicates
         Ðf    Filter, keeping elements where:
      P=         their product is equal to {the original input, by default}
        ¥      Parse preceding two links as a unit

Çıktısı Ḋxsıralandığından, her bir alt sıra da sıralanmalıdır ve dolayısıyla bunları ayrı ayrı sıralamak zorunda değiliz. Bu nedenle, sorunun farklı çıktısındaki "aynı çıktının bir kopyası" kısmıdır ve sorunun çıktısındaki "çıktıdaki tüm değerler> 1" kısmı üretimle çözülür. Bunun dışında, temelde burada P=³yaptığımız şey, söz konusu tüm listeleri oluşturarak ve ardından yanlış olanları filtreleyerek yaptığımız (inanılmaz derecede yetersiz bir şekilde) yaptığımız “ tüm listeleri bul ”.

(Açıkçası, birinin Jelly ve Brachylog melezini icat etmesi gerekiyor, ayrıca bir gerçekten iyi bir kısıtlayıcı çözücüsü , böylece satırlar boyunca bir şeyler yazabiliriz {P=³}~ve bazı tekilleştirme kodlarını çözebiliriz ve programı çok daha kısa bir sürede çözebiliriz. biraz uzakta olsa da.)


Lütfen, biri burada tasarruf karakterini bulur. Girişlerin her seferinde bir bayt daha kısa tutmaya devam ettiği bir "bayt savaşı" isterdim. Programın yapısal bölümlerine boşa harcanan yeterli bayt var.

1
Çok çarpıcı bir şey göndermek üzereydim. (Daha sık yenilenmeli.) 2rOlabilir ve P=³$$olabilir P=¥.
Dennis,

P=¥Tercümanda denediğimde işe yaramıyor, neden tamamen emin olmasam da (mantıksal olarak çalışması gerekir ve yazıyı yazarken denediğim şeylerden biriydi; emin olmak için tekrar denedim, kesinlikle beklediğim şeyi yapmaz). öyle olsa da, sanırım bir bayt tasarrufumuz var :-)

1
Başka bir ayrıntıya dikkat etmedi. Sen değiştirmek zorunda kalacak µolan ¹iyi yanı sıra µtekrarlanan aralık yeni sol argüman yapar.
Dennis,

Oh elbette. Şimdi 11'e düştük, daha az karakterle, bu beni daha iyi hissettiriyor. ( Sadece çeşitlilik için ³değil, onu kullandım ¹.)

2

JavaScript (ES6), 74 67 bayt

f=(n,m=2,a=[])=>n>1?m>n?[]:f(n,m+1,a).concat(f(n/m,m,[...a,m])):[a]

for (var i = 1; i < 31; i++) console.log(JSON.stringify(f(i)));

Doğrudan yinelemeli sorunu çözer: Her tam sayı için m den 2'ye kadar n , biz bölümlerin her alır , n / m , minimum elemanı m ve ekleme (yinelenen bölümleri önlemek için) m . (Herhangi biri için m bölmüyorsa n , bu ondalığa tamsayı katları arasında hiçbir düzenleme olarak boş dizi verir.) Bu boş dizinin bir temel durumunun 1 sonsuz özyinelemeye mani olmak için.


1

Python2, 198 191 172 180 bayt

from itertools import*
n=input()
for i in range(2,len(bin(n))):
 for P in combinations_with_replacement(range(2,n),i):
  if reduce(lambda a,b:a*b,P)==n:print(P)
print[(n,),()][n<2]

Tam bir program. Bu çok geliştirilebilir, bu nedenle önerileriniz derinden memnuniyetle karşılanır!

1 ile 31 aralığındaki çıkışlar (dahil):

(1,)
(2,)
(3,)
(2, 2), (4,)
(5,)
(2, 3), (6,)
(7,)
(2, 4), (2, 2, 2), (8,)
(3, 3), (9,)
(2, 5), (10,)
(11,)
(2, 6), (3, 4), (2, 2, 3), (12,)
(13,)
(2, 7), (14,)
(3, 5), (15,)
(2, 8), (4, 4), (2, 2, 4), (2, 2, 2, 2), (16,)
(17,)
(2, 9), (3, 6), (2, 3, 3), (18,)
(19,)
(2, 10), (4, 5), (2, 2, 5), (20,)
(3, 7), (21,)
(2, 11), (22,)
(23,)
(2, 12), (3, 8), (4, 6), (2, 2, 6), (2, 3, 4), (2, 2, 2, 3), (24,)
(5, 5), (25,)
(2, 13), (26,)
(3, 9), (3, 3, 3), (27,)
(2, 14), (4, 7), (2, 2, 7), (28,)
(29,)
(2, 15), (3, 10), (5, 6), (2, 3, 5), (30,)
(31,)

Bu işe yarıyor mu? 4 -> {2, 2}, {4}Söz konusu test durumu var, girişinizde böyle bir çıktı göremiyorum.
Borsunho

@Borsunho Eski sürümü geri alırken, buna +1 eklemeyi unuttum int(math.log(n,2)). +2 bayt ve işe yarayacak. Teşekkürler!
Yytsi,

İçe aktarmadınız, mathancak kullanıyorsunuz math.log.
orlp

@ orlp ben ...? Üçüncü satırda.
Yytsi,

@TuukkaX Afedersiniz, ithalat için sadece en üst sıralara baktım, hemen hemen her zaman oradalardı ... Söylendiği gibi len(bin(n))-2, daha kısa int(math.log(n,2)).
orlp


1

Clojure, 91 bayt

(defn f[n](conj(set(for[i(range 2 n):when(=(mod n i)0)j(f(/ n i))](sort(flatten[i j]))))n))

Örnek çalışır:

(map f [20 84])
(#{20 (2 2 5) (4 5) (2 10)} #{(7 12) (2 2 3 7) (2 3 14) (2 2 21) (2 6 7) (6 14) (3 4 7) (3 28) (4 21) (2 42) 84})

Değer tek bir sayı olarak döndürülür (a değil list), diğerleri liste olarak çıkar. nSonunda ile değiştirilebilir [n]buna da dizisi yapmak için, ya da (list n)bir listesini yapmak.



0

J, 35 bayt

([:~.]<@/:~@(*//.)"$~#\#:i.@!@#)@q:

Göre çözeltiZaman kısıtlı bir faktoring zorluğunun .

Bu sürüm çok daha verimsiz ve temel faktörlerin sayısına bağlı olarak faktoring zamanında çalışıyor. Faktoradik sayılar üreterek bölümler oluşturur.

Çevrimiçi deneyin!(Çevrimiçi olarak büyük değerleri denemeyin!)

açıklama

([:~.]<@/:~@(*//.)"$~#\#:i.@!@#)@q:  Input: integer n
                                 q:  Prime factorization
(                              )@    Operate on them
                              #        Length
                            !@         Factorial
                         i.@           Range [0, i)
                     #\                Range [1, i]
                       #:              Mixed based conversion - Creates factoradic values
     ]                                 Get factors
            (    )"$~                  For each factoradic value
               /.                        Partition the factors based on equal
                                         digits in the factoradic value
             */                          Get the product of each block
        /:~@                             Sort it
      <@                                 Box it
 [:~.                                  Deduplicate

0

D, 95 bayt

void g(int n,int[]r){for(int i=r[0];i*i<=n;i++)(n%i)?0:g(n/i,i~r);r.back=n;r.writeln;}g(n,[2]);

Sadece özyinelemeli bir çözüm. In g(n,r), rbölüm şu ana kadar ve nhala faktörlere ayrılmak için bırakılan değer. Sırasız bölümlerin her birini yalnızca bir kez almak için, faktörleri rartmayan sırayla sıralarız. Son eleman, mümkün olan en az faktör olarak rbaşlar 2ve üzerine yazılır.n her çıktı işleminden hemen önce her kopyada .

Çünkü n = 60çıktı aşağıdaki gibidir:

[3, 2, 2, 5]
[2, 2, 15]
[3, 2, 10]
[5, 2, 6]
[2, 30]
[4, 3, 5]
[3, 20]
[4, 15]
[5, 12]
[6, 10]
[60]

Çevrimiçi deneyin!


Şablonları kullanın, Gassa, şablonları kullanın:void g(T)(T n,T[]r){for(T i=r[0];i*i<=n;i++)n%i0:r;r.back=n;r.writeln;}g(n,[2])
Zacharý

Her neyse, bu geçerli bir cevap bile değil, çünkü içe aktarmanız std.stdiove std.rangegirişin 1hiçbir şey yazdırmaması gerekiyor [1].
Zacharý

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.