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


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


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.


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.


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


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.