13
\$\begingroup\$

Your program / function, etc. will take 2 inputs. The first will be a list of who came to my party and when. Example:

Kevin 13:02  
Ruby 5  
Sam 3  
Lisa 6  
Bob 12  

What does that mean? It means that Kevin got to my party first (at 13:02, 24-hour time), then Ruby 5 minutes later, then Sam 3 minutes later, then Lisa 6 minutes later, and last Bob 12 minutes later.

The second input will be when my party started. Example:

13:15

(24-hour time). Your output must be the list of people who were late. (Anyone exactly on time is fine.) Example calculations (just for example, don't output these)

Kevin 13:02
Ruby 13:07
Sam 13:10
Lisa 13:16
Bob 13:28

Lisa and Bob arrived after 13:15, therefore this program should print "Lisa,Bob".

Input assumptions

  • Input 1 will always be a name (regex [A-Z][a-z]*), then a space, then a 24-hour time in the form hours:minutes on the first line, then a name, a space, and a positive integer (number of minutes later) on the next lines. There will always be at least 1 line.
  • If you would like, you may take input 1 with any other character instead of a line break.
  • Input 2 will be in the format hours:minutes.
  • You may take your inputs as one string separated by any character if you want. This is optional.
  • Don't worry about day crossover. My parties never to after 23:59.

Output rules

  • Output can be a function return value or a string echoed to STDIN, a file, etc. You must return a string or an array / list.
    • If you return a string, it must be each person who was late (order does not matter), separated by any non-alphanumeric delimiter.
    • If you return an array / list, it must be a list of everyone who was late.
\$\endgroup\$
14
  • 2
    \$\begingroup\$ Is the strict input format necessary? Could, for example, the first input be a list of lists, each being a "line" containing the two data items? \$\endgroup\$ Apr 14, 2017 at 19:24
  • \$\begingroup\$ @JonathanAllan yes. \$\endgroup\$
    – user58826
    Apr 14, 2017 at 19:49
  • 2
    \$\begingroup\$ I assume you meant "yes the strict input format is necessary". \$\endgroup\$ Apr 14, 2017 at 19:54
  • 2
    \$\begingroup\$ Strict input format makes this challenge less interesting \$\endgroup\$
    – Luis Mendo
    Apr 14, 2017 at 22:35
  • 3
    \$\begingroup\$ "My parties never to after 11:59." do you mean 23:59? \$\endgroup\$
    – tsh
    Apr 15, 2017 at 4:32

17 Answers 17

5
\$\begingroup\$

JavaScript (ES6), 98 97 bytes

Saved 1 byte thanks to Neil

Takes the list of guests l and the party time h in currying syntax (l)(h). Expects a trailing linebreak on the list. Returns a space-separated list of names such as Lisa Bob.

l=>h=>l.replace(/(.* )(.*)\n/g,(_,a,b)=>(t-=T(b))<0?a:'',t=(T=h=>eval(h.replace(/:/,'*60+')))(h))

Formatted and commented

l => h =>                         // given a list of guests l and a party time h
  l.replace(                      // for each guest in l:
    /(.* )(.*)\n/g,               //   extract the name a and arrival time b
    (_, a, b) =>                  //   subtract the arrival time from the time counter
      (t -= T(b)) < 0 ?           //   if the result is negative:
        a                         //     the guest is late: keep the name
      :                           //   else:
        '',                       //     the guest is on time: remove this entry
    t = (                         //   initialize the time counter t
      T = h =>                    //   define T():
        eval(                     //     a function that takes either a time
          h.replace(/:/, '*60+')  //     in hh:mm format or an amount of minutes
        )                         //     and returns an amount of minutes   
    )(h)                          //   call it with the party time
  )                               // end of replace()

Demo

let f =

l=>h=>l.replace(/(.* )(.*)\n/g,(_,a,b)=>(t-=T(b))<0?a:'',t=(T=h=>eval(h.replace(/:/,'*60+')))(h))

console.log(f(`Kevin 13:02
Ruby 5
Sam 3
Lisa 6
Bob 12
`)('13:15'))

\$\endgroup\$
5
  • \$\begingroup\$ Clever solution! +1. Mine is way far.......:( \$\endgroup\$
    – Arjun
    Apr 15, 2017 at 7:07
  • \$\begingroup\$ Doesn't (.*) (.*)\n work? \$\endgroup\$
    – Neil
    Apr 15, 2017 at 10:42
  • \$\begingroup\$ @Neil Being greedy by default, the first (.*) would match the entire line. \$\endgroup\$
    – Arnauld
    Apr 15, 2017 at 10:44
  • \$\begingroup\$ Then what would the space match? \$\endgroup\$
    – Neil
    Apr 15, 2017 at 10:45
  • \$\begingroup\$ @Neil Oh, sorry, you're right. \$\endgroup\$
    – Arnauld
    Apr 15, 2017 at 10:47
5
\$\begingroup\$

PHP, 118 98 95 91 bytes

while($n=$argv[++$i])$i&1?$p=$n:($t=($f=strtotime)($n)?:$t+60*$n)<=$f(end($argv))?:print$p;

takes input from command line arguments (you may interprete that as lines separated by spaces if you like); prints names without a delimiter. Run with -r or test it online.

edit 1: saved 20 bytes with direct printing
edit 2: saved 3 bytes by removing the delimiter
edit 3: saved 4 bytes by exploiting that plain integers are no valid dates for strtotime

breakdown

while($n=$argv[++$i])       # loop through arguments, skip [0]
    $i&1                        # if index is odd   
    ?   $p=$n                   # then assign name to $p
    :   ($t=                    # else $t =
        ($f=strtotime)($n)          # if $n is a valid time, parse it
        ?:$t+60*$n                  # else add $n minutes to current $t
        )<=$f(end($argv))           # if $t <= parsed party start
        ?                           # then do nothing
        :print$p;                   # else print name
\$\endgroup\$
5
\$\begingroup\$

c, 178 bytes

main(c,o,d,e,g,O,l,f,x,y)char**o,d[80],*O,*l,*f;{for(sscanf(o[2],"%d:%d",&e,&g),x=e*60+g,l=";",f=o[1];O=strtok(f,l);f=0)(y=sscanf(O,"%s%d:%d",d,&e,&g)^2?e*60+g:y+e)>x?puts(d):0;}

Try it online

\$\endgroup\$
4
\$\begingroup\$

JavaScript ES6, 185 bytes

l=>t=>l.split`
`.map(p=>p.split` `).map((p,i,a)=>[p[0],i?d(a[0][1])+a.slice(1,i+1).reduce((a,p)=>a+=+p[1],0)*6e4:(d=x=>Date.parse(`2017T${x}`))(p[1])]).filter(p=>p[1]>d(t)).map(p=>p[0])

Try it online!

const f = l=>t=>l.split`
`.map(p=>p.split` `).map((p,i,a)=>[p[0],i?d(a[0][1])+a.slice(1,i+1).reduce((a,p)=>a+=+p[1],0)*6e4:(d=x=>Date.parse(`2017T${x}`))(p[1])]).filter(p=>p[1]>d(t)).map(p=>p[0])


console.log(f('Kevin 13:02\nRuby 5\nSam 3\nLisa 6\nBob 12')('13:15'))

\$\endgroup\$
6
  • \$\begingroup\$ As far as I can tell from the spec the input form may be more strict. \$\endgroup\$ Apr 14, 2017 at 19:22
  • \$\begingroup\$ I think it is correct now. \$\endgroup\$
    – powelles
    Apr 14, 2017 at 19:24
  • \$\begingroup\$ Yep - I have also asked about input strictness. \$\endgroup\$ Apr 14, 2017 at 19:25
  • \$\begingroup\$ ...actually you have the times in your input, not the offsets it should be f('Kevin 13:02\nRuby 5\nSam 3... \$\endgroup\$ Apr 14, 2017 at 19:28
  • 1
    \$\begingroup\$ @JonathanAllan Thanks. Got it now. \$\endgroup\$
    – powelles
    Apr 14, 2017 at 20:00
3
\$\begingroup\$

PowerShell, 215 196 180 bytes

param($a,$b)$x,[array]$a=$a-split',';$z=@{};$i,$j=-split$x;$z[$i]=($y=date $j);0..($a.count-1)|%{$i,$j=-split$a[$_];$z[$i]=($y=$y|% *es $j)};($z|% *or|?{$_.value-gt(date $b)}).Name

Try it online!

Roughly 1/3rd of this is input parsing, so I'm not sure how much further I can golf it.

Takes input $a as a comma-delimited string of names and times/minutes, and $b as hh:mm as a string. First, we -split $a on ,, store the first result into $x and the remaining into $a, with an explicit re-cast of $a as an array (so that the loop later works properly). We the initialize our hashtable $z, set $i and $j to be $x -split on whitespace, and set $z[$i] to be the date of $j (stored into $y for use later).

Then we loop through the remaining $a. Each iteration, we do similar -- -split the string on whitespace, set the appropriate $z index to be that many more minutes beyond where we're currently at. This uses a shortened property name trick to save some bytes, using |% *es $j instead of .AddMinutes($j).

Finally, we .GetEnumerator() (again using the trick) of our hashtable, and Where-Object select those entries with a value that's -greaterthan $b (i.e., they're late to the party). We then select just the .Names thereof. Output is as an implicit array, which the default Write-Output inserts newlines between.

Saved a bunch thanks to briantist for reminding me that [array] is a thing. And a bunch more for shortened property name tip.

\$\endgroup\$
4
  • \$\begingroup\$ I admit I did minimal reading and testing of this, but, couldn't you just do $x,[array]$a=$a-split','? \$\endgroup\$
    – briantist
    Apr 14, 2017 at 21:20
  • 1
    \$\begingroup\$ @briantist Yes, thank-you. I kept trying to find a way to use the comma-operator in the multiple-assignment, and it just was not working. I had completely forgotten that [array] is a valid cast. Haha. Too much golfing, I guess. \$\endgroup\$ Apr 15, 2017 at 0:47
  • \$\begingroup\$ I'm on mobile so out would be difficult to test but I think GetEnumerator and AddMinutes are good candidates for the % method syntax \$\endgroup\$
    – briantist
    Apr 15, 2017 at 1:32
  • \$\begingroup\$ @briantist Yep. Saves another 16. Thanks! \$\endgroup\$ Apr 17, 2017 at 12:45
3
\$\begingroup\$

Python 2, 140,148,144 bytes

t,h,n=map(str.split,input().replace(':','').split(';')),100,0
for a,v in t[:-1]:
 n+=int(v)
 if n%h/60:n=n/h*h+n%h%60+h
 if`n`>t[-1][0]:print a,

Try it online!

Input Format:

'Kevin 13:02;Ruby 5;Sam 3;Lisa 6;Bob 12;13:15'
\$\endgroup\$
2
  • \$\begingroup\$ Doesn't correctly handle minute overflow: 'Kevin 13:47;Ruby 5;Sam 3;Lisa 6;Bob 12;14:00' prints nothing, even though Lisa and Bob are still late. \$\endgroup\$
    – L3viathan
    Apr 19, 2017 at 10:56
  • 1
    \$\begingroup\$ oh yeah. There was a glitch! Fixed it. Thanks you! \$\endgroup\$ Apr 19, 2017 at 16:12
2
\$\begingroup\$

MATL, 31 bytes

jYb1L&)1&)XUYs1440/0whwYO+jYO>)

