독특한 소수의 조합 제품


21

문제 진술

고유하고 연속적인 소수 (2를 반드시 포함 할 필요는 없음)가 주어지면 이러한 소수의 1 차 거듭 제곱의 모든 조합의 곱을 생성합니다 (예 : 반복 없음). 또한 예를 들어 {2, 3, 5, 7}, {1, 2, 3, 5, 6, 7, 10, 14, 15, 21, 30, 35, 42, 70, 105, 210}을 생성합니다.

  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

입력 세트의 카디널리티가 k 인 경우 출력 세트에 2 ^ k 멤버가 제공됩니다.

규칙 / 조건

  1. 모든 언어를 사용할 수 있습니다. 가장 작은 문자 수의 소스 코드를 목표로합니다.
  2. 솔루션은 완전한 프로그램이거나 완전한 기능이어야합니다. 이 기능은 익명 일 수 있습니다 (언어가 익명 기능을 지원하는 경우).
  3. 솔루션은 최대 2 ^ 31까지 제품을 지원할 수 있어야합니다. 제품이 표현하기에 너무 큰 숫자를 전달받은 경우 정수 오버플로 감지 또는 처리에 대해 걱정하지 마십시오. 그러나 계산 한도를 명시하십시오.
  4. 목록 또는 세트를 승인하고 목록 또는 세트를 생성 할 수 있습니다. 입력이 정렬되었다고 가정 할 수 있지만 정렬 된 출력을 생성 할 필요는 없습니다.

배경

언제 또는 왜 이것이 유용한가요? 한 가지 유용한 점은 Square Forms Factorization 이라는 정수 인수 알고리즘에서 병렬로 곱하기 위해 승수 테이블을 생성하는 것입니다.. 거기에서 시도하는 홀수 승수는 하드 세미 프라임에서 알고리즘 실패 확률 (인수 찾기)을 약 50 % 줄입니다. 따라서 병렬로 경주 할 16 개의 시험 승수 세트를 생성하는 소수 ({3, 5, 7, 11})를 생성하면 알고리즘은 하드 세미 프라임에서 약 2 ^ -16의 시간에 실패합니다. 소수 목록에 13을 추가하면 32 개의 시험 곱셈기가 생성되어 실패 확률을 약 2 ^ -32로 줄이며 추가 계산 비용없이 결과를 획기적으로 개선합니다 (2 배의 곱셈기가 동시에 경주하기 때문에 평균은 여전히 ​​동일한 총 단계 수에서 답을 찾습니다).

답변:


18

순수한 배쉬, 32 바이트

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

명령 행 인수로 전달 된 입력 목록 (단일 공백으로 구분)을 읽습니다.

세 가지 다른 쉘 확장이 사용됩니다.

  1. ${1// /\}*{1,}A는 매개 변수 확장 에 공백을 대체 2 3 5 7와 함께 }*{1,제공하는이 2}*{1,3}*{1,5}*{1,7. \$[{1,그리고 }]시작과 끝에 각각 추가되어 \$[{1,2}*{1,3}*{1,5}*{1,7}]. 는 \$[백 슬래시 이스케이프이 단계에서 연산 확장을 할 시도를 방지하는 것입니다.
  2. \$[{1,2}*{1,3}*{1,5}*{1,7}]A는 중괄호 확장은 . 때문에 중괄호 확장은 일반적으로 매개 변수 확장 전에 발생 , 우리는 사용해야 사용하십시오 eval첫번째 일이 매개 변수 확장을 강제로. 가새 확장의 결과는 $[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]산술 확장 목록이며 , 필요한 숫자 목록을 제공하기 위해 평가됩니다.

산출:

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

3
마음 ... 부는 ...와!
Todd Lehman

Wtf ... 내가 얻는1 0
username.ak

@ username.ak 입력 내용은 무엇입니까? 어떻게 입력합니까 (명령 줄 인수)? 어떤 버전의 bash를 실행하고 있습니까? bash --version
Digital Trauma

12

CJam, 13 바이트

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

[2 3 5 7]STDIN에서 배열 (예 :)을 읽습니다 . 온라인으로 사용해보십시오.

익명 함수는 동일한 바이트 수를 갖습니다.

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

예제 실행

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

작동 원리

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

4
와우, 그것은 모든 부분 집합을 반복하는 영리한 방법입니다.
Martin Ender

9

하스켈, 22

해결책은 익명의 기능입니다.

map product.mapM(:[1])

사용법 예 :

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

설명 :
(:[1]) 숫자 x가 주어진 목록을 반환 하는 함수입니다 [x,1].
mapM(:[1])숫자 목록이 주어진 함수 (:[1])는 그 위에 함수 를 매핑하고 모든 목록에서 요소를 선택하는 가능한 모든 방법을 반환 하는 함수 입니다. 예를 들어, mapM(:[1]) $ [3,4]먼저 함수를 get에 매핑합니다 [[3,1] , [4,1]]. 다음 가능한 선택이된다 [3,4](모두의 첫 번째 숫자를 선택) [3,1] [1,4]하고 [1,1]그래서 반환합니다 [[3,4],[3,1],[1,4],[1,1]].

그런 다음 map product모든 선택 사항 을 매핑하고 원하는 출력 인 제품을 반환합니다.

이 함수는 모든 유형의 숫자에서 작동 할 수 있다는 의미에서 다형성입니다. 목록을 입력 Int하면 결과가 목록이 Int되지만 유형 목록에도 적용 할 수 있습니다.Integer의 목록을 반환합니다 Integer. 이는 오버플로 동작이이 함수가 아니라 입력 유형 (yay Haskell의 표현 유형 시스템)에 의해 지정됨을 의미합니다.


좋은! 숫자 크기에 제한이 있습니까?
Todd Lehman

1
@ToddLehman 아뇨. 기본 숫자 유형은 Integer무제한 정수 유형입니다. 이 또한의 Int32 비트 정수는하지만 대부분은 단지 기존의 일이다.
John Dvorak

실제로 @JanDvorak는 그렇습니다. 그러나 언급하지 않을 정도로 형식 시스템을 너무 좋아합니다. :). 주목해야 할 또 다른 사항은 익명이기 때문에 일부 경우에 단일성 제한이 적용될 수 있으므로 사용 방법에 중요하다는 것입니다.
자랑스런 Haskeller

