Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I like patterns in time. My favorite is when the time lines up. For example, all of these line up:

3:45
12:34
23:45
3:21
6:54

This is because each digit in the hour/minute is increasing/decreasing by one each time.

Your task is to take the current time and check if it "lines up" in this pattern in a program. (You will output a truthy or falsey value according to this check.) Along with the times above, your program should match these:

1:23
4:32
2:10

And not match these:

1:00
12:13
1:21
1:34

You may take the time as an argument to a function/through STDIN, but this incurs a +125% byte penalty on your program. You may take the time from UTC or system time; 12-hour or 24-hour. This is a code golf, so the shortest program in bytes wins.

share|improve this question
3  
This challenge is very similar to Find all times that follow a pattern, things valid for this program are also valid for the other program – Ferrybig Feb 20 at 20:20
    
@Ferrybig except this uses the actual time and includes a different method – Seadrus Feb 20 at 20:30
14  
+125%? Seems like it should be +25%. – CalculatorFeline Feb 20 at 20:41
16  
-1 for penalty. Either take current time or time via input, but trying to do both makes for silly scores. – Geobits Feb 21 at 3:09
1  
Should it match 9:01? – Daniel M. Feb 21 at 4:37

15 Answers 15

Jolf, 10 21 19 28 bytes

Replace with \x11, or use this link.

 eZd♂Μf5dpq+EH20d&=FnH h±01H

This can be golfed (?).

Explanation:

 eZd♂Μf5dpq+EH20d&=FnH h±01H
       f5                      [hours, minutes]
      Μ  dpq+EH20              pad (>_>)
     ♂                         singleton; so [13,45] => [1,3,4,5]
  Zd                           delta list; [1,3,4,5] => [2,1,1]
_e               d             check if
                   =FnH        each member is equal to the first
                  &    _h±01H  and if it is in the array [-1,1] (0 +- 1)
share|improve this answer
    
Unless I'm misunderstanding something, this would return true at 1:00, because the minutes aren't padded to two digits. – Dennis Feb 21 at 4:07
    
@Dennis Nice catch. How did you notice? – Cᴏɴᴏʀ O'Bʀɪᴇɴ Feb 21 at 4:13
    
I ran f5 alone to see what it does, and it was 1:05 when I did it. – Dennis Feb 21 at 4:13
    
@Dennis o_o wow. This challenge is certainly full of coincidences. – Cᴏɴᴏʀ O'Bʀɪᴇɴ Feb 21 at 4:15

Pyth, 67.5 54 38 bytes

sm.v%"q1l.{.e%skvb+`.d6.[\0`.d7 2"d"+-

Or old version, 30 bytes (takes input from stdin)

 zsm.v%"q1l.{.e%skvb:z\:k"d"+-

Thanks @drobilc for reminding me of the other .d arguments ;)

Explanation:

sm.v%"q1l.{.e%skvb+`.d6.[\0`.d7 2"d"+-
 m                                 "+- -  [V for d in "+-"]
    %                             d    -   V%d
     "                           "     -    stringify code V
                   `.d6                -          repr(current_hour)
                  +                    -         ^+V
                           `.d7        -           repr(current_minute)
                       .[\0     2      -          pad("0",^,2)
           .e                          -        [V for k,b in enumerate(^)]
                vb                     -          eval(b)
             %s                        -         V (either + or -) ^
               k                       -          k
         .{                            -       set(^)
        l                              -      len(^)
      q1                               -     ^==1
  .v                                   -  eval(^)
s                                      - True in ^

Basically, for both + and - it tests to see if by performing that operation on the index on the character and the character itself you get the same values.

Try it here!

Or try a test suite!

share|improve this answer
    
There's a 125% penalty for reading the time as user input. – Dennis Feb 20 at 20:43
    
Can't you get the time using something like +.d6+k.d7? – drobilc Feb 20 at 21:34
    
Oh yeah, I didn't get it when I searched for time ;) – muddyfish Feb 20 at 21:37
    
Unless I'm misunderstanding something, this would return true at 1:00, because the minutes aren't padded to two digits. – Dennis Feb 21 at 4:17

Pyth, 23 bytes

}+.d6%"%02d".d7jk+U7_U7

Constructs the string "0123456543210" and check if the time without the colon is a substring of it.

In pythonic pseudocode:

                   k = ""
}+.d6%"%02d".d7    ( currentHour() + format("%02d",currentMinute()) ) in \
  jk+U7_U7             (range(7) + range(7)[::-1]).join(k)
