Sản phẩm kết hợp của số nguyên tố độc đáo


21

Bản tường trình vụ việc

Đưa ra một tập hợp các số nguyên tố liên tiếp duy nhất (không nhất thiết phải bao gồm 2), tạo ra các sản phẩm của tất cả các kết hợp sức mạnh đầu tiên của các số nguyên tố này - ví dụ: không lặp lại - và cả 1. Ví dụ, được đưa ra bộ {2, 3, 5, 7}, bạn sản xuất {1, 2, 3, 5, 6, 7, 10, 14, 15, 21, 30, 35, 42, 70, 105, 210} vì:

  1  =  1
  2  =  2
  3  =  3
  5  =  5
  6  =  2 x 3
  7  =  7
 10  =  2 x 5
 14  =  2 x 7
 15  =  3 x 5
 21  =  3 x 7
 30  =  2 x 3 x 5
 35  =  5 x 7
 42  =  2 x 3 x 7
 70  =  2 x 5 x 7
105  =  3 x 5 x 7
210  =  2 x 3 x 5 x 7

Lưu ý rằng nếu số lượng thẻ của bộ đầu vào của bạn là k, thì số này sẽ cung cấp cho bạn 2 ^ k thành viên trong bộ đầu ra của bạn.

Quy tắc / điều kiện

  1. Bạn có thể sử dụng bất kỳ ngôn ngữ. Nhằm mục đích cho số lượng ký tự nhỏ nhất của mã nguồn.
  2. Giải pháp của bạn phải là một chương trình hoàn chỉnh hoặc một chức năng hoàn chỉnh. Chức năng có thể ẩn danh (nếu ngôn ngữ của bạn hỗ trợ các chức năng ẩn danh).
  3. Giải pháp của bạn sẽ có thể hỗ trợ các sản phẩm tối thiểu 2 ^ 31. Đừng lo lắng về việc phát hiện hoặc xử lý tràn số nguyên nếu bạn được thông qua các số có sản phẩm quá tuyệt vời để thể hiện. Tuy nhiên, xin vui lòng nêu giới hạn tính toán của bạn.
  4. Bạn có thể chấp nhận một danh sách hoặc một bộ và tạo ra một danh sách hoặc một bộ. Bạn có thể giả sử đầu vào được sắp xếp nhưng bạn không bắt buộc phải tạo đầu ra được sắp xếp.

Lý lịch

Khi nào hoặc tại sao điều này hữu ích? Một nơi rất hữu ích là trong việc tạo một bảng số nhân để chạy song song trong một thuật toán bao thanh toán số nguyên được gọi là Hệ số hình dạng vuông. Ở đó, mỗi số nhân lẻ bạn thử làm giảm xác suất của thuật toán thất bại (để tìm một yếu tố) khoảng 50% cho các bán kết cứng. Vì vậy, với tập hợp các số nguyên tố tạo {3, 5, 7, 11}, tạo ra một bộ gồm 16 số nhân dùng thử để chạy song song, thuật toán thất bại khoảng 2 ^ thời gian trên các bán kết cứng. Việc thêm 13 vào danh sách số nguyên tố sẽ tạo ra một bộ gồm 32 số nhân thử nghiệm, giảm khả năng thất bại xuống còn khoảng 2 ^, 32, mang lại sự cải thiện mạnh mẽ về kết quả mà không phải trả thêm chi phí tính toán (bởi vì thậm chí có gấp đôi số nhân tăng gấp đôi trung bình nó vẫn tìm thấy câu trả lời trong cùng tổng số bước).

Câu trả lời:


18

Bash thuần túy, 32 byte

