Contando da 1 a n senza numeri consecutivi


19

Obbiettivo

Ti viene dato un numero intero n( n > 1). È necessario uscita quanti permutazioni degli interi 1a nci sono, che inizierà alle 1, fine a n, e non hanno due numeri interi consecutivi che differiscono dal 1.

In alternativa, se si prende il grafico completo K_ne si rimuovono i bordi del percorso, 1-2-3-...-nè necessario contare i percorsi hamiltoniani da 1a nnel grafico rimanente.

Gli esempi verranno utilizzati f(n)per una funzione che accetta ne genera il numero di permutazioni valide, ma l'invio può essere una funzione o un programma.


Esempi

Perché n = 6, una possibile soluzione è1-3-5-2-4-6

Tuttavia, 1-3-5-2-6-4non è una soluzione valida poiché non termina con 6.

In effetti, per n = 6, ci sono solo 2 soluzioni ( 1-4-2-5-3-6è l'altra).

Quindi f(6) = 2.


Per n = 4le uniche permutazioni che iniziano 1e finiscono in 4sono 1-2-3-4e 1-3-2-4. In entrambi 2è adiacente al 3, dando numeri interi consecutivi che differiscono di 1. Pertanto f(4) = 0.


Casi test

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

Criterio vincente

Questo è code-golf, vince la risposta più breve.


7
Vedi, ragazzi, non potete semplicemente controllare quante permutazioni [2..n-1]non contengono delta 1o -1, dovete anche controllare che nessuna di esse inizi con 2o finisca con n-1...
ETHproductions

1
L'elenco deve iniziare con 1 e terminare con il numero?
Okx,

3
Forse l'OP significa "adiacente" non "consecutivo"?
Stilez,

6
Stranamente la sequenza è qui: algo.inria.fr/libraries/autocomb/graphs99.ps dove è scritto a pagina 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^14Passo ora un po 'di tempo cercando di usare le formule, ma non riesco a comporne una che generi la sequenza. Incredibile vedere l'esponente di z è l'input della formula e il risultato è il fattore di moltiplicazione. Quello che può dedurre la formula da lì potrebbe essere quello con la risposta più breve in byte
Christiaan Westerbeek,

1
@ChristiaanWesterbeek che è chiamata la funzione generatrice per la sequenza. Esistono molte sequenze con una funzione generatrice che ha una forma chiusa più gradevole della sequenza stessa, è roba interessante!
Carmeister,

Risposte:


6

MATL , 16 byte

qtq:Y@0&Yc!d|qAs

Provalo online!

Per input superiori 12a memoria insufficiente.

Spiegazione

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
Funziona bene, ben fatto :)
Philippe,

1
Sebbene ci siano stati dei progressi davvero interessanti in questo problema, la tua soluzione è ancora la più breve. È anche più veloce di quello di Jelly. Congratz!
Philippe,

19

Mathematica, 58 byte, tempo polinomiale ( n )

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

Come funziona

Invece di iterare sulle permutazioni con forza bruta, usiamo il principio di inclusione-esclusione per contarle in modo combinatorio.

Sia S l'insieme di tutte le permutazioni di [1, ..., n] con σ 1 = 1, σ n = n , e sia S che l'insieme delle permutazioni σ ∈ S tale che | σ I - σ i + 1 | = 1. Quindi il conteggio che stiamo cercando è

| 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 |.

Ora, | S i 2 ∩ ⋯ ∩ S i k - 1 | dipende solo da k e dal numero j di serie di indici consecutivi in ​​[ i 1 , i 2 ,…, i k - 1 , i k ] dove per comodità fissiamo i 1 = 0 e i k = n . In particolare,

| S i 2 ∩ ⋯ ∩ S i k - 1 | = 2 j - 2 ( n - k ) !, per 2 ≤ jkn ,
| S i 2 ∩ ⋯ ∩ S i k - 1 | = 1, per j = 1, k = n + 1.

Il numero di tali set di indici [ i 1 , i 2 ,…, i k - 1 , i k ] con j run è

( k - 1 C j - 1 ) ( n - k C j - 2 ), per 2 ≤ jkn ,
1, per j = 1, k = n + 1.

Il risultato è quindi

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

La somma interna oltre j può essere scritta utilizzando il ipergeometrica 2 F 1 funzione :

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

a cui applichiamo una trasformazione Pfaff che ci consente di scartare i poteri di −1 usando un valore assoluto:

(−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 )! |.

dimostrazione

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
La mia mente è saltata, bel lavoro
Philippe,

6

Gelatina , 17 16 byte

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

Un collegamento monadico.

Provalo online!

Come?

ṖḊŒ!ð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)

Siamo spiacenti ma non soddisfa i casi di test
Philippe

1
Sì, hai fatto lo stesso errore Okx e io all'inizio. Devi tenere conto del fatto che il secondo numero non può essere 2 e il penultimo numero non può essere n-1
ETHproductions

@Philippe ha risolto il problema.
Jonathan Allan,

Non credo che l'uso IỊṀsia valido. In particolare, cosa succede se, -2ad esempio, uno dei delta è presente? È possibile correggere con IAỊṀper +1.
Erik the Outgolfer,

1
@JonathanAllan Ooh, ho pensato che fosse tornato x <= 1.
Erik the Outgolfer,

5

Japt , 19 18 byte

o2 á è_pU äÉ m²e>1