share|improve this answer

Bash, 79 78 bytes

[[ $(date +%-H%M|fold -1|sed 'p;{1d;$d}'|paste -sd-\\n|bc|sort -u) =~ ^-?1$ ]]

Remarkably competitive for the usually-painfully-verbose Bash.

Thanks to @DigitalTrauma for 2 bytes!

Walkthrough:

  • date +%-H%M: returns the date in HHMM form (ex. 1234).

  • fold -1: puts each character on a separate line (so now we have 1\n2\n3\n4\n).

  • sed:

    • p: duplicate each line.

    • {1d;$d}: delete the first and last lines.

    Now we have 1 2 2 3 3 4 (spaces used in place of newlines for readability).

  • paste -sd '-\n': turns this into 1-2 2-3 3-4.

  • bc: piped through an arithmetic calculator, now we have -1 -1 -1.

  • sort -u: remove duplicates, so now we have -1.

  • [[ $(...) =~ ^-?1$ ]]: check if the resulting string matches the regex /^-?1$/.

    If the time is "linear," the differences between each consecutive line will all be either 1 or -1.

share|improve this answer
    
Remarkably competitive, yes. But not as competitive as this ;-). Looks like I posted 1 minute after you. – Digital Trauma Feb 20 at 22:08
    
Bash brace expansions can be very useful to produce sequences in either direction. – Digital Trauma Feb 20 at 22:17
    
paste -sd-\\n – Digital Trauma Feb 21 at 6:22
    
I think you need date +%-H%M too so 1-digit hours are not space-padded – Digital Trauma Feb 21 at 6:26
    
What about date +%-H%M|fold -1|sed 'p;{1d;$d}'|paste -sd-\\n|bc|grep -Evc ^-?1$? Outputs 0 for truthy and +ve for falsey. – Digital Trauma Feb 21 at 6:31

Jelly, 24.75 22.5 bytes

~ḟ0IµḢ×=1P

The code is 10 bytes long and is subject to the 125% penalty.

Try it online!

How it works

~ḟ0IµḢ×=1P  Main link. Input: S (time string)

~           Apply bitwise NOT to all characters.
            This attempts to cast to integer, and returns 0 on failure.
            For example, '1'~ -> 1~ -> -2, but ':'~ -> 0.
 ḟ0         Filter out the 0, which corresponds to the colon.
   I        Compute all increments/deltas.
    µ       Begin a new, monadic chain. Argument: A (list of deltas)
     Ḣ      Pop the first delta.
      ×     Multiply the remaining list items by the popped one.
            The list should now consist of 1's for a truthy test case.
       =1   Compare the list items with 1.
         P  Take the product of the resulting Booleans.
share|improve this answer

JavaScript (ES6), 75 73 bytes

_=>"0123456543210".match((m=(new Date+"").match`([1-9].?):(..)`)[1]+m[2])

2 bytes saved thanks to @Neil!

Explanation

Credit to @busukxuan for the digit string idea!

Checks the digits of the current time in the string 0123456543210. Returns null for false and an array containing the time digits for true.

_=>
  "0123456543210".match(     // check if the time digits are in this string
    (m=
      (new Date+"")          // get a string with the current time (among other things)
      .match`([1-9].?):(..)` // get time digits with leading zero removed
    )
    [1]+m[2]                 // construct a string of only the time digits
  )
share|improve this answer
    
I tried (m=(new Date+"").match(/([1-9].?):(..)/))[1]+m[2] but it's the same length. – Neil Feb 21 at 10:06
    
@Neil Ah, I forgot to try using capture groups. Thanks, this saves 2 bytes by calling match with a tagged template string. – user81655 Feb 21 at 10:25
    
Well, I'm glad I was of help after all! – Neil Feb 21 at 16:29

05AB1E, 10 × 125% = 24.75 22.5 bytes

Code:

R.d¬¹1£ŸJQ

Explanation:

