Considere um triângulo ABC, em que cada lado tem comprimento inteiro (um triângulo integral ). Defina uma mediana de ABC como um segmento de linha de um vértice até o ponto médio do lado oposto. Na figura abaixo, os segmentos de linha vermelha representam as medianas. Observe que qualquer triângulo tem três medianas.
Seja n um número inteiro positivo. Quantos triângulos integrais não degenerados com comprimento lateral menor ou igual a n têm pelo menos uma mediana integral?
Desafio
Escreva um programa para calcular o número de triângulos integrais com pelo menos uma mediana integral para um determinado comprimento lateral máximo n . A ordem dos comprimentos laterais não importa, isto é, <6,6,5> representa o mesmo triângulo que <5,6,6> e deve ser contada apenas uma vez. Exclua triângulos degenerados como <1,2,3>.
Pontuação
O maior n para o qual seu programa pode gerar o número de triângulos em 60 segundos na minha máquina é sua pontuação. O programa com a pontuação mais alta vence. Minha máquina é uma Sony Vaio SVF14A16CLB, Intel Core i5, 8 GB de RAM.
Exemplos
Deixe- T ( N ) ser o programa de entrada com N .
T(1) = 0
T(6) = 1
T(20) = 27
T(22) = 34
Observe que T (1) = T (2) = T (3) = T (4) = T (5) = 0 porque nenhuma combinação de lados integrais produzirá uma mediana integral. No entanto, quando chegamos a 6, podemos ver que uma das medianas do triângulo <5,5,6> é 4, então T (6) = 1.
Observe também que T (22) é o primeiro valor no qual a contagem dupla se torna um problema: o triângulo <16,18,22> tem medianas 13 e 17 (e 2sqrt (85)).
Computando as medianas
As medianas de um triângulo podem ser calculadas pelas seguintes fórmulas:
Current top score: Sp3000 - 7000 points - C
fonte
Respostas:
C, força bruta - n = 6080
Isso é mais uma linha de base do que um candidato sério, mas pelo menos deve começar as coisas.
n = 6080 é o mais alto que obtive em um minuto de tempo de execução em minha própria máquina, que é um MacBook Pro com um Intel Core i5. O resultado que obtive para esse valor é:
O código é uma força puramente bruta. Enumera todos os triângulos dentro do limite de tamanho e testa a condição:
fonte
lrintf()
ou em(int)roundf()
vez de adicionar 0.5f e usar o truncamento padrão. Às vezes, você precisa usá-ffast-math
-lo para compilar com uma únicacvtss2si
instrução. inline gcclrintf()
esqrtf
with only-fno-math-errno
, para que você obtenha asm eficiente: godbolt.org/g/E3hncQ . (Eu usei-march=ivybridge
porque essa é a CPU do OP). Com-ffast-math
, clang transforma o sqrt em uma iteração rsqrt + Newton; IDK se isso é uma vitória.roundf
. Use(int)nearbyintf()
selrintf()
não estiver alinhado, porque ele usa o modo de arredondamento atual em vez de um modo estranho específico. stackoverflow.com/questions/37620659/…C, aproximadamente
66506900Realmente não uso C com frequência, mas com a quantidade de aritmética em andamento parecia uma boa escolha de idioma. O algoritmo principal é a força bruta, como a resposta do @ RetoKoradi , mas com algumas otimizações simples. Não tenho certeza se nossos valores são comparáveis, porque o computador do @ RetoKoradi parece ser mais rápido que o meu.
A principal otimização é ignorar
% 4
completamente a verificação. Um quadrado inteiron*n
é 0 ou 1 módulo 4, dependendo sen
ele é 0 ou 1 módulo 2. Portanto, podemos examinar todas as possibilidades de(x, y, z) % 2
:Convenientemente, existem apenas dois casos a considerar:
(0, 0, 0)
e(1, 1, 0)
que, dados os dois primeiros ladosa, b
, equivale ao terceiro ladoc
com paridadea^b
:a^b
é a mesma paridade quea-b
, então, em vez de pesquisarc = a-b+1
e aumentar 1s, isso nos permite pesquisar emc = a-b+2
e subir 2s.Outra otimização vem do fato de que, para o
(1, 1, 0)
caso, precisamos chamar is_square uma vez, pois apenas uma permutação funciona. Isso é especial no código, desenrolando a pesquisa.A outra otimização incluída é simplesmente uma falha rápida no
is_square
função.A compilação foi feita com
-std=c99 -O3
.(Agradecemos a @RetoKoradi por apontar que o
0.5
in is_square precisava ser0.5f
para evitar uma dupla conversão.)fonte
0.5f
vez de0.5
emis_square()
.0.5
é uma constante do tipodouble
; portanto, a expressão produzirá um valor duplo ao adicionar0.5
, incluindo a conversão de tipo defloat
paradouble
para o outro termo.f
, na verdade.Felix, desconhecido
Basicamente, uma porta da resposta C, mas é mais rápida que ela, testada com
clang -O3
eicc -O3
. Felix e Nim são literalmente as únicas duas linguagens que conheço que podem superar o C e o C ++ nos benchmarks. Estou trabalhando em uma versão paralela, mas vai demorar um pouco até terminar, então decidi postar isso adiante.Eu também coloquei "desconhecido" porque meu computador não é necessariamente o mais rápido do mundo ...
Comando usado para criar:
O C ++ gerado é bastante interessante de se olhar:
fonte
C # (cerca de 11000?)
n
é tomado como um argumento de linha de comando.Explicação
Podemos reescreverm = ( 2 a2+ 2 b2- c2) / 4---------------√ Como 2 a2+ 2 b2= 4 m2+ c2 , de onde é óbvio que c2 deve ser uniforme, e assim c é par. Deixeic = 2 C e reescrevemos novamente como uma2+ b2= 2 ( m2+ C2) . Portantouma2+ b2 deve ser par, então uma e b deve ter a mesma paridade.
A equaçãouma2+ b2= 2 ( m2+ C2) é a base do algoritmo meet-in-the-middle empregado aqui.
E seuma e b são estranhos, então não temos risco de contar duas vezes, porque apenas uma das três medianas pode ser integral. Se todos os três forem iguais, precisamos tomar cuidado com a contagem dupla. Portanto, trato dos dois casos separadamente, para que o caso ímpar-ímpar-par possa ser processado mais rapidamente do que o caso par-par.
fonte
n=5000
são de 67 segundos para a resposta de Reto Koradi, 48 segundos para a resposta do Sp3000 e 13 segundos para a minha resposta.C, n = 3030 aqui
resultados:
o código acima seria a tradução em C da resposta do Axiom (se não contarmos a função isq ()).
Meu compilador não vincula uma função que outros usam sqrtf () ... aqui não há função sqrt para float ... Eles têm certeza de que sqrtf é uma função padrão C?
fonte
APL NARS, n =
239282 em 59 segundos(traduzo o Axiom responda um, no APL):
fonte
Axioma, n = 269 em 59 seg
Se a, b, cx são o comprimento dos lados de um triângulo do lado máximo do comprimento n ...
Saberíamos que m: = sqrt ((2 * (a ^ 2 + b ^ 2) -cx ^ 2) / 4)
Como Peter Taylor havia dito, 4 | (2 * (a ^ 2 + b ^ 2) -cx ^ 2) e porque 2 | 2 * (a ^ 2 + b ^ 2) que 2 | cx ^ 2 => cx = 2 * c. Então a partir de 1 será
a e eb devem ter a mesma paridade, para que possamos escrever b em função de a
do que nós temos
para que o (1) possa ser reescrito, veja (2) (3) (4) como:
Onde
resultados
fonte
VBA 15.000 em DEZ segundos!
Eu esperava muito menos depois desses outros posts. Em um Intel 7 com 16 GB de RAM, recebo 13-15.000 em dez segundos. Em um Pentium com 4 GB de RAM, recebo de 5 a 7.000 em dez segundos. O código está abaixo. Aqui está o resultado mais recente sobre o Pentium
Chegou a um triângulo com lados 240, 239, 31 e um meio de 121. A contagem de meios é 7.371.
fonte