Distribuzione uniforme costanti su record

di il
5 risposte

Distribuzione uniforme costanti su record

Buonasera a tutti.

Vi scrivo per chiedere lumi alla community su un algoritmo che dovrei implementare, per rendere più semplice una parte del mio lavoro.

Cercherò di descrivere con dovizia di dettagli i presupposti, per cercare di rendere il più chiare possibili le mie richieste.

Dunque, alla fine di ogni mese, il mio responsabile sul mio luogo di lavoro mi consegna, tramite posta elettronica aziendale, le letture delle mie timbrature in ufficio relative al mese appena trascorso.

Queste letture compaiono secondo il file che vi allego quì sotto.

I dati che mi interessano sono i vari record che identificano nel dettaglio ogni giorno, tutte le ore che ho lavorato e, il dato più importante è quello che si trova in calce al modulo, che riporta il numero complessivo di ore lavorate relative a quel particolare mese.

Nel modulo che ho allegato qui come esempio, ho lavorato nel mese 167 ore e 18 minuti.

Ora, nel database aziendale devo registrare il computo delle ore definitivo per ogni mese, ma questo sistema ha una particolarità molto fastidiosa, perchè ammette per ogni giornata lavorata come orario lavorabile solamente una cifra intera, ovvero in questo sistema posso selezionare, per ogni giorno o 7 ore, oppure 7.30 ore oppure 8 ore, oppure 8.30 e così via.

Questo significa che io, ogni mese, devo cambiare a mano le mie timbrature inserendo per ogni giornata solo uno di questi possibili valori, ma facendo in modo che il computo complessivo delle ore non sia eccessivamente lontanop da quello che compare sul report ufficiale.

In pratica, devo aggiustare ogni giornata lavorativa segnando quando 7.30 ore, quando 8, ma facendo in modo che la somma di tutte queste sia il più possibile prossima alla lettura ufficiale.

Tutto questo, fatto a mano mi porta via molto tempo, e quindi vorrei sapere se c'è un metodo per calcolare e distribuire in maniera automatica tutti questi margini in maniera tale che, alla fine la risultante sia il più possibile prossima.

Di solito, ordinare le varie letture in maniera ascendente o discendente, non mi crea problemi, ma cerco aiuto per quanto riguarda l'implementazione, almeno logica dell'algoritmo.

In quale maniera posso calcolare, come distribuire le varie quantità marginali, in modo da ottenere un computo risultante idoneo?

Spero che la richiesta sia abbastanza chiara.

Vi ringrazio per la disponibilità.

Saluti.
Allegati:
18557_af710206aaac395d3d2f26af8cd70f7b.png
18557_af710206aaac395d3d2f26af8cd70f7b.png