R           # Reverse the input
 .d         # Keep the digits
   ¬        # Head, push the first character of the string
    ¹       # First value from the input register
     1£     # Take the first character from the input
       Ÿ    # Inclusive range
        J   # Join the list to a string
         Q  # If equal to the input, return 1, else 0

Try it online! or Try all test cases at once!

share|improve this answer
1  
@Dennis Which in my opinion is not fair for languages who don't have time support... – Adnan Feb 20 at 20:45
    
I don't disagree... – Dennis Feb 20 at 20:48

MATL, 24 18 19 bytes

'%i%2i'1$4:5Z'YDdtdw|qh~

Try it online!

Output is an array consisting of only ones (which is truthy) if the time matches, and an array with at least one zero (that's falsy) otherwise.

To test the code it's better to split it in two parts as follows:

  • 1$4:5Z' produces a 2-number vector with the current hour and minute.
  • '%i%2i'iYDdtdw|qh~ takes from stdin a 2-number vector with hours and minutes and computes the result.

In the combined code, the second part takes its input from the stack as produced by the first.

Explanation

A matching occurs if the following two conditions are met:

  • All differences between consecutive digits have absolute value 1;
  • All differences between those consecutive differences are 0.

Minutes have to be zero padded (thanks to Dennis for that!). Zero-padding, if it actually occurs (minute is 9 or less) will always produce a falsy result. So I use space-padding instead, whivh has the same effect.

Code:

'%i%2i'     % format string for sprintf, including padding for minutes
1$4:5Z'     % get current hour and minute as a 2x1 numeric array
d           % differences between consecutive digits (chars)
td          % duplicate. Compute differences again. Will be all zero if time matches
w|q         % swap, absolute value, subtract 1. Will be all zero if time matches
h~          % concatenate both arrays and apply logical negate
share|improve this answer

Pyth, 38*2.25 = 86 bytes

JsMfnT\:zK.b-NYt.>J1tJ|qlKlx1KqlKlx_1K

Try it here!

Explanation

Works by converting the time to a list of integers, mapping this to a list of differences and checking if this list only contains -1 or 1.
Difference checking works by rotating the integer list one to right and doing an elementwise subtraction with the original integer list using all elements but the first one in each list.

JsMfnT\:zK.b-NYt.>J1tJ|qlKlx1KqlKlx_1K  # z = input

   fnT\:z                               # filter the : out
 sM                                     # map the digits to integers
J                                       # assign the list to J
          .b                            # parallel  map (with N and Y) to
            -NY                         # difference of N and Y
               t.>J1                    # over all but the first element of J, rotated right
                    tj                  # and all but the first element of J
         K                              # assign the result to K
                      |qlKlx1KqlKlx_1K  # check if K only contains -1 or 1
share|improve this answer

Bash + coreutils, 59

t=`date +%-H%M`
((`eval printf %s {${t::1}..${t: -1}}`==t))

Shell return code is set to 0 (truthy) or 1 (falsey).

  • Save just the hours and minutes numbers of the date in variable t
  • Construct a bash brace expansion that runs from the first digit to the last digit of $t. The run produced by the expansion will automatically run in the right direction
  • eval allows the variable expansions to happen before the brace expansion
  • printf outputs the concatenated expansion as one string with no space separators
  • The result will be equal to $t in the truthy case - arithmetic evaluation to test this is shorter than the usual [ ... ] test.

Ideone.

share|improve this answer

Julia, 92 71 bytes

f(d=diff(["$(Dates.hour(now()))""$(now())"[15:16]...]))=all(d[1]d.==1)

This is a function that takes no arguments and returns a boolean. To call it, simply execute f().

We define the keyword argument d of f to be the cumulative difference in the ASCII codes associated with the digits of the hours and minutes of the current time. Then, for each difference, we multiply the first difference in the list by each successive difference and determine whether all are equal to 1. If so, the digits of the time are either monotone increasing by 1 or monotone decreasing by 1.

Saved 21 bytes and fixed an issue thanks to Dennis!

share|improve this answer

Batch, 130 bytes

@set t=%time:~,5%
@goto %t::=% 2>nul
:0012
:0123
:0210
:0234
:0321
:0345
:0432
:0456
:0543
:0654
:1234
:2345
@echo 1

Edit: Back to the old approach. %time% contains the time in hh:mm:ss.ss format. The first 5 characters are extracted into t and the colon is deleted. If the result is one of the 12 possible linear times then 1 is output to indicate a truthy value, otherwise there is no output to indicate a falsy value.

share|improve this answer
    
I liked your jump-table approach :-) – Kenney Feb 21 at 1:10
    