8

매스 매 티카, 18 17 바이트

1##&@@@Subsets@#&

그것은 익명의 기능입니다. 처럼 불러

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

그리고 Martin은 아주 짧은 대답으로 시작했습니다!
Todd Lehman

@ToddLehman 이제이 답을 능가하는 J 응답을 기다립니다. ;)
Martin Ender

1
Mathematica가 비공개 소스가 아닌 경우 누군가 골프 버전을 작성할 수 있습니다. ×@@@𝒫@#타의 추종을 불허해야합니다.
Dennis

@Dennis Wolfram Language 사양은 Mathematica와 독립적으로 사용할 수 있으며 하나 또는 두 개의 (불완전한) 오픈 소스 구현이 있다고 생각합니다. Mathematica의 유니 코드 별명 버전 작성은 몇 번 제안되었지만 PPCG에서 잘 수신 될 것이라고는 생각하지 않습니다. ^^
Martin Ender

2
@ MartinBüttner 기다리게해서 죄송합니다 : (*/@#~2#:@i.@^#)J의 16 자;)
algorithmshark

4

업데이트 : C (기능 f), 92

함수로도 여기에서 가장 긴 항목입니다. C에서 함수 인수로 알 수없는 길이의 배열을 전달한 것은 이번이 처음이며 인수가 포인터로 전달되므로 C 함수가 전달 된 배열의 길이를 알 수있는 방법이 없습니다. 사용 된 구문에 관계없이). 따라서 길이를 나타내려면 두 번째 인수가 필요합니다.

정수 배열을 설정하고 반환하는 것이 거의 확실히 길기 때문에 출력을 stdout으로 유지했습니다.

팁을 준 Dennis에게 감사합니다.

f아래 테스트 프로그램에서 기능 (필요한 공백을 제외한 92 자)을 참조하십시오.

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

배열 포인터를 통한 출력

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 (프로그램), 108

불필요한 공백 제외.

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

명령 행에서 입력하고 stdout으로 출력합니다. C는 여기서 이길 수는 없지만 내일 함수로 변환하려고 시도 할 것입니다.

기본적으로 우리는 모든 1<<c프라임 조합을 반복하며 , 각 비트 i/c는 제품의 특정 프라임의 유무와 관련이 있습니다. 은 "내부 루프" i%c의 값에 따라 이들 승산 소수 통해 실행 i/c.하면 i%c, 제품은 그 다음 "외부"반복에 대해 1로 설정 출력에 도달 0이다.

흥미롭게도 printf("%d ",p,p=1)작동하지 않습니다 (항상 1을 인쇄합니다). 값이에 사용되고 printf나중에 동일한 괄호에 할당 될 때 이상한 동작을 본 것은 처음이 아닙니다 . 이 경우 두 번째 쉼표를 인수 구분 기호로 취급하지 않고 연산자로 취급 할 수 있습니다.

용법

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

C는 인수가 평가되는 순서를 엄격하게 정의하지 않습니다. 특히 많은 C 함수 호출에는 오른쪽에서 왼쪽으로 인수가 평가됩니다.
COTO

ISO / IEC 9899 의 섹션 6.5.2.2:TC3 : 함수 지정자의 평가 순서, 실제 인수 및 실제 인수 내의 하위 표현식은 지정되지 않습니다 [.] 따라서 함수의 순서는 컴파일러에 달려 있습니다. 인수가 평가됩니다. 로 -Wsequence-point또는 -Wall, GCC는 불평 할 것이다.
Dennis

1. 당신은 변경할 수 있습니다 c-=1c--또는 사용 i=--c<<c이 UB 마음을하지 않는 경우 (이 GCC와 함께 작동하는 것 같다). 2. 두 용도는 ||원 사업자로 대체 할 수 있습니다 p=i%c?p:!!printf("%d ",p)p*=(i/c>>i%c)&1?1:atoi(v[i%c+1])
데니스

