Sequenze magiche di lunghezza n


11

Una sequenza magica è una sequenza di numeri interi non negativi in ​​modo x[0..n-1]tale che ci siano esattamente x[i]istanze dii

Ad esempio, 6,2,1,0,0,0,0,0,0,0,0 è una sequenza magica poiché ci sono 6 0, 2 1 e così via.

Scrivi una funzione che quando viene dato n, genera tutte le sequenze magiche di lunghezza n


Vince il programma in grado di produrre l'output corretto per il valore più alto di n entro 10 secondi. (Tutti i programmi sono i benvenuti, però)

Ad esempio, il programma di Alice può gestire fino a n = 15 entro 10 secondi, mentre quello di Bob può gestire fino a n = 20 contemporaneamente. Bob vince.

Piattaforma: Linux 2.7GHz @ 4 CPU


5
Benvenuti in PPCG! Questa è una grande sfida, ma hai bisogno di un criterio vincente. Ad esempio, potresti dire che il vincitore è il programma più breve.
Ypnypn,


2
Non modificare il criterio vincente dopo aver pubblicato le risposte. Inoltre, questo era molto meglio come codice golf che come codice più veloce, almeno secondo me.
Alex A.

2
@xnor puoi iniziare generando le partizioni intere di n e controllando se possono essere auto-descrittive.
Martin Ender,

2
Qual è la più piccola n>5con una soluzione non del modulo [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? Ho cercato n=20e non trovato uno, e mi chiedo se sto facendo un errore.
xnor

Risposte:


19

Python, n. 10 8

def magic_sequences(n):
    if n==4:
        return (1, 2, 1, 0),(2, 0, 2, 0) 
    elif n==5:
        return (2, 1, 2, 0, 0),
    elif n>=7:
        return (n-4,2,1)+(0,)*(n-7)+(1,0,0,0),
    else:
        return ()

Questo utilizza il fatto, che dimostrerò, che le sole sequenze magiche di lunghezza nsono:

  • [1, 2, 1, 0]e [2, 0, 2, 0]pern=4
  • [2, 1, 2, 0, 0] per n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] per n>=7

Quindi, per n>=7, bisogna solo restituire un'enorme tupla. Posso farlo fino a circa n=10^8sul mio laptop, che è probabilmente limitato dalla memoria; non più e si blocca. (Grazie a trichoplax per l'idea di usare le tuple anziché le liste.) O, se invece si può stampare un dizionario di voci diverse da zero {0:n-4, 1:2, 2:1, (n-4):1}, si può fare questo per ginormous n.

Dimostro l'unicità di n>=7; gli altri possono essere controllati con forza bruta o casework.

La somma delle voci di lè il conteggio totale di tutti i numeri dell'elenco, che è la sua lunghezza n. L'elenco ha l[0]zero e quindi n-l[0]voci diverse da zero. Ma per definizione l[0]deve essere diverso da zero o si ottiene una contraddizione, e ciascuna delle altre voci diverse da zero è almeno 1. Ciò rappresenta già una somma della l[0] + (n-l[0]-1)*1 = n-1somma complessiva di n. Quindi, senza contare l[0], ci può essere al massimo un 2 e nessuna voce maggiore di 2.

Ciò significa che le uniche voci diverse da zero sono l[0], l[1], l[2], and l[l[0]], i cui valori sono al massimo l[0]e una permutazione di 1,1,2, che fornisce una somma massima di l[0]+4. Dal momento che questa somma è n, che è almeno 7, abbiamo l[0]>=3, e così l[l[0]]=1. Ora, ce n'è almeno uno 1, il che significa l[1]>=1, ma se l[1]==1quello è un altro 1, quindi l[1]>=2, ciò implica che l[1]è solo 2. Questo dà l[2]=1, e tutte le voci rimanenti sono 0, quindi l[0]=n-4, che completa la soluzione.


E la lingua è ...?
edc65,

@ edc65 Sembra pitone. Ma non sono sicuro.
Ismael Miguel,

4

Python 3, n≈40

