-4
\$\begingroup\$

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.

\$\endgroup\$
  • 3
    \$\begingroup\$ 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 \$\endgroup\$ – Ferrybig Feb 20 '16 at 20:20
  • \$\begingroup\$ @Ferrybig except this uses the actual time and includes a different method \$\endgroup\$ – Seadrus Feb 20 '16 at 20:30
  • 14
    \$\begingroup\$ +125%? Seems like it should be +25%. \$\endgroup\$ – CalculatorFeline Feb 20 '16 at 20:41
  • 16
    \$\begingroup\$ -1 for penalty. Either take current time or time via input, but trying to do both makes for silly scores. \$\endgroup\$ – Geobits Feb 21 '16 at 3:09
  • 1
    \$\begingroup\$ Should it match 9:01? \$\endgroup\$ – Daniel M. Feb 21 '16 at 4:37

16 Answers 16

5
\$\begingroup\$

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)
\$\endgroup\$
  • \$\begingroup\$ Unless I'm misunderstanding something, this would return true at 1:00, because the minutes aren't padded to two digits. \$\endgroup\$ – Dennis Feb 21 '16 at 4:07
  • \$\begingroup\$ @Dennis Nice catch. How did you notice? \$\endgroup\$ – Conor O'Brien Feb 21 '16 at 4:13
  • \$\begingroup\$ I ran f5 alone to see what it does, and it was 1:05 when I did it. \$\endgroup\$ – Dennis Feb 21 '16 at 4:13
  • \$\begingroup\$ @Dennis o_o wow. This challenge is certainly full of coincidences. \$\endgroup\$ – Conor O'Brien Feb 21 '16 at 4:15
4
\$\begingroup\$

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!

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

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.

\$\endgroup\$
  • \$\begingroup\$ Remarkably competitive, yes. But not as competitive as this ;-). Looks like I posted 1 minute after you. \$\endgroup\$ – Digital Trauma Feb 20 '16 at 22:08
  • \$\begingroup\$ Bash brace expansions can be very useful to produce sequences in either direction. \$\endgroup\$ – Digital Trauma Feb 20 '16 at 22:17
  • \$\begingroup\$ paste -sd-\\n \$\endgroup\$ – Digital Trauma Feb 21 '16 at 6:22
  • \$\begingroup\$ I think you need date +%-H%M too so 1-digit hours are not space-padded \$\endgroup\$ – Digital Trauma Feb 21 '16 at 6:26
  • \$\begingroup\$ 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. \$\endgroup\$ – Digital Trauma Feb 21 '16 at 6:31
3
\$\begingroup\$

Pyth, 23 22 bytes

}+.d6%"%02d".d7jks_BU7

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 \
  jks_BU7             sum([range(7),range(7)[::-1]]).join(k)
\$\endgroup\$
2
\$\begingroup\$

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.
\$\endgroup\$
2
\$\begingroup\$

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.

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

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
  )
\$\endgroup\$
  • \$\begingroup\$ I tried (m=(new Date+"").match(/([1-9].?):(..)/))[1]+m[2] but it's the same length. \$\endgroup\$ – Neil Feb 21 '16 at 10:06
  • \$\begingroup\$ @Neil Ah, I forgot to try using capture groups. Thanks, this saves 2 bytes by calling match with a tagged template string. \$\endgroup\$ – user81655 Feb 21 '16 at 10:25
  • \$\begingroup\$ Well, I'm glad I was of help after all! \$\endgroup\$ – Neil Feb 21 '16 at 16:29
2
\$\begingroup\$

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!

\$\endgroup\$
  • 1
    \$\begingroup\$ @Dennis Which in my opinion is not fair for languages who don't have time support... \$\endgroup\$ – Adnan Feb 20 '16 at 20:45
  • 1
    \$\begingroup\$ I don't disagree... \$\endgroup\$ – Dennis Feb 20 '16 at 20:48
2
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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.

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

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!

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

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].

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

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.

\$\endgroup\$
  • \$\begingroup\$ Doubled spaces? I'm suspicious. \$\endgroup\$ – CalculatorFeline Mar 9 '16 at 22:51
  • \$\begingroup\$ thanks to xxxx Digital Trauma \$\endgroup\$ – CalculatorFeline Mar 9 '16 at 23:38
  • \$\begingroup\$ Ahh... right ok, edited :P \$\endgroup\$ – FryAmTheEggman Mar 9 '16 at 23:57
0
\$\begingroup\$

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"
    
\$\endgroup\$
0
\$\begingroup\$

Python 2, 93 bytes

import time,numpy
print len(set(numpy.diff([int(time.asctime()[10+k])for k in[1,2,4,5]])))==1

Not subject to the byte penalty. Small chance this doesn't work if time.asctime() changes during the loop. +4 bytes to fix this:

import time,numpy
x=time.asctime()
print len(set(numpy.diff([int(x[10+k])for k in[1,2,4,5]])))==1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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