Encontre os ponteiros do relógio mais próximos

15

Desafio

Dado um número de segundos após a meia-noite, produza o menor ângulo entre dois ponteiros em um relógio, usando o mínimo de bytes possível.

Você pode assumir que o número de segundos é sempre menor que 86400. Os ângulos podem ser representados em graus ou radianos.

Uma solução de referência está em: http://ideone.com/eVdgC0

Casos de teste (resultados em graus)

0 -> 0
60 -> 0.5
600 -> 5
3600 -> 0
5400 -> 45
6930 -> 84.75
50000 -> 63.333

Esclarecimentos

  • O relógio possui três ponteiros: horas, minutos e segundos.
  • Todos os ponteiros se movem continuamente, portanto, os ponteiros de horas e minutos podem ser encontrados entre as graduações no mostrador do relógio.
toto
fonte
Desafio relacionado (somente ponteiros de minutos e horas, em graus)
Sp3000 29/07
1
Você provavelmente deve especificar que há um ponteiro dos segundos no relógio.
Isaacg
Você pode adicionar alguns casos de teste?
Beta Decay
1
Em alguns relógios, o ponteiro dos minutos pula para o próximo minuto quando o ponteiro dos segundos chega ao topo. Em outros, ele se move continuamente. Eu acho que este é um relógio onde se move continuamente? Além disso, embora esteja claro quando você lê com atenção, inicialmente achei ambígua a "segunda mão", porque a maioria dos relógios tem pelo menos duas mãos, então adicionar a "segunda mão" realmente adiciona uma terceira mão.
Reto Koradi 29/07/2015
1
@BetaDecay Certamente. Eu poderia ter dito algo como: "Os relógios têm três ponteiros: horas, minutos e segundos".
Reto Koradi 29/07/2015

Respostas:

10

CJam, 36 35 34 32 30 bytes

riP*30/_60/_C/]2m*::-:mc:mC$3=

A saída está em radianos. Eu verifiquei as soluções para todas as 86400 entradas possíveis.

Experimente on-line no intérprete CJam .

Idéia

Como radianos é uma volta completa, cada intervalo de minuto / segundo no relógio tem 2π / 60 = π / 30 radianos de largura.

Assim, dividir o número de segundos por π / 30 produz a posição do ponteiro dos segundos.

O ponteiro dos minutos se move a 1/60 do ritmo do ponteiro dos segundos, portanto, dividir o resultado de cima por 60 gera a posição do ponteiro dos minutos.

Da mesma forma, dividir o último resultado por 12 gera a posição do ponteiro das horas.

Observe que nossos três quocientes acima não estão necessariamente no intervalo [0,2π).

Ao calcular todas as nove possíveis diferenças dos ângulos das mãos, obtemos três 0 (distância angular entre uma mão e ela mesma) e as seis distâncias entre as diferentes mãos.

Se os ponteiros mais próximos estiverem na metade que não inclui 12 , uma das diferenças acima será a saída desejada (mod ).

No entanto, às 01:55:30 (por exemplo), o ponteiro das horas está em um ângulo de 1.008 rad (57.75 graus) e o ponteiro dos minutos em um ângulo de 5.812 rad (333.00 graus) de 12 , dando uma diferença de 4.804 rad (275,25 graus). Subtraindo esse resultado de uma volta completa, obtemos o ângulo medido "na outra direção", que é igual a 1,479 rad (84,75 rad).

Agora, em vez de mapear cada ângulo θ em [0,2π) e subtrair condicionalmente o resultado de π , podemos simplesmente calcular arccos (cos (θ)) , pois cos é periódico e par e os arccos sempre produzem um valor em [ 0, π) .

Ignorando os três menores resultados (todos zero), o quarto menor será a saída desejada.

Código

ri                             e# Read an integer from STDIN.
  P*30/                        e# Multiply by π and divide by 30.
       _60/                    e# Divide a copy by 60.
           _C/                 e# Divide a copy by 12.
              ]2m*             e# Push the array of all pairs of quotients.
                  ::-          e# Replace each pair by its difference.
                     :mc       e# Apply cosine to each difference.
                        :mC    e# Apply arccosine to each cosine.
                           $3= e# Sort and select the fourth smallest element.