Provalo online! Non consiglierei il test su qualcosa di più grande di 10.

Spiegazione

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

Buon lavoro! Divertente come il mio codice di forza bruta non possa superare n = 13 né ahah
Philippe

@Philippe Non consiglierei di accettare così in fretta, sono sicuro che questo sarà più breve in 05AB1E o Jelly ;-)
ETHproductions

Errore nella testcase 1.
Okx,

2
@Okx OP ha specificato che possiamo supporre n > 1.
ETHproductions


5

Haskell, 76 65 byte

Salvato 11 byte grazie a @xnor.

Usando il risultato per Q_reca pagina 7 della ricerca di @ ChristiaanWesterbeek, otteniamo

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

Non capisco come il loro prossimo risultato sia hacollegato a questo, ma dopo aver accelerato (prima con la memoizzazione, vedi le versioni precedenti, poi come sotto) ottengo i loro numeri.

Mentre quanto sopra va bene n=20, è essenzialmente un esempio di come non fare la ricorsione. Ecco una versione più veloce (solo per n>=6) che avrebbe anche bisogno solo di memoria costante - se solo i numeri non continuassero ad aumentare ...

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]]

Questo dà

Prelude> f 50
1610762789255012501855846297689494046193178343355755998487686
Prelude> f 500
659178618863924802757920269977240274180092211041657762693634630044383805576666007245903670780603497370173231423527767109899936008034229541700392144282505597945561328426013937966521561345817045884498867592832897938083071843810602104434376305964577943025310184523643816782047883794585616331928324460394146825636085453532404319881264974005968087265587062691285454120911586459406436421191277596121471930913837355151842093002557978076653884610826296845041929616496533544124347765641367732716560025553179112645454078955409181466212732427071306363820080109636358537270466838558068527692374178581063316309789026101221004745226182671038004326069705775312654329754698423385241664984156235692539255677944294995403233446243315371404887473868003155621849544566385172835597260848972758443874423271017007843907015007416644383573987606586308556317833384896267539628278571497402655322562624217658332870157802254043614726316296058329670971054977099155788604175817828380564156329839201579006169173002756295957371639199917376529472990059986681882194726437566769717959443857298155265292535858523609764515938314672724480762724541633037484152303637096

Non è un problema anche ottenere, f 5000ma non voglio incollare il risultato ...


A proposito, è possibile non usare la matematica fantasia e ancora non usare la forza (ultra) bruta. Innanzitutto, invece di esaminare tutte le permutazioni, osserva le permutazioni parziali e le estendi solo quando non sono già invalide. È inutile guardare tutte le permutazioni a partire da 1 6 5. Secondo, alcune permutazioni parziali gradiscono 1 3 5 7e 1 5 3 7hanno esattamente le stesse continuazioni valide, quindi gestiscile insieme. Usando queste idee, ho potuto calcolare i valori fino a n=16 0,3 secondi.


È possibile scrivere l'espressione ricorsiva più breve come un punto estraendo i coefficienti: f n=sum$zipWith((*).f)[n-5..][n-4,1,10-2*n,4,n-2].
xnor

@xnor Bene, grazie!
Christian Sievers,

Questo è un buon lavoro, sono stupito dai risultati ottenuti da questa community! Peccato che sia un golf ^^
Philippe

4

Python, 125 byte

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)))

Sembra abbastanza veloce, buon lavoro!
Philippe,


3

Mathematica, 66 byte

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

Spiegazione

Functioncon il primo argomento #.

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 byte

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

Di seguito è la versione prima della padronanza del golf di @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)

Grazie alla risposta di @ChristianSievers che è riuscita a redigere una soluzione Haskell da un documento che ho trovato dopo aver cercato su Google '0, 2, 10, 68, 500, 4174, 38774, 397584', ecco una versione Javascript che non permuta.

uso

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
La descrizione dell'attività richiede solo f(n)quando n>1, quindi non importa cosa restituisci n=1. Inoltre penso f(1)=1sia corretto.
Christian Sievers,

È possibile combinare i casi speciali come n<6?n==1|0:per un ulteriore risparmio di due caratteri.
Peter Taylor,

Grande. Mi sono adattato per quei 2 commenti.
Christiaan Westerbeek,

1
E riordinando i termini e basandosi sull'ordine di valutazione è possibile scendere a 60:f=n=>n--<6?!n|0:f(n)*--n+4*f(n--)-2*f(n--)*--n+f(n)*++n+f(n)
Peter Taylor,

1

Brachylog , 26 byte

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

Provalo online!

Spiegazione

{                    }ᶜ       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 byte

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)

Provalo online!

Rimossi quattro byte non provando a una riga la funzione (come suggerito da @shooqie) e un altro byte sostituendolo abscon un quadrato. (Richiede Python 3.5+)




0

Mathematica, 134 byte

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


casi di test n: da 2 a 12

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


0

Python 2 , 105 byte

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]

Provalo online!

Questo si basa sul documento di Philippe Flajolet scoperto da @Christiaan Westerbeek ; è molto più veloce e due byte più breve della mia soluzione Python 3 che elenca le possibili permutazioni. (In Python 3, reduceè stato fastidiosamente spostato infunctools .)

Esiste una versione molto più breve che utilizza il prodotto dot di numpy, ma trabocca abbastanza rapidamente e richiede che numpy sia stato importato. Ma per quello che vale:

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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.