The first input uses space instead of line break (allowed by the challenge).

Output uses line break as separator.

Try it online!

Explanation

j       % Input first string
Yb      % Split at spaces. Gives cell array of strings
1L&)    % Separate into subarrays with odd and even indices. Odd are names, even
        % are time and increments in minutes
1&)     % Separate the subarray of even indices into first entry and remaining
        % entries. The first is a string representing the time of first arrival,
        % the rest are strings representing increments in minutes
XU      % Convert strings representing increments into the actual numbers
Ys      % Cumulative sum
1440/   % Divide by 1440 (number of minutes in a day)
0wh     % Prepend a 0
w       % Swap. Bring the string with time of first arrival to the top
YO      % Convert to serial date number. Fractional part indicates time
+       % Add. This gives all arrivals as serial date numbers
j       % Input second string
YO      % Convert to serial date number
>       % Less than?, element-wise
)       % Index: select the names for which the comparison gave true
        % Implicitly display
\$\endgroup\$
2
\$\begingroup\$

Bash, 135 124 115 bytes

a=($1)
for i in `seq 3 2 ${#a[@]}`
do((v+=a[i]))
((`date -d${a[1]} +%s`+v*60>`date -d$2 +%s`))&&echo ${a[i-1]}
done

Try it online!

\$\endgroup\$
2
\$\begingroup\$

