Liệt kê tất cả các phân vùng nhân của n


28

Cho một số dương n , xuất ra tất cả các phân vùng nhân khác biệt của n ở bất kỳ định dạng thuận tiện nào.

Phân vùng nhân của n là một tập hợp các số nguyên, tất cả đều lớn hơn một, sao cho sản phẩm của chúng là n . Ví dụ: 20 có các phân vùng nhân khác biệt sau:

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

Thứ tự không quan trọng, 2 * 2 * 5phân vùng cũng vậy 2 * 5 * 2.


Ví dụ:

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}


Câu trả lời:


6

Brachylog , 16 byte

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

Đây là một hàm (không phải là một chương trình đầy đủ) lấy số dương làm đầu vào và tạo ra tất cả các phân vùng nhân của nó. .

Hãy thử trực tuyến! (Mã bổ sung đã được thêm vào xung quanh chức năng ở đây để biến nó thành một chương trình đầy đủ; nếu bạn cung cấp chức năng được hiển thị ở trên cho TIO trực tiếp, nó sẽ chạy chức năng nhưng không in đầu ra của nó ở bất cứ đâu, điều này vô dụng như một minh chứng .)

Chương trình này thực sự làm tôi thất vọng, vì phần lớn nó đang khắc phục các lỗi trong trình thông dịch Brachylog và thiếu sót trong đặc tả của nó, thay vì thực sự giải quyết vấn đề; nhưng thông dịch viên là những gì nó được. . bạn chỉ có thể viết ~*.o.:{>1}a,, sẽ ngắn hơn 4 byte, nhưng tôi cần thêm các ràng buộc bổ sung để giúp trình thông dịch ra ngoài một chút. (Tôi không thực sự thích Brachylog nhiều, và thà gắn bó với Prolog, nhưng nó cần những gợi ý tương tự để làm cho chương trình hoạt động và chúng còn dài hơn để viết. Vì vậy, Brachylog là vậy.)

Giải trình:

Như thường lệ, chương trình Brachylog là một tập hợp các ràng buộc; theo mặc định, ràng buộc thứ nhất ràng buộc đầu vào đối với một ẩn số (mà tôi sẽ gọi là A ), ràng buộc thứ hai ràng buộc A đối với B không xác định thứ hai , và cứ thế cho đến khi chúng ta đạt được đầu ra. Một số ký tự, chẳng hạn như {}, có thể thay đổi luồng chung này, vì vậy tôi sử dụng một tập hợp các chữ cái khác (ví dụ X / Y ) để biểu thị các ẩn số trong các vị từ lồng nhau.

>       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

Vẫn chưa rõ chương trình hoạt động như thế nào, vì vậy hãy thử đơn giản hóa các ràng buộc một chút. C , D , G , HI đều giống nhau (và bằng với đầu ra). EF cũng giống nhau (và bằng với đầu vào). Vì vậy, các ràng buộc của chúng tôi đun sôi điều này:

  • A là chiều dài của B và của đầu ra, và nhỏ hơn đầu vào.
  • B bao gồm tất cả 1 và không đặc biệt hữu ích (đó là một phần của chương trình đơn giản vì trong trình thông dịch Brachylog hiện tại, :{1<}acần đối số bên trái của nó có độ dài bị ràng buộc hoặc nếu không thì trình thông dịch đi vào một vòng lặp vô hạn).
  • Đầu ra bao gồm toàn bộ các số lớn hơn 1 (nghĩa là lớn hơn phần tử tương ứng của B ).
  • Tích của các phần tử của đầu ra bằng với đầu vào.
  • Đầu ra không thay đổi bằng cách sắp xếp nó (tức là theo thứ tự được sắp xếp).

Ngẫu nhiên, tôi đã không xác định rõ ràng rằng tất cả các yếu tố của đầu ra là số nguyên, một cái gì đó dường như được yêu cầu; tuy nhiên, bộ giải ràng buộc của Brachylog không thể xử lý các số nguyên, vì vậy nó sẽ chỉ tạo ra các giải pháp liên quan đến số nguyên một cách thuận tiện.

