최단 가산 체인


23

추가 체인은 1로 시작하는 일련의 정수이며 초기 1 이외의 모든 정수는 2 개의 이전 정수의 합입니다.

예를 들어 다음은 추가 체인입니다.

[1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

추가 체인으로 만드는 합계는 다음과 같습니다.

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
3 + 4 = 7
1 + 7 = 8
8 + 8 = 16
16 + 16 = 32
7 + 32 = 39
32 + 39 = 71

이 과제에서는 양의 정수가 주어지며로 n끝나는 가장 짧은 덧셈 체인 중 하나를 출력해야합니다 n.

예-가능한 많은 출력이 있다는 것을 명심하십시오. 찾아야 할 모든 것은 짧은 짧은 추가 체인입니다.

1: [1]
2: [1, 2]
3: [1, 2, 3]
4: [1, 2, 4]
5: [1, 2, 3, 5]
6: [1, 2, 3, 6]
7: [1, 2, 3, 4, 7]
11: [1, 2, 3, 4, 7, 11]
15: [1, 2, 3, 5, 10, 15]
19: [1, 2, 3, 4, 8, 11, 19]
29: [1, 2, 3, 4, 7, 11, 18, 29]
47: [1, 2, 3, 4, 7, 10, 20, 27, 47]
71: [1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

표준 I / O 규칙 등 표준 허점이 금지되었습니다. 코드 골프 : Fewest bytes가 승리합니다.




1
체인을 역순으로 출력 할 수 있습니까?
Arnauld

@Arnauld 아니요,이 특정 주문입니다.
isaacg

답변:


6

하스켈 , 57 바이트

c=[1]:[x++[a+b]|x<-c,a<-x,b<-x]
f n=[x|x<-c,last x==n]!!0

무차별 대입 솔루션. 온라인으로 사용해보십시오!

설명

무한리스트 c는 길이에 따라 순서대로 모든 추가 체인을 포함합니다. 이 요소 는 목록 x에서 c두 개의 요소를 가져 와서 x합계를에 추가하여 자체적으로 귀납적으로 정의 됩니다 x. 이 함수 fc원하는 숫자로 끝나는 첫 번째 목록을 찾습니다 .

c=            -- c is the list of lists
 [1]:         -- containing [1] and
 [x           -- each list x
  ++[a+b]     -- extended with a+b
 |x<-c,       -- where x is drawn from c,
  a<-x,       -- a is drawn from x and
  b<-x]       -- b is drawn from x.
f n=          -- f on input n is:
 [x           -- take list of those lists x
 |x<-c,       -- where x is drawn from c and
  last x==n]  -- x ends with n,
 !!0          -- return its first element.

4

Brachylog , 14 바이트

∧≜;1{j⊇Ċ+}ᵃ⁽?∋

온라인으로 사용해보십시오!

올바른 인수를 포함하는 체인이 발견되면 중지하면서 반복 심화를 사용하여 가능한 모든 추가 체인을 작성하는 무차별 제출. 대부분의 Brachylog 제출과 달리, 이것은 오른쪽 인수 (일반적으로 출력이라고 함)를 통해 입력하고 왼쪽 인수 (일반적으로 입력이라고 함)를 통해 출력하는 함수 제출입니다. 이를 수행하는 것은 다소 논란의 여지가 있지만 주제에 대해 가장 많이 투표 된 메타 답변 은 합법적이라고 말합니다 (그리고 그렇게하는 것은 기능에 대한 일반적인 I / O 기본값과 일치합니다). 보다 일반적인 방식으로 입력과 출력을 사용한 경우 16 바이트 (∧≜;1{j⊇Ċ+}ᵃ⁽.∋?∧), 프로그램의 오른쪽이 암시 적 제약 조건을 사용할 수 없기 때문에 (2 바이트의 비용으로 비활성화 및 새로운 명시 적 제약 조건이 필요함).

설명

∧≜;1{j⊇Ċ+}ᵃ⁽?∋
∧               Disable implicit constraint to read the left argument
 ≜;        ⁽    Evaluation order hint: minimize number of iterations
    {    }ᵃ     Repeatedly run the following:
   1      ᵃ       From {1 on the first iteration, results seen so far otherwise}
     j            Make {two} copies of each list element
      ⊇           Find a subset of the elements
       Ċ          which has size 2
        +         and which sums to {the new result for the next iteration}
             ∋    If the list of results seen so far contains {the right argument}
            ?     Output it via the left argument {then terminate}

여기서 흥미로운 미묘한 점은 첫 번째 반복에서 발생하는 것입니다. 여기서 입력은 다른 반복과 같은 목록이 아닌 숫자입니다. 우리는 숫자 1로 시작하고 모든 숫자의 사본 두 개를 만들고 (숫자 11을 만든 후) 2 자리 하위 시퀀스 (숫자 11)를 찾습니다. 그런 다음 우리는 2의 숫자 합계를 취하므로 [1,2]원하는 순서가 시작됩니다 . 미래의 반복에, 우리는 같은 목록을 시작하고 [1,2]그것을 배로, [1,2,1,2](다음 두 요소의 서브 순서를 복용, [1,1], [1,2], [2,1], 또는 [2,2]); 분명히, 이들 각각의 합은 추가 체인의 다음 요소가 될 것입니다.

여기서 평가 순서 힌트, 특히 구성 요소 ( 기본적으로 평가 순서 힌트를 기본적으로 외부가 아닌 내부 에서 가져 와서 문제를 강제하기 위해 다소 거친 사용으로 나타남)가 필요합니다 .


나는이 도전을 수행하는 짧은 방법을 찾기 위해 약 30 분 동안 시도했습니다. 내 솔루션은 이것보다 길었습니다.
치명적

1
@ Fatalize : 드물게 나오는 내장 중 하나이지만 다른 컨트롤 구문을 사용하여 원격으로 구현할 수있는 방법이 없기 때문에 필요할 때 실제로 필요합니다. 이것이 도전 이라는 것을 깨달았을 때 , 나머지는 거기에서 직접왔다.

2

젤리 , 17 바이트

’ŒP;€µ+þ;1Fḟ@µÐḟḢ

사전 식으로 첫 번째 솔루션을 지수 시간으로 출력합니다.

온라인으로 사용해보십시오!

작동 원리

’ŒP;€µ+þ;1Fḟ@µÐḟḢ  Main link. Argument: n (integer)

’                  Decrement; n-1.
 ŒP                Powerset; generate all subarrays of [1, ..., n-1], sorted first
                   by length, then lexicographically.
   ;€              Append n to all generate subarrays.
     µ       µÐḟ   Filterfalse; keep only subarrays for which the chain between the
                   two chain separators (µ) returns a falsy value.
     µ             Monadic chain. Argument: A (array of integers)
      +þ               Add table; compute the sums of all pairs of elements in x,
                       grouping the results by the right addend.
        ;1             Append 1 to the resulting 2D array.
          F            Flatten the result.
           ḟ@          Filterfalse swapped; remove all elements of A that appear in
                       the result. This yields an empty list for addition chains.
                Ḣ  Head; select the first result.

2

자바 스크립트 (ES6), 83 86 바이트

편집 : 목록을 역순으로 출력하도록 수정되었습니다.

n=>(g=(s,a=[1])=>s-n?s>n||a.map(v=>g(v+=s,a.concat(v))):r=1/r|r[a.length]?a:r)(r=1)&&r

데모


2

PHP, 195 바이트

function p($a){global$argn,$r;if(!$r||$a<$r)if(end($a)==$argn)$r=$a;else foreach($a as$x)foreach($a as$y)in_array($w=$x+$y,$a)||$w>$argn||$w<=max($a)?:p(array_merge($a,[$w]));}p([1]);print_r($r);

온라인으로 사용해보십시오!


불행히도이 알고리즘은 최적의 해답을 제공하지 않습니다 (예 : 15).
Neil

@ Neil 이제는 더 길지만 작동합니다. 나는 두 가지 방법 중 어느 것이 올바른 방법인지 결정하는 방법을 모릅니다. 아마도 소수가 중요한 역할을 할 것입니다
Jörg Hülsermann

이 코드는 149 테스트를 통과하지 못합니다. 길이는 11이 아닌 10이어야합니다.
J42161217

@Jenny_mathy 수정
Jörg Hülsermann

1

Mathematica, 140 바이트

t={};s={1};(Do[While[Last@s!=#,s={1};While[Last@s<#,AppendTo[s,RandomChoice@s+Last@s]]];t~AppendTo~s;s={1},10^4];First@SortBy[t,Length@#&])&

.

당신이 그것을 실행할 때마다 다른 가장 짧은 추가 체인을 생성

온라인
으로 ctrl + v를 사용하여 코드를 붙여넣고 코드 끝에 입력 (예 : [71])을 입력 한 다음 Shift + Enter를 누르십시오.


Mathematica에 액세스 할 수 없으므로 15의 입력에 대해 체인의 길이는 얼마입니까?
Neil

올바른 것 {1, 2, 3, 5, 10, 15}
J42161217

3
입력 149의 경우 프로그램에서 길이 11의 체인을 얻었지만 길이 10 ( [1,2,4,5,9,18,36,72,77,149]) 중 하나가 있습니다 . 프로그램이 무작위 샘플링을 사용하는 것으로 보이며 최적의 솔루션을 찾지 못할 수도 있습니다.
Zgarb

결정된! 하지만 시간이 더 오래 걸립니다
J42161217

1

Pyth, 13 바이트

h-DsM^N2/#QyS

테스트 스위트

사 전적으로 가장 짧은 체인을 제공합니다. 꽤 느리지 만 그렇게 나쁘지는 않습니다 19-pypy를 사용하여 약 30 초 안에 완료됩니다.

@Dennis 솔루션의 아이디어.

나는 이것을 정말로 좋아한다-많은 깔끔한 트릭이 관련되어있다.

설명:

h-DsM^N2/#QyS
h-DsM^N2/#QySQ    Implicit variable introduction
            SQ    Inclusive range, 1 to input.
           y      Subsets - all subsets of the input, sorted by length then lexicographically
                  Only sorted subsets will be generated.
                  Our addition chain will be one of these.
        /#Q       Filter for presence of the input.
  D               Order by
 -                What's left after we remove
     ^N2          All pairs of numbers in the input
   sM             Summed
h                 Output the list that got sorted to the front.

이것은 여전히 ​​이해하기 어렵지만 좀 더 자세히 설명해 드리겠습니다.

로 시작하여 ySQ모든 가능한 정렬 된 부분 집합 [1, 2, ... Q]을 크기 순서대로 증가시킵니다. 가장 짧은 추가 체인은 분명히 이들 중 하나이지만 우리는 그것을 찾아야합니다.

가장 먼저 할 일은을 포함하는 목록 만 유지하도록 목록을 필터링하는 것 Q입니다. 우리는이 작업을 수행합니다 /#Q.

다음으로, 우리는 특정 함수의 결과를 제거한 후 남은 것을 기준으로 목록을 정렬합니다. -D무언가를 제거한 후 나머지 주문.

물건의 우리의 제거는 sM^N2곳, N우리가에서 사물을 제거하고 목록입니다. ^N2의 데카르트 곱을 N두 요소의 가능한 모든 쌍으로 제공합니다 N. sM그런 다음 각 쌍을 합산합니다.

제거 후 가장 작은 결과는 무엇입니까? 음, 모든 숫자가 양수이므로 입력 목록에서 가장 작은 요소는 그대로 유지되므로 두 숫자의 합계는 가장 작은 숫자보다 큽니다. 입력이 목록에 있는지 확인했기 때문에 하나 이상의 숫자가 있습니다. 따라서 가장 작은 숫자를 제외한 모든 숫자가 목록에서 다른 두 숫자의 합이고 목록에서 가장 작은 숫자가 1 인 경우 가능한 가장 작은 결과가됩니다.이 경우 정렬 키는입니다 [1]. 이러한 요구 사항은 목록이 추가 체인이어야한다는 것을 의미합니다.

그래서 우리는 추가 체인을 앞에 정렬합니다. 그 기억 y앞에 정렬 목록이 짧은 또한 체인 중 하나 여야합니다, 그래서 크기의 증가하는 순서에서의 부분 집합을 제공합니다. h해당 목록을 선택합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.