Versão alternativa (34 bytes)

rd6*_60/_C/]360f%2m*::m360X$f-+$6=

A saída é em graus e nenhuma função trigonométrica é usada.

Experimente on-line no intérprete CJam .

Dennis
fonte
9

Mathematica, 40 bytes

Min@Abs@Mod[#{11,708,719}/120,360,-180]&

Explicação: Seja o tnúmero de segundos desde a meia-noite. A posição de cada mão é

hour: t/120 (mod 360)
min:  t/10 (mod 360)
sec:  6t (mod 360)

Para calcular a distância angular absoluta entre xgraus e ygraus, podemos modificar y - x360 no intervalo [-180, 180]e, em seguida, pegar o valor absoluto. (Note que não há nenhuma restrição xe y.) Então, esta função apenas calcula as diferenças de pares t/10-t/120, 6t-t/10e, 6t-t/120e faz isso.

jcai
fonte
Desculpe, não estou familiarizado com o Mathematica, mas isso realmente aceita um argumento ou variável pelo número de segundos desde a meia-noite?
29515 Winny
1
@ Winin Sim, é uma função pura (indicada por &) e o primeiro argumento que é passado é referido dentro como #.
jcai
7

Python, 65

lambda n,l={720,60,1}:6*min((n/x-n/y)%60for x in l for y in{x}^l)

A distância percorrida pela hora, minuto e ponteiro dos segundos, em unidades de 1/60 do círculo, é h,m,s = n/720, n/60, n/1. Podemos pegar esses mod 60 para obter sua posição no círculo de 0para 60.

Se considerarmos a diferença 60, obtemos o número de unidades que uma está na frente da outra. Tomamos todas as seis diferenças possíveis, encontramos o mínimo e multiplicamos por 6para redimensionar para 360graus.

A compreensão da lista de duas camadas primeiro escolhe o primeiro lado, como representado por 720, 60ou 1, então escolhe o outro lado de fora do referido conjunto com a primeira escolha removido por meio de conjunto xor.

Eu testei isso exaustivamente contra o código de referência.

xnor
fonte
6

C #, 163 152 bytes

Isso cria todas as mãos duas vezes para contar a volta, depois percorre todas as combinações e encontra o ângulo mínimo entre as mãos. Os cálculos são realizados em 60 divisões, depois multiplicados por 6 para obter graus.

Recuado para maior clareza:

float F(int s){
    float b=60,c;
    float[]a={c=s/b/b%12*5,c+b,c=s/b%b,c+b,s%=60,s+b};
    for(s=36;s-->0;)
        b=s%6!=s/6&(c=(c=a[s%6]-a[s/6])<0?-c:c)<b?c:b;
    return b*6;
}

Exemplo de saída:

    0 seconds, 00:00:00, smallest angle is 0°
43200 seconds, 12:00:00, smallest angle is 0°
86399 seconds, 23:59:59, smallest angle is 0.09164429°
 3330 seconds, 00:55:30, smallest angle is 54.75°
39930 seconds, 11:05:30, smallest angle is 60.25001°
21955 seconds, 06:05:55, smallest angle is 65.49998°
21305 seconds, 05:55:05, smallest angle is 59.50001°
 5455 seconds, 01:30:55, smallest angle is 75.45831°
41405 seconds, 11:30:05, smallest angle is 44.95834°
Mão-E-Comida
fonte
Solução agradável para explicar o envoltório
31715
2

TI-BASIC, 17 bytes

min(cos⁻¹(cos(ΔList(Ans{6,.1,5!⁻¹,6

Usa Dennis's arccos(cos(para normalizar distâncias; no entanto, em vez de calcular todas as distâncias aos pares, calcula apenas as três necessárias usando ΔList([seconds],[minutes],[hours],[seconds].

Este programa espera o Degreemodo e retorna a resposta em graus.

EDIT: 5!é um byte menor que 120.

lirtosiast
fonte