Rõ ràng, "độ dài của đầu ra nhỏ hơn đầu vào" sẽ là đúng bất cứ khi nào đầu ra là một phân vùng nhân của đầu vào (vì 2 x > x cho tất cả x không âm , tức là 2 x dương ). Vì vậy, chúng ta có thể bỏ qua sự ràng buộc đó; nó chỉ ở đó để cung cấp cho trình thông dịch Brachylog một chiến lược làm việc để đánh giá chương trình. Các ràng buộc khác (rằng đầu ra được sắp xếp, sản phẩm của nó là đầu vào và các phần tử của nó đều lớn hơn 1) là định nghĩa của phân vùng nhân, và do đó, chức năng này chỉ là một câu hỏi trực tiếp.


6

Brachylog 1, 14 byte

:{$pp~c:*ao}fd

Hãy thử trực tuyến!

Brachylog 2, 11 10 byte, thách thức ngôn ngữ

{ḋp~c×ᵐo}ᵘ

Hãy thử trực tuyến!

Maltysen đã trả lời câu hỏi này bằng 17 byte của Pyth, vì vậy tôi đã đưa ra giải pháp Brachylog 16 byte hoạt động bằng cách dịch đặc tả của câu hỏi sang Brachylog. Trong khi tôi đang làm điều đó, Dennis đã viết một giải pháp Jelly 15 byte. Vì vậy, tôi đã phải xuống đến 14 byte. Đây là một hàm lấy đầu vào làm đối số và trả về danh sách tất cả các phân vùng (chứ không phải là trình tạo, như với giải pháp khác của tôi).

Một thời gian sau khi tôi viết câu trả lời này, Dennis và tôi đã xoay sở để hợp tác đưa giải pháp Jelly xuống còn 11 byte. Hóa ra có một phiên bản mới của Brachylog, với cú pháp chặt chẽ hơn; nó hoãn thử thách, vì vậy không thực sự được tính, nhưng nó có thể quản lý tổng số 11 byte quá nhiều ngay khi phát hành; bản sửa đổi sau này của ngôn ngữ (lấy cảm hứng từ những thách thức khác) có thể xuống thấp đến 10, như được thấy ở đây. Hai chương trình giống hệt nhau, với sự khác biệt duy nhất là cú pháp.

Không giống như giải pháp khác của tôi, vốn không sử dụng nhiều "nguyên thủy chơi gôn" mà chỉ nói trực tiếp vấn đề, giải pháp này bỏ qua khá nhiều sức mạnh của các ràng buộc Brachylog và thay vào đó là ấn tượng Jelly tốt nhất, viết một chuỗi các ràng buộc đối số bên trái đã được biết đến (và do đó, các ràng buộc chỉ hoạt động giống như các đơn nguyên Jelly chứ không phải là các ràng buộc toàn diện). Do đó, nó sử dụng thuật toán tương tự như giải pháp Pyth của @ Maltysen, đây có lẽ là cách dễ nhất để giải quyết vấn đề này bằng cách sử dụng các nguyên thủy đánh gôn điển hình. (Thật thú vị, giải pháp "chỉ nêu vấn đề" trong câu trả lời khác của tôi sẽ ngắn hơn nếu không có lỗi / thiếu sót trong trình thông dịch Brachylog, mặc dù nó không sử dụng các nguyên tắc chơi gôn. Một ngày nào đó tôi cần viết một "Brachylog cải tiến". để có được một giải pháp tốt cho loại vấn đề này; như ngôn ngữ chơi gôn, Brachylog thực sự rất dài dòng.)

Chương trình bao gồm một máy phát điện và một trình bao bọc xung quanh nó. Đầu tiên, đây là một lời giải thích về máy phát điện:

$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

