in reply to Determining gaps in time ranges

#! perl -slw use strict; use Data::Dumper; sub hm2mins{ $_[ 0 ] =~ m[^(\d\d):(\d\d)$] and return $1 * 60 + $2; } sub mins2hm{ sprintf '%02d:%02d', int( $_[ 0 ] / 60 ), $_[ 0 ] % 60 ; } my @HM = ( [ '03:30', '05:45' ], [ '05:45', '09:15' ], [ '10:00', '11:35' ], [ '11:00', '15:40' ] ); my $stick = '0' x ( 60 * 24 ); for ( @HM ) { my( $start, $stop ) = ( hm2mins( $_->[ 0 ] ), hm2mins( $_->[ 1 ] +) ); substr( $stick, $start, $stop - $start ) = '1' x ( $stop - $start) +; } my @out; push @out, [ pos( $stick ), length $1 ] while $stick =~ m[(0+)]g; @out = map{ my $start = $_->[ 0 ] - $_->[ 1 ]; my $stop = $_->[ 0 ]; [ mins2hm( $start ), mins2hm( $stop ) ] } @out; print Dumper \@out; __END__ P:\test>341852 $VAR1 = [ [ '00:00', '03:30' ], [ '09:15', '10:00' ], [ '15:40', '24:00' ] ];

Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail

Replies are listed 'Best First'.
Re: Re: Determining gaps in time ranges
by tachyon (Chancellor) on Apr 02, 2004 at 02:41 UTC

    Or TIMTOWDI

    my @array = ( [ '03:30', '05:45' ], [ '05:45', '09:15' ], [ '10:00', '11:35' ], [ '11:00', '15:40' ] ); sub hhmm2min { die "Data error $_[0] not in format HH:MM\n" unless $_[0] =~ m/(\d +\d):(\d\d)/; return $1*60+$2; } sub min2hhmm { die "Data error $_[0] > 24:00\n" if $_[0] > 24*60; return sprintf "%02d:%02d", int($_[0]/60), $_[0]%60; } @array = sort{ $a->[0]<=>$b->[0] }map{ [ hhmm2min($_->[0]), hhmm2min($ +_->[1]) ] }@array; my $cur = 0; my @missing = (); for my $r( @array ) { push @missing, [ min2hhmm($cur), min2hhmm( $r->[0] ) ] if $cur < $ +r->[0]; #$cur = $r->[1]; # bug $cur = $r->[1] unless $cur > $r->[1]; } push @missing, [ min2hhmm($cur), '24:00' ] unless $cur == 24*60; use Data::Dumper; print Dumper \@missing; __DATA__ $VAR1 = [ [ '00:00', '03:30' ], [ '09:15', '10:00' ], [ '15:40', '24:00' ] ];

    cheers

    tachyon

      tachyon's code, as well as the other suggestions, works very well (and is plenty efficient for my needs). Much thanks guys!

        Unfortunately, tachyon's code doesn't work for many cases.

        #! perl -sw use strict; my @array = ( [ '03:30', '05:45' ], [ '05:45', '09:15' ], [ '10:00', '11:35' ], [ '10:00', '10:01' ], [ '11:00', '15:40' ] ); sub hhmm2min { die "Data error $_[0] not in format HH:MM\n" unless $_[0] =~ m/(\d +\d):(\d\d)/; return $1*60+$2; } sub min2hhmm { die "Data error $_[0] > 24:00\n" if $_[0] > 24*60; return sprintf "%02d:%02d", int($_[0]/60), $_[0]%60; } @array = sort{ $a->[0] <=> $b->[0] }map{ [ hhmm2min($_->[0]), hhmm2min($_->[1]) ] }@array; my $cur = 0; my @missing = (); for my $r( @array ) { push @missing, [ min2hhmm($cur), min2hhmm( $r->[0] ) ] if $cur < $ +r->[0]; $cur = $r->[1]; } push @missing, [ min2hhmm($cur), '24:00' ] unless $cur == 24*60; use Data::Dumper; print Dumper \@missing; __END__ P:\test>test $VAR1 = [ [ '00:00', '03:30' ], [ '09:15', '10:00' ], [ '10:01', '11:00' ], [ '15:40', '24:00' ] ];

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail

        My code has a bug. The update on the $cur pointer should be:

        $cur = $r->[1] unless $cur > $r->[1];
        ie we only want to update it if it is greater than our last known greatest end or range. It will fail on
        @array = ( [ '00:00', '24:00' ], [ '01:00', '02:00' ] );

        for example.

        cheers

        tachyon