8
\$\begingroup\$

Challenge

Write a program that greets a user depending on what time of day (GMT) it is.


Output

A string (printed or returned) according to these rules:

  • If the time is 06:00 to 11:59 the greeting has to be "Good morning"
  • If the time is 12:00 to 17:59 the greeting has to be "Good afternoon"
  • If the time is 18:00 to 19:59 the greeting has to be "Good evening"
  • If the time is 20:00 to 05:59 the greeting has to be "Zzz"


Clarifications

  • There is no input
  • The times and greetings must be exactly as shown
  • The time zone is +0 GMT

Examples

Time: 14:45 -> Good afternoon

Time: 05:59 -> Zzz

Time: 9:23 -> Good morning

Time: 18:00 -> Good evening
\$\endgroup\$
  • 1
    \$\begingroup\$ Without a testing environment in which one can manipulate the current time, how would you test this? Wouldn't it be better for the code to receive the current time as input instead? \$\endgroup\$ – Skidsdev Aug 8 '18 at 12:57
  • 2
    \$\begingroup\$ If not taking input should we be using UTC / local timezone according to some OS spec / whatever we want (needs some restriction though as it's always morning somewhere in the world) \$\endgroup\$ – Jonathan Allan Aug 8 '18 at 13:04
  • 1
    \$\begingroup\$ @mbomb007 the program is sleeping at night \$\endgroup\$ – lolad Aug 8 '18 at 14:19
  • 2
    \$\begingroup\$ Well, there goes my Novell login script solution - its %GREETING_TIME variable doesn't have "Zzz", it just switches from "evening" to "morning" at midnight. \$\endgroup\$ – Neil Aug 8 '18 at 15:34
  • 9
    \$\begingroup\$ I recommend against restricting to a specific time zone, but am in favor of restricting to your own system time instead. Many answers are currently invalid because of it. \$\endgroup\$ – Erik the Outgolfer Aug 8 '18 at 18:16

18 Answers 18

12
\$\begingroup\$

JavaScript (ES6), 87 bytes

As noticed by TFeld, my original formula was overcomplicated. We can just do:

_=>['Zzz','Good morning','Good afternoon','Good evening'][new Date().getHours()%20/6|0]

Try it online!

Or test this version that takes the hour as parameter.


JavaScript (ES6), 90 bytes

_=>['Zzz','Good morning','Good afternoon','Good evening'][new Date().getHours()*7%20%7>>1]

Try it online!

Or test this version that takes the hour as parameter.

Formula

Given the current hour \$h\$, we find the appropriate greeting index \$i\$ with:

$$i=\left\lfloor\frac{((7\times h) \bmod 20) \bmod 7}{2}\right\rfloor$$

A good thing about this formula is that it does not require any parenthesis once converted to JS:

h * 7 % 20 % 7 >> 1

Table

 Hour |  *7 | mod 20 | mod 7 | >> 1
------+-----+--------+-------+------
   0  |   0 |    0   |   0   |   0
   1  |   7 |    7   |   0   |   0
   2  |  14 |   14   |   0   |   0
   3  |  21 |    1   |   1   |   0
   4  |  28 |    8   |   1   |   0
   5  |  35 |   15   |   1   |   0
   6  |  42 |    2   |   2   |   1
   7  |  49 |    9   |   2   |   1
   8  |  56 |   16   |   2   |   1
   9  |  63 |    3   |   3   |   1
  10  |  70 |   10   |   3   |   1
  11  |  77 |   17   |   3   |   1
  12  |  84 |    4   |   4   |   2
  13  |  91 |   11   |   4   |   2
  14  |  98 |   18   |   4   |   2
  15  | 105 |    5   |   5   |   2
  16  | 112 |   12   |   5   |   2
  17  | 119 |   19   |   5   |   2
  18  | 126 |    6   |   6   |   3
  19  | 133 |   13   |   6   |   3
  20  | 140 |    0   |   0   |   0
  21  | 147 |    7   |   0   |   0
  22  | 154 |   14   |   0   |   0
  23  | 161 |    1   |   1   |   0
\$\endgroup\$
6
\$\begingroup\$

Python 2, 120 106 102 bytes

import time
print['Zzz','Good morning','Good afternoon','Good evening'][int(time.time()/3600%24%20/6)]

Try it online!

Testable here: Try it online!


Similar to Arnauld's answer, but slightly different:

h  %20 /6
---------
0   0   0
1   1   0
2   2   0
3   3   0
4   4   0
5   5   0
6   6   1
7   7   1
8   8   1
9   9   1
10  10  1
11  11  1
12  12  2
13  13  2
14  14  2
15  15  2
16  16  2
17  17  2
18  18  3
19  19  3
20  0   0
21  1   0
22  2   0
23  3   0

Saved:

  • -3 bytes, thanks to Arnauld
  • -1 byte, thanks to N. P.
\$\endgroup\$
  • 3
    \$\begingroup\$ I think you can do /3600%24%20/6. \$\endgroup\$ – Arnauld Aug 8 '18 at 15:03
  • 2
    \$\begingroup\$ I think you can save a byte by importing time and using time.time() as well \$\endgroup\$ – N. P. Aug 8 '18 at 18:55
  • \$\begingroup\$ @Arnauld Thanks :) \$\endgroup\$ – TFeld Aug 9 '18 at 6:49
  • \$\begingroup\$ @JonathanAllan Doesn't work unfortunately. It's still a float \$\endgroup\$ – TFeld Aug 9 '18 at 6:49
  • \$\begingroup\$ Oh my mistake, you need to index with it :( \$\endgroup\$ – Jonathan Allan Aug 9 '18 at 6:59
4
\$\begingroup\$

R, 97 95 93 Bytes

Using methods found above in R

c("Zzz","Good morning","Good afternoon","Good evening")[as.POSIXlt(Sys.time(),"G")$h%%20/6+1]

Explanation:

c("Zzz","Good morning","Good afternoon","Good evening")      # Creates a vector with the greetings
[                                                            # Open bracket. The number in the bracket will extract the corresponding greeting from the vector below
as.POSIXlt(                                                  # as.POSIXlt converts the object to one of the two classes used to represent date/times
Sys.time(),                                                  # Retrieves the current time on the OS
"G")                                                         # Converts the time to the desired time zone. Does output a warning, but still converts properly to GMT
$h                                                           # Extracts the hour from the object created by as.POSIXlt
%%20/6                                                       # Methodology as used by other golfers
+1]                                                          # Vectors in R start from 1, and not 0 like in other languages, so adding 1 to the value ensures values range from 1 to 4, not 0 to 3

Example

Notice how this line of code, without adding 1, is short 10 elements

c('Zzz','Good morning','Good afternoon','Good evening')[0:23%%20/6]

[1] "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"           
[7] "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"  
[13] "Good afternoon" "Good afternoon"

Adding 1 ensures that the result obtained is greater than 0

c('Zzz','Good morning','Good afternoon','Good evening')[as.integer(0:23)%%20/6+1]

[1] "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"           
[7] "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"  
[13] "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon"
[19] "Good evening"   "Good evening"   "Zzz"            "Zzz"            "Zzz"            "Zzz"
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! I think you can just divide by 6 regularly to save 2 bytes. You may need to turn it into a function as well, something like this: Try it online!. \$\endgroup\$ – BLT Aug 8 '18 at 23:03
  • \$\begingroup\$ @BLT Thank You. When I tested the code in pieces / was yielding floating point numbers, which I didn't think would work in the brackets, thus I used %/% for floor division. I learned something new today. As for turning it into a function, Sys.time() automatically retrieves the current time on any given computer, itself being the sole input in the equation. \$\endgroup\$ – Sumner18 Aug 8 '18 at 23:22
  • 2
    \$\begingroup\$ It seems like we can use timezone "G" and it'll autocomplete to "GMT". It gives a warning but outputs GMT on my UK-based Windows 10 machine, though it may be region/platform specific? I don't see anything about it in the docs. Saves 2 bytes if we can use it though. \$\endgroup\$ – CriminallyVulgar Aug 8 '18 at 23:42
  • \$\begingroup\$ @CriminallyVulgar That works here on my US-based Windows 10 machine. Thanks! \$\endgroup\$ – Sumner18 Aug 9 '18 at 17:01
3
\$\begingroup\$

T-SQL, 153 bytes

SELECT CASE WHEN a>18THEN'Good afternoon'WHEN a>12THEN'Good morning'WHEN a>2THEN'Zzz'ELSE'Good evening'END
FROM(SELECT(DATEPART(hh,GETUTCDATE())+6)%24a)a

Try the SQL Fiddle

Explanation:

SELECT
  CASE WHEN a>18 THEN'Good afternoon' --CASE returns the first value in order whose condition is met
       WHEN a>12 THEN'Good morning'
       WHEN a>2  THEN'Zzz'
       ELSE 'Good evening'
       END
FROM( SELECT (      --Use a subquery to treat the time like a 1x1 table - shorter than declaring a variable
    DATEPART(hh,    --Returns the hour part (hh) of the date
      GETUTCDATE()) --Returns current UTC time (as far as the SQL Server is concerned)
        +6)%24      --Virtual time zone where no period crosses midnight, so everything is ordered
        a)          --Give column a 1-letter alias
        a           --Give subquery an alias so SQL Server doesn't complain
\$\endgroup\$
2
\$\begingroup\$

Perl 5, 77 bytes

$_=(gmtime)[2]%20;say$_<6?Zzz:"Good ".($_<12?morning:$_<18?afternoon:evening)

Try it online!

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

Excel, 97 bytes

=VLOOKUP(Hour(Now()),{0,"Zzz";6,"Good morning";12,"Good afternoon";18,"Good evening";20,"Zzz"},2)

Start with the list of cases

0 <= HOUR < 6 : "Zzz"
6 <= HOUR < 12 : "Good morning"
12 <= HOUR < 18 : "Good afternoon"
18 <= HOUR < 20 : "Good evening"
20 <= HOUR : "Zzz"

Then just use a Range-based Vlookup (default if you ommit the 4th argument) with an Array of values:

H= 0 | "Zzz"
H= 6 | "Good morning"
H=12 | "Good afternoon"
H=18 | "Good evening"
H=20 | "Zzz"

{0,"Zzz"; 6,"Good morning"; 12,"Good afternoon"; 18, "Good evening"; 20,"Zzz"}

I experimented with using MOD(HOUR(NOW())+18,24 to shift the hour back by 6 and reduce the cases by 1, but that resulted in 99 bytes. :(

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

05AB1E, 36 bytes

”‚¿”…•´¯âžÖ#1ú«…Zzz¸«ža•1Ý;`{ùí4²•èè

Try it online!


”‚¿”                                 # Push 'Good'
    …•´¯âžÖ                          # Push 'morning afternoon evening'
           #                         # Split on spaces.
            1ú                       # Pad each with 1 space.
              «                      # Concat good onto it: ['Good morning',...,'Good evening']
               …Zzz¸«                # Concat 'Zzz' onto it.
                     ža              # Get current hour.
                       •1Ý;`{ùí4²•   # Push 33333000000111111222.
                                  è  # indexes[current_hour]->i[6:00AM]->0
                                   è # phrases[indexes[current_hour]]->p[i[6AM]]->'Good morning'.
\$\endgroup\$
1
\$\begingroup\$

Powershell, 82 72 bytes

Port of TFeld's answer

('Zzz','Good morning','Good afternoon','Good evening')[(date).Hour%20/6]
\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 103 bytes

(nth(floor(mod(nth-value 2(get-decoded-time))20)6)'("Zzz""Good morning""Good afternoon""Good evening"))

Ungolfed

(nth (floor (mod (nth-value 2 (get-decoded-time))
                 20)
            6)
     '("Zzz" "Good morning" "Good afternoon" "Good evening"))

Common Lisp mostly ignores whitespace as long as it can unambiguously determine where each sub-expression ends, so much of the golfing here is just removing whitespace. Common Lisp also provides the ability for functions to return multiple values, with all but the first discarded if the caller hasn't explicitly requested the 2nd/3rd/etc return values. This allows functions to return auxiliary data, like the floor function performs floor division, but as a secondary return value returns the remainder. This also allows for functions to avoid the overhead of having to package up their return values in a datastructure if the caller is likely to immediately destructure it again. (get-decoded-time) (really itself a shorthand for (decode-universal-time (get-universal-time))) returns the most values of just about any standard function in common lisp... 9, to be exact. The 3rd return value ((nth-value 2 ...) ) is the current hour in 24 hour time. Then it's just computing the proper index into the list of responses and passing that to nth. I have to use floor here as CL would return a proper fraction if I used / for division.

Try it online!

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

Batch, 178 bytes

@for /f "tokens=3" %%a in ('wmic path Win32_UTCTime') do @set/ag=%%a%%20/6
@for %%a in (Zzz.0 "Good morning.1" "Good afternoon.2" "Good evening.3") do @if %%~xa==.%g% echo %%~na

Uses @TFeld's formula. Locale-dependent version is only 128 bytes:

@set/ag=%time:~,2%%%20/6
@for %%a in (Zzz.0 "Good morning.1" "Good afternoon.2" "Good evening.3") do @if %%~xa==.%g% echo %%~na
\$\endgroup\$
1
\$\begingroup\$

C# (.NET Core), 177 bytes

using System;namespace a{class b{static void Main(string[] a){Console.WriteLine(new String[]{"Zzz","Good morning","Good afternoon","Good evening"}[DateTime.Now.Hour%20/6|0]);}}}

Try it online!

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

Japt, 52 bytes

`Zzz,Good ¶rÍÁ,Good af’rÍ9,Good evÀxg`q, gKd %20/6|0

Try it online!

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

C# (Visual C# Interactive Compiler), 91 bytes

Write("Zzz,Good morning,Good afternoon,Good evening".Split(',')[DateTime.UtcNow.Hour%20/6])

Try it online!

Uses Utc Now to get the UTC time.

If it can be a function instead of a full program:

C# (Visual C# Interactive Compiler), 88 bytes

()=>"Zzz,Good morning,Good afternoon,Good evening".Split(',')[DateTime.UtcNow.Hour%20/6]

Try it online!

Test with all the hours(code stolen shamelessly from Arnauld)

\$\endgroup\$
  • \$\begingroup\$ This is pretty good! Although you probably should use DateTime.UtcNow to get the correct timezone. \$\endgroup\$ – dana Dec 29 '18 at 1:51
  • \$\begingroup\$ You could remove the trailing semicolon (;) character though! \$\endgroup\$ – dana Dec 29 '18 at 1:58
  • \$\begingroup\$ The semicolon totally slipped by me. Thanks! \$\endgroup\$ – Embodiment of Ignorance Dec 29 '18 at 16:20
0
\$\begingroup\$

05AB1E, 45 42 bytes

ža7*20%7%2÷U”‚¿”Xi'•´ëX<i'¯âë'žÖ]ðýX>i…Zzz

(h*7%20%7)//2 ported from @Arnauld's JavaScript (ES6) answer.

Try it online or verify all hours.


Original 45 bytes answer:

žaDV6÷U”‚¿”Xi'•´ëX<i'¯âë'žÖ]ðýX3%>iY2÷9Êi…Zzz

Try it online or verify all hours.

Explanation:

ža                 # Get the current hours
  DV               # Duplicate it, and store it in variable `Y`
    6÷U            # Integer-divide it by 6, and store it in variable `X`
”‚¿”               # String "Good"
    Xi             # If `X` is 1:
      '•´          #  Use string 'morning'
    ëX<i           # Else-if `X` is 2:
        '¯â        #  Use string 'afternoon'
    ë              # Else:
     'žÖ           #  Use string 'evening'
           ]       # Close all if-elses
            ðý     # Join the two string literals with a space
X3%>i              # If `X` modulo-3 is 0:
     Y2÷9Êi        # And if `Y` integer-divided by 2 is not 9:
           …Zzz    #  Output string "Zzz" instead
                   # (Implicit else:
                   #   output top of stack, which is the "Good ...")

See the explanation here to understand why ”‚¿” is "Good"; '•´ is "morning"; '¯â is "afternoon"; and 'žÖ is "evening".

\$\endgroup\$
0
\$\begingroup\$

Noether, 106 bytes

"Good "~g{2D~d5>d12<&}{g"morning"+P}d{11>d18<&}{g"afternoon"+P}d{17>d20<&}{g"evening"+P}d{20>d6<&}{"Zzz"P}

Try it online!

The command 2D returns the hour part of the current the time and the rest is a load of if statements.

\$\endgroup\$
0
\$\begingroup\$

Haskell, 174 bytes

import Data.UnixTime
v h|h<10="Zzz"|1>0="Good "++y h
y h|h<16="morning"|h<22="afternoon"|1>0="evening"
main=do;t<-getUnixTime;print$v$mod(div(read.show.utSeconds$t)3600+4)24
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 127 bytes

The only really sneaky trick is coercing the hours into unsigned int so that I can force the night values to >14. As the struct tm structure only has integers, I can pretend that it's an array being passed from gmtime_r.

char*s[]={"morning","afternoon","evening"};t,u[9];f(){t=time(0);gmtime_r(&t,u);printf(u[2]-6U>13?"Zzz":"Good %s",s[u[2]/6-1]);}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Suggest (char*[]){"morning","afternoon","evening"} instead of s \$\endgroup\$ – ceilingcat Sep 6 '18 at 18:38
0
\$\begingroup\$

J, 65 bytes

Another port of TFeld's answer.

('Zzz','Good '&,&>;:'morning afternoon evening'){~<.6%~20|3{6!:0''
  • 3{6!:0'' gets the hour, which is index 3 of the current time vector, from the builtin 6!:0''
  • <.6%~20| is floor of ((hour mod 20) divided by 6)
  • use that as an index {~ into a 4x14 character array containing the greetings.
  • save a few chars by concatenating (,) the string Good to the words morning, afternoon, and evening which are split on whitespace by the J "words" tokenizer (;:). It technically is for tokenizing J sentences, but since J has bare words it ends up splitting on whitespace.
\$\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.