Підрахунок від 1 до n без жодних послідовних чисел


19

Мета

Вам дається ціле число n( n > 1). Ви повинні вивести скільки перестановок цілих чисел 1до nних, які починаються 1, закінчуються в n, і не мають двох послідовних цілих чисел, які відрізняються на 1.

Крім того, якщо ви візьмете повний графік K_nі видалите краї шляху, 1-2-3-...-nви повинні порахувати гамільтонові шляхи від 1до nв графі, що залишився.

Приклади використовуватимуть f(n)для функції, яка приймає nта виводить кількість дійсних перестановок, але ваше подання може бути функцією чи програмою.


Приклади

Бо n = 6можливе рішення є1-3-5-2-4-6

Однак 1-3-5-2-6-4це не є дійсним рішенням, оскільки воно не закінчується 6.

Насправді, для n = 6цього є лише 2 рішення ( 1-4-2-5-3-6це інше).

Звідси f(6) = 2.


Для n = 4єдиних перестановок, які починаються 1і закінчуються, 4є 1-2-3-4і 1-3-2-4. В обох вони 2суміжні з 3, даючи послідовні цілі числа, які різняться на 1. Тому f(4) = 0.


Тестові справи

f(6) = 2
f(4) = 0
f(8) = 68
f(13) = 4462848

Критерій виграшу

Це код-гольф, найкоротша відповідь виграє.


7
Розумієте, діти, ви не можете просто перевірити, скільки перестановок не [2..n-1]містять дельти 1або -1, ви також повинні перевірити, що жодна з них не починається 2або закінчується n-1...
ETHproductions

1
Чи повинен список починатися з 1 і закінчуватися цифрою?
Okx

3
Може, ОП означає «сусідні», а не «послідовні»?
Stilez

6
Странно послідовність тут: algo.inria.fr/libraries/autocomb/graphs99.ps, де на сторінці 6 написано, Q_ser:=z + 2 z^6 + 10 z^7 + 68 z^8 + 500 z^9 + 4174 z^10 + 38774 z^11 + 397584z^12 + 4462848 z^13 + 54455754 z^14я витрачаю деякий час на намагання використовувати формули, але я не можу скласти ту, яка генерує послідовність. Дивовижно бачити показник z z введення формули, а результат - коефіцієнт множення. Той, як можна вивести звідти формулу, може бути такий, який має найкоротшу відповідь у байтах
Крістіан Вестербек

1
@ChristiaanWesterbeek, яку називають функцією генерування послідовності. Існує багато послідовностей з функцією, що генерує, яка має приємнішу закриту форму, ніж сама послідовність, це класні речі!
Кармейстер

Відповіді:


6

MATL , 16 байт

qtq:Y@0&Yc!d|qAs

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

Для входів, що перевищують, 12не вистачає пам'яті.

Пояснення

q      % Implicitly input n. Push n-1
tq     % Duplicate and subtract 1: pushes n-2
:      % Range [1 2 ... n-2]
Y@     % Matrix with all permutations, each in a row
0      % Push 0
&Yc    % Append n-1 and predend 0 to each row
!      % Tranpose
d      % Consecutive differences along each column
|      % Absolute value
q      % Subtract 1
A      % All: true if all values in each column are non-zero
s      % Sum. Implicitly display

1
Працюю чудово, молодець :)
Філіп

1
Хоча в цій проблемі було дуже приємне просування, ваше рішення все ще є найкоротшим. Це також швидше, ніж желе. Конграц!
Філіп

19

Mathematica, 58 байт, поліном ( n ) час