@Dennis 팁 주셔서 감사합니다! 잠자리에 들기 전에 프로그램을 실행했습니다. c-=1그런 기본적인 골프입니다.하지만 놓칠 수는 없지만 argv (프로그램 이름)에 하나의 추가 문자열이 i=..c<<cGCC / cygwin에서 작동 한다는 것을 잊었 기 때문에 빠른 버그 수정이었습니다. 하지만 원래는 그대로 두었습니다. 프로그램을 그대로 유지하고 기능으로 넘어갑니다. 그래서 방금 sizeof함수 인수로 전달 된 배열에서 작동하지 않는다는 것을 알게 되었습니다. 삼항 연산자에 대한 제안을 함수에 통합했습니다. 배열을 반환하는 짧은 방법이 없으므로 stdout에 출력이 붙어 있습니다.
Level River St

예, 함수 인수로 전달 된 배열은 포인터로 붕괴합니다. -C에서 결과를 함수 매개 변수로 포함해야하는 포인터를 배열에 전달하는 것은 드문 일이 아닙니다. 문제는 제품이 2 ^ 31보다 작다고 가정 할 수 있으므로 512 크기의 배열 만 전달하면된다는 것입니다.
Dennis

3

하스켈, 27 바이트

이것은 @sudo의 CJam 응답을 익명 함수로 Haskell 구현 한 것입니다. @proud haskeller의 멋진 Haskell 솔루션을 능가하지는 않지만 어쨌든 여기에 놓을 것입니다.

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

설명 : foldr 이진 함수, 값 및 목록을받습니다. 그런 다음 함수의 응용 프로그램으로 목록의 각 cons 셀을 대체하고 다음과 같이 목록 끝을 값으로 대체합니다 foldr f v [a,b,c] == f a (f b (f c v)). 우리의 값은을 포함하는 단일 요소 목록 1이며 이진 함수는 f = (=<<)(++).map.(*)입니다. 이제 f숫자를 취 n함수하게 (n*)곱하여가 n, 그로부터 만드는 기능 g = map(n*)리스트의 모든 요소에 해당 함수를 적용하고, 피드 해당 하는 기능 (=<<)(++). 여기에서, (++)병합 함수이며, (=<<)이다 모나드 바인딩 이 경우에 소요 (++)하고 g, 적용되며, 목록에서 취하는 함수를 준다g 그것의 사본에, 그리고 둘을 연결합니다.

한마디로 :로 시작 하고 입력 목록의 [1]각 숫자 n에 대해 현재 목록의 사본을 가져 와서 모든 것을 곱한 다음 현재 목록에 n추가하십시오.


3

파이썬 : 55 자

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

각 번호를 차례로 포함하거나 제외하도록 선택하여 제품을 재귀 적으로 생성합니다.


재귀 솔루션! 시원한!
Todd Lehman

and다른 방법으로 합계를 쓰면 공백을 놓을 수 있다고 생각 합니까?
mathmandan

@mathmandan Yup, 작동합니다. 감사합니다.
xnor

3

PARI / GP , 26 바이트

v->divisors(factorback(v))

더 긴 버전은 다음을 포함합니다

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

(30 바이트) 및

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

(31 바이트).

입력이 세트가 아닌 인수 분해 행렬 인 경우 divisors단독으로 사용하여 18 바이트를 저장할 수 있습니다 . 그러나 집합을 인수 분해 행렬로 변환하는 데 18 바이트 이상이 필요한 것 같습니다. (나는 v->concat(Mat(v~),Mat(vectorv(#v,i,1)))곱하고 리팩토링 하여 39 바이트 또는 24 바이트 로 직접 v->factor(factorback(v))할 수 있습니다. 누가 더 잘 할 수 있습니까?)


2

세이지 – 36 34

본질적으로 Martin Büttner의 솔루션 과 동일 합니다. 의견에서 언급했듯이 답변으로 게시 할 수도 있습니다.

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

이것은 익명 함수이며, 예를 들어 다음과 같이 호출 할 수 있습니다.

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

1
익명 함수 (질문에 의해 허용됨)로 2 바이트를 면도 할 수 있습니다
자랑스러운 haskeller

2

J (20)

이것은 내가 기대했거나 예상했던 것보다 오래 걸렸습니다.

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

용법:

    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

이것은 소수뿐만 아니라 모든 숫자 세트에서 작동합니다. 또한 배열에 접미사가있는 경우 소수는 무제한 크기가 될 수 있습니다 x.2 3 5 7x


*/@#~2#:@i.@^#14 바이트의 대안입니다.
마일


1

R, 56 바이트

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

나는 여기서 s가 세트 (및 목록)라고 생각하고 있습니다. 더 짧아 질 수 있다고 확신합니다. 볼게요


1

PHP, 97 바이트

<?for(;$i++<array_product($a=$_GET[a]);){$t=$i;foreach($a as$d)$t%$d?:$t/=$d;if($t<2)echo"$i\n";}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.