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


24

Теорема полігональних чисел Ферма стверджує, що кожне додатне ціле число може бути виражене сумою не більше н н -гональних чисел. Це означає, що кожне додатне ціле число може бути виражене сумою до трьох чисел трикутника, чотирьох квадратних чисел, п'яти п’ятикутних чисел тощо. Ваше завдання - взяти додатне ціле число х , ціле число с3 і вивести с -гональні цілі числа, які дорівнюють х .

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

трикутники

Дивіться тут приклади з великим с .

Визначення math-y здійснюється за допомогою формули для П(н,с) , яка дає н -го с -гонального числа:

П(н,с)=н2(с-2)-н(с-4)2

яка наведена тут на сторінці Вікіпедії .

Вхідні дані

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

Вихідні дані

Список цілих чисел, L , з максимальною довжиною с , де сума L дорівнює х а всі цілі числа в L - с -гональні цілі числа. Знову-таки, цілі числа можуть бути виведені в натуральному поданні на вашій мові з будь-яким чітким, послідовним роздільником (таким чином, недесятковим символом для десяткового виводу, символом, відмінним від того, який використовується для одинакового виведення тощо).

Правила

  • Входи або виходи ніколи не перевищуватимуть цілої межі для вашої мови
  • 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,0замість просто 5,12?
недолік

@flawr Поки довжина масиву не перевищує , навіть з підкладкою, це добрес
caird coinheringaahing

Чи дозволено повторення чи слід додати Qдо моєї подачі?
Джонатан Аллан

@JonathanAllan Повторні виходи ідеально чудові (якщо виводиться декілька рішень)
caird coinheringaahing

Відповіді:


6

Haskell , 78 80 77 байт

Ми обчислюємо декартовий добуток першого н s-гональних чисел, а потім знаходимо перший запис, який дорівнюєн .

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

Спробуйте в Інтернеті!


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 для обчислення с -гональних чисел у JS, тобто для початку з н=0 та для обчислення П(н+1,с) :

П(н+1,с)=((н+1)2(с-2)-(н+1)(с-4))/2=(н2(с-2)+нс+2)/2=-(н+1)((н-1)-нс/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

@AZTECCO Я можу спробувати виправити це пізніше. Наразі видалено.
Арнольд

Спасибі. Чекаю!
AZTECCO



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
хс



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

Проблема в цьому: це не знайде якесь рішення має деяку кількість повторень у сумі ...


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.