5 Risposte

  • Re: Distribuzione uniforme costanti su record

    L'algoritmo che mi è venuto in mente è questo:
    Sia S=0 lo scarto minimo.
    Per ogni ora H associata ad un giorno G
        se H è intera allora aggiungi H nel DB
        altrimenti trova l'ora intera Hi più prossima ad H+S tale che Hi<H+S
            aggiungi Hi nel DB
            rendi S uguale a H-Hi
    decidi cosa fare con S
    Per "ora intera" intendo verifica che sia 7:30, 8:00, 8:30, ecc.
  • Re: Distribuzione uniforme costanti su record

    In questo modo, alla fine del ciclo, per tutti i giorni, mi ritroverei con una variabile "s" all'interno della quale sono accumulati tutti gli scarti di tutte le giornate lavorate.

    Questi "scarti" dovrebbero poi essere ridistribuiti in tutte le giornate, in maniera tale che, sia le giornate abbiano sempre una lettura arrotondata alla mez'ora precedento o successiva, sia anche che il computo finale delle ore lavorate nel mese sia quanto più prossimo possibile alla lettura ufficiale.

    Dunque alla fine di tutto il problema si riduce a: con quale criterio decido come ridistribuire il contenuto dell'accumulo?

    Io avevo pensato a questo: Arrotondo inizialmente tutte le letture alla mez'ora precedente, appongiando in una variabile di accumulo, tutti gli scarti.

    Ordino poi le letture con un ordinamento crescente del campo prestazioni, e questi valori li approssimo alla lettura della mez'ora seguente, distribuendo i minuti presi dalla variabile di accumulo, in questo modo però, sospetto che, alla fine del ciclo, potrei trovarmi con un residuo all'interno dell'accumulatore eccessivo.

    Suggerimenti n merito?
  • Re: Distribuzione uniforme costanti su record

    La variabile S contiene lo scarto minimo. Non è detto che sia sufficiente ad arrivare ad una sola mezzora.
    Con il mio algoritmo lo scarto è di 28 miniti (EDIT: 18 minuti).
    Con il tuo otterresti uno scarto di 6 ore e 28 minuti, poi ordini le ore, spalmi le 6 ore ai primi dodici campi arrotondandoli alla mezzora seguente. Alla fine ti rimane sempre lo scarto di 28 minuti.

    Alla fine l'algoritmo che ti ho mostrato è più efficiente (non devi ordinare nulla e riscorrere nulla).
    Per quanto riguarda lo scarto solo tu sai come gestirlo. Potresti memorizzarlo da qualche parte e usarlo nel mese successimo o se è maggiore di 15 minuti arrotondarlo a mezzora.
  • Re: Distribuzione uniforme costanti su record

    harpefalcata ha scritto:


    Io avevo pensato a questo: Arrotondo inizialmente tutte le letture alla mezz'ora precedente, appoggiando in una variabile di accumulo, tutti gli scarti.

    Ordino poi le letture con un ordinamento crescente del campo prestazioni, e questi valori li approssimo alla lettura della mezz'ora seguente, distribuendo i minuti presi dalla variabile di accumulo, in questo modo però, sospetto che, alla fine del ciclo, potrei trovarmi con un residuo all'interno dell'accumulatore eccessivo.
    Mi pare che questa proposta sia eccessivamente intricata per il tuo problema.

    Per fare in modo che la somma delle ore che vai a registrare sia il più vicino possibile a quelle effettive io seguirei un algoritmo simile a quello che ha proposto @xneo, ovvero se la prestazione ha una durata intera (comprendo come hai fatto tu anche le mezze ore in questa categoria) allora registro la durata effettiva, altrimenti arrotondo la durata all'ora intera precedente o successiva in modo da minimizzare la differenza tra la somma delle ore effettive e quelle registrate.

    Otterrai quindi un totale di ore registrate che sfora al massimo di 15 minuti dal "vero" totale (nel tuo caso il risultato sarebbe 167:30), e sarà sempre il più vicino possibile al totale.
    In questo modo però ti capiterà diverse volte di arrotondare la durata della prestazione alla mezz'ora "più lontana", e non escludo che esista un modo per arrotondare quasi sempre alla mezz'ora più vicina e contemporaneamente mantenere il risultato vicino all'effettivo, ma complicherebbe di molto l'algoritmo (almeno credo).

    Giusto per farti un esempio la prima prestazione di 07:42 ore verrebbe ovviamente registrata come 07:30. La seconda prestazione di 07:43 non verrà invece registrata come 07:30, anche se sarebbe l'arrotondamento più vicino, perché a quel punto lo scarto totale sarebbe di 25 minuti, e noi vogliamo che sia il minore possibile. Scriverò quindi 08:00, con uno scarto totale di 5 minuti.

    L'algoritmo quindi, adattando un po' la notazione già usata da @xneo, sarebbe:
    
    H = Durata prestazione effettiva di un giorno G.
    H0 = Durata prestazione arrotondata per difetto.
    H1 = Durata prestazione arrotondata per eccesso.
    Hi = Durata prestazione in ore intere (mezz'ore comprese) registrata.
    S0 = Scarto totale tra H e Hi (cumulato) che avrei a una data registrazione ponendo Hi = H0.
    S1 = Scarto totale tra H e Hi (cumulato) che avrei a una data registrazione ponendo Hi = H1.
    S = Scarto totale tra H e Hi, ovvero differenza tra il totale delle durate effettive e delle durate registrate, la quantità da minimizzare (S = sum (Hi) - sum (H)).
    
    Con S (t-1) indicherò invece lo scarto totale al momento della registrazione precedente, ovviamente S varrà iniziamente 0.
    
    Dati H, H0 e H1 (H0 e H1 si calcolano in modo elementare ad ogni passo, ovviamente se H è già una durata intera si avrà H = H0 = H1) l'algoritmo procede nel modo seguente:
    
    Calcolo S0 = S (t-1) + H0 - H
    Calcolo S1 = S (t-1) + H1 - H
    
    Se abs (S0) <= abs (S1) allora Hi = H0
    Altrimenti Hi = H1
    
    Aggiorno S = S (t-1) + Hi - H
    
    Con i tuoi dati otterresti il risultato che posto sotto in allegato.

    Se non è quello che vorresti magari specifica un po' meglio come vorresti che venisse "a mano" e vediamo se è facilmente realizzabile, se invece vuoi provare a implementare questa soluzione e ti servisse qualche suggerimento non esitare a chiedere
    Allegati:
    Esempio di uso dell'algoritmo
    Esempio di uso dell'algoritmo
  • Re: Distribuzione uniforme costanti su record

    Ho commesso un errore nel post precedente, nel mio algoritmo lo scarto minimo è di 18 minuti.
    Come ho suggerito, visto che è superiore a 15 minuti, si potrebbe arrotondare a 30, aggiungendo la mezzora ad una prestazione qualsiasi. Alla fine "rubi" solo 12 minuti, che è lo scarto che esce dall'algoritmo di @Ansharja.
Devi accedere o registrarti per scrivere nel forum
5 risposte