Encontre o período geral em uma lista de frequências

8

Inspirado em http://xkcd.com/1331/

Nesta história em quadrinhos do xkcd, existem vários gifs que piscam com frequência diferente. Quero saber qual seria o período se fosse um único GIF. Dada uma lista de números que representam as frequências individuais, imprima o período do GIF geral.

Definição formal

Entrada:

N
f1
f2
.
.
.
fN

Resultado:

P

Onde N é o número de frequências, fi é a i-ésima frequência e P é o período resultante do GIF total.

Você pode optar por usar qualquer caractere delimitante que desejar (em vez de \ n) e excluir o N, se desejar, e isso será deduzido pelo número de delímetros.

Algumas especificidades

As frequências são a representação de ponto flutuante de precisão dupla mais próxima dos números fornecidos como entrada.

O período de saída é um número inteiro não assinado de 64 bits, arredondado (acima de 0,5) para o todo mais próximo. Qualquer entrada que produza um período maior que 2 ^ 64-1 é considerado comportamento indefinido.

Da mesma forma, qualquer entrada <= 0 é considerada comportamento indefinido.

Condição da vitória

Código de golfe para ganhar o menor código!

Triturador
fonte
Possível spoiler ... isso não seria apenas o produto das frequências especificadas?
Danmcardle
@crazedgremlin Não, não é, mas você está bem perto.
Victor Stafusa
@crazedgremlin - Se A for 2s e B for 4s, o período resultante será 4s, não 8s.
Digital Trauma
Ah, entendo obrigado. @Cruncher, o que exatamente você quer dizer com "frequência"? Repetições por segundo ou a quantidade de tempo que uma repetição leva? Suponho que o primeiro, como geralmente é o que significa frequência.
Danmcardle
Existem pelo menos 2 métodos para isso: Pegue a frequência geral como o GCD das frequências de entrada e inverta-a. Ou pegue as frequências de entrada, inverta todas para obter os períodos e considere o LCM como o período geral. Eu peguei o GCD. @DavidCarraher levou o LCM. Você só precisa lidar com os não-inteiros.
Victor Stafusa

Respostas:

8

APL, 4

∧/∘÷

é LCM lógico e numérico (com domínio sobre números inteiros, flutuantes, complexos, racionais, qualquer pilha de números suportada pela implementação da APL), assim ∧/como a redução pelo LCM ou a computação do LCM de uma matriz.

Monádico ÷é inverso numérico. Portanto, a composição ∧/∘÷é o LCM dos inversos dos números fornecidos.

A outra fórmula, inversa do GCD, seria ÷∘(∨/)onde os parênteses são necessários para fixar a precedência entre e /.

Você pode experimentá-lo online em http://tryapl.com/

Exemplos

      ∧/∘÷ .12 .02 3.9 .15 .99
100
      ∧/∘÷ (16÷5)(2÷3)(2.35)(1÷7)
420
Tobia
fonte
Holy bananas!
triturador
3
@ Cruncher que seria †))! no APL.
21414 Tobia
Bravo. Eu acho que temos um vencedor.
Victor Stafusa
Simplesmente incrível. Tiro o chapéu para você.
DavidC
4

Mathematica 43 28

Segunda tentativa

Minha primeira tentativa não foi correta, embora tivesse alguns dos ingredientes necessários (LCM, Racionalize). A solução completa requer levar em consideração o numerador e o denominador de cada frequência (expressa como uma fração comum).

l é a lista de frequências.

A racionalização de 2,35 o converte na fração comum 235/100.

f@l_:=LCM@@(1/Rationalize@l)

Suponha que todos os GIFs sejam disparados em t = 0.

A abordagem a seguir não exige que as frequências sejam expressas como "números reais", ou seja. como frações decimais. Eles podem ser outro tipo de frações. O exemplo abaixo é um caso em que as frações estão em quintos, terços, centésimos e sétimos.

Se duas ou mais frequências são incomensuráveis ​​(nesse caso, pelo menos uma deve ser um número irracional), não há solução. Em outras palavras, não haverá um ponto no tempo, t> 0, no qual todos os componentes serão acionados ao mesmo tempo.

Exemplo 1

f[{50, 10}]

1/10


Exemplo 2

f[{16/5, 2/3, 2.35, 1/7}]

420

Se multiplicarmos o menor período geral por cada uma das frequências, encontraremos um número inteiro de ciclos em cada caso:

420*{16/5, 2/3, 2.35, 1/7}

{1344, 280, 987, 60}