Điều này gần như giải quyết được vấn đề, nhưng cuối cùng chúng tôi tạo ra nhiều phân vùng nhiều lần. Vì vậy, chúng ta cần một trình bao bọc để lặp lại các giải pháp:

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

{…}ᵘ      Convert generator to list of unique elements

Tại sao không chỉnh sửa câu trả lời xuất thần của bạn?
Hạ cấp

3
@Downgoat: Hai câu trả lời sử dụng các cách tiếp cận hoàn toàn khác nhau; các thuật toán là khác nhau, các tính năng ngôn ngữ được sử dụng chủ yếu là độc lập và tương tự. Sẽ không có ý nghĩa gì khi thay thế cái cũ bằng cái mới hơn (và tôi có thể đã đăng cái mới ngay cả khi nó dài hơn). Bài đăng meta này cho thấy rằng đăng câu trả lời riêng biệt là thích hợp hơn trong loại tình huống này.

1
Tôi không biết nếu bạn biết điều này nhưng bạn có thể truy xuất đầu ra bằng cách đặt đối số trên TIO thành một biến (tức là một chữ cái viết hoa). Ví dụ .
Gây tử vong

5

Toán học, 61 byte

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

Xác định một toán tử đơn nguyên (đệ quy) ±trả về danh sách các phân vùng.


Không toán học không yêu cầu dấu chấm phẩy ở cuối?
Pavel

@Pavel không, dấu chấm phẩy chỉ triệt tiêu đầu ra trong notebook tương tác. Cảm ơn đã chỉ ra điều này, btw, tôi đã vô tình để lại một dấu chấm phẩy ở cuối.
Martin Ender

4

Pyth - 17 byte

Lấy tất cả các hoán vị của thừa số nguyên tố, sau đó phân vùng từng cái và sau đó sản phẩm tất cả các phân vùng, sau đó chỉ giữ lại các phân vùng riêng biệt.

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

Phòng thử nghiệm .


4

Python 2, 70 byte

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]

Xuất ra một danh sách các danh sách được sắp xếp. Ví dụ f(20)[[2, 2, 5], [2, 10], [4, 5], [20]].


Vì loại số nguyên tích hợp của Python không có giới hạn, dấu phẩy động không phải là một giải pháp chấp nhận được vì tính không chính xác sẽ phá vỡ câu trả lời cho các đầu vào quá lớn.
orlp

@orlp Ok, quay lại Python 2 rồi.
xnor

TL; DR Tôi nghĩ 998 không phải là một đầu vào quá lớn ;-) IMO một mã tuyệt vời thực sự, giống như độ trễ O(n)và so sánh với đối thủ Python 2 có thể O(n^4)phong cách hơn - trong khi f (998) có thể thổi bộ nhớ hoặc phần cứng có thể chết trong khi chạy thời gian của est. 80 ngày với thuật toán khác, cái này ở đây hội tụ sau khoảng. 7 milli giây trên máy của tôi để mang lại kết quả [[2, 499], [998]]. IMO vấn đề có thể là nhiều hơn vì N > 998các RecursionError: maximum recursion depth exceeded in comparisonđiểm dừng của mã Python 3 ở trên ... chơi golf vui vẻ :-)
Dilettant

@Dilettant Không chắc chắn liệu O(n^4)có đủ để gửi Python2 của tôi không: D Xem xét trường hợp thử nghiệm 998, mã của tôi sẽ chạy 9 lần và tính toán (n+r-1)! / r! / (n-1)!số lượng bộ dữ liệu mỗi lần, trong đó rtăng trưởng tuyến tính từ 2 và n 9 - 2. Nhưng hey, ít nhất bạn không cần phải tinh chỉnh giới hạn đệ quy ...
Yytsi

