Esse desafio é parcialmente um desafio de algoritmos, parcialmente um desafio de otimização e parcialmente simplesmente um desafio de código mais rápido.
Uma matriz cíclica é totalmente especificada por sua primeira linha r
. As linhas restantes são permutações cíclicas da linha r
com deslocamento igual ao índice da linha. Permitiremos matrizes cíclicas que não são quadradas, para que elas simplesmente estejam faltando algumas de suas últimas linhas. No entanto, sempre assumimos que o número de linhas não passa do número de colunas. Por exemplo, considere a seguinte matriz cíclica 3 por 5.
10111
11011
11101
Dizemos que uma matriz tem propriedade X se contiver dois conjuntos de colunas não vazios com índices não idênticos que tenham a mesma soma (vetor). A soma vetorial de duas colunas é simplesmente um somatório por elementos das duas colunas. Essa é a soma de duas colunas contendo x
elementos, cada uma com outra coluna contendo x
elementos.
A matriz acima trivialmente possui a propriedade X, pois a primeira e a última coluna são as mesmas. A matriz de identidade nunca tem propriedade X.
Se apenas removermos a última coluna da matriz acima, obteremos um exemplo que não possui a propriedade X e daria uma pontuação de 4/3.
1011
1101
1110
A tarefa
A tarefa é escrever código para encontrar a matriz cíclica de maior pontuação cujas entradas são todas 0 ou 1 e que não possuem a propriedade X.
Ponto
Sua pontuação serão as colunas numéricas divididas pelo número de linhas em sua matriz de melhor pontuação.
Desempate
Se duas respostas tiverem a mesma pontuação, a primeira submetida vence.
No caso (muito) improvável de alguém encontrar um método para obter pontuações ilimitadas, a primeira prova válida de tal solução será aceita. No evento ainda mais improvável em que você possa encontrar uma prova de otimização de uma matriz finita, é claro que também premiaremos a vitória.
Sugestão
Obter uma pontuação de 12/8 não é muito difícil.
Línguas e bibliotecas
Você pode usar qualquer idioma que tenha um compilador / intérprete disponível gratuitamente / etc. para Linux e quaisquer bibliotecas que também estão disponíveis gratuitamente para Linux.
Entradas principais
- 36/19 por Peter Taylor (Java)
- 32/17 por Suboptimus Prime (C #)
- 21/12 por justhalf (Python 2)
fonte
01
possui a propriedade X porque o conjunto da primeira coluna possui a mesma soma vetorial que o conjunto vazio. Talvez você quis dizer conjuntos de colunas não vazios? Eu acho que é mais limpo não mudar isso.01
tem a propriedade X:(1) = (0) + (1)
. Se você deseja excluir isso, deve dizer que os dois conjuntos de colunas devem ser separados.2^m
combinações de colunas a verificar a propriedade X. Se pudéssemos de alguma forma criar um esquema de "encontro no meio" (consulte o problema "soma do subconjunto"), isso provavelmente poderia reduzir isso param * 2^(m/2)
...Respostas:
16/9 20/11 22/12 28/15 30/16 32/1734/18 36/19 (Java)Isso usa várias idéias para reduzir o espaço e o custo da pesquisa. Veja o histórico de revisões para obter mais detalhes sobre versões anteriores do código.
0
e1
) e malhando; Utilizo o algoritmo descrito em Código A Gray para colares de densidade fixa e palavras de Lyndon em tempo amortizado constante , Sawada e Williams, Theoretical Computer Science 502 (2013): 46-54.BigInteger
para fazer um teste exato. Recebo uma melhoria significativa da velocidade, correndo o risco de falsos negativos, operando um módulo grande e mantendo tudo em primitivos. O primo que escolhi é o maior menor que 2 57 , pois permite multiplicar pela base da minha representação vetorial nocional sem transbordar.{-1,0,1}^m
tem sua negação também{-1,0,1}^m
, é necessário armazenar apenas um dos dois.2n/(n+1)
, estou acelerando as coisas apenas testando isso.O primeiro encontrado é
e esse é o único hit em 15 horas.
Vencedores menores:
fonte
n
vez derows
, embora seja à prova de falhas, no sentido de descartar soluções válidas em vez de aceitar soluções inválidas. Também não afeta os resultados.Python 2-21/12
No processo de provar que
2-(3/n)
sempre existe um para qualquern
Inspirado por essa pergunta , usei a sequência De Bruijn para forçar a força bruta das matrizes possíveis. E, depois de forçar brute
n=6,7,8,9,10
, encontrei um padrão em que a solução mais alta está sempre na forma de(n, 2n-3)
.Então, criei outro método para aplicar força nesse formato de matriz e usar o multiprocessamento para acelerar as coisas, pois essa tarefa é altamente distribuível. No ubuntu de 16 núcleos, ele pode encontrar solução
n=12
em cerca de 4 minutos:A maior parte da computação vai para a verificação da propriedade X, que requer a verificação de todos os subconjuntos (existem
2^(2n-3)
subconjuntos)Observe que eu giro a primeira linha para a esquerda, não para a direita, como na pergunta. Mas estes são equivalentes, pois você pode reverter toda a matriz. =)
O código:
Resposta antiga, para referência
A solução ideal até agora (
n=10
):Para
n=7
:Uma solução com a forma descrita por OP (
n=8
):Mas um melhor (
n=8
):Também encontrou outra solução ideal em
n=9
:O código é o seguinte. É apenas força bruta, mas pelo menos pode encontrar algo melhor do que a reivindicação do OP =)
fonte
n >= 31
, o que implica que eu precisaria verificar as2^(2n-3) = 2^59
combinações do vetor 31-dimensional. Não terminará na nossa vida = Dn*(2n-3)
24/13 26/14 28/15 30/1632/17 (c #)Editar: informações desatualizadas excluídas da minha resposta. Estou usando o mesmo algoritmo de Peter Taylor ( Editar: parece que ele está usando um algoritmo melhor agora), embora tenha adicionado algumas das minhas otimizações:
HasPropertyXFast
função, que verifica rapidamente se há conjuntos pequenos com somas iguais antes de usar a abordagem "meet in the middle".HasPropertyXFast
função, começo verificando conjuntos de colunas com 1 coluna, depois com 2, 3 e assim por diante. A função retorna assim que a primeira colisão de somas de coluna é encontrada. Na prática, isso significa que geralmente tenho que verificar apenas algumas centenas ou milhares de conjuntos de colunas em vez de milhões.long
variáveis para armazenar e comparar colunas inteiras e suas somas de vetor. Essa abordagem é pelo menos uma ordem de magnitude mais rápida que comparar colunas como matrizes.long
tipo de dados e para meus padrões de uso.Saída do programa:
Código:
Arquivo de configuração:
fonte
ulong
e deixando o turno quebrar em vez de usarBigInteger
.GetSumOfColumns
adiciona um loop extra que eu esperaria custar mais do que o fator de 2. A classificação da máscara parece interessante: talvez você possa editar a resposta para falar um pouco sobre isso? (E, em algum momento, experimentarei uma maneira alternativa de fazer o aborto antecipado: a razão pela qual não posso fazer isso é que o HashSet não suporta iteração e modificação simultâneas, mas tenho idéias para evitar a necessidade de um iterador) .