Genera sequenze Skolem


10

Sequenze di Skolem

Una sequenza Skolem è una sequenza di 2nnumeri in cui ogni numero itra 1e si nverifica esattamente due volte, e la distanza tra le due occorrenze di iè esattamente ipassi. Ecco alcuni esempi di sequenze Skolem:

1 1
1 1 4 2 3 2 4 3
16 13 15 12 14 4 7 3 11 4 3 9 10 7 13 12 16 15 14 11 9 8 10 2 6 2 5 1 1 8 6 5

Le seguenti sequenze non sono sequenze Skolem:

1 2 1 2      (The distance between the 1's is 2, not 1)
3 1 1 3      (The number 2 is missing)
1 1 2 1 1 2  (There are four 1's)

Obbiettivo

Scrivi un programma, una funzione o un'espressione per contare il numero di tutte le sequenze Skolem di una determinata lunghezza. Più esplicitamente, l'input è un numero intero ne l'output è il numero di sequenze Skolem di lunghezza 2n. Questa sequenza ha una voce OEIS . Per n = 0, è possibile restituire 0o 1. I primi valori, a partire da 0, sono

0, 1, 0, 0, 6, 10, 0, 0, 504, 2656, 0, 0, 455936, 3040560, 0, 0, 1400156768

Regole e punteggio

Questo è il codice golf. Il formato di output è poco chiaro entro limiti ragionevoli.


Solo curioso, ma qual è la 0, 1, 0, 0, 6...tua domanda? È lo snippet di codice, in caso affermativo che lingua è?
PhiNotPi

2
Perché il primo elemento nel tuo output 0? Se hai intenzione di ammetterlo 0come input valido, l'output dovrebbe essere 1.
Peter Taylor,

1
Alcuni (incluso il mio codice) credono che ci siano zero sequenze vuote. Se 1 ti fa sentire meglio, restituiscilo.
stand,

2
AFAIK in ogni contesto supponete che ci sia una sola sequenza vuota / oggetto null / set vuoto etc / funzione-a / da-il-set-vuoto / grafico vuoto / qualsiasi altra cosa.
Bakuriu,

1
@boothby, hai appena definito Knuth uno sciocco?
Peter Taylor,

Risposte:


8

GolfScript, 48 46 caratteri

:b,1,{)2\?){{.2$&!{.2$|@@}*.+.4b?<}do;;}+%}@/,

La versione più veloce ( prova online ): funziona abbastanza velocemente, ad esempio n=8impiega circa due secondi. E l'approccio scelto richiede davvero pochi personaggi.

Questa versione funziona anche con maschere di bit. Costruisce il possibile array di risultati da 1 in su, ovvero per n=3:

1: 000011        000110 001100 011000 110000
2: 010111 101011 101110        011101 110101 111010

Mentre alcuni risultati (come 000011) hanno due possibili continuazioni, altri (cioè 001100) non ne hanno e vengono rimossi dall'array dei risultati.

Spiegazione del codice:

:b           # save the input into variable b for later use
,            # make the list 0..b-1 (the outer loop)
1,           # puts the list [0] on top of the stack - initially the only possible
             # combination
{)           # {...}@/ does the outer loop counting from i=1 to b
  2\?)       # computes the smalles possible bit mask m=2^i+1 with two bits set 
             # and distance of those equal to i (i.e. i=1: 11, i=2: 101, ...)
  {          # the next loop starts with this bitmask (prepended to code via
             # concatination {...}+
             # the loop itself iterates the top of the stack, i.e. at this point 
             # the result array                 
             # stack here contains item of result array (e.g. 00000011)
             # and bitmask (e.g. 00000101)
    {        # the inner-most loop tries all masks with the current item in the result set
      .2$&!  # do item and result set share not single bit? then - {...}*
      {
        .2$| # then generate the new entry by or-ing those two
        @@   # push it down on the stack (i.e. put working items to top)
      }*
      .+     # shift the bit mask left by one
      .4b?<  # if still in the range loop further
    }do;;    # removes the remainders of the loop (i.e. item processed and mask)
  }+%        # stack now contains the new result array
}@/
,            # length of result array, i.e. the number of Skolem sequences

Accettare il più veloce delle soluzioni legate.
stand,

6

Espressione J, 47 caratteri

 +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y

Esempio:

    y=:5
    +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y
10

Richiede circa 30 secondi per y=:5sulla mia macchina.