@TuukkaX Caveat: Tôi không phân tích mã, chỉ lướt qua và so sánh sự phát triển của thời gian chạy giữa hai ứng cử viên cho một số N lên đến 41 sau đó nghĩ rằng tôi chỉ đưa ra nhận xét ;-) ngăn xếp và đệ quy thường dễ dàng, nhưng sau đó gọi cho các câu hỏi kiểu như thế nào sâu trong những tình huống khó chịu ... hy vọng tôi đặt ra nó đủ mờ cho số lượng nghiên cứu mà bước vào.
Dilettant

3

Thạch , 14 13 11 byte

Ḋx³ŒPQP=¥Ðf

Hãy thử trực tuyến!

Tôi khá chắc chắn rằng giải pháp Jelly của Dennis có thể được cải thiện. Thật không may, tôi đã không thể đánh bại kỷ lục Brachylog, nhưng tôi đã xoay sở để buộc nó. Cập nhật : Với sự giúp đỡ của @Dennis, giờ đây nó đã được cải thiện; Tôi đoán Jelly lấy lại vương miện.

Chương trình này cực kỳ kém hiệu quả, có hiệu suất O (2 n 2 ) (đó là lý do tại sao trường hợp thử nghiệm ở trên cho thấy nó cho đầu vào 4). Nó hoàn thành nhanh chóng trên 4, rất chậm trên 5 và thực tế có thể không chạy được với số lượng lớn hơn.

Thật thú vị, Brachylog đã được cải thiện bằng cách đi từ một giải pháp mô tả vấn đề (mà Brachylog giỏi) đến một giải pháp sử dụng thuật toán dựa trên yếu tố đầu vào (mà Jelly giỏi); Trong khi đó, giải pháp Jelly đã được cải thiện bằng cách di chuyển khỏi các điểm mạnh của nó và quay trở lại một giải pháp chỉ mô tả vấn đề.

Giải trình:

Ḋ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

Bởi vì đầu ra của Ḋxđược sắp xếp, mỗi thứ tự cũng phải được sắp xếp, và do đó chúng ta không phải sắp xếp chúng riêng lẻ. Vì vậy, "cùng một đầu ra trong các đơn hàng khác nhau là một phần trùng lặp" của vấn đề và "tất cả các giá trị trong đầu ra là> 1" của vấn đề, được giải quyết bằng cách tạo. Ngoài ra, về cơ bản, những gì chúng ta đang làm ở đây là "tìm tất cả các danh sách P=³", mà chúng ta làm (theo cách không hiệu quả) bằng cách tạo ra tất cả các danh sách được đề cập và sau đó lọc ra những danh sách không chính xác.

(Rõ ràng, ai đó cần phải đi phát minh ra một lai của Jelly và Brachylog, cộng với một thực sự tốt chế giải, để chúng ta có thể viết một cái gì đó dọc theo dòng của {P=³}~cộng một số mã pc, và giải quyết các chương trình trong một thời gian ngắn hơn nhiều. Đó có thể là một số khoảng cách, mặc dù.)


Xin vui lòng, ai đó tìm thấy một nhân vật tiết kiệm ở đây. Tôi thích một "cuộc chiến byte" trong đó các mục tiếp tục ngắn hơn một byte mỗi lần. Có đủ byte bị lãng phí trên các phần cấu trúc của chương trình ở đây mà có vẻ như điều này có thể là ngẫu hứng.

1
Heh, tôi vừa định đăng một cái gì đó tương tự nổi bật. (Nên làm mới thường xuyên hơn.) 2rCó thể trở thành , và P=³$$có thể trở thành P=¥.
Dennis

P=¥không hoạt động khi tôi thử nó trong trình thông dịch, mặc dù tôi không hoàn toàn chắc chắn tại sao (về mặt logic, nó nên hoạt động và đó là một trong những điều tôi đã thử trong khi viết bài; tôi chỉ thử lại lần nữa để chắc chắn, nó chắc chắn không làm những gì tôi mong đợi). tuy nhiên, vì vậy tôi đoán có tiết kiệm một byte của chúng tôi :-)

1
Không chú ý đến một chi tiết khác. Bạn cũng sẽ phải thay thế µbằng ¹, µlàm cho phạm vi lặp lại thành đối số bên trái mới.
Dennis

