Alba e tramonto


12

Sono un po 'romantico, adoro portare mia moglie a vedere albe e tramonti nel luogo in cui ci troviamo. Per il bene di questo esercizio, diciamo che non ho un codice che mi indichi l'ora del tramonto o dell'alba per qualunque data, latitudine e longitudine mi trovassi.

Il tuo compito, programmatori, è generare il codice più piccolo possibile che richieda una latitudine e una longitudine decimali (prese in gradi N e W, quindi i gradi S ed E saranno considerati negativi) e una data nel formato AAAA-MM-GG ( dal 1 ° gennaio 2000 in poi) e uscirà due volte in formato 24 ore per l'alba e il tramonto.

ad es. per oggi a Sydney, in Australia

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Bonus: -100 se riesci a calcolare l'altezza -100 se riesci a tenere conto dell'ora legale

Il codice DEVE sputare i tempi nel relativo fuso orario specificato nell'input in base alla latitudine e alla longitudine OPPURE nel fuso orario della macchina client.


3
Aspetta, cosa dobbiamo fare una ricerca [latitudine x longitudine] => [fuso orario]? Abbiamo un file di dati per questo? O un server a cui possiamo accedere? O c'è un linguaggio in cui sono incorporate queste cose? Puoi dirci quale? O dobbiamo memorizzare i confini del fuso orario? Con quale precisione? Dove otteniamo questi dati? Ti rendi conto che questi dati occuperanno la maggior parte della lunghezza del codice? Che dire delle coordinate che ricadono esattamente sul limite del fuso orario? Dire, i poli geografici? Inoltre, quale comportamento è consentito quando l'ingresso è una regione polare durante una notte / giorno polari? Che dire delle coordinate fuori portata?
John Dvorak,

Mi piace la sfida per calcolare l'orizzonte sulla base di un punto al di sopra una sfera idealizzata, ma io odio la sfida associato per trovare, a mano impacco, programatically decopmress e poi cercare in un fuso orario Lookup mappa. A meno che, naturalmente, non possiamo usare fusi orari idealizzati (l'offset è scelto in modo che il sole sia il più alto a mezzogiorno, quindi è arrotondato all'ora più vicina).
John Dvorak,

1
@JanDvorak Usa tutto quello che puoi, se la lingua che usi può sfruttare il fuso orario del cliente, allora fallo ...
WallyWest,

1
Qual è il comportamento desiderato per le regioni polari quando è un giorno / notte polare?
John Dvorak,

1
Ecco uno strumento che fa esattamente lo stesso: weatherimages.org/latlonsun.html
Eisa Adil,

Risposte:


4

Ho trascorso parecchio tempo a scrivere questo:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from math import *