l'algoritmo è lento quanto può essere:

  • ~.(i.!+:y)A.,~>:i.ygenera ogni permutazione 1 2 .. y 1 2 .. ye rimuove voci duplicate
  • ((=&{:+.2-#@])#;.2)\"1 calcola:
    • (...)\"1 per ogni prefisso di ogni riga:
      • #;.2 conta gli elementi prima di ogni occorrenza dell'ultimo elemento
      • #@] conta il numero di conteggi (ovvero il numero di occorrenze dell'ultimo elemento)
      • =&{: determina l '"uguaglianza" "degli" "ultimi elementi" dell'elenco conteggi e dell'elenco originale.
      • +.è un OR logico. =&{:+.2-#@]legge "o gli ultimi elementi [della lista dei conteggi e della lista originale] sono uguali, oppure esiste solo un elemento [nella lista dei conteggi] anziché due".
  • */"1 si moltiplica (AND logico) sulle righe della tabella delle condizioni, determinando quali permutazioni sono sequenze di Skolem.
  • +/ somma insieme quelli e zero.

6

GolfScript (46 caratteri)

:&1,\,{0,2@)?)2&*{2${1$^}%@+\2*}*;+}/{4&?(=},,

Questa è un'espressione che accetta input nello stack. Per trasformarlo in un programma completo che accetta input su stdin, anteporre~

È abbastanza inefficiente - la maggior parte dei risparmi che ho fatto giocando a golf da 56 caratteri non rigati è stato espandendo la gamma di anelli in modi che non introducono risultati errati ma fanno il calcolo dei rifiuti.

L'approccio è il mascheramento bit a bit dei prodotti cartesiani. Ad esempio (usando il binario per le maschere) per n=4il codice ungolf calcolerebbe lo xor di ogni elemento nel prodotto cartesiano [00000011 00000110 ... 11000000] x [00000101 00001010 ... 10100000] x ... x [00010001 ... 10001000]. Qualsiasi risultato con 8 bit potrebbe essere ottenuto solo con maschere non sovrapposte.

Al fine di ottimizzare le dimensioni anziché la velocità, il codice accumula prodotti parziali ( S1 u S1xS2 u S1xS2xS3 ...) e rende ogni prodotto composto da 2nelementi anziché solo da quelli 2n-1-iche possono effettivamente contribuire a una sequenza valida.

Velocità

La versione golfizzata dura n=510 secondi sul mio computer e più di 5 minuti per n=6. La versione originale non modificata viene calcolata n=5in meno di un secondo e n=6in circa 1 minuto. Con un semplice filtro sui risultati intermedi, può calcolare n=8in 30 secondi. L'ho passato a 66 caratteri (come programma - 65 caratteri come espressione) mantenendo i loop il più limitati possibile e filtrando le collisioni intermedie:

~:&1,\,{0,\).2\?)2&*@-{.{[\].~^.@~+<{;}*}+3$%@+\2*}*;\;}/{4&?(=},,

Dannazione. Proprio quando ho pensato che la mia soluzione 48char J fosse abbastanza buona per essere pubblicata.
John Dvorak,

Dannazione. Il nostro pareggio di 47 personaggi non è durato a lungo. +1
John Dvorak,

5

GolfScript, 49 caratteri

~:/..+?:d(,{d+/base(;:w;/,{.w?)w>1$?=},,/=},,/1=+

Si aspetta il numero nsu STDIN. Questo è code-golf - non provare il codice con un numero nmaggiore di 5.


Ahi, non più di 5?
stand,

@boothby È stato il primo tentativo diretto. Spesso dobbiamo prendere la velocità della decisione rispetto alle dimensioni - e il code-golf è circa le dimensioni. Ecco perché ho anche aggiunto la versione veloce, che in origine era molto più lunga ma ora è ancora più corta.
Howard,

0

Salvia, 70 anni

Questo è un po 'più corto del mio originale.

sum(1for i in DLXCPP([(i-1,j,i+j)for i in[1..n]for j in[n..3*n-i-1]]))

Come funziona:

Data una matrice 0/1, il problema esatto di copertura per quella matrice è trovare un sottoinsieme delle righe che sommano (come numeri interi) al vettore tutti. Per esempio,

11001
10100
01001
00011
00010

ha una soluzione

10100
01001
00010

Il mio approccio preferito ai problemi è di lanciarli su un esatto problema di copertura. Le sequenze Skolem facilitano efficacemente questo. Faccio un esatto problema di copertura in cui le soluzioni sono in biiezione con sequenze di lunghezza di Skolem 2n. Ad esempio, una riga del problema n=6è

  a   |  b  
001000|001001000000 # S[b] = S[b+a+1] = a

dove un 1 in posizione a < nsignifica che aviene usato il simbolo . Le posizioni rimanenti corrispondono alle posizioni effettive nella sequenza. Una copertina esatta corrisponde a ogni simbolo che viene utilizzato esattamente una volta e ogni posizione viene riempita esattamente una volta. Per costruzione, qualsiasi simbolo kin una posizione è kspazi lontani dal suo partner.

In Sage, DLXCPPè un'implementazione di "collegamenti danzanti": risolve l'esatto problema di copertura in un modo eccezionalmente grazioso. È uno dei miei algoritmi preferiti di sempre, ed essere proprio in superficie in Sage rende l'enumerazione combinatoria una gioia.


Caspita, collegamento danzante. L'uso len(list(...))salverà 4 caratteri.
Ray,

@Ray Il mio computer morirebbe semplicemente se calcolassi len(list(...))per n = 16. E ucciderebbe completamente il runtime.
stand dal

Esatto, perché convertire un generatore in un elenco è costato molta memoria.
Ray,
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.