페르마의 다각형 수 정리


24

Fermat의 다각형 수 정리 는 모든 양의 정수가 최대 n n 곤수 의 합으로 표현 될 수 있음을 나타 냅니다. 모든 양의 정수가 삼각형의 세 숫자 네 정사각 수 다섯 오각 수 등 내 작업은 양의 정수 인출하는 최대의 합으로 표현 될 수 있음이 수단 x , 그리고 정수 s3 , 출력에 s -gonal 에있는 정수 합 x .

n 번째 s -gonal 정수, n1 과는 s3 , 몇 가지 방법으로 정의 할 수 있습니다. 수학이 아닌 방법은 n 번째 s gonal 수를 각각 길이가 n 인 s 면을 가진 일반 다각형으로 구성 할 수 있다는 것 입니다. 예를 들어, s = 3 (삼각 숫자)의 경우 :ns=3

삼각형

s 가 더 큰 예제는 여기 를 참조 하십시오 .s

math-y 정의는 P(n,s) 대한 공식을 사용 하여 n 번째 s 곤수 를 산출합니다 .

P(n,s)=n2(s2)n(s4)2

이것은 Wikipedia 페이지 에서 제공 됩니다.

입력

두 양의 정수, sx 조건으로, s3 . 언어에서 가장 자연스럽게 표현 된 정수 (10 진수, 단항, 교회 숫자, 정수 값 부동 소수점 숫자 등)를 입력 할 수 있습니다.

산출

정수의리스트 L 의 최대 길이, s 의 합계, L 동일하다 x 및 모든 정수 L 있다 s -gonal 정수. 다시 말하지만, 정수는 명확하고 일관된 구분 기호를 사용하여 언어의 자연스러운 표현으로 출력 될 수 있습니다 (따라서 십진 출력의 비 10 진수 문자, 단항 출력에 사용되는 것과 다른 문자)

규칙

  • 입력 또는 출력은 언어의 정수 제한을 초과하지 않습니다
  • L 은 주문할 필요가 없습니다
  • 여러 개의 가능한 출력의 경우, 일부 또는 전부가 허용됩니다
  • 이것은 이므로 바이트 단위의 가장 짧은 코드가 승리합니다.

테스트 사례

   x,  s => L
   1,  s => 1
   2,  s => 1, 1
   5,  6 => 1, 1, 1, 1, 1
  17,  3 => 1, 6, 10
  17,  4 => 1, 16
  17,  5 => 5, 12
  36,  3 => 36
  43,  6 => 15, 28
 879, 17 => 17, 48, 155, 231, 428
4856, 23 => 130, 448, 955, 1398, 1925


출력에 제로 패딩이있을 수 있습니까? 예를 들어, 우리가 생각하는 대신 그냥 x=17, s=5출력 할 수 있습니까? 5,12,0,0,05,12
flawr

@flawr 배열의 길이가 초과하지 않는 한 , 패딩을해도 괜찮습니다s
caird coinheringaahing

반복이 허용 Q됩니까? 또는 제출물에을 추가해야 합니까?
Jonathan Allan

@JonathanAllan 반복 출력은 완벽하게 훌륭합니다 (여러 솔루션을 출력하는 경우)
caird coinheringaahing at

답변:



6

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

출력의 가장 작은 항을 최대화하는 빠른 재귀 검색

로 입력을 (s)(x)받습니다.

s=>g=(x,n=0,a=[],y=~n*(~-n-n*s/2))=>x<y?x|a[s]?0:a:g(x,n+1,a)||g(x-y,n,[...a,y])

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

공식

sn=0P(n+1,s):

P(n+1,s)=((n+1)2(s2)(n+1)(s4))/2=(n2(s2)+ns+2)/2=(n+1)((n1)ns/2)

which can be written in 14 bytes:

~n*(~-n-n*s/2)

Commented

s =>                         // main function taking s
  g = (                      // recursive function g
    x,                       // taking x
    n = 0,                   // start with n = 0
    a = [],                  // a[] = list of s-gonal numbers
    y =                      // y = P(n + 1, s)
      ~n * (~-n - n * s / 2) //   = -(n + 1) * ((n - 1) - n * s / 2)
  ) =>                       //
    x < y ?                  // if x is less than P(n + 1, s):
      x | a[s] ?             //   if x is not equal to 0 or a[] is too long:
        0                    //     failed: return 0
      :                      //   else:
        a                    //     success: return a[]
    :                        // else:
                             //   process recursive calls:
      g(x, n + 1, a) ||      //   preferred: try to increment n
      g(x - y, n, [...a, y]) //   fallback : try to use the current s-gonal number

@AZTECCO I may try to fix it later. Removed for now.
Arnauld

Thanks. Waiting for it!
AZTECCO


4

Haskell, 55 bytes

n%s=[l|l<-mapM(\_->scanl(+)0[1,s-1..n])[1..s],sum l==n]

Try it online!

Outputs all possible solutions. Defines the s-gonal numbers as the cumulative sum of the arithmetic progression

1, s-2, 2*s-3, 3*s-4, ...

3

Jelly, 17 bytes

x’2;’ÄÄx⁸ŒPS⁼¥Ƈ⁹Ḣ

A (very very inefficient) dyadic Link accepting s on the left and x on the right which yields the shortest possible answer as a list of integers (sorted ascending).

Try it online! - not much point trying it for much higher values!

How?