class RiseSet(object):

    __ZENITH = {'official': 90.833,
                'civil': '96',
                'nautical': '102',
                'astronomical': '108'}

    def __init__(self, day, month, year, latitude, longitude, daylight=False,
                 elevation=840, zenith='official'):
        ''' elevation is set to 840 (m) because that is the mean height of land above the sea level '''

        if abs(latitude) > 63.572375290155:
            raise ValueError('Invalid latitude: {0}.'.format(latitude))

        if zenith not in self.__ZENITH:
            raise ValueError('Invalid zenith value, must be one of {0}.'.format
                            (self.__ZENITH.keys()))

        self.day = day
        self.month = month
        self.year = year
        self.latitude = latitude
        self.longitude = longitude
        self.daylight = daylight
        self.elevation = elevation
        self.zenith = zenith

    def getZenith(self):
        return cos(radians(self.__ZENITH[self.zenith]))

    def dayOfTheYear(self):
        n0 = floor(275*self.month/9)
        n1 = floor((self.month + 9) / 12)
        n2 = (1 + floor((self.year - 4*floor(self.year/4) + 2) / 3))
        return n0 - (n1*n2) + self.day - 30

    def approxTime(self):
        sunrise = self.dayOfTheYear() + ((6 - (self.longitude/15.0)) / 24)
        sunset = self.dayOfTheYear() + ((18 - (self.longitude/15.0)) / 24)
        return (sunrise, sunset)

    def sunMeanAnomaly(self):
        sunrise = (0.9856 * self.approxTime()[0]) - 3.289
        sunset = (0.9856 * self.approxTime()[1]) - 3.289
        return (sunrise, sunset)

    def sunTrueLongitude(self):
        sma = self.sunMeanAnomaly()
        sunrise = sma[0] + (1.916*sin(radians(sma[0]))) + \
                  (0.020*sin(radians(2*sma[0]))) + 282.634

        if sunrise < 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = sma[1] + (1.916*sin(radians(sma[1]))) + \
                 (0.020*sin(radians(2*sma[1]))) + 282.634

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        return (sunrise, sunset)

    def sunRightAscension(self):
        stl = self.sunTrueLongitude()
        sunrise = atan(radians(0.91764*tan(radians(stl[0]))))

        if sunrise <= 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = atan(radians(0.91764*tan(radians(stl[1]))))

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        sunrise_stl_q = (floor(stl[0]/90)) * 90
        sunrise_ra_q = (floor(sunrise/90)) * 90
        sunrise = sunrise + (sunrise_stl_q - sunrise_ra_q)
        sunrise = sunrise/15.0

        sunset_stl_q = (floor(stl[1]/90)) * 90
        sunset_ra_q = (floor(sunset/90)) * 90
        sunset = sunrise + (sunset_stl_q - sunset_ra_q)
        sunset /= 15.0

        return (sunrise, sunset)

    def sunDeclination(self):
        sunrise_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[0]))
        sunrise_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        sunset_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[1]))
        sunset_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        return (sunrise_sin_dec, sunrise_cos_dec,
                sunset_sin_dec, sunset_cos_dec)

    def sunHourAngle(self):
        sd = self.sunDeclination()
        sunrise_cos_h = (cos(radians(self.getZenith())) - (sd[0]* \
                         sin(radians(self.latitude))) / (sd[1]* \
                         cos(radians(self.latitude))))
        if sunrise_cos_h > 1:
            raise Exception('The sun never rises on this location.')

        sunset_cos_h = (cos(radians(self.getZenith())) - (sd[2]* \
                         sin(radians(self.latitude))) / (sd[3]* \
                         cos(radians(self.latitude))))
        if sunset_cos_h < -1:
            raise Exception('The sun never sets on this location.')

        sunrise = 360 - acos(radians(sunrise_cos_h))
        sunrise /= 15.0

        sunset = acos(radians(sunrise_cos_h))
        sunset /= 15.0

        return (sunrise, sunset)

    def localMeanTime(self):
        sunrise = self.sunHourAngle()[0] + self.sunRightAscension()[0] - \
                 (0.06571*self.approxTime()[0]) - 6.622
        sunset = self.sunHourAngle()[1] + self.sunRightAscension()[1] - \
                 (0.06571*self.approxTime()[1]) - 6.622
        return (sunrise, sunset)

    def convertToUTC(self):
        sunrise = self.localMeanTime()[0] - (self.longitude/15.0)

        if sunrise <= 0:
            sunrise += 24
        if sunrise > 24:
            sunrise -= 24

        sunset = self.localMeanTime()[1] - (self.longitude/15.0)

        if sunset <= 0:
            sunset += 24
        if sunset > 24:
            sunset -= 24

        return (sunrise, sunset)

    def __str__(self):
        return None

Ora non è ancora funzionale (ho rovinato alcuni calcoli) - Ci tornerò più tardi (se avrò ancora il coraggio) per completarlo / commentarlo .

Inoltre, alcune risorse interessanti che ho trovato durante la ricerca dell'argomento:


3
Ho appena visto il tuo commento di # It's late, I'm tired, and OP is a prick for asking me to do this. Non c'era alcun obbligo di fare questo compito ... Per favore, non inserire commenti come questo nel tuo codice ... Non si adatta favorevolmente con altri programmatori ... incluso me. Ammiro il fatto che tu l'abbia fatto andare rovente e gli altri link che hai fornito, ma per favore non usare mai più commenti come questo ...
WallyWest,

@Eliseod'Annunzio Hai le mie scuse.
Deneb,

@Eliseod'Annunzio non avevo intenzione di offenderti. Vorrei anche ringraziarvi per avermi dato un'idea assolutamente fantastica per la ricerca e il codice. Ora voglio trasformarlo in un modulo Python autonomo (con argomenti sys e così via). Risulta essere un po 'più complicato di quanto pensassi in precedenza, ma ho intenzione di farlo. Grazie ancora.
Deneb,

@Alex, ti rendi conto che questa sfida ha un anno? Sono abbastanza sicuro che abbia vinto.
mbomb007,

@ mbomb007: non me ne sono accorto.
Alex A.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.