Defina a função f (n) para um número inteiro positivo n da seguinte maneira:
- n / 2 , se n for par
- 3 * n + 1 , se n for ímpar
Se você aplicar repetidamente esta função a qualquer n maior que 0, o resultado sempre parecerá convergir para 1 (embora ninguém tenha conseguido provar isso ainda). Essa propriedade é conhecida como Conjectura Collatz .
Defina o tempo de parada de um número inteiro como o número de vezes que você deve passar pela função Collatz f antes de atingir 1. Aqui estão os tempos de parada dos 15 primeiros números inteiros:
1 0
2 1
3 7
4 2
5 5
6 8
7 16
8 3
9 19
10 6
11 14
12 9
13 9
14 17
15 17
Vamos ligar para qualquer conjunto de números com o mesmo tempo de parada primos Collatz . Por exemplo, 5 e 32 são primos de Collatz, com um tempo de parada de 5.
Sua tarefa: escreva um programa ou função que use um número inteiro não negativo e gere o conjunto de primos Collatz cujo tempo de parada é igual a esse número inteiro.
Entrada
Um número inteiro não negativo S, fornecido via STDIN, ARGV ou argumento de função.
Saída
Uma lista de todos os números cujo tempo de parada é S, classificados em ordem crescente . A lista pode ser impressa pelo seu programa ou retornada ou impressa pela sua função. O formato de saída é flexível: espaço separado, nova linha ou qualquer formato de lista padrão do seu idioma é adequado, desde que os números sejam facilmente distinguíveis um do outro.
Exigências
Seu envio deve fornecer resultados corretos para qualquer S ≤ 30. Ele deve terminar em segundos ou minutos, não horas ou dias.
Exemplos
0 -> 1
1 -> 2
5 -> 5, 32
9 -> 12, 13, 80, 84, 85, 512
15 -> 22, 23, 136, 138, 140, 141, 150, 151, 768, 832, 848, 852, 853, 904, 906, 908, 909, 5120, 5376, 5440, 5456, 5460, 5461, 32768
Aqui está uma síntese da saída para S = 30 .
Este é o código-golfe : o programa mais curto em bytes vence. Boa sorte!
Respostas:
Pitão,
262421 bytesEste código é executado instantaneamente para
S=30
. Experimente você mesmo: DemonstraçãoObrigado a @isaacg por salvar 5 bytes.
Explicação
Meu código começa com
1
e desfaz a função Collatz. Ele mapeia todos os númerosd
daS-1
etapa para2*d
e(d-1)/3
. O último nem sempre é válido.fonte
-F
.- ... 1
ao redor da soma dentro da redução, não precisará que a redução seja a.u
, nem a parte-F
externa. Salva 2 caracteres.q4%d6
é equivalente a!%hhd6
, mas 1 caractere menor.Mathematica,
989289 bytesEsta solução resolve
S = 30
imediatamente:Esta é uma função sem nome, tendo
S
como único parâmetro e retornando uma lista dos primos Collatz.O algoritmo é uma pesquisa simples e abrangente. Os primos Collatz para um dado
S
são todos os números inteiros que podem ser alcançados a partir dos primos Collatz paraS-1
via2*n
ou números ímpares que podem ser alcançados via(n-1)/3
. Também precisamos garantir que produzimos apenas os números inteiros alcançados pela primeira vez após asS
etapas, para acompanhar todos os primos anterioresp
e removê-los do resultado. Como estamos fazendo isso de qualquer maneira, podemos salvar alguns bytes calculando as etapas de todos os primos anteriores (não apenas os deS-1
) para salvar alguns bytes (o que o torna um pouco mais lento, mas não notavelmente para o necessárioS
).Aqui está uma versão um pouco mais legível:
fonte
Python 2,
8683757371 bytesLigue como
f(30)
.n = 30
é praticamente instantâneo.(Agradecemos a @DLosc pela idéia de recursão
k
sendo um número, e não uma lista de primos, e alguns bytes. Agradecemos a @isaacg por desistir~-
.)Essa variante é muito mais curta, mas infelizmente leva muito tempo devido à ramificação exponencial:
fonte
f=lambda d,n=1:d and sorted(sum((c(d-1,x)for x in[n*2]+[~-n/3][:n>4==n%6]),[]))or[n]
. É menos eficiente com as chamadas de função, mas ainda o fazn = 30
em menos de um segundo.f=lambda n,k=1:sorted([k][n:]or(k>4==k%6and f(n-1,~-k/3)or[])+f(n-1,k*2))
~-
é desnecessário porque você está usando a divisão inteira.CJam,
2926 bytesO crédito vai para @isaacg por sua idéia de remover 1s após cada iteração, o que me salvou dois bytes diretamente e outro indiretamente.
Experimente online no intérprete CJam (deve terminar em menos de um segundo).
Como funciona
fonte
CJam, 35 bytes
Explicação em breve. Esta é uma versão muito mais rápida que a abordagem "bastante direta" (veja no histórico de edições).
Experimente on-line aqui, para
N = 30
execução em segundos na versão on-line e instantaneamente no Java Compilerfonte
It should finish in seconds or minutes, not hours or days.
S=15
não funciona.Java 8, 123
Quando
x
30, o programa leva 15 minutos e 29 segundos.Expandido
fonte
javac 1.7.0_79
no Ubuntu me deu muitos erros de sintaxe.i > 1 && ++n <= x
(você também pode soltarn++
) parece ser ainda mais rápido para apenas mais 5 caracteres ... cerca de 3 minutos para S = 30 para mim. Que fica raspada com segurança menos de um minuto se eu incluir.parallel()
também, mas uma vez que este é o código-golf ...Python 2, 118 bytes
Bem, imaginei que não alcançaria a melhor pontuação em Python depois de ver a solução do @ Sp3000. Mas parecia um pequeno problema divertido, então eu queria tentar uma solução independente de qualquer maneira:
A mesma coisa antes de remover o espaço em branco:
Esta é uma implementação muito direta de uma primeira pesquisa abrangente. Em cada etapa, temos o conjunto com o tempo de parada
k
e derivamos o conjunto com o tempo de paradak + 1
adicionando os possíveis predecessores de cada valort
no conjunto da etapak
:2 * t
é sempre um possível antecessor.t
pode ser escrito como3 * u + 1
, ondeu
é um número ímpar que não é1
, entãou
é um predecessor.Demora cerca de 0,02 segundos para executar
N = 30
no meu MacBook Pro.fonte
s.add(x)
é desnecessário em um golfe, pois geralmente você pode fazê-los|={x}
. Além disso, usar em~-x
vez de(x+1)
salvar entre colchetes. Mas por outro lado, bom trabalho :)s.add()
porque ele se torna uma tarefa e não pode mais fazer parte da expressão. Funciona para o primeiro. Osfor
loops baseados em contadores também são sempre bem detalhados. Eu pensei que poderia reduzi-lo usando umwhile
loop, mas acabou sendo exatamente do mesmo tamanho.for
loop, desde que você não use a entrada de qualquer outra forma provavelmente você pode fazerexec"..."*input()
em vez :)PHP 5.4+, 178 bytes
A função
Teste e Saída
S (30) é executado em 0,24 segundos * , retorna 732 elementos. Um casal é
* Para economizar em bytes, eu tinha que adicionar
ksort
earray_keys
a cada passo. A única outra opção que tive foi criar uma pequena função de invólucro que chamac()
e depois chamaarray_keys
eksort
no resultado uma vez. Mas devido ao tempo ainda estar decentemente decente, decidi levar o desempenho para uma baixa contagem de bytes. Sem a classificação e processamento adequados, o tempo é em média de 0,07 segundos para S (30).Se alguém tiver alguma maneira inteligente de obter o processamento adequado apenas uma vez sem muitos bytes adicionais, informe-me! (Eu guardo meus números como chaves de matriz, daí o uso de
array_keys
eksort
)fonte
Linguagem C
fonte
{}
botão para formatar seu código, o que eu fiz para você. Mas como Alex diz, adicione o nome do idioma (C?) E tente jogar com ele :) Mas seja bem-vindo!f
não está se comportando corretamente. Coms=5
, recebo vários resultados incorretos.if (r == s)return true;
deveria serreturn (r==s)
, jáf
que não retornará nada significativo quando(r < s)
. Além disso, eu acho que você deve declarari
emf
quelong
, uma vez que ele irá transbordar rapidamente para alguns valores.return (r==s);