Secuencias mágicas de longitud n

11

Una secuencia mágica es una secuencia de enteros no negativos, de x[0..n-1]modo que hay x[i]casos exactos dei

Por ejemplo, 6,2,1,0,0,0,1,0,0,0 es una secuencia mágica ya que hay 6 0's, 2 1's, etc.

Escriba una función que cuando se le da n, emite todas las secuencias mágicas de longitud n


El programa que puede producir la salida correcta para el valor más alto de n en 10 segundos gana. (Sin embargo, todos los programas son bienvenidos)

Por ejemplo, el programa de Alice puede manejar hasta n = 15 en 10 segundos, mientras que el de Bob puede manejar hasta n = 20 en el mismo tiempo. Bob gana.

Plataforma: Linux 2.7GHz @ 4 CPU

Agnishom Chattopadhyay
fuente
55
Bienvenido a PPCG! Este es un gran desafío, pero necesita un criterio ganador. Por ejemplo, se podría decir que el ganador es el programa más corto.
Ypnypn
1
Relevante: Número
autodescriptivo
2
No cambie el criterio ganador después de que se hayan publicado las respuestas. Además, esto era mucho mejor como código de golf que como código más rápido, al menos en mi opinión.
Alex A.
2
@xnor puede comenzar generando las particiones enteras de n y verificando si pueden ser autodescriptivas.
Martin Ender
2
¿Cuál es el más pequeño n>5con una solución no de la forma [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? He admirado n=20y no he encontrado uno, y me pregunto si estoy cometiendo un error.
xnor

Respuestas:

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

Esto utiliza el hecho, que demostraré, de que las únicas secuencias de longitud de Magic nson:

  • [1, 2, 1, 0]y [2, 0, 2, 0]paran=4
  • [2, 1, 2, 0, 0] para n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] para n>=7

Entonces, para n>=7, uno solo necesita devolver una gran tupla. Puedo hacer esto hasta aproximadamente n=10^8en mi computadora portátil, que probablemente esté limitada por la memoria; más y se congela. (Gracias a trichoplax por la idea de usar tuplas en lugar de listas). O, si uno puede imprimir un diccionario de entradas distintas de cero {0:n-4, 1:2, 2:1, (n-4):1}, puede hacerlo por descomunal n.

Pruebo la unicidad para n>=7; los otros pueden ser verificados por fuerza bruta o trabajo de casos.

La suma de las entradas de les el recuento total de todos los números de la lista, que es su longitud n. La lista tiene l[0]ceros y, por lo tanto, n-l[0]entradas distintas de cero. Pero, por definición, l[0]debe ser distinto de cero o tenemos una contradicción, y cada una de las otras entradas distintas de cero es al menos 1. Esto ya representa una suma l[0] + (n-l[0]-1)*1 = n-1de la suma total de n. Entonces, sin contar l[0], puede haber a lo sumo un 2 y ninguna entrada mayor que 2.

Pero eso significa que las únicas entradas distintas de cero son l[0], l[1], l[2], and l[l[0]], cuyos valores son como máximo l[0]y una permutación de 1,1,2, lo que da una suma máxima de l[0]+4. Como esta suma es n, que es al menos 7, tenemos l[0]>=3, y así l[l[0]]=1. Ahora, hay al menos uno 1, lo que significa l[1]>=1, pero si l[1]==1ese es otro 1, entonces l[1]>=2, lo que implica l[1]es el solitario 2. Esto da l[2]=1, y todas las entradas restantes son 0, por l[0]=n-4lo tanto , lo que completa la solución.

xnor
fuente
¿Y el idioma es ...?
edc65
@ edc65 Parece python. Pero no estoy seguro.
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)

Realiza una búsqueda amplia de listas posibles, completa las entradas de derecha a izquierda, detiene la búsqueda en un sufijo si no es plausible, lo que puede suceder si:

  • La suma de las entradas en el sufijo excede n(la suma de toda la lista debe ser n)
  • La suma ponderada de i*l[i]en el sufijo excede n(la suma de toda la lista debe ser n)
  • Cualquier número aparece en el sufijo más veces que el sufijo dice que debería
  • El número de puntos restantes sin llenar es demasiado pequeño para dar cuenta de todos los números que deben aparecer más veces.

Tenía los prefijos probados originales de izquierda a derecha, pero eso fue más lento.

Las salidas hasta n=30son:

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]

Excepto por las primeras tres listas [1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0], hay exactamente una lista de cada longitud n>6, y tiene la forma [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]. Este patrón persiste al menos hasta n=50. Sospecho que se mantiene para siempre, en cuyo caso es trivial generar una gran cantidad de estos. Incluso si no, una comprensión matemática de las posibles soluciones aceleraría en gran medida una búsqueda.

xnor
fuente
@Ypnypn, tengo una carcasa especial n=0. Extrañaba que devolviéramos el resultado para un sencillo n, sin contar los de arriba n. Esto me lleva hasta n=40.
xnor
0

Pyth - 15 bytes

Utiliza la fuerza bruta por todas las secuencias posibles de len ny luego los filtros.

f.A.eq/TkYT^UQQ

Explicación completa próximamente.

Pruébalo aquí en línea .

Maltysen
fuente
2
Para su información, el OP cambió el criterio ganador al código más rápido.
Alex A.
2
Independientemente del criterio ganador, aquí hay un golf de 3 bytes: `fqm / TdQT ^ UQQ`
Jakube
0

K, 26 bytes

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

Como el enfoque de Maltysen, fuerza bruta. El corazón del programa es un predicado que prueba si un vector dado es "mágico":

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

Construya un vector iota siempre que el vector de entrada ( !#x), cuente las ocurrencias de cada dígito ( (+/x=)') y compare el resultado con el vector de entrada ( x~). Si hay una coincidencia, tienes una secuencia mágica.

Desafortunadamente, esta primera puñalada parece ser bastante lenta. Las pruebas con Kona en mi computadora portátil tardan unos 12 segundos en manejar n = 7. Necesito pensar esto un poco más.

JohnE
fuente