(1344 saltos de 16/5 unidades) chegam a 420. (280 saltos de 2/3 unidades) chegam a 420. (987 saltos de 2,35 unidades) chegam a 420. (60 saltos de 7 unidades) chegam a 420.

DavidC
fonte
A ferramenta certa para o trabalho certo.
Victor Stafusa
Não sei se entendi. Se as entradas forem frequências, f [{50,10}] significaria o ciclo comum de sinal que dispara 50 vezes por segundo e um ciclo que arquiva 10 vezes por segundo? A resposta correta seria 1/10 de segundo, mas f [{50, 10}] retorna 1. Na verdade, muitas coisas aleatórias retornam uma resposta de 1. f [{345345, h}] retorna 1.
Michael Stern
Minha abordagem original estava incompleta (e, portanto, incorreta). Eu a alterei de forma a abordar sua observação. A solução atual também faz sentido geometricamente (usando segmentos de linha em relação à linha real).
DavidC
Eu estava indo postar exatamente essa solução, mas você me venceu. Muito agradável.
Jonathan Van Matre
@Jonathan. Sim, sua abordagem era quase idêntica à minha. Mas não vejo a necessidade de Round. Rationalize e LCM não garantem que os resultados sejam inteiros?
DavidC
2

Javascript: 191 caracteres

O formato de entrada que eu escolhi (dentro das regras) são os números de frequência separados por vírgulas. Não são permitidos espaços nem novas linhas. O N inicial não deve ser fornecido. Cada número deve ser apenas uma série de pelo menos um [0-9] dígitos com um ponto opcional em algum lugar. Se a entrada estiver malformada, o comportamento será indefinido.

Como funciona:

O período de alguns números inteiros de frequência é o GCD desses números. Se os números fornecidos não são números inteiros, ele os multiplica sucessivamente por 10 até obter tudo como um número inteiro (isso explora o fato de que os números não inteiros são dados na base 10). Depois de calcular o GCD, ele divide o resultado pela potência de dez usada para multiplicar os números de entrada e, portanto, obter a frequência geral. Invertendo isso, obtemos o período.
Nota: Tenho certeza de que agora que dei essa resposta, alguém codificará o mesmo em APL ou J e vencê-lo. :(

O código:

d=1,s=prompt().split(",");for(a in s){s[a]=parseFloat(s[a]);while(s[a]*d%1>0)d*=10}g=s[0]*d;for(a in s){u=g;v=s[a]*=d;p=2;q=1;while(u>=p&v>=p)if(u%p|v%p)p++;else{u/=p;v/=p;q*=p}g=q}alert(d/g)

Testando:

Input: 50,10
Output: 0.1
Interpretation: One GIF blinks 10 times per second (period = 0.1s) and the other 50 times (period = 0.02s). So a combined GIF would repeat itself in 0.1 seconds.

Input: 2.7,3.4
Output: 10
Interpretation: One blinking at 2.7 times per second will blink 27 times in 10 seconds. One blinking 3.4 times per second will blink 34 times in 10 seconds. So, 10 seconds is a period, and since GCD(27,34)=1, it is the smallest.

Input: 4.8,7.2
Output: 0.4166666666666667
Interpretation: One blinking at 4.8 times per second and the other at 7.2 times per second, gives a frequency of 2.4 times per second, which is a period 0.41666... seconds.

Input: 0.6,12,7.9,4.33
Output: 100
Interpretation: Similar to second case. 60, 1200, 790 and 433 times each 100 seconds. The GCD of these numbers is 1.

Input: 400,200,25,350
Output: 0.04
Interpretation: The slowest is the 25 times per second, which is the overall frequency. 25 times per second is a period of 0.04 seconds.

Input: 440,200,35,360
Output: 0.2
Interpretation: In 0.2 seconds, we have 88, 40, 7 and 72 blinks.
Victor Stafusa
fonte
GCD? Esse é o maior divisor comum, portanto sempre seria menor que as frequências. Eu acho que você quer dizer LCM (mínimo múltiplo comum).
23714 Justin
@ Quincunx Não, é o GCD. O período total é o LCM dos períodos individuais, não as frequências individuais.
Victor Stafusa
1
Aqui está o APL:(⊃x÷z)×∨/z←{⍵×10}⍣{⍵≡⌈⍵}x←⎕
marinus
Você executaria um caso de teste com números racionais ou "números reais" (no sentido de ciência da computação do termo)? Não acho que uma abordagem baseada no GCD funcione.
DavidC
@DavidCarraher Eu estraguei a frequência com o período, mas agora eu já consertei. Apenas mudei g/dpara d/g. Vou adicionar alguns casos de teste.
Victor Stafusa