x’2;’ÄÄx⁸ŒPS⁼¥Ƈ⁹Ḣ - Link: s, x                    e.g.  5, 17
x                 - repeat (s) (x) times                [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
 ’                - decrement (vectorises)              [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
  2;              - prepend a two                       [2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
    ’             - decrement (vectorises)              [1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
     Ä            - cumulative sums                     [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52]
      Ä           - cumulative sums                     [1, 5, 12, 22, 35, 51, 70, 92, 117, 145, 176, 210, 247, 287, 330, 376, 425, 477]
       x⁸         - repeat (each of those) (s) times    [1, 1, 1, 5, ..., 425, 477, 477, 477]
         ŒP       - power-set                           [[], [1], [1], ..., [1, 1], ..., [5, 22, 70], ... etc]
                      (this has 2^(x(s+1)) entries ...this example would have 2^(17(5+1)) = 2^102 = 5070602400912917605986812821504 entries!)
                      (Note: the lengths increase left to right)
              Ƈ   - filter keep if:
             ¥    -   last two links as a dyad:
           S      -     sum
            ⁼  ⁹  -     equals (x)?                     [[5,12], ... , [5,12], [1, 1, 5, 5, 5], ... , [1, 1, 5, 5, 5], [1, 1, 1, 1, 1, 12], ...]
                Ḣ - head                                [5,12]

@AZTECCO That's perfectly fine, it times out on TIO there at 60 seconds (I'm pretty sure even far smaller input number than that will time out). As I point out in my answer, this is "very very inefficient" and that there's "not much point trying it for much higher values!". Remember, the code given for a code-golf solution only need work given infinite resources.
Jonathan Allan

ok I tested with s=3 and n=5 and it taken 12 seconds!! I like this inefficient solution and I'll trust you, even if it's almost impossible to test it :) thank you!
AZTECCO

1
@AZTECCO Indeed, it's hard to test - I originally did not have the so was repeating the elements of the cumulative sum result x times each rather than s times each (which is incorrect) and it was hard to spot that it was actually doing anything wrong without running just parts of the code!
Jonathan Allan

3

Ruby, 79 bytes

Computes the first n s-gonal numbers and zero, gets the cartesian product of itself s times, and finds the first entry that matches. Later test cases run out of memory on TIO but theoretically work.

n2(s2)n(s4)2 is reorganized into n(ns2ns+4)2 because it saves bytes in Ruby.

->n,s{a=(0..n).map{|i|i*(i*s-2*i-s+4)/2};a.product(*[a]*~-s).find{|a|a.sum==n}}

Try it online!



2

Retina, 111 bytes

\d+
*
~(`$
$"
0%["^_+ "|""]'$L$`\G_(?<=(?=___(_*))_+)
((_(?($.(2*$>`))$1\$.(2*$>`)))$*)
1%|' L$`\G_
$$.$.($`$>`

Try it online! Link includes test cases. Takes input in the order s n. Explanation:

\d+
*

Convert to unary.

~(`

After processing the remaining stages, treat them as a Retina program and execute them on the same input.

$
$"

Duplicate the line.

0%["^_+ "|""]'$L$`\G_(?<=(?=___(_*))_+)
((_(?($.(2*$>`))$1\$.(2*$>`)))$*)

Replace the first copy with a regular expression that skips over the first number and then matches s s-gonal numbers. The numbers themselves are captured in odd capture groups and the even capture groups are used to ensure that all of the numbers are s-gonal.

1%|' L$`\G_
$$.$.($`$>`

Replace the second copy with a space-separated list of the odd capture groups.

As an example, the generated code for an input of 5 17 is as follows:

^_+ ((_(?(2)__\2))*)((_(?(4)__\4))*)((_(?(6)__\6))*)((_(?(8)__\8))*)((_(?(10)__\10))*)$
$.1 $.3 $.5 $.7 $.9

1

APL(NARS), 149 chars, 298 bytes

r←f w;n;s;i;k
(n s)←w⋄r←⍬⋄→0×⍳s<3⋄i←1
→0×⍳n<k←2÷⍨(i×i×s-2)-i×s-4⋄r←r,k⋄i+←1⋄→2

h←{0=≢b←((v←↑⍵)=+/¨a)/a←{0=≢⍵:⊂⍬⋄m,(⊂1⌷⍵),¨m←∇1↓⍵}f⍵:v⍴1⋄k←↑⍋≢¨b⋄k⊃b}

if not find solutions "0=≢b" than return for (n s) input, n times 1; else it would return the sum of s numbers that has less addend...

test:

  h 1 3
1 
  h 2 8
1 1 
  h 5 6
1 1 1 1 1 
  h 17 3
1 6 10 
  h 17 4
1 16 
  h 17 5
5 12 
  h 36 3
36 
  h 43 6
15 28 
  h 879 17
17 48 155 231 428 
  h 4856 23
321 448 596 955 2536 
  +/h 4856 23
4856

The problem of this: It not find some solution has some number repeat in the sum...


0

C++ (clang), 198 bytes

#import<vector>
using V=std::vector<int>;V f(int n,int s){V _{0};int z=1,a=0,b=1,i,t;for(;a<n;b+=s-2)_.push_back(a+=b),++z;V o;for(t=a=0;t-n;b=++a)for(o=V(s),t=i=0;b;b/=z)t+=o[i++]=_[b%z];return o;}

Try it online!

V=vector<int> 
V _{0}; // initialized with one element =0 
int z=1, // vector size 
a=0,b=1,i,t;for(;a<n;b+=s-2)_.push_back(a+=b),++z;
// pushes polygons in V
V o; // vector to be returned 
for(t=a=0;t-n;b=++a) // ends when t=n
// loop to generate multi-dimension indexes
// for example a=1234 z=10
// a%z->4 , a/=z , a%z-> 3 , ... 2 , 1
for(o=V(s),t=i=0;b;b/=z)// loop to extract indexes
t+=o[i++]=_[b%z]; // put the sum in t and values in o
return o
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.