Ajude o blog! PIX para doações: 6d8bc7a8-5d74-493a-ab7a-3515baf35956
Fala, pessoal! Hoje vim resolver o problema 2686. Eu resolvi esse exercício de algumas formas, mas só uma delas passou. Há problemas de precisão no cálculo, de forma que ele arredonde os segundos quando não deve. Enfim, percebido isso, consegui lidar mais com valores inteiros e o problema não ocorreu.
Antes de resolver qualquer algoritmo do BEECROWD, recomendamos seguir os seguintes passos:
- Ler todo enunciado do problema.
- Ler os tópicos do fórum em caso de dúvidas
- Preparar arquivos de entrada para teste, considerando as entradas de exemplo do URI, do udebug e outros valores limite;
- Preparar o ambiente de desenvolvimento e utilizar os mesmos parâmetros dos compiladores do URI
- Preparar um código-fonte padrão, já contendo a chamada às bibliotecas padrão, pré-processadores, retorno de função e um comando de escrita com "\n", pois no URI a grande maioria dos problemas exige a quebra de linha final.
Plataforma: URI (BEECROWD)
Problema: 2686
Enunciado:
Novamente Júlio pede sua ajuda, ele esqueceu de um pequeno detalhe. Como o seu o programa anterior só informava uma saudação, ele pediu que transformasse o grau do Sol/Lua em HH:MM:SS. Então caso aceite: dado um grau relativo a posição do Sol/Lua, refaça o sistema só que agora além da saudação de cada período do dia, informe exatamente as horas, os minutos e segundos.
Linguagens: C e C++
Solução:
Resolvi a questão da precisão usando valores inteiros no cálculo de horas, minutos e segundos.
As horas se calcula com (6+(m * 240) / (60*60)) % 60) % 24;
Os minutos se calcula com (m * 240) / 60) % 60;
Os segundos se calcula com (m * 240) % 60;
No caso das horas é necessário acrescentar 6, pois zero grau é igual a 6 horas. Para evitar que isso acabe excedendo as 24 horas, faz-se (horas + 6) % 24, ou direto como mostrei acima. Nos meus códigos eu fiz das duas formas para ficar mais claro. No caso dos minutos, o cálculo é dividir m por 0.25. Isso estava trazendo erros de precisão, bem como m * 4. Assim, optei por usar multiplicação por 240 e depois divisão por 60. O resto (%60) depois é para pegar somente a part excedente, que é o que nos interessa para o cálculo do horário. No caso dos segundos, a lógica é a mesma.
Em C a formatação da saída é feita com %02d. Em C++ usa-se setw e setfill, da biblioteca iomanip.
Cada código utiliza um valor de ponto flutuante. Em C++ utilizei float, em C utilizei o flutuante de dupla precisão (double). Isso foi feito para demonstrar que com qualquer um desses tipos dá pra conseguir o aceite na questão.
Código em C:
#include <stdio.h>
int main() {
double m;
int horas, minutos, segundos;
while (scanf("%lf", &m) != EOF) {
if (m >= 0.0 && m < 90.0 || m == 360.0)
printf("Bom Dia");
else if (m < 180.0)
printf("Boa Tarde");
else if (m < 270.0)
printf("Boa Noite");
else if (m < 360.0)
printf("De Madrugada");
printf("!!\n");
horas = 6 + ((int)(m * 240) / (60*60)) % 60;
minutos = ((int)(m * 240) / 60) % 60;
segundos = (int)(m * 240) % 60;
printf("%02d:%02d:%02d\n", horas % 24, minutos, segundos);
}
return 0;
}
Código em C++:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
float m;
int horas, minutos, segundos;
while (cin >> m) {
if (m >= 0.0 && m < 90.0 || m == 360.0)
cout << "Bom Dia";
else if (m < 180.0)
cout << "Boa Tarde";
else if (m < 270.0)
cout << "Boa Noite";
else if (m < 360.0)
cout << "De Madrugada";
cout << "!!" << endl;
horas = (6 + ((int)(m * 240) / (60*60)) % 60) % 24;
minutos = ((int)(m * 240) / 60) % 60;
segundos = (int)(m * 240) % 60;
cout << setw(2) << setfill('0') << horas << ":"
<< setw(2) << setfill('0') << minutos << ":"
<< setw(2) << setfill('0') << segundos << endl;
}
return 0;
}
Nenhum comentário:
Postar um comentário