Теорема Ферма о полигональных числах

24

Теорема Ферма о полигональных числах утверждает, что каждое положительное целое число может быть выражено как сумма не более чем -угольных чисел. Это означает, что каждое положительное целое число может быть выражено как сумма до трех треугольных чисел, четырех квадратных чисел, пяти пятиугольных чисел и т. Д. Ваша задача состоит в том, чтобы взять положительное целое число и целое число и вывести -угольные целые числа, которые суммируются с .n nxs3sx

В -й -gonal целым числом, где и , может быть определено в несколькими способами. Нематематический способ состоит в том, что е -угольное число может быть построено как правильный многоугольник с сторонами, каждая из которых имеет длину . Например, для (треугольные числа):NsN1s3nssns=3

треугольники

Смотрите здесь примеры с большими .s

Математика у-определение, используя формулу для , что дает -й -gonal номер:P(n,s)ns

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

который приведен на странице Википедии здесь .

вход

Два натуральных числа и с условием . Вы можете ввести эти целые числа в наиболее естественном представлении на вашем языке (десятичные, унарные, церковные цифры, целочисленные числа с плавающей запятой и т. Д.).sxs3

Выход

Список целых чисел с максимальной длиной , где сумма равна а все целые числа в являются -угольными целыми числами. Снова, целые числа могут быть выведены в естественном представлении на вашем языке, с любым отличным, непротиворечивым разделителем (таким образом, недесятичный символ (ы) для десятичного вывода, символ, отличный от того, который используется для унарного вывода и т. Д.)LsLxLs

правила

  • Входы или выходы никогда не превысят целочисленное ограничение для вашего языка
  • 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
Caird Coneheringaahing
источник
Песочница пост
Caird Coneheringaahing
Может ли вывод иметь нулевое заполнение? Например, если мы рассмотрим, x=17, s=5можем ли мы вывести 5,12,0,0,0вместо просто 5,12?
flawr
@flawr До тех пор, пока длина массива не превышает , даже с s
отступами
Разрешено ли повторение или я должен добавить Qк своему представлению?
Джонатан Аллан
@JonathanAllan Повторные выходы прекрасно (если выводят несколько решений)
caird coinheringaahing

Ответы:

6

Haskell , 78 80 77 байт

Мы вычисляем декартово произведение первых N s-гональных чисел, а затем находим первую запись, которая суммирует с N .

s#n=[x|x<-mapM(map(\n->s*(n^2-n)`div`2+n*(2-n)))([0..n]<$[1..s]),sum x==n]!!0

Попробуйте онлайн!

flawr
источник
6

JavaScript (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])

Попробуйте онлайн!

формула

Оказывается, короче использовать формулу, основанную на 0, для вычисления s -гональных чисел в JS, то есть для начала с Nзнак равно0 и для вычисления п(N+1,s) :

п(N+1,s)знак равно((N+1)2(s-2)-(N+1)(s-4))/2знак равно(N2(s-2)+Ns+2)/2знак равно-(N+1)((N-1)-Ns/2)

который может быть записан в 14 байтах:

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

комментарии

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
Arnauld
источник
@AZTECCO Я могу попытаться исправить это позже. Удалено на данный момент.
Арно
Спасибо. Ждет его!
AZTECCO
4

Haskell , 55 байтов

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

Попробуйте онлайн!

Выводит все возможные решения. Определяет s-угольные числа как совокупную сумму арифметической прогрессии

1, s-2, 2*s-3, 3*s-4, ...
XNOR
источник
3

Желе , 17 байт

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

Диадическая ссылка (очень очень неэффективная), принимаемая sслева и xсправа, которая дает кратчайший возможный ответ в виде списка целых чисел (отсортированных по возрастанию).

Попробуйте онлайн! - не так много смысла пробовать это для гораздо более высоких значений

Как?

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 Это прекрасно, время ожидания на TIO составляет 60 секунд (я уверен, что даже намного меньшее входное число будет превышено по времени). Как я отмечаю в своем ответе, это «очень, очень неэффективно», и что «нет особого смысла пробовать это для гораздо более высоких значений!». Помните, что код, данный для решения для игры в гольф, требует только работы с бесконечными ресурсами.
Джонатан Аллан
хорошо, я проверил с s = 3 и n = 5, и это заняло 12 секунд! Мне нравится это неэффективное решение, и я буду вам доверять, даже если его практически невозможно протестировать :) спасибо!
AZTECCO
1
Иксs
3

Рубин , 79 байтов

N ss

N2(s-2)-N(s-4)2N(Ns-2N-s+4)2

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

Попробуйте онлайн!

Значение чернил
источник
2

Сетчатка , 111 байт

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

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Вводит заказ в порядке s n. Объяснение:

\d+
*

Преобразовать в одинарный.

~(`

После обработки оставшихся этапов обработайте их как программу Retina и выполните их на том же входе.

$
$"

Дублируйте строку.

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

Замените первую копию регулярным выражением, которое пропускает первое число, а затем соответствует s s-угольным числам. Сами числа записываются в нечетные группы захвата, а четные группы захвата используются для обеспечения того, чтобы все числа были s-гональными.

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

Замените вторую копию разделенным пробелами списком нечетных групп захвата.

Например, сгенерированный код для ввода 5 17выглядит следующим образом:

^_+ ((_(?(2)__\2))*)((_(?(4)__\4))*)((_(?(6)__\6))*)((_(?(8)__\8))*)((_(?(10)__\10))*)$
$.1 $.3 $.5 $.7 $.9
Нил
источник
1

APL (NARS), 149 символов, 298 байтов

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}

если не найти решения "0 = ≢b", чем вернуть для (ns) ввода, n раз 1; иначе это возвратило бы сумму чисел s, у которой есть меньше сложения ...

тест:

  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

Проблема этого: не найти какое-то решение имеет некоторое число повторений в сумме ...

RosLuP
источник
0

C ++ (лязг) , 198 байт

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

Попробуйте онлайн!

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
AZTECCO
источник