Sequências mágicas de comprimento n

11

Uma sequência mágica é uma sequência de números inteiros não negativos, de x[0..n-1]modo que existem exatamente x[i]instâncias dei

Por exemplo, 6,2,1,0,0,0,1,0,0,0 é uma sequência mágica, pois existem 6 0, 2 1 e assim por diante.

Escreva uma função que, quando dada n, produz todas as seqüências mágicas de comprimento n


O programa que pode produzir a saída correta para o valor mais alto de n em 10 segundos vence. (Todos os programas são bem-vindos, no entanto)

Por exemplo, o programa de Alice pode lidar com até n = 15 em 10 segundos, enquanto o programa de Bob pode lidar com até n = 20 no mesmo tempo. Bob vence.

Plataforma: Linux 2.7GHz @ 4 CPUs

Agnishom Chattopadhyay
fonte
5
Bem-vindo ao PPCG! Este é um grande desafio, mas você precisa de um critério de vitória. Por exemplo, você poderia dizer que o vencedor é o programa mais curto.
Ypnypn
1
Relevante: número auto-descritivo
Sp3000 14/05
2
Por favor, não mude o critério vencedor depois que as respostas forem postadas. Além disso, isso era muito melhor como código de golfe do que como código mais rápido, pelo menos na minha opinião.
Alex A.
2
@xnor você pode começar gerando as partições inteiras de n e verificando se elas podem ser auto-descritivas.
Martin Ender
2
Qual é o menor n>5com uma solução que não é da forma [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? Procurei n=20e não encontrei um e me pergunto se estou cometendo um erro.
Xnor 14/05

Respostas:

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

Isso usa o fato, que vou provar, de que as únicas sequências mágicas de comprimento nsão:

  • [1, 2, 1, 0]e [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

Portanto, n>=7basta apenas retornar uma tupla enorme. Eu posso fazer isso aproximadamente n=10^8no meu laptop, o que provavelmente é limitado pela memória; mais e congela. (Graças a trichoplax pela idéia de usar tuplas em vez de listas.) Ou, se alguém pode imprimir um dicionário de entradas diferentes de zero {0:n-4, 1:2, 2:1, (n-4):1}, pode fazer isso por ginormous n.

Eu provo a singularidade de n>=7; os outros podem ser verificados por força bruta ou trabalho de casa.

A soma das entradas de lé a contagem total de todos os números da lista, que é seu comprimento n. A lista possui l[0]zeros e, portanto, n-l[0]entradas diferentes de zero. Mas, por definição, l[0]deve ser diferente de zero ou temos uma contradição, e cada uma das outras entradas diferentes de zero é pelo menos 1. Isso já é responsável por uma soma da l[0] + (n-l[0]-1)*1 = n-1soma total de n. Portanto, sem contar l[0], pode haver no máximo um 2 e nenhuma entrada maior que 2.

Mas isso significa que as únicas entradas diferentes de zero são l[0], l[1], l[2], and l[l[0]], cujos valores são no máximo l[0]e uma permutação de 1,1,2, o que fornece uma soma máxima de l[0]+4. Como essa soma é n, que é pelo menos 7, temos l[0]>=3, e assim l[l[0]]=1. Agora, há pelo menos um 1, o que significa l[1]>=1, mas se l[1]==1é outro 1, o l[1]>=2que implica l[1]é o único 2. Isso fornece l[2]=1, e todas as entradas restantes são 0, portanto l[0]=n-4, o que completa a solução.

xnor
fonte
E a linguagem é ...?
Edc65 14/05
@ edc65 Parece python. Mas eu não tenho certeza.
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)

Faz uma pesquisa abrangente de possíveis listas, preenchendo entradas da direita para a esquerda, interrompendo a pesquisa com um sufixo, se não for plausível, o que pode acontecer se:

  • A soma das entradas no sufixo excede n(a soma da lista inteira deve ser n)
  • A soma ponderada de i*l[i]no sufixo excede n(a soma da lista inteira deve ser n)
  • Qualquer número aparece no sufixo mais vezes que o sufixo diz que deveria
  • O número de pontos não preenchidos restantes é muito pequeno para responder a todos os números que precisam aparecer mais vezes.

Eu tinha prefixos originais testados da esquerda para a direita, mas isso foi mais devagar.

As saídas até n=30são:

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]

Exceto pelas três primeiras listas [1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0], existe exatamente uma lista de cada comprimento n>6e o formato [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]. Esse padrão persiste até pelo menos n=50. Suspeito que isso se mantenha para sempre; nesse caso, é trivial produzir um grande número deles. Mesmo se não, um entendimento matemático sobre as possíveis soluções aceleraria bastante a pesquisa.

xnor
fonte
@Ypnypn Eu tenho casos especiais n=0. Eu senti falta de que estamos retornando o resultado para um single n, sem contar os resultados n. Isso me faz bem n=40.
Xnor 14/05
0

Pitão - 15 bytes

Usa força bruta em todas as sequências possíveis de len ne, em seguida, filtra.

f.A.eq/TkYT^UQQ

Explicação completa em breve.

Experimente aqui online .

Maltysen
fonte
2
Para sua informação, o OP mudou o critério vencedor para o código mais rápido.
Alex A.
2
Independentemente do critério de ganhar, aqui está um campo de golfe de 3 bytes: `fqm / TdQT ^ UQQ`
Jakube
0

K, 26 bytes

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

Como a abordagem de Maltysen, força bruta. O coração do programa é um predicado que testa se um determinado vetor é "mágico":

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

Crie um vetor iota contanto que o vetor de entrada ( !#x), conte as ocorrências de cada dígito ( (+/x=)') e compare o resultado com o vetor de entrada ( x~). Se houver uma correspondência, você terá uma sequência mágica.

Infelizmente, essa primeira facada parece bem lenta. Testar usando Kona no meu laptop leva cerca de 12 segundos para lidar com n = 7. Eu preciso pensar um pouco mais nisso.

JohnE
fonte