def plausible_suffix(l,N):
    if sum(l)>N:
        return False

    pairs = [(N-1-i,l[i]) for i in range(len(l))]

    if sum(i*x for i,x in pairs)>N:
        return False

    num_remaining = N - len(l)

    for index, desired_count in pairs:
        count = l.count(index)
        more_needed = desired_count - count
        if more_needed<0: 
            return False
        num_remaining -= more_needed
        if num_remaining<0:
            return False
    return True

plausible_func = plausible_suffix

def generate_magic(N):
    l=[0]
    while l:
        extend = False
        if plausible_func(l,N):
            if len(l)==N:
                yield l[::-1]
            else:
                extend = True
        if extend:
            l.append(0)
        else:
            while l[-1]>=N-2:
                l.pop(-1)
                if not l:raise StopIteration
            l[-1]+=1

n=40 #test parameter

if n>0:
    for x in generate_magic(n):
        print(n,x)

Esegue una prima ricerca di possibili elenchi, compilando le voci da destra a sinistra, interrompendo la ricerca al suffisso se non è plausibile, cosa che può accadere se:

  • La somma delle voci nel suffisso supera n(la somma per l'intero elenco deve essere n)
  • La somma ponderata di i*l[i]nel suffisso supera n(la somma per l'intero elenco deve essere n)
  • Qualsiasi numero appare nel suffisso più volte di quanto il suffisso dice che dovrebbe
  • Il numero di punti vuoti rimanenti è troppo piccolo per tenere conto di tutti i numeri che devono apparire più volte.

Avevo i prefissi testati originali da sinistra a destra, ma ciò è andato più lentamente.

Le uscite fino a n=30sono:

4 [1, 2, 1, 0]
4 [2, 0, 2, 0]
5 [2, 1, 2, 0, 0]
7 [3, 2, 1, 1, 0, 0, 0]
8 [4, 2, 1, 0, 1, 0, 0, 0]
9 [5, 2, 1, 0, 0, 1, 0, 0, 0]
10 [6, 2, 1, 0, 0, 0, 1, 0, 0, 0]
11 [7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0]
12 [8, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
13 [9, 2, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
14 [10, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
15 [11, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
16 [12, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
17 [13, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
18 [14, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
19 [15, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
20 [16, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
21 [17, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
22 [18, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
23 [19, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
24 [20, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
25 [21, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
26 [22, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
27 [23, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
28 [24, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
29 [25, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
30 [26, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

Ad eccezione delle prime tre liste [1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0], esiste esattamente una lista per ogni lunghezza n>6e ha il modulo [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]. Questo modello persiste almeno fino a n=50. Sospetto che rimanga per sempre, nel qual caso è banale produrre un numero enorme di questi. Anche in caso contrario, una comprensione matematica delle possibili soluzioni accelererebbe notevolmente una ricerca.


@Ypnypn Ho un caso speciale n=0. Mi mancava che stiamo restituendo il risultato per un singolo n, senza contare n. Questo mi fa venire voglia di n=40.
xnor

0

Pyth - 15 byte

Usa la forza bruta di tutte le possibili sequenze di len ne quindi i filtri.

f.A.eq/TkYT^UQQ

Spiegazione completa in arrivo.

Provalo qui online .


2
Cordiali saluti, l'OP ha cambiato il criterio vincente in codice più veloce.
Alex A.

2
Indipendentemente dal criterio vincente, ecco un golf a 3 byte: `fqm / TdQT ^ UQQ`
Jakube

0

K, 26 byte

{f@&{x~(+/x=)'!#x}'f:!x#x}

Come l'approccio di Maltysen, la forza bruta. Il cuore del programma è un predicato che verifica se un determinato vettore è "magico":

{x~(+/x=)'!#x}

Costruisci un vettore iota fino a quando il vettore di input ( !#x), conta le occorrenze di ogni cifra ( (+/x=)') e confronta il risultato con il vettore di input ( x~). Se c'è una partita, hai una sequenza magica.

Sfortunatamente, questa prima pugnalata sembra essere piuttosto lenta. Test usando Kona sul mio laptop ci vogliono circa 12 secondi per gestire n = 7. Devo pensarci un po 'di più.

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.