Ồ dĩ nhiên rồi. Vì vậy, bây giờ chúng tôi xuống còn 11, với ít nhân vật hơn, điều đó khiến tôi cảm thấy tốt hơn nhiều. (Tôi đã sử dụng ³thay vì ¹chỉ cho sự đa dạng.)

2

JavaScript (ES6), 74 67 byte

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)));

Trực tiếp giải quyết vấn đề một cách đệ quy: với mỗi số nguyên m từ 2 đến n , chúng tôi lấy từng phân vùng của n / m với phần tử tối thiểu là m (để tránh phân vùng trùng lặp) và nối thêm m . (Đối với bất kỳ m nào không chia n , điều này sẽ cho mảng trống, vì không có sự sắp xếp nào của số nguyên nhân với một số thập phân.) Chúng tôi xác định trường hợp cơ sở của mảng trống cho 1 để tránh đệ quy vô hạn.


1

Python2, 198 191 172 180 byte

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]

Một chương trình đầy đủ. Điều này có thể được cải thiện rất nhiều, vì vậy các đề xuất rất được hoan nghênh!

Đầu ra từ phạm vi 1 đến 31 (bao gồm):

(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,)

Điều này thậm chí làm việc? Có trường hợp thử nghiệm 4 -> {2, 2}, {4}trong câu hỏi, tôi không thấy đầu ra như vậy trong nhật ký của bạn.
Borsunho

@Borsunho Khi tôi quay lại phiên bản cũ, tôi đã quên thêm +1 vào int(math.log(n,2)), điều này gây ra điều đó. +2 byte và nó sẽ hoạt động. Cảm ơn!
Yytsi

Bạn chưa nhập mathnhưng đang sử dụng math.log.
orlp

@orlp Tôi có ...? Trên dòng thứ ba.
Yytsi

@TuukkaX Xin lỗi, tôi, tôi chỉ nhìn vào các dòng hàng đầu cho hàng nhập khẩu, vì chúng hầu như luôn ở đó ... Điều đó có nghĩa là, len(bin(n))-2ngắn hơn int(math.log(n,2)).
orlp


1

Clojure, 91 byte

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

Ví dụ chạy:

(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})

Giá trị được trả về dưới dạng một số duy nhất (không phải a list), các giá trị khác xuất hiện dưới dạng danh sách. Các ncuối cùng có thể được thay thế bằng[n] để làm cho nó một chuỗi là tốt, hoặc (list n)để làm cho nó một danh sách.



0

J, 35 byte

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

Dựa trên giải pháp cho một thách thức nhân tố hạn chế thời gian.

Phiên bản này không hiệu quả hơn nhiều và chạy trong thời gian giai đoạn dựa trên số lượng các yếu tố chính. Tạo phân vùng bằng cách tạo số nhân tố.

Hãy thử trực tuyến!(Đừng thử giá trị lớn trực tuyến!)

Giải trình

([:~.]<@/:~@(*//.)"$~#\#: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 byte

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]);

Chỉ là một giải pháp đệ quy. Trong g(n,r), rlà phân vùng cho đến nay, và nlà giá trị vẫn còn để chia thành các yếu tố. Để có được mỗi phân vùng không có thứ tự chỉ một lần, chúng tôi sắp xếp các yếu tố theo rthứ tự không tăng. Yếu tố cuối cùng rbắt đầu ở mức 2ít nhất có thể, và bị ghi đè bởin trong mỗi bản sao ngay trước mỗi thao tác đầu ra.

Đối với n = 60, đầu ra như sau:

[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]

Hãy thử trực tuyến!


Sử dụng các mẫu, Gassa, sử dụng các mẫu: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ý

Dù sao, đây thậm chí không phải là một câu trả lời hợp lệ, vì bạn cần nhập std.stdiostd.range, đầu vào 1sẽ không in gì cả, không phải [1].
Zacharý

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.