Arbeitszeitnachweise berechnen

14

Stundenzettel

An einem Arbeitsplatz müssen Sie häufig Arbeitszeitnachweise ausfüllen. Diese Aufgabe besteht darin, Code zu schreiben, um dies zu unterstützen.

Eingang

Zweimal im 12-Stunden-Format, das nicht dem Standard entspricht und den Beginn und das Ende des Tages durch ein Leerzeichen voneinander trennt. Eine dritte Zahl gibt die Anzahl der Minuten an, die für das Mittagessen benötigt werden. Beispielsweise

9:14 5:12 30

Das bedeutet, dass Sie um 9:14 Uhr mit der Arbeit begonnen haben, um 17:12 Uhr mit der Arbeit fertig sind und 30 Minuten zum Mittagessen gebraucht haben.

Das können Sie annehmen

  • Jeder Zeitpunkt in der ersten Spalte ist von 00:00 Uhr (Mitternacht) bis einschließlich 13:00 Uhr und jeder Zeitpunkt in der zweiten Spalte ist frühestens 13:00 Uhr bis 23:59 Uhr.
  • Die Mittagspause ist nicht länger als der Arbeitstag!

Das Eingabeformat muss den angegebenen Beispielen entsprechen.

Aufgabe

Ihr Code sollte eine Datei (oder Standardeingabe) dieser Tripel einlesen und für jede Ausgabe angeben, wie lange Sie gearbeitet haben. Diese Ausgabe sollte die Anzahl der Stunden anzeigen. Für das obige Beispiel ist dies:

7 Stunden und 58 Minuten minus 30 Minuten, was 7 Stunden und 28 Minuten entspricht.

Ausgabe

Ihre Ausgabe muss die (vollständige) Anzahl von Stunden und Minuten angeben und darf nicht mehr als 59 Minuten enthalten. Das heißt, Sie können nicht 2 Std. 123 Min. Ausgeben. Abgesehen davon kann Ihr Code in jedem für Sie geeigneten, leicht lesbaren Format ausgegeben werden.

Beispiele

10:00 1:00 30    --> 2hr 30min
12:59 1:00 0     --> 0hr 1min
00:00 11:59 0    --> 23hr 59min
10:00 2:03 123   --> 2hr 0min 
Anush
quelle
3
Ich verstehe nicht, wie das strikte Eingabeformat ( :begrenzte Zeiten im 12-Stunden- Format ) dieser Herausforderung etwas hinzufügt.
Shaggy
3
@ Shaggy Das Parsen des Eingabeformats war zumindest für mich die größte Herausforderung, da Sie keine Zeichenpositionen annehmen können, da Stunden entweder ein oder zwei Zeichen sein können ...
Ryan
Muss der Code mehrere Zeilen lesen? Oder reicht es, wenn es eine Zeile liest?
Luis Mendo
1
Ja, der Code muss mehrere Zeilen akzeptieren.
Anush
5
@ mbomb007 Du kannst abstimmen, aber das Eingabeformat nicht zu mögen ist kein Grund für VTC.
Okx

Antworten:

7

MATL , 28 Bytes

`jYb0&)YOd.5+wgU13L/- 15XODT

Probieren Sie es online!

Luis Mendo
quelle
1
Das ist sehr beeindruckend!
Anush
Sollte die Ausgabe nicht in diesem Format sein "XXhr YYmin"?
Ibrahim Mahrir
@ibrahimmahrir Die Herausforderung besagt, dass Ihr Code in jedem für Sie geeigneten, leicht lesbaren Format ausgegeben werden kann
Luis Mendo
1
Ah ich sehe! Ich werde meine Antwort bearbeiten, um sie zu kürzen. Vielen Dank!
Ibrahim Mahrir
5

Retina 0.8.2 , 83 Bytes

\d+
$*
 (1+:)
 12$*1$1
+`1:
:60$*
(1*) :\1(1*)(1*) \2
$3
:(1{60})*(1*)
$#1hr $.2min

Probieren Sie es online! Link enthält Testfälle. Erläuterung:

\d+
$*

Konvertieren Sie die Eingabe in Unary.

 (1+:)
 12$*1$1