CJam, 66 54 58 54 51 49 46 bytes

{{':/60b}:K~)rSrKs++q+S/2/z~:i[{1$+}*]2$+$@#>}

Input 1 is given through STDIN, input 2 is given as a string on the stack. Output is an array on the stack. Separator for input 1 is a space, e.g. Kevin 13:02 Ruby 5 Sam 3 Lisa 6 Bob 12.

Stack trace:

         e# Stack:               | "13:15"
{        e# Define K and run it:
  ':/    e#   Split on colon:    | ["13" "15"]
  60b    e#   From base 60:      | 795
}:K~     e# End def
)        e# Increment:           | 796
r        e# Read token:          | 796 "Kevin"
S        e# Push space:          | 796 "Kevin" " "
r        e# Read another token:  | 796 "Kevin" " " "13:02"
K        e# K()                  | 796 "Kevin" " " 782
s        e# Convert to string:   | 796 "Kevin" " " "782"
++       e# Add together:        | 796 "Kevin 782"
q        e# Read rest of input:  | 796 "Kevin 782" " Ruby 5 Sam 3 Lisa 6 Bob 12"
+        e# Add together:        | 796 "Kevin 782 Ruby 5 Sam 3 Lisa 6 Bob 12"
S/       e# Split on spaces:     | 796 ["Kevin" "782" "Ruby" "5" "Sam" "3" "Lisa" "6" "Bob" "12"]
2/       e# Group by 2:          | 796 [["Kevin" "782"] ["Ruby" "5"] ["Sam" "3"] ["Lisa" "6"] ["Bob" "12"]]
z        e# Transpose:           | 796 [["Kevin" "Ruby" "Sam" "Lisa" "Bob"] ["782" "5" "3" "6" "12"]]
~        e# Unpack:              | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] ["782" "5" "3" "6" "12"]
:i       e# Convert all to int:  | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] [782 5 3 6 12]
[{1$+}*] e# Accumulate:          | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] [782 787 790 796 808]
2$       e# Copy back element:   | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] [782 787 790 796 808] 796
+        e# Add into array:      | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] [782 787 790 796 808 796]
$        e# Sort:                | 796 ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] [782 787 790 796 796 808]
#        e# Find index:          | ["Kevin" "Ruby" "Sam" "Lisa" "Bob"] 3
>        e# Slice:               | ["Lisa" "Bob"]

Explanation:

  • The procedure K converts between a time hh:mm and a number representing how many minutes that is since midnight.
  • We read the first person and replace their time with K(their time). We then add this to the front of the input.
  • We then preform some string operations to get a list of names and a list of times, like [782 5 3 6 12].
  • By accumulating this list, we get [782 787 790 796 808], which gives the times that everybody came.
  • The shortest way to find who is late is to insert the start time into the array and then re-sort it to place it where it should be. We then find the index to figure out where it places, and then slice the list of names from that index.
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 285 283 bytes

Takes the list of guests i and the party time p in currying syntax (i)(p). Returns a comma-separated list of names such as Lisa,Bob.

i=>p=>{n=i.split`
`,a=new Date(0,0,0,...n[0].split` `[1].split`:`),y=new Date(0,0,0,...p.split`:`),t=[a];w=a;n.slice(1).map((j,k,l)=>{h=l[k].split` `[1]*6e4;t.push(new Date(w.getTime()+h));w=new Date(w.getTime()+h)});return n.filter((j,k,l)=>t[k]>y).map(j=>j.split` `[0]).join()}

I know it's pretty long and currently at last place by a fair margin, but that's what I could come up with.

f=i=>p=>{n=i.split`
`,a=new Date(0,0,0,...n[0].split` `[1].split`:`),y=new Date(0,0,0,...p.split`:`),t=[a];w=a;n.slice(1).map((j,k,l)=>{h=l[k].split` `[1]*6e4;t.push(new Date(w.getTime()+h));w=new Date(w.getTime()+h)});return n.filter((j,k,l)=>t[k]>y).map(j=>j.split` `[0]).join()}

console.log(f(`Kevin 13:02
Ruby 5
Sam 3
Lisa 6
Bob 12
`)('13:15'))

\$\endgroup\$
1
\$\begingroup\$

C#, 269 267 bytes


Golfed

(l,t)=>{var h=System.DateTime.MinValue;var s=System.DateTime.ParseExact(t,"HH:mm",null);var o="";foreach(var p in l.Split('\n')){var i=p.Split(' ');h=h.Ticks<1?System.DateTime.ParseExact(i[1],"HH:mm",null):h.AddMinutes(int.Parse(i[1]));if(h>s)o+=i[0]+" ";}return o;};

Ungolfed

( l, t ) => {
   var h = System.DateTime.MinValue;
   var s = System.DateTime.ParseExact( t, "HH:mm", null );
   var o = "";
   
   foreach( var p in l.Split( '\n' ) ) {
      var i = p.Split( ' ' );
      
      h = h.Ticks < 1
         ? System.DateTime.ParseExact( i[ 1 ], "HH:mm", null )
         : h.AddMinutes( int.Parse( i[ 1 ] ) );
      
      if( h > s )
         o += i[ 0 ] + " ";
   }
   
   return o;
};

Ungolfed readable

( l, t ) => {
   // var to check the time of arrival
   var h = System.DateTime.MinValue;
   
   // var to store the start time of the party
   var s = System.DateTime.ParseExact( t, "HH:mm", null );
   
   // var with the names of those who arrived late
   var o = "";
   
   // Cycle through which line
   foreach( var p in l.Split( '\n' ) ) {
      // Split the name and time
      var i = p.Split( ' ' );
      
      // Check if the time of arrival still has the initial value
      h = h.Ticks < 1
         
         // If so, grab the time of the first person
         //   Expects to have a time format of 'hh:mm'
         ? System.DateTime.ParseExact( i[ 1 ], "HH:mm", null )
         
         // Otherwise, add the difference to the var
         : h.AddMinutes( int.Parse( i[ 1 ] ) );
      
      // Check if the current time is later than the party start time
      if( h > s )
      
         // If so, add the name to the list
         o += i[ 0 ] + " ";
   }
   
   // Return the names of the persons who arrived late
   return o;
};

Full code

using System;
using System.Collections.Generic;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<String, String, String> f = ( l, t ) => {
            var h = System.DateTime.MinValue;
            var s = System.DateTime.ParseExact( t, "HH:mm", null );
            var o = "";
            
            foreach( var p in l.Split( '\n' ) ) {
               var i = p.Split( ' ' );
               
               h = h.Ticks < 1
                  ? System.DateTime.ParseExact( i[ 1 ], "HH:mm", null )
                  : h.AddMinutes( int.Parse( i[ 1 ] ) );
               
               if( h > s )
                  o += i[ 0 ] + " ";
            }
            
            return o;
         };

         List<KeyValuePair<String, String>>
            testCases = new List<KeyValuePair<String, String>> {
               new KeyValuePair<String, String>(
                  "Kevin 13:02\nRuby 5\nSam 3\nLisa 6\nBob 12",
                  "13:15"
               ),
               new KeyValuePair<String, String>(
                  "Kevin 13:15\nRuby 5\nSam 3\nLisa 6\nBob 12",
                  "13:15"
               ),
            };
         
         foreach( KeyValuePair<String, String> testCase in testCases ) {
            Console.WriteLine( $" Input:\n{testCase.Key}\n\n{testCase.Value}\n\nOutput:\n{f( testCase.Key, testCase.Value )}\n" );
         }

         Console.ReadLine();
      }
   }
}

