Suponha que definamos uma matriz infinita M
, on N^2 -> {0, 1}
(de onde N
começa em 1
vez de 0
) desta maneira:
M(1, 1)
=0
.Para todo
x > 1
,M(x, 1)
=1
sex
é primo e0
caso contrário.Para todos
y > 1
,M(1, y)
= oy
th termo noThue-Morse sequence
.Para cada
x, y > 1
,M(x, y)
=M(x, y-1) + M(x-1, y) mod 2
.
A 16x16
seção superior esquerda desta matriz se parece (com x
linhas e y
colunas):
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
1 0 1 1 0 0 0 1 0 0 0 1 1 0 1 1
1 1 0 1 1 1 1 0 0 0 0 1 0 0 1 0
0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1
1 0 1 1 0 0 1 0 1 0 1 1 1 1 0 1
0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1
1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 1
0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 1
0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 1
0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0
1 0 1 1 1 0 0 1 1 0 1 0 1 0 1 1
0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1
1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0
0 1 1 1 0 0 1 0 0 1 0 1 1 0 1 1
0 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1
Sua tarefa é criar um programa que avalie o valor de uma entrada arbitrária nessa matriz com a maior precisão possível.
Seu programa terá dois números inteiros x
e, y
como entrada, em qualquer forma que você escolher, e retornará M(x, y)
, que será um 0
ou 1
.
Seu código pode ser escrito em qualquer idioma, mas não deve exceder 64 kilobytes (65.536 bytes) de tamanho de código-fonte ou 2 MB (2.097.152 bytes) de uso total de memória. Seu programa deve iniciar com memória vazia (ou seja, não pode carregar dados de outro lugar) e executar independentemente para cada entrada (ou seja, pode não armazenar dados comuns para várias execuções). Seu programa também deve poder avaliar todas as entradas no 8192x8192
quadrado superior esquerdo em um período de tempo razoável.
O programa que avaliar mais entradas corretamente no 8192 x 8192
quadrado superior esquerdo será o vencedor, com um código mais curto atuando como desempate.
fonte
Respostas:
J -
4238 charMuito rápido, 100% preciso e dentro das restrições de memória.
A estratégia é a seguinte: calcularemos antidiagonais sucessivos dessa matriz, executando um XOR em pares para avançar e adicionando os atuais bits Thue-Morse e primos às extremidades. Em seguida, puxamos o dígito necessário para fora do antidiagonal quando chegamos lá.
Explicação por explosão:
O uso desse verbo é
x m y
para M (x, y), conforme especificado na pergunta, ondem
está o verbo.Para salvar as teclas digitadas, não tentamos dizer se ainda precisamos de mais bits primos ou Thue-Morse, portanto calculamos todo o antidiagonal para obter o bit que queremos. No entanto,
8192 m 8192
ainda é executado em menos de 0,07 se cerca de 100 KiB no meu laptop modesto.fonte
Mathematica - 100% de precisão,
223193189 bytesAqui está uma versão legível:
Basicamente pré-calculo ao longo de diagonais de constante
x+y
.Recursos:
O(x*y)
.f[8192,8192]
leva cerca de 400 segundos. Suponho que haja espaço para melhorias (talvezRotateLeft
possa substituir o loop interno).Ele usa apenas uma matriz de até
max(x,y)
resultados intermediários na memória. Portanto, não há necessidade de usar mais do que cerca de 32k (assumindo números inteiros de 32 bits) para o próprio algoritmo (além disso, o que quer que o Mathematica use). De fato, o Mathematica usa o 31M por si só no meu sistema, mas isso funciona sem problemas:fonte
O(x*y)
tempos, mas o tempo total de execução aumenta mais rápido que isso. Não tenho muita certeza do que está acontecendo. Se algum Mathematica Guru pudesse me esclarecer, qual operação no loop nãoO(1)
seria muito útil! :) (bem,PrimeQ
eTotal@IntegerDigits
não o são, mas eu tive-los lá desde o início, e eles só chamadaO(y)
eO(x)
vezes, respectivamente)Matlab: 100% de precisão, 120 caracteres, tempo de execução não razoável
Usar:
fonte
M(8192, 8192)
, eu não aguento.Python, 192 caracteres
100% de precisão, calcula M (8192,8192) em ~ 10 segundos na minha máquina.
fonte
Haskell - 261 bytes - 100% - 1MB - Acho que não vai acabar tão cedo
Leva cerca de 10 segundos para
m 16 16
com-O2
, mas como eu ter escrito isso de qualquer maneira eu posso mostrar que apesar este problema:Talvez algum bom Haskeller seja capaz de otimizá-lo?
fonte
f p|p=not|0<1=id
deve ser melhor. Além disso, tente usarmorse = False : concat $ iterate [True] (\a -> a ++ map not a)
para aumentar a preguiça. Eu me pergunto como isso afetará o desempenho.True
para0<1
eFalse
para0>1
.Perl, 137
Não para 'vencer' :-), mas como ainda não há Perl aqui e o código foi escrito de qualquer maneira, aqui está.
Leva alguns segundos, se chamado
print f(8192,8192)
, armazena uma única linha de matriz na memória (matriz de 8192 números inteiros (escalares)), cerca de 3,5 Mb de processo Perl inteiro. Tentei fazê-lo com string em vez de array (com regexps ou acessando com substr), consome menos memória e pode ser jogado mais, mas corre muito mais devagar.Recuado:
fonte
Haskell, 223
isso tem tempo de execução rápido (5,7 segundos com
-O3
). a memória ainda não foi verificada, embora deva ser linear.isso usa o algoritmo diagonal visto aqui antes.
No que diz respeito à velocidade, as únicas coisas que importam são o algoritmo diagonal
-O3
, e o|foldr seq(0>1)s=0<1
guarda, o que torna a lista rígida. tudo o mais é implementado de maneira ineficiente - a verificação primária é feita verificando todos os números menores de divisão, os elementos da sequência Morse são recalculados constantemente. mas ainda é rápido o suficiente :-).fonte