Fügen Sie der Stoppzeit 12 Stunden hinzu.

+`1:
:60$*

Multiplizieren Sie die Stunden mit 60 und addieren Sie sie zu den Minuten.

(1*) :\1(1*)(1*) \2
$3

Subtrahieren Sie die Start- und Pausenzeit von der Stoppzeit.

:(1{60})*(1*)
$#1hr $.2min

Divmod by 60. (Sparen Sie 5 Bytes für ein langweiligeres Ausgabeformat.)

Neil
quelle
4

Python 3, 161 Bytes

Ich weiß, dass dies nicht annähernd das kleinste ist, aber es liest eine Datei ein:

for l in open('t'):
    l=l[:-1].split(':')
    m=-int(l[0])*60+int(l[1][:2])+(int(l[1][3:])*60+720+int(l[2][:2])-int(l[2][2:]))
    print(f'{m//60}hr {m-(m//60*60)}min')

Ich fühle die Ironie, meine Arbeitszeittabelle anzuhalten, um dies zu tun ...

Python 2.7, 133 Bytes

Danke für die Anregungen in den Kommentaren! Wenn Sie zu Python 2.7 wechseln, werden einige weitere Bytes gespart, da standardmäßig die Ganzzahldivision verwendet wird:

for l in open('t'):i,h,l=int,60,l[:-1].split(':');m=-i(l[0])*h+i(l[1][:2])+(i(l[1][3:])*h+720+i(l[2][:2])-i(l[2][2:]));print m/h,m%60

Der gleiche Ansatz mit python3 ist 135 Byte, da die print-Anweisung standardmäßig die float-Division verwendet:

for l in open('t'):i,h,l=int,60,l[:-1].split(':');m=-i(l[0])*h+i(l[1][:2])+(i(l[1][3:])*h+720+i(l[2][:2])-i(l[2][2:]));print(m//h,m%60)
Ryan
quelle
1
Sie könnten 4 Bytes sparen, indem Sie i=intam Anfang setzen und die dritte Zeile aufm=-i(l[0])*60+i(l[1][:2])+(i(l[1][3:])*60+720+i(l[2][:2])-i(l[2][2:]))
DJMcMayhem
@DJMcMayhem Vielen Dank! Ich habe versucht, einen Weg zu finden, um diese zu vereinfachen ...
Ryan
2
Sehr schöne erste Antwort, willkommen bei Programming Puzzles & Code Golf! Um das Golfen ein wenig zu erleichtern, können Sie möglicherweise Eingaben von STDIN übernehmen, map(int,l[:-1].split(':'))die mehrfachen Konvertierungen in int verwenden und ablegen, alles zu einem Einzeiler reduzieren, indem Sie den Einzug durch ;etc. ersetzen , um ein paar Bytes zu sparen. Darüber hinaus finden Sie unter Tipps zum Golfen in Python weitere interessante Tricks, die andere Benutzer während ihres Golfsportlebens entdeckt haben :).
Mr. Xcoder
1
Darüber hinaus scheint das OP das Ausgabeformat weniger restriktiv zu gestalten , daher print(m,m%60)würde es meiner Meinung nach ausreichen. (Beachten Sie auch die Verwendung von m%60anstelle von m-(m//60*60))
Mr. Xcoder
@ Mr.Xcoder Danke!
Ryan
4

C 105 Bytes

a,b,c,d,e;f(){for(;scanf("%d:%d%d:%d%d",&a,&b,&c,&d,&e);)a=(12+c-a)*60+d-b-e,printf("%d:%d ",a/60,a%60);}

Ganz einfach. Probieren Sie es hier online aus .

Ungolfed:

a, b, c, d, e; // start hours, minutes; end hours, minutes; break - all implicitly int
f() { // function - return type is implicitly int (unused)
    for(; scanf("%d:%d%d:%d%d", &a, &b, &c, &d, &e) ;) // until EOF is hit, read line by line
        a = (12 + c - a) * 60 + d - b - e, printf("%d:%d,", a / 60, a % 60); // calculate the minutes and store, then output separated: "h m"
}
OOBalance
quelle
Schlagen Sie a,b,c,d;f(e)anstelle von a,b,c,d,e;f()und ;printf("%d:%d ",a/60,a%60))a=(12+c-a)*60+d-b-e;}anstelle von;)a=(12+c-a)*60+d-b-e,printf("%d:%d ",a/60,a%60);
Ceilingcat
4

Wolfram Language 125 119 111 Bytes

i=Interpreter;j=IntegerPart;Row@{j[t=(i["Time"][#2<>"pm"]-i["Time"][#])[[1]]-#3/60],"hr ",j[60Mod[t,1]],"min"}&

8 Bytes gespart dank Benutzer 202729

Beispiel

Abkürzungen werden hier nicht verwendet, um das Verfolgen der Logik zu erleichtern.

Row[{IntegerPart[
 t = (Interpreter["Time"][#2 <> "pm"] - 
      Interpreter["Time"][#])[[1]] - #3/60], "hr ",
IntegerPart[60 Mod[t,1]], "min"}] &["9:00", "4:12", 20]

6 Std. 51 Min

Interpreter["Time"][#2 <> "pm"] interpretiert als Zeit den zweiten Parameter gefolgt von "pm", in diesem Fall "4:12 pm", und gibt einen TimeObjectWert zurück, der 4:12 pm entspricht.

-Interpreter["Time"][# <> "am"])[[1]] - #3/60]. #3ist der dritte Parameter, nämlich 20min. Das Minuszeichen subtrahiert das Mittagsstundenintervall vom Ende der Schichtzeit. Sie gibt die eingestellte Schichtendezeit zurück, dh das Schichtende, das gelten würde, wenn die Person keine Mittagspause eingelegt hätte.

Interpreter["Time"][#] interpretiert als Zeit den ersten Parameter, in diesem Fall "9:00", und gibt einen TimeObjectWert zurück, der 9:00 Uhr entspricht.

Subtrahiert man den Schichtstart vom eingestellten Schichtende, ergibt tsich das in Stunden ausgedrückte Zeitintervall. IntegerPart[t]Gibt die Anzahl der geleisteten Arbeitsstunden zurück. IntegerPart[60 Mod[t,1]], "min"}]gibt die zusätzlich geleisteten Minuten zurück.

DavidC
quelle
Ja. Vielen Dank. Zum ersten Mal sehe ich Mod[x, 1]gebraucht.
DavidC
Entnommen aus diesen (gelöschten) Tipps . / Tatsächlich verhält sich Mod 1 anders als der Bruchteil für negative Zahlen. / Kann Floorverwendet werden für IntegerPart?
user202729
Floor gibt ein für mich unerklärliches Ergebnis -6hr 52minfür die von mir verwendeten Beispielwerte zurück. Ich muss das untersuchen, um zu verstehen, warum ein negativer Wert für Stunden (und anscheinend Minuten) erzeugt wurde.
DavidC
3

JavaScript, 83 Bytes 76 Bytes

s=>(r=s.match(/\d+/g),r=(r[2]-r[0]+12)*60-r[4]-r[1]+ +r[3],(r/60|0)+':'+r%60)

Habe gerade die innere Funktion von unten gelöst (Was habe ich gedacht?). Das Ausgabeformat wurde ebenfalls geändert.

Probieren Sie es online!


ALT: JavaScript, 112 Bytes 111 Bytes 110 Bytes

s=>(t=(h,m,a)=>(a?12+h:h)*60+m,r=s.match(/\d+/g),r=t(+r[2],r[3]-r[4],1)-t(r[0],+r[1]),`${r/60|0}hr ${r%60}min`)

Erläuterung:

In der Hauptfunktion definieren wir zunächst eine andere, mit deren Hilfe wir die Minuten einer bestimmten Zeit berechnen können. Dem Stundenparameter werden 12 Stunden hinzugefügt, wenn der dritte Parameter wahr ist:

(hours, minutes, addTwelve) =>
    (addTwelve? hours + 12: hours) * 60 + minutes

Als nächstes teilen' '':' wir die Zeichenkette entweder durch oder stimmen mit den Zahlen in der Zeichenkette überein, was zu einem Array aller Zahlen in der Zeichenkette führt.

Dann berechnen wir die Differenz von End- und Startzeit und subtrahieren die Mittagszeit mit der zuvor definierten Funktion (konvertieren die Zeichenfolgen bei Bedarf in Zahlen).

Schließlich erzeugen wir die Ergebniszeichenfolge: Stunden sind der ganzzahlige Teil von r/60und Minuten sind r%60.

Probieren Sie es online!

ibrahim mahrir
quelle
@ Jakob Ich bin ein neuer Codegolf-Benutzer. Ich weiß immer noch nicht, wie die Dinge hier funktionieren, einschließlich des TIO. Außerdem habe ich in diesem Kommentar gefragt, wie ich mit Javascript vorgehen würde, aber niemand hat geantwortet.
Ibrahim Mahrir
@ Jakob TIO behoben. Und ich benutze kein NodeJS, sondern die Konsole des Browsers. NodeJS wurde von TIO hinzugefügt.
Ibrahim Mahrir
Wir sind uns immer noch nicht sicher, ob die Eingabemethode legal ist (diese Frage ist leider einschränkend), benötigen jedoch möglicherweise einen erfahreneren JS-Golfer, um sich einzuloggen. Beachten Sie jedoch auch, dass Programme mehrere Tage an Eingabedaten unterstützen müssen - was leider nicht gemacht wurde sehr klar in der Beschreibung.
Jakob
@ Jakob Wenn mehr Tage als Eingabe verwendet werden sollen, könnte ich die Funktion einfach dazu bringen, ein Array zu akzeptieren und zu verwenden map : a=>a.map(...). Es werden 5 Bytes zu meiner Antwort hinzugefügt. Aber ich warte immer noch auf die Antwort von OP (oder irgendjemandem) auf meinen Kommentar.
Ibrahim Mahrir
Da reines JavaScript keinen Zugriff auf Standardeingaben oder -dateien hat
OOBalance
3

Python 2 , 100 Bytes

for I in open('x'):x,y,z,w,l=map(int,I.replace(':',' ').split());d=60*(12+z-x)+w-y-l;print d/60,d%60

Probieren Sie es online!

Vollständiges Programm, das gemäß den Anweisungen von OP mehrere Zeilen aus einer Textdatei liest. Eine Funktion, die nur eine einzelne Zeile analysiert, würde zusätzliche 10 Bytes einsparen.

Chas Brown
quelle
1
Das ist auch viel besser lesbar als mein Versuch!
Ryan
3

Java 10, 194 191 Bytes

u->{var s=new java.util.Scanner(System.in).useDelimiter("\\D");for(int i,a[]=new int[5];;i=(12+a[2]-a[0])*60+a[3]-a[1]-a[4],System.out.println(i/60+":"+i%60))for(i=0;i<5;)a[i++]=s.nextInt();}

I / O ist in Java schmerzhaft. Wird abnormal beendet, wenn keine weitere zu lesende Eingabezeile vorhanden ist. Probieren Sie es hier online aus .

Ungolfed:

u -> { // lambda taking a dummy input – we're not using it, but it saves a byte
var s = new java.util.Scanner(System.in).useDelimiter("\\D"); // we use this to read integers from standard input; the delimiter is any character that is not part of an integer
for(int i, a[] = new int[5]; ; // infinite loop; i will be used to loop through each line and to store the result in minutes between lines; a will hold the inputs
    i = (12 + a[2] - a[0]) * 60 + a[3] - a[1] - a[4], // after each line, calculate the result in minutes ...
    System.out.println(i / 60 + ":" + i % 60)) // ... and output the result in hours:minutes, followed by a newline
    for(i = 0; i < 5; ) // read the five integers on the current line ...
        a[i++] = s.nextInt(); // ... into the array
}
OOBalance
quelle
2

rot , 35 Bytes

func[s e l][e + 12:0 - s -(l * 60)]

Probieren Sie es online!

Hinweis: Die Ausgabe erfolgt im Format hh:mm:ss

Galen Ivanov
quelle
Beeindruckend! Das ist sehr überraschend :)
Anush
@Anush Ja, Red (und natürlich Rebol) hat einen schönen Zeitdatentyp.
Galen Ivanov