Cálculo de hojas de tiempo


14

Hojas de horas

En un lugar de trabajo, a menudo tiene que completar hojas de tiempo. Esta tarea es escribir código para ayudar a esto.

Entrada

Dos veces en un reloj de 12 horas ligeramente no estándar que significa el inicio y el final del día separados por un espacio. Un tercer número representa la cantidad de minutos que se toman para el almuerzo. Por ejemplo

9:14 5:12 30

Esto significa que comenzó a trabajar a las 9:14 am, terminó el trabajo a las 5:12 pm y tomó 30 minutos para el almuerzo.

Puedes asumir que

  • Cualquier momento en la primera columna es desde las 00:00 (medianoche) hasta la 1 p.m., pero sin incluirlo, y cualquier momento en la segunda columna es la 1 p.m. como máximo hasta las 11:59 p.m.
  • ¡La pausa para el almuerzo no es más que la jornada laboral!

El formato de entrada debe ser como en los ejemplos dados.

Tarea

Su código debe leer en un archivo (o entrada estándar) de estos triples, y para cada uno de ellos, cuánto tiempo trabajó. Esta salida debe indicar el número de horas. Para el ejemplo anterior esto es:

7 horas y 58 minutos menos 30 minutos, que es 7 horas y 28 minutos.

Salida

Su salida debe especificar el número (completo) de horas y minutos y no debe incluir más de 59 minutos. Es decir, no puede generar 2 horas y 123 minutos. Aparte de eso, su código puede salir en cualquier formato de lectura humana que sea conveniente para usted.

Ejemplos

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 

3
No veo cómo el formato de entrada estricto ( :tiempos delimitados en el reloj de 12 horas) agrega algo a este desafío.
Shaggy

3
@Shaggy Analizar el formato de entrada fue la mayor parte del desafío para mí, al menos, porque no puedes asumir posiciones de personaje ya que las horas podrían ser uno o dos personajes ...
Ryan

¿El código tiene que leer varias líneas? ¿O es suficiente si lee una línea?
Luis Mendo

1
Sí, el código tiene que aceptar varias líneas.
Anush

55
@ mbomb007 Puede votar a favor, pero no le gusta el formato de entrada no es una razón para VTC.
Okx

Respuestas:



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

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

\d+
$*

Convierta la entrada a unario.

 (1+:)
 12$*1$1

Agregue 12 horas al tiempo de parada.

+`1:
:60$*

Multiplique las horas por 60 y agregue los minutos.

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

Reste el tiempo de inicio y el tiempo de descanso del tiempo de parada.

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

Divmod por 60. (Ahorre 5 bytes para un formato de salida más aburrido).



4

Python 3, 161 bytes

Sé que esto ni siquiera será cercano al más pequeño, pero sí se lee en un archivo:

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')

Siento la ironía de pausar mi hoja de tiempo para hacer esto ...

Python 2.7, 133 bytes

Gracias por las sugerencias en los comentarios! Cambiar a python 2.7 ahorra unos pocos bytes más porque el valor predeterminado es la división de enteros:

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

El mismo enfoque con python3 es de 135 bytes debido a la declaración de impresión y a la división flotante por defecto:

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)

1
Puede guardar 4 bytes colocando i=intal principio y cambiando la tercera línea am=-i(l[0])*60+i(l[1][:2])+(i(l[1][3:])*60+720+i(l[2][:2])-i(l[2][2:]))
DJMcMayhem

@DJMcMayhem Gracias! Estaba tratando de pensar en una forma de simplificar esos ...
Ryan

2
Muy buena primera respuesta, ¡bienvenido a Programming Puzzles & Code Golf! Para ayudar un poco al golf, es posible que pueda tomar la entrada de STDIN, usar map(int,l[:-1].split(':'))y soltar las conversiones múltiples a int, colapsar todo en una sola línea reemplazando la sangría con ;etc. para guardar un par de bytes. Además, puede visitar Consejos para jugar golf en Python para obtener algunos trucos más interesantes que otros usuarios descubrieron durante su vida de golfista :).
Sr. Xcoder

1
Además, el OP parece ser menos restrictivo sobre el formato de salida , así que creo que print(m,m%60)sería suficiente. (También tenga en cuenta el uso de m%60en lugar de m-(m//60*60))
Sr. Xcoder

@ Mr.Xcoder Gracias!
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);}

Completamente sencillo. Pruébalo en línea aquí .

Sin golf:

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"
}

Sugerir en a,b,c,d;f(e)lugar de a,b,c,d,e;f()y en ;printf("%d:%d ",a/60,a%60))a=(12+c-a)*60+d-b-e;}lugar de;)a=(12+c-a)*60+d-b-e,printf("%d:%d ",a/60,a%60);
ceilingcat

4

Wolfram Lenguaje 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 guardados gracias al usuario 202729

Ejemplo

Las abreviaturas no se usan aquí, para facilitar el seguimiento de la lógica.

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

6hr 51min

Interpreter["Time"][#2 <> "pm"] interpreta como una hora el segundo parámetro seguido de "pm", es decir, en este caso, "4:12 pm", devolviendo un TimeObjectcorrespondiente a 4:12 pm.

-Interpreter["Time"][# <> "am"])[[1]] - #3/60]. #3es el tercer parámetro, es decir, 20min. El signo menos resta el intervalo de la hora del almuerzo del final del turno. Devuelve el final del turno ajustado, es decir, el final del turno que se aplicaría si la persona no hubiera tomado un descanso para almorzar.

Interpreter["Time"][#] interpreta como una hora el primer parámetro, en este caso, "9:00", devolviendo un TimeObjectcorrespondiente a las 9:00 am.

Restando el inicio del turno del final del tiempo de turno ajustado t, el intervalo de tiempo expresado en horas. IntegerPart[t]devuelve el número de horas completas trabajadas. IntegerPart[60 Mod[t,1]], "min"}]devuelve los minutos adicionales trabajados.


Si. Gracias. Primera vez que veo Mod[x, 1]usado.
DavidC

Tomado de estos consejos (eliminados) . / En realidad, mod 1 se comporta de manera diferente a la parte fraccionaria para el número negativo. / ¿Se Floorpuede usar para IntegerPart?
user202729

Floor devuelve un resultado inexplicable -6hr 52minpara los valores de muestra que utilicé. Necesito analizar esto para entender por qué se produjo un valor negativo por horas (y aparentemente minutos).
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)

Acabo de deshacerme de la función interna de la solución a continuación (¿Qué estaba pensando?). Cambió el formato de salida también.

Pruébalo en línea!


ANTIGUO: 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`)

Explicación:

Dentro de la función principal, comenzamos definiendo otro que nos ayudará a calcular los minutos de un tiempo dado, agregando 12 horas al parámetro horas si el tercer parámetro es verdadero:

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

Luego, dividimos la cadena por cualquiera ' 'o':' hacemos coincidir los números dentro de la cadena dando como resultado una matriz de todos los números en la cadena.

Luego calculamos la diferencia entre la hora de finalización y la hora de inicio y restando la hora del almuerzo utilizando la función definida anteriormente (convirtiendo las cadenas en números cuando sea necesario).

Finalmente producimos la cadena de resultados: las horas son la parte entera de r/60 y los minutos son r%60.

Pruébalo en línea!


@Jakob Soy un nuevo usuario de codegolf. Todavía no sé cómo funcionan las cosas por aquí, incluido el TIO. También he preguntado en este comentario cómo abordaría esto usando JavaScript, pero nadie respondió.
ibrahim mahrir

@Jakob TIO arreglado. Y no estoy usando NodeJS, estoy usando la consola del navegador. NodeJS fue agregado por TIO.
ibrahim mahrir

Todavía no estoy seguro de que el método de entrada sea legal (desafortunadamente, esta pregunta es restrictiva), pero es posible que necesitemos un golfista JS con más experiencia para intervenir. Muy claro en la descripción.
Jakob

Si @Jakob más días deben utilizarse como entrada tan sólo pudiera hacer que la función acepta una matriz y su uso map: a=>a.map(...). Agregará 5 bytes a mi respuesta. Pero todavía estoy esperando la respuesta de OP (o cualquiera) a mi comentario.
ibrahim mahrir

Dado que JavaScript puro no tiene acceso a entradas o archivos estándar , le sugiero que use el método predeterminado de usar un indicador de GUI: codegolf.meta.stackexchange.com/a/2459/79343
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

Pruébalo en línea!

Programa completo que lee varias líneas de un archivo de texto, según las instrucciones de OP. Una función que solo analiza una sola línea ahorraría una adición de 10 bytes.


1
¡Esto también es mucho más legible que mi intento!
Ryan

3

Java 10, 194191 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 es doloroso en Java. Termina anormalmente cuando no hay una línea de entrada para leer. Pruébelo en línea aquí .

Sin golf:

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
}


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.