eval echo \$[{1,${1// /\}*{1,}}]

Đọc danh sách đầu vào (không gian riêng biệt được phân tách) được truyền dưới dạng đối số dòng lệnh.

Ba bản mở rộng vỏ khác nhau được sử dụng:

  1. ${1// /\}*{1,}là một mở rộng tham số thay thế khoảng trống trong 2 3 5 7với }*{1,để cung cấp cho 2}*{1,3}*{1,5}*{1,7. \$[{1,}]được thêm vào đầu và cuối tương ứng để cung cấp \$[{1,2}*{1,3}*{1,5}*{1,7}]. Dấu \$[gạch chéo được thoát ra để ngăn các nỗ lực thực hiện mở rộng số học ở giai đoạn này.
  2. \$[{1,2}*{1,3}*{1,5}*{1,7}]là một mở rộng cú đúp . Bởi vì mở rộng cú đúp thường xảy ra trước khi mở rộng tham số , chúng tôi sử dụng phải sử dụng evalđể buộc mở rộng tham số xảy ra trước tiên. Kết quả của việc mở rộng cú đúp là $[1*1*1*1] $[1*1*1*7] $[1*1*5*1] ... $[2*3*5*7].
  3. $[1*1*1*1] $[1*1*1*7] $[1*1*5*1] ... $[2*3*5*7]là một danh sách các mở rộng số học , sau đó được đánh giá để đưa ra danh sách các số chúng tôi yêu cầu.

Đầu ra:

$ ./comboprime.sh "2 3 5 7"
1 7 5 35 3 21 15 105 2 14 10 70 6 42 30 210
$

3
Tâm trí ... thổi ... wow!
Todd Lehman

Wtf ... tôi nhận được1 0
tên người

@ username.ak Đầu vào của bạn là gì? Làm thế nào bạn nhập nó (đối số dòng lệnh?). Phiên bản bash nào bạn đang chạy? bash --version
Chấn thương kỹ thuật số

12

CJam, 13 byte

1aq~{1$f*+}/p

Đọc một mảng (ví dụ, [2 3 5 7]) từ STDIN. Hãy thử trực tuyến.

Một hàm ẩn danh sẽ có cùng số byte:

{1a\{1$f*+}/}

Chạy ví dụ

$ cjam <(echo '1aq~{1$f*+}/p') <<< '[]'
[1]
$ cjam <(echo '1aq~{1$f*+}/p') <<< '[2 3 5 7]'
[1 2 3 6 5 10 15 30 7 14 21 42 35 70 105 210]

Làm thế nào nó hoạt động

1a               " Push R := [1].              ";
  q~             " Read an array A from STDIN. ";
    {     }/     " For each a ∊ A:             ";
     1$f*+       "     R += { ra : r ∊ R }     ";
            p    " Print.                      ";

4
Wow, đó là một cách thông minh để lặp qua tất cả các tập con.
Martin Ender

9

Haskell, 22

giải pháp là một chức năng ẩn danh:

map product.mapM(:[1])

sử dụng ví dụ:

*Main> map product.mapM(:[1]) $ [2,3,5]
[30,6,10,2,15,3,5,1]

giải thích:
(:[1]) là một hàm cho một số xtrả về danh sách [x,1].
mapM(:[1])là một hàm đưa ra một danh sách các số ánh xạ hàm (:[1])trên chúng và trả về mọi cách có thể để chọn một phần tử từ mọi danh sách. ví dụ, mapM(:[1]) $ [3,4]đầu tiên ánh xạ chức năng để có được [[3,1] , [4,1]]. sau đó các lựa chọn có thể là [3,4](chọn số đầu tiên của cả hai) [3,1] [1,4][1,1]vì vậy nó trả về [[3,4],[3,1],[1,4],[1,1]].

sau đó map productánh xạ qua tất cả các lựa chọn và trả về sản phẩm của họ, đó là đầu ra mong muốn.

Hàm này là đa hình trong loại của nó có nghĩa là nó có thể hoạt động trên tất cả các loại số. bạn có thể nhập vào danh sách Intvà kết quả sẽ là danh sách Intnhưng cũng có thể được áp dụng trong danh sách loạiIntegervà trả về một danh sách Integer. điều này có nghĩa là hành vi tràn không được chỉ định bởi chức năng này mà bởi loại đầu vào (hệ thống loại biểu cảm của yay Haskell :))


Tốt đẹp! Có bất kỳ giới hạn cho kích thước số?
Todd Lehman

1
@ToddLehman không. Kiểu số mặc định là Integer, kiểu số nguyên không giới hạn. Ngoài ra Int, số nguyên 32 bit, nhưng đó hầu hết chỉ là một thứ kế thừa.
John Dvorak

@JanDvorak trong thực tế có nhưng tôi yêu hệ thống loại quá nhiều để không đề cập đến nó :). một điều khác cần chú ý là bởi vì nó ẩn danh, vấn đề là bạn sử dụng nó như thế nào bởi vì hạn chế tính đơn hình có thể được áp dụng trong một số trường hợp.
tự hào

8

Toán học, 18 17 byte

1##&@@@Subsets@#&

Đó là một chức năng ẩn danh. Gọi nó như thế

1##&@@@Subsets@#&[{2,3,5,7}]

Và Martin đi vào với một câu trả lời ngắn đẹp!
Todd Lehman

@ToddLehman Bây giờ, hãy chờ câu trả lời J đánh bại câu này. ;)
Martin Ender

1
Nếu Mathematica không phải là nguồn đóng, ai đó có thể viết một phiên bản chơi gôn. ×@@@𝒫@#nên là vô địch.
Dennis

@Dennis Đặc tả ngôn ngữ Wolfram có sẵn độc lập với Mathicala và tôi nghĩ có một hoặc hai triển khai nguồn mở (chưa hoàn chỉnh). Việc tạo một phiên bản Mathicala có biệt danh Unicode đã được đề xuất một vài lần, nhưng tôi không nghĩ rằng nó sẽ được đón nhận rất tốt trên PPCG. ^^
Martin Ender

2
@ MartinBüttner Xin lỗi vì đã khiến bạn chờ đợi: (*/@#~2#:@i.@^#)16 ký tự trong J;)
thuật toán bắt đầu từ

4

Cập nhật: C (chức năng f), 92

Ngay cả khi là một chức năng, đây vẫn là mục dài nhất ở đây. Đây là lần đầu tiên tôi vượt qua một mảng có độ dài không xác định làm đối số hàm trong C và dường như không có cách nào để hàm C biết được độ dài của một mảng được truyền cho nó, vì đối số được truyền dưới dạng con trỏ ( bất kể cú pháp được sử dụng). Do đó, một đối số thứ hai là cần thiết để chỉ ra độ dài.

Tôi giữ đầu ra cho thiết bị xuất chuẩn, bởi vì thiết lập một mảng số nguyên và trả về nó gần như chắc chắn sẽ dài hơn.

Cảm ơn Dennis vì những lời khuyên.

Xem chức năng f(92 ký tự không bao gồm khoảng trắng không cần thiết) trong các chương trình thử nghiệm bên dưới.

Đầu ra qua printf

j;

f(int c,int*x){
  int p=1,i;
  for(i=c<<c;i--;p=i%c?p:!!printf("%d ",p))p*=(i/c>>i%c)&1?1:x[i%c];
}

main(int d,char**v){
  d--;
  int y[d];
  for(j=d;j--;)y[j]=atoi(v[j+1]);
  f(d,y);
}

Đầu ra thông qua con trỏ mảng

j,q[512];

f(int c,int*x,int*p){
    for(int i=-1;++i-(c<<c);p[i/c]*=(i/c>>i%c)&1?1:x[i%c])i%c||(p[i/c]=1);
}

main(int d,char**v){
  d--;
  int y[d];
  for(j=d;j--;)y[j]=atoi(v[j+1]);
  f(d,y,q);
  for(j=1<<d;j--;)printf("%d ",q[j]);
}

C (chương trình), 108

Không bao gồm khoảng trắng không cần thiết.

p=1,i;
main(int c,char**v){
  c-=1;
  for(i=c<<c;i--;i%c||(printf("%d ",p),p=1))(i/c>>i%c)&1||(p*=atoi(v[i%c+1]));
}

Đầu vào từ dòng lệnh, đầu ra đến thiết bị xuất chuẩn. C sẽ không giành chiến thắng ở đây, nhưng có lẽ tôi sẽ thử chuyển đổi sang một chức năng vào ngày mai.

Về cơ bản, chúng tôi lặp đi lặp lại qua tất cả các 1<<ckết hợp các số nguyên tố, với mỗi bit i/cđược liên kết với sự hiện diện hoặc vắng mặt của một số nguyên tố cụ thể trong sản phẩm. "Vòng lặp bên trong" i%cchạy qua các số nguyên tố, nhân chúng theo giá trị của i/c.Khi i%cđạt 0, sản phẩm là đầu ra, sau đó được đặt thành 1 cho lần lặp "bên ngoài" tiếp theo.

tò mò, printf("%d ",p,p=1)không hoạt động (nó luôn in 1.) Đây không phải là lần đầu tiên tôi thấy hành vi kỳ quặc khi một giá trị được sử dụng trong một printfvà được gán sau trong cùng một dấu ngoặc. Trong trường hợp này có thể là dấu phẩy thứ hai không được coi là dấu phân cách đối số, mà là toán tử.

Sử dụng

$ ./a 2 3 5 7
1 2 3 6 5 10 15 30 7 14 21 42 35 70 105 210

C không xác định chặt chẽ thứ tự mà các đối số được ước tính. Đặc biệt, nhiều lệnh gọi hàm C có các đối số được đánh giá từ phải sang trái.
COTO

Từ phần 6.5.2.2 của ISO / IEC 9899: TC3 : Thứ tự đánh giá của người chỉ định hàm, các đối số thực tế và các biểu thức con trong các đối số thực tế là không xác định [.] Vì vậy, tùy thuộc vào trình biên dịch theo thứ tự một hàm lập luận được đánh giá. Với -Wsequence-pointhoặc -Wall, GCC sẽ khiếu nại.
Dennis

1. Bạn có thể thay đổi c-=1để c--hoặc thậm chí sử dụng i=--c<<cnếu bạn không nhớ UB (có vẻ như để làm việc với GCC). 2. Cả hai cách sử dụng ||có thể được thay thế bằng toán tử ternary: p=i%c?p:!!printf("%d ",p)p*=(i/c>>i%c)&1?1:atoi(v[i%c+1])
Dennis

@Dennis Cảm ơn lời khuyên! Tôi đã đăng ngay trước khi đi ngủ để tôi chạy chương trình. c-=1là môn đánh gôn cơ bản như vậy tôi không nên bỏ qua, nhưng đó là cách sửa lỗi nhanh vì tôi quên rằng có thêm một chuỗi trong argv (tên chương trình.) i=..c<<choạt động trên GCC / cygwin, nhưng tôi đã rời khỏi bản gốc của mình chương trình như nó được và chuyển sang một chức năng. Vì vậy, tôi đã học được rằng sizeofkhông hoạt động trên các mảng được truyền dưới dạng đối số hàm. Tôi đã kết hợp các đề xuất của bạn cho các nhà khai thác ternary vào chức năng. Tôi đã bị mắc kẹt với đầu ra cho thiết bị xuất chuẩn vì tôi thấy không có cách nào ngắn để trả về một mảng.
Cấp sông St

Có, mảng được truyền dưới dạng đối số hàm phân rã thành con trỏ. - Không có gì lạ khi C chuyển một con trỏ tới mảng nên chứa kết quả dưới dạng tham số hàm. Câu hỏi nói rằng bạn có thể giả sử rằng các sản phẩm nhỏ hơn 2 ^ 31, vì vậy bạn chỉ có thể vượt qua một mảng có kích thước 512.
Dennis

3

Haskell, 27 byte

Đây là một triển khai Haskell của câu trả lời CJam của @ sudo như một chức năng ẩn danh. Nó sẽ không đánh bại giải pháp Haskell tuyệt vời của @proud haskeller, nhưng dù sao tôi cũng sẽ bỏ nó ở đây.

foldr((=<<)(++).map.(*))[1]

Giải thích: foldr có một hàm nhị phân, một giá trị và một danh sách. Sau đó, nó thay thế từng ô khuyết điểm trong danh sách bằng một ứng dụng của hàm và cuối danh sách bằng giá trị, như thế này : foldr f v [a,b,c] == f a (f b (f c v)). Giá trị của chúng tôi là danh sách một thành phần có chứa 1và hàm nhị phân là f = (=<<)(++).map.(*). Bây giờ, flấy một số n, tạo một hàm (n*)nhân với n, làm cho nó một hàm g = map(n*)áp dụng hàm đó cho tất cả các thành phần của danh sách và cung cấp hàm đó cho (=<<)(++). Ở đây, (++)là hàm ghép và (=<<)liên kết đơn , trong trường hợp này sẽ đưa vào (++)g, và đưa ra một hàm có trong danh sách, áp dụngg đến một bản sao của nó, và ghép hai cái đó lại.

Tóm lại: bắt đầu bằng [1]và cho mỗi số ntrong danh sách đầu vào, lấy một bản sao của danh sách hiện tại, nhân mọi thứ với nvà thêm nó vào danh sách hiện tại.


3

Python: 55 ký tự

f=lambda l:l and[x*l[0]for x in f(l[1:])]+f(l[1:])or[1]

Đệ quy tạo ra các sản phẩm bằng cách chọn bao gồm hoặc loại trừ lần lượt từng số.


Giải pháp đệ quy! Mát mẻ!
Todd Lehman

Tôi nghĩ bạn có thể bỏ không gian sau andnếu bạn viết tổng theo cách khác?
mathmandan

@mathmandan Yup, hoạt động, cảm ơn.
xnor

3

PARI / GP , 26 byte

v->divisors(factorback(v))

Các phiên bản dài hơn bao gồm

v->divisors(prod(i=1,#v,v[i]))

(30 byte) và

v->divisors(fold((x,y)->x*y,v))

(31 byte).

Lưu ý rằng nếu đầu vào là ma trận nhân tố thay vì tập hợp, 18 byte có thể được lưu chỉ bằng divisorsmột mình. Nhưng việc chuyển đổi một tập hợp thành một ma trận nhân tố dường như mất hơn 18 byte. (Tôi có thể làm điều đó trong 39 byte trực tiếp v->concat(Mat(v~),Mat(vectorv(#v,i,1)))hoặc 24 byte bằng cách nhân và bao thanh toán lại v->factor(factorback(v)), bất cứ ai cũng có thể làm tốt hơn?)


2

Hiền nhân - 36 34

Về cơ bản, giống như giải pháp của Martin Büttner , nếu tôi hiểu đúng. Như tôi đã đề cập trong một bình luận, tôi cũng có thể đăng nó như một câu trả lời.

lambda A:map(prod,Combinations(A))

Đây là một hàm ẩn danh, ví dụ có thể được gọi như sau:

(lambda A:map(prod,Combinations(A)))([2,3,5,7])

1
Bạn có thể cạo 2 byte bằng cách biến nó thành một hàm ẩn danh (câu hỏi được cho phép)
tự hào

2

J (20)

Điều này hóa ra lâu hơn tôi mong đợi hoặc dự kiến ​​.Still: ngắn hơn haskel!

*/@:^"1#:@i.@(2&^)@#

Sử dụng:

    f=:*/@:^"1#:@i.@(2&^)@#
    f 2 3 5 7
1 7 5 35 3 21 15 105 2 14 10 70 6 42 30 210

Điều này làm việc cho bất kỳ bộ số, không chỉ các số nguyên tố. Ngoài ra, các số nguyên tố có thể có kích thước không giới hạn, miễn là mảng có hậu tố x:2 3 5 7x


*/@#~2#:@i.@^#là một thay thế cho 14 byte.
dặm


1

R, 56 byte

r=1;for(i in 1:length(s))r=c(r,apply(combn(s,i),2,prod))

Tôi đang xem xét ở đây đó là tập hợp (và một danh sách). Tôi chắc chắn rằng nó có thể được thực hiện thậm chí ngắn hơn. Tôi sẽ xem.


1

PHP, 97 byte

<?for(;$i++<array_product($a=$_GET[a]);){$t=$i;foreach($a as$d)$t%$d?:$t/=$d;if($t<2)echo"$i\n";}
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.