Abs[Sum[(k-1)Hypergeometric2F1[k,k-#,2,2](#-k)!,{k,#}]-1]&

Як це працює

Замість того, щоб повторювати перестановки з грубою силою, ми використовуємо принцип включення-виключення, щоб рахувати їх комбінаторно.

Нехай S - множина всіх перестановок [1,…, n] з σ 1 = 1, σ n = n , а S i - множина перестановок σ ∈ S така, що | σ i - σ i + 1 | = 1. Тоді вважаємо кількість, яку ми шукаємо

| S | - | S 1 ∪ ⋯ ∪ S n - 1 | = ∑ 2 ≤ kn + 1; 1 ≤ i 2 <⋯ < i k - 1 < n (−1) k - 2 | S i 2 ∩ ⋯ ∩ S i k - 1 |.

Тепер, | S i 2 ∩ ⋯ ∩ S i k - 1 | залежить лише від k та від кількості j прогонів послідовних індексів у [ i 1 , i 2 ,…, i k - 1 , i k ], де для зручності фіксуємо i 1 = 0 і i k = n . Зокрема,

| S i 2 ∩ ⋯ ∩ S i k - 1 | = 2 j - 2 ( n - k ) !, для 2 ≤ jkn ,
| S i 2 ∩ ⋯ ∩ S i k - 1 | = 1, при j = 1, k = n + 1.

Кількість таких наборів індексів [ i 1 , i 2 ,…, i k - 1 , i k ] з j пробігами є

( k - 1 C j - 1 ) ( n - k C j - 2 ), для 2 ≤ jkn ,
1, для j = 1, k = n + 1.

Результат тоді

(−1) n - 1 + ∑ 2 ≤ kn2 ≤ jk (−1) k - 2 ( k - 1 C j - 1 ) ( n - k C j - 2 ) 2 j - 2 ( п - к )!

Внутрішня сума по J можна записати з допомогою гіпергеометричний 2 F 1 функції :

(−1) n - 1 + ∑ 2 ≤ kn (−1) k ( k - 1) 2 F 1 (2 - k , k - n ; 2; 2) ( n - k )!

до якого ми застосовуємо перетворення Pfaff, яке дозволяє нам відіграти сили -1, використовуючи абсолютне значення:

(−1) n - 1 + ∑ 2 ≤ kn (−1) n ( k - 1) 2 F 1 ( k , k - n ; 2; 2) ( n - k )!
= | −1 + ∑ 1 ≤ kn ( k - 1) 2 F 1 ( k , k - n ; 2; 2) ( n - k )! |.

Демо

In[1]:= Table[Abs[Sum[(k-1)Hypergeometric2F1[k,k-#,2,2](#-k)!,{k,#}]-1]&[n],{n,50}]

Out[1]= {1, 0, 0, 0, 0, 2, 10, 68, 500, 4174, 38774, 397584, 4462848, 

>    54455754, 717909202, 10171232060, 154142811052, 2488421201446, 

>    42636471916622, 772807552752712, 14774586965277816, 297138592463202402, 

>    6271277634164008170, 138596853553771517492, 3200958202120445923684, 

>    77114612783976599209598, 1934583996316791634828454, 

>    50460687385591722097602304, 1366482059862153751146376304, 

>    38366771565392871446940748410, 1115482364570332601576605376898, 

>    33544252621178275692411892779180, 1042188051349139920383738392594332, 

>    33419576037745472521641814354312790, 

>    1105004411146009553865786545464526206, 

>    37639281863619947475378460886135133496, 

>    1319658179153254337635342434408766065896, 

>    47585390139805782930448514259179162696722, 

>    1763380871412273296449902785237054760438426, 

>    67106516021125545469475040472412706780911268, 

>    2620784212531087457316728120883870079549134420, 

>    104969402113244439880057492782663678669089779118, 

>    4309132147486627708154774750891684285077633835734, 

>    181199144276064794296827392186304334716629346180848, 

>    7800407552443042507640613928796820288452902805286368, 

>    343589595090843265591418718266306051705639884996218154, 

>    15477521503994968035062094274002250590013877419466108978, 

>    712669883315580566495978374316773450341097231239406211100, 

>    33527174671849317156037438120623503416356879769273672584588, 

>    1610762789255012501855846297689494046193178343355755998487686}

3
Моя душа роздута, хороша робота
Філіпп

6

Желе , 17 16 байт

ṖḊŒ!ð1;;⁹IỊṀðÐḟL

Монадійне посилання.

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

Як?

ṖḊŒ!ð1;;⁹IỊṀðÐḟL - Link: number n
Ṗ                - pop (implicit range build) -> [1,n-1]
 Ḋ               - dequeue -> [2,n-1]
  Œ!             - all permutations of [2,n-1]
    ð       ðÐḟ  - filter discard those entries for which this is truthy:
     1;          -   1 concatenated with the entry
       ;⁹        -   ...concatenated with right (n)
         I       -   incremental differences
          Ị      -   is insignificant (absolute value <=1)
           Ṁ     -   maximum
               L - length (the number of valid arrangements)

Вибачте, але це не відповідає тестовим випадкам
Philippe

1
Так, ти помилився Окс, і я спершу зробив. Ви повинні врахувати той факт, що друге число не може бути 2, а друге число до останнього не може бути n-1
ETHproductions

@Philippe виправив це.
Джонатан Аллан

Я не думаю, що використання IỊṀє дійсним. Зокрема, що робити, якщо, наприклад, -2є одна з дельт? Ви можете поправити IAỊṀ+1.
Ерік Аутгольфер

1
@JonathanAllan Ooh Я думав, що це повернулося x <= 1.
Erik the Outgolfer

5

Japt , 19 18 байт

o2 á è_pU äÉ m²e>1

Перевірте це в Інтернеті! Я б не рекомендував тестувати щось більше, ніж 10.

Пояснення

o2 á è_  pU äÉ  m²  e>1
o2 á èZ{ZpU ä-1 mp2 e>1}
                          : Implicit: U = input integer
o2                        : Create the range [2..U-1].
   á                      : Generate all permutations of this range.
     èZ{               }  : Check how many permutations Z return a truthy value:
        ZpU               :   Push U to the end of Z.
            ä-1           :   Push 1 to the beginning of Z, then take the difference
                          :   of each pair of items.
                m         :   Map each item X to
                 p2       :     X ** 2. This gives a number greater than 1 unless the
                          :     item is 1 or -1.
                    e>1   :   Return whether every item in this list is greater than 1.
                          :   This returns `true` iff the permutation contains no
                          :   consecutive pairs of numbers.
                          : Implicit: output result of last expression

Хороша робота! Смішно, як мій брутальний код не може подолати n = 13 ні ага
Філіп

@Philippe Я б не рекомендував приймати так швидко, я впевнений, що це буде коротше в 05AB1E або Jelly ;-)
ETHproductions

Помилка на тесті 1.
Okx

2
@Okx OP вказав, що ми можемо припустити n > 1.
ETHproductions


5

Haskell, 76 65 байт

Збережено 11 байт завдяки @xnor.

Використання результату для Q_rec на сторінці 7 пошуку @ ChristiaanWesterbeek, ми отримуємо

f 1=1
f n|n<6=0
f n=sum$zipWith((*).f)[n-5..][n-4,1,10-2*n,4,n-2]

Я не розумію, як їх наступний результат haстосується цього, але після прискорення роботи (спочатку шляхом запам'ятовування, див. Більш ранні версії, потім як нижче) я отримую їх кількість.

Хоча вищезазначене нормально n=20, важливим є приклад того, як не робити рекурсії. Ось більш швидка версія (лише для n>=6), яка також потребувала б лише постійної пам'яті - якби тільки цифри не зростали ...

f n=last$foldl(#)[1,0,0,0,0][6..n]
l#n=tail l++[sum$zipWith(*)l[n-4,1,10-2*n,4,n-2]]

Це дає

Prelude> f 50
1610762789255012501855846297689494046193178343355755998487686
Prelude> f 500
659178618863924802757920269977240274180092211041657762693634630044383805576666007245903670780603497370173231423527767109899936008034229541700392144282505597945561328426013937966521561345817045884498867592832897938083071843810602104434376305964577943025310184523643816782047883794585616331928324460394146825636085453532404319881264974005968087265587062691285454120911586459406436421191277596121471930913837355151842093002557978076653884610826296845041929616496533544124347765641367732716560025553179112645454078955409181466212732427071306363820080109636358537270466838558068527692374178581063316309789026101221004745226182671038004326069705775312654329754698423385241664984156235692539255677944294995403233446243315371404887473868003155621849544566385172835597260848972758443874423271017007843907015007416644383573987606586308556317833384896267539628278571497402655322562624217658332870157802254043614726316296058329670971054977099155788604175817828380564156329839201579006169173002756295957371639199917376529472990059986681882194726437566769717959443857298155265292535858523609764515938314672724480762724541633037484152303637096

Це також не проблема f 5000 але я не хочу вставляти результат ...


До речі, не можна використовувати фантазійну математику і досі не використовувати (ультра) грубу силу. По-перше, замість того, щоб дивитись на всі перестановки, подивіться на часткові перестановки та розтягніть їх лише тоді, коли вони вже не є недійсними. Немає сенсу дивитися на всі перестановки, починаючи з цього 1 6 5. По-друге, деякі часткові перестановки люблять 1 3 5 7і 1 5 3 7мають абсолютно однакове дійсне продовження, тому обробляйте їх разом. Використовуючи ці ідеї, я міг обчислити значення до n=16 0,3 с.


Ви можете написати рекурсивне вираз коротше як точка, витягуючи з коефіцієнтів: f n=sum$zipWith((*).f)[n-5..][n-4,1,10-2*n,4,n-2].
xnor

@xnor Правильно, дякую!
Крістіан Сіверс

Це хороша робота, я здивований результатами, які ця спільнота придумала! Шкода, що це гольф ^^
Філіп

4

Пітон, 125 байт

from itertools import*
lambda n:sum(p[-1]-p[0]==n-1and all(~-abs(x-y)for x,y in zip(p,p[1:]))for p in permutations(range(n)))

Виглядає досить швидко, хороша робота!
Філіп


3

Математика, 66 байт

Count[Permutations@Range@#,x:{1,__,#}/;FreeQ[Differences@x,1|-1]]&

Пояснення

Functionз першим аргументом #.

Count[                                                             (* Count the number of *)
      Permutations@                                                (* permutations of *)
                   Range@#,                                        (* the list {1, ..., #} *)
                           x:{1,__,#}                              (* of the form {1, __, #} *)
                                     /;                            (* such that *)
                                             Differences@x,        (* the list of differences of consecutive elements *)
                                       FreeQ[                      (* is free of elements of the form *)
                                                           1|-1    (* 1 or -1 *)
                                                               ]]&

3

Javascript (ES6), 100 74 72 60 байт

f=n=>n--<6?!n|0:f(n)*--n+4*f(n--)-2*f(n--)*--n+f(n)*++n+f(n)

Нижче представлена ​​версія до майстерності гольфу @PeterTaylor

f=n=>n<6?n==1|0:(n-4)*f(n-5)+f(n-4)-2*(n-5)*f(n-3)+4*f(n-2)+(n-2)*f(n-1)

Завдяки відповіді від @ChristianSievers, що вдалося скласти рішення Haskell з паперу, який я знайшов після googling '0, 2, 10, 68, 500, 4174, 38774, 397584', ось версія Javascript, яка також не перестановляється.

Використання

for (i=1; i<=20; i++) {
  console.log(i, f(i))
}

1 1 
2 0 
3 0 
4 0 
5 0 
6 2 
7 10 
8 68 
9 500 
10 4174 
11 38774 
12 397584 
13 4462848 
14 54455754 
15 717909202 
16 10171232060 
17 154142811052 
18 2488421201446 
19 42636471916622 
20 772807552752712

1
Опис завдання запитує лише f(n)коли n>1, тому не має значення для чого ви повернетесь n=1. Також я думаю, що f(1)=1це правильно.
Крістіан Сіверс

Ви можете комбінувати окремі випадки, що n<6?n==1|0:стосуються подальшої економії на двох картках.
Пітер Тейлор

Чудово. Я підкоригував ці 2 коментарі.
Крістіан Вестербек

1
І переупорядкувавши терміни та покладаючись на порядок оцінювання, можна перейти до 60:f=n=>n--<6?!n|0:f(n)*--n+4*f(n--)-2*f(n--)*--n+f(n)*++n+f(n)
Пітер Тейлор

1

Брахілог , 26 байт

{⟦₁pLh1&~tLs₂ᶠ{-ȧ>1}ᵐ}ᶜ|∧0

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

Пояснення

{                    }ᶜ       Output = count the number of outputs of:
 ⟦₁pL                           L is a permutation of [1, …, Input]
    Lh1                         The head of L is 1
       &~tL                     The tail of L is the Input
          Ls₂ᶠ                  Find all sublists of length 2 of L
              {    }ᵐ           Map on each sublist:
               -ȧ>1               The elements are separated by strictly more than 1
                       |      Else (no outputs to the count)
                        ∧0    Output = 0

1

Python 3 , 109 107 102 байт

q=lambda s,x,n:sum(q(s-{v},v,n)for v in s if(v-x)**2>1)if s else x<n;f=lambda n:q({*range(2,n)},1,n-1)

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

Видалено чотири байти, не намагаючись однорядно функцію (як запропонував @shooqie) та інший байт, замінивши absна квадрат. (Потрібен Python 3.5+)




0

Математика, 134 байти

(s=Permutations@Range[2,#-1];g=Table[Join[Prepend[s[[i]],1],{#}],{i,Length@s}];Length@Select[Union@*Abs@*Differences/@g,FreeQ[#,1]&])&


тестові випадки n: 2 - 12

{0, 0, 0, 0, 2, 10, 68, 500, 4174, 38774, 397584}


0

Python 2 , 105 байт

lambda n:reduce(lambda a,i:a+[i*a[-5]+a[-4]+2*(1-i)*a[-3]+4*a[-2]+(i+2)*a[-1]],range(2,n),[0,1]+4*[0])[n]

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

Це засновано на роботі Філіппа Флайолета, відкритого @Christiaan Westerbeek ; це набагато швидше і на два байти коротше мого рішення Python 3, що перераховує можливі перестановки. (У Python 3 reduceприкро перенесли наfunctools .)

Існує набагато коротша версія, що використовує крапковий продукт numpy, але вона переповнюється досить швидко і вимагає імпортування numpy. Але для чого це варто:

lambda n:reduce(lambda a,i:a+[dot([i,1,2-2*i,4,i+2],a[-5:])],range(2,n),[0,1]+4*[0])[n]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.