@Kenney Good news, it's back! (I had some useless entries in the table which was bloating the answer, but that's fixed now.) – Neil Feb 21 at 8:00

Retina, 78 63 62 60 * 125% = 135

:

.
$0$*aa:
^(a*)(:\1a:\1aa(:\1aaa)?|aaa:\1aa:+\1a(:\1)?):$

15 bytes thanks to Maria^H^H^H^H^HDigital Trauma, and for paving the way for 3 additional bytes.

Prints 1 for success, 0 for failure. I imagine this isn't optimal, but I can't think of a better approach. This method requires that 1 be added to each of the time digits, otherwise 0 causes some problems.

Try it online!

You can try a slightly modified program here that runs on multiple lines.

share|improve this answer
    
Doubled spaces? I'm suspicious. – CalculatorFeline Mar 9 at 22:51
    
thanks to xxxx Digital Trauma – CalculatorFeline Mar 9 at 23:38
    
Ahh... right ok, edited :P – FryAmTheEggman Mar 9 at 23:57

Perl, 90 65 bytes

@i=`date +%R`=~/\d/g;@n=reverse@m=0..9;print"@m"=~/@i/|"@n"=~/@i/

New approach: generate strings "0 1 2 3 4 5 6 7 8 9" and it's reverse and do a regexp match.


The previous approach (90 bytes):

@l=map{("$_=>1,","$_-")}`date +%R`=~/\d/g;@a=%h=eval"@l[1..$#l-1]";print@a==2&&1==abs$a[1]

Commented:

@l=
    map{
        ("$_=>1,","$_-")      # return parts of expressions
    }
    `date +%R`=~              # grab the time, quick 'n' dirty, and apply a regexp
       /\d/g;                 # match all digits and return a list

@a=                           # 'cast' the hash to a list
   %h=                        # 'cast' the list to a hash
      eval                    # evaluate the string
           "@l                # this string is interpolated as join ' ', @l
            [1..$#l-1]";      # but only after discarding the first and last element

print @a==2 && 1==abs $a[1]   # check that the hash has 1 key and that it's value is +1/-1

It's not going to win any prizes, but I had fun on this one so I'll share my work. The basic idea is the same as some/most other answers: calculate the deltas and make sure they are all either -1 or +1.

The expression that is evaled for the time 12:34 is constructed as follows:

@l=                     [1,      $#l]          "@l[...]"                    %h
(("1=>1", "1-"),        (        "1-",           
 ("2=>1", "2-"),  ->     "2=>1", "2-",   ->    1-2=>1, 2-3=>1, 3-4=>1      (-1 => 1)
 ("3=>1", "3-"),         "3=>1", "3-",
 ("4=>1", "4-"))         "4=>1",      )

Some things I tried that don't work:

  • using exit to save a byte. It sometimes returns 2.

  • merely calculating the number of hash keys (74 bytes). This also matches all the time pattern where all the digits are the same.

    @l=map{("$_=>1,","$_-")}`date +%F`=~/\d/g;%h=eval"@l[1..$#l-1]";print%h==1
    
  • calculating the absolute normalized sum of the deltas (79 bytes). This grew from the approach to eval into a scalar. The total sum would have to be ±2 for 3 digits and ±3 for 4 digits, easily normalized with the $#array syntax. The false positive 12:24 made this approach unfeasible:

    @l=map{($_,"+","$_-")}@x=`date +%R`=~/\d/g;print 1==eval"abs(@l[2..$#l-2])/$#x"
    
share|improve this answer

Mathematica, 85 84 bytes

#==Range[#[[1]],Last@#,Sign[Last@#-#[[1]]]]&@Flatten@IntegerDigits@DateList[][[4;;5]]

Pretty basic. Compares the time (as a list of digits) to a range from [first digit] to [last digit].

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.