Releases

  • v1.1 - - 2 bytes - Thanks to VisualMelon
  • v1.0 - 269 bytes - Initial solution.

Notes

  • Output format: Outputs the names separated by spaces
\$\endgroup\$
6
  • \$\begingroup\$ You can save a few bytes by adding a using D=System.DateTime; directive (don't forget to replace the vars!). You should really provide types for the lambda parameters to make this code completely unambiguous (i.e. (string l,string f)). I also think there is a slight bug, you need h>s rather than h>=s (1byte saving!) as per "(Anyone exactly on time is fine.)". Can you do h.Ticks<1 ? You may find a nullable DateTime cheaper than using DateTime.Min, but I've not checked the full implications here. With the using clause, ==D.Min should work also. \$\endgroup\$ Apr 17, 2017 at 18:05
  • \$\begingroup\$ About the using I doubt I could still pull off a lambda expression with it. I'm pretty sure I can't add it in mid-code. Explicit lambda types are another thing that I haven't seen people doing it, and I went with that -- if it is illegal, say so, but even the mods haven't said anything, maybe it's ok?. h>s I'll do that one. h.Ticks<1 and this one too. \$\endgroup\$
    – auhmaan
    Apr 17, 2017 at 20:35
  • \$\begingroup\$ I'm confident we allow usings and such with lambdas, I can't find anything saying this explicitly on meta, but this question strongly suggests it is permitted. There is a reasonable consensus that explicit parameter types should be required (I should add that I'm firmly in favour). By the by, Mods are there to keep things civil from SE's perspective, not to enforce PPCG's own rules. \$\endgroup\$ Apr 17, 2017 at 22:21
  • \$\begingroup\$ I'm kinda against the usings, mostly because I would then feel that it would require a full code, hence me saying that I doubt I could pull off a function as a solution -- maybe adding two blocks, one for usings and another for the lambda function? About the consensus, I think adding the missing Func<...> f = ...; would solve it, although it should be specified the full name System.Func<...> f = ...; \$\endgroup\$
    – auhmaan
    Apr 18, 2017 at 9:39
  • \$\begingroup\$ You might be better off just having a well named function (only adds string s with C#7 (6? I can't remember) syntax) if you'd rather not mix lambdas and usings. \$\endgroup\$ Apr 18, 2017 at 9:44
1
\$\begingroup\$

CJam, 43 41 bytes

q~':/60b:Y;Sf/()':/60b+a\+{)iT+:TY>{;}|}%

Try it online!

Explanation

q~        e# Read and eval all input.

':/       e# Split the start time on colons.
60b       e# Convert the result from base 60, to get the start time in minutes.
:Y;       e# Store this time in variable Y, and discard it from the stack.

Sf/       e# Split each string in the guest list on spaces.
(         e# Pull out the first guest from the list.
)         e# Pull out the time from the guest.
':/60b+   e# Convert the time to a number of minutes (same way as before), then add it back
          e#   to the guest.
a\+       e# Add the guest back to the start of the guest list.

          e# At this point, the first guest has his/her arrival time in minutes, and everyone
          e#  else still has their original number.

{         e# Apply this block to each guest:
 )i       e#  Pull out the number and cast it to an integer.
 T+       e#  Add the value of variable T to it (T is initially 0).
 :T       e#  Store the result back into T.
 Y>{;}|   e#  If the resulting number of minutes is not after the start time, delete the 
          e#    guest's name.
}%        e# (end of block)

          e# Implicit output.
\$\endgroup\$
1
\$\begingroup\$

Lua, 211 206 Bytes

First codegolf of the year for me, should still be golfable.

Edit: Saved 5 Bytes by using a shorthand for string.match

function f(l,T)m=T.match
r=function(X)return
m(X,"^%d+")*3600+60*m(X,"%d+$")end
T=r(T)z={}y=0
for i=1,#l do
h=m(l[i],"%d.*")h=i>1 and y+h*60or r(h)y=h
z[#z+1]=h>T and m(l[i],"%u%l*")or nil
end return z end

Explanations

function f(l,T)                         -- declare the function f(list,partyTime)
  r=function(X)                         -- declare a function r that convert hh:mm in seconds
    return X:match("^%d+")*3600         -- return the sum of seconds the hours
          +60*X:match("%d+$")           -- and in the seconds
  end                                   
  T=r(T)                                -- convert the partyTime in seconds
  z={}                                  -- create the shameList for late partygoers
  y=0                                   -- y will keep us updated on the second count
  for i=1,#l                            -- iterate over l
  do                                    
    h=l[i]:match("%d.*")                -- h is a shorthand for the time of arrival
    h=i>1                               -- if we're on the second line at least
        and y+h*60                      -- update h with the time of arrival in second
      or r(h)                           -- else use r()(for the first partygoer only)
    y=h                                 -- update our reference for adding time
    z[#z+1]=h>T                         -- if the last partygoer was late
                and l[i]:match("%u%l*") -- add its name to the shameList
              or nil                    -- else, don't do anything
  end                                   
  return z                              -- return the shameList
end                                 

if you want to try this code, you can use the following snippet

function f(l,T)r=function(X)return
X:match("^%d+")*3600+60*X:match("%d+$")end
T=r(T)z={}y=0
for i=1,#l do
h=l[i]:match("%d.*")h=i>1 and y+h*60or r(h)y=h
z[#z+1]=h>T and l[i]:match("%u%l*")or nil
end return z end

retour = f({"Kevin 13:02","Ruby 5","Sam 3","Lisa 6","Bob 12"},"13:15")
for i=1,#retour
do
  print(retour[i])
end
\$\endgroup\$
1
\$\begingroup\$

Java, 346 304 284 275 bytes

  • -9 bytes, thanks to @KevinCruijssen
void g(int m,String[]n,String[]a,int M){for(int i=0;i<n.length;i++)if((M+=i>0?p(a[i]):0)>m)System.out.print(n[i]);}
int p(String n){return new Short(n);}
int h(String t){return p(t.split(":")[0])*60+p(t.split(":")[1]);}
void f(String[]n,String[]a,String b){g(h(b),n,a,h(a[0]));}

Detailed Live

public static void g(int m, String[] n, String[] a, int M)
{
    for(int i = 0; i < n.length; i++)
    {
        if((M += i>0 ? p(a[i]) : 0) > m)
        {
            System.out.println(n[i]);
        }
    } 
}

public static int p(String n)
{
    return Integer.parseInt(n);
}

public static int h(String t)
{
    return p(t.split(":")[0])*60+p(t.split(":")[1]);
}

public static void f(String[] n, String[] a, String b)
{
    g(h(b),n,a,h(a[0]));
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice golfing (for Java.) Do you need the space between String[] n, and String[] a? \$\endgroup\$
    – user58826
    Apr 17, 2017 at 11:12
  • \$\begingroup\$ @programmer5000 no, I also removed the hours variable & accumulated them as minutes. \$\endgroup\$
    – Khaled.K
    Apr 17, 2017 at 11:42
  • 1
    \$\begingroup\$ You can replace Integer.parseInt(n) with new Short(n). And based on the comments of the challenge, LisaBob is also a valid output, so you can change the println to print. \$\endgroup\$ May 12, 2017 at 7:00
0
\$\begingroup\$

Batch, 163 bytes

@set/pp=
@set/ap=%p::=*60+%
:l
@set g=
@set/pg=
@if "%g%"=="" exit/b
@set t=%g:* =%
@set/ap-=%t::=*60+%
@for %%g in (%g%)do @(if %p% lss 0 echo %%g)&goto l

Takes input on STDIN. First line is the start time of the party, then the list of guests. Uses @Arnauld's trick to convert the hh:mm into minutes.

Batch's preferred input for this would be as a series of command-line parameters (starting with the time of the party, then each guest and time as separate arguments). This would only take 129 bytes:

@set p=%1
@set/ap=%p::=*60+%
:l
@set t=%3
@set/ap-=%t::=*60+%
@if %p% lss 0 echo %2
@shift
@shift
@if not "%2"=="" goto l
\$\endgroup\$
0
\$\begingroup\$

Groovy, 121 bytes

{g,t->y={Date.parse('hh:mm',it)};u=y(t);d=y(g.remove(0)[1]);g.find{z=it[1];use(groovy.time.TimeCategory){d+z.minutes}>u}}
\$\endgroup\$
0
\$\begingroup\$

PowerShell, 170 160 bytes

select-string '(?m)^((\w*) )?((\d\d):)?(\d?\d)$'-a|% matches|%{,$_.groups[2,4,5].value}|%{}{$b+=($c=60*$_[1]+$_[2]);$a+=,@{n=$_[0];t=$b}}{$a|? n|? t -gt $c|% n}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Better late than never! \$\endgroup\$
    – user58826
    Apr 17, 2017 at 17:08
  • \$\begingroup\$ I'm in rest today therefore have a some time for a some fun \$\endgroup\$ Apr 17, 2017 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.