19
\$\begingroup\$

In this challenge you will need to determine whether it's Pi Day, Pi Minute, or Pi Second.

Because Pi is irrational, it wants your code to be as short as possible.

Examples

No input is provided, your program should use the system time. I've just added it for clarity

March 14, 2016 0:00:00
Pi Day
December 25, 2015 3:14:45
Pi Minute
December 29, 2015 0:03:14
Pi Second
January 1, 2016 0:00:00
<No Output>

What is Pi Day / Minute / Second

  • Pi Day is when the month is March, and the date is the 14th
  • Pi Minute is when the hour is 3, and the minute is 14
  • Pi Second is when the minute is 3, and the second is 14
  • Pi Day should be preferred instead of Pi Minute or Pi Second, and Pi Minute should be preferred instead of Pi Second.
  • For this challenge you should use 12-hour time (15:14 == 3:14). The date/time used to determine the Pi Day/Minute/Second should be based on system time.

Scoring & Bonus

-15 byte Bonus: If you print "No Pi Time" when it's not Pi time.


As always, standard loopholes are disallowed. This is shortest code in bytes wins!

\$\endgroup\$
14
  • 7
    \$\begingroup\$ I don't think Costco allows you to purchase the mathematical constant pi at any time of the year. \$\endgroup\$
    – Alex A.
    Jan 2, 2016 at 1:35
  • 2
    \$\begingroup\$ You've changed it to regular pie. That's also false because you can get pie from Costco all year. \$\endgroup\$
    – Alex A.
    Jan 2, 2016 at 1:39
  • 1
    \$\begingroup\$ @AlexA. Hmm, weird I can never find it in the summer... \$\endgroup\$
    – Downgoat
    Jan 2, 2016 at 1:40
  • 9
    \$\begingroup\$ I went to Costco today - they were closed. \$\endgroup\$ Jan 2, 2016 at 5:18
  • 2
    \$\begingroup\$ @immibis Or March 14 1592 6:53:58? \$\endgroup\$
    – wizzwizz4
    Jan 3, 2016 at 9:11

17 Answers 17

8
\$\begingroup\$

Javascript (ES6), 114 112 - 15 = 97 bytes

x=>['Pi Day','Pi Minute','Pi Second'].find((x,i)=>[/ar 14/,/(03|15):14:/,/03:14/][i].test(Date()))||'No Pi Time'

Ungolfed:

x=>
['Pi Day', 'Pi Minute', 'Pi Second']  // array of outputs
.find(                                // find first element in the array
    (x, i)=>                          // which returns truthy for this function
    [/ar 14/, /(03|15):14:/, /03:14/] // array of regex patterns
    [i]                               // get corresponding regex based on index
    .test(Date())                     // test it against current date, date is automatically cast to string
) || 'No Pi Time'                     // if no result, then return "No Pi Time"

Thanks for -2 bytes @edc65

\$\endgroup\$
6
  • \$\begingroup\$ Could be Date() instead of new Date \$\endgroup\$
    – edc65
    Jan 2, 2016 at 10:56
  • \$\begingroup\$ 'Pi '+['Day','Minute','Second'].find((x,i)=>................ \$\endgroup\$
    – wizzwizz4
    Jan 3, 2016 at 9:13
  • \$\begingroup\$ @wizzwizz4 this won't work. If it's not Pi time, it returns "Pi undefined" \$\endgroup\$
    – nderscore
    Jan 3, 2016 at 17:04
  • \$\begingroup\$ Would a check for undefined be shorter than 6 chars? \$\endgroup\$
    – wizzwizz4
    Jan 3, 2016 at 17:39
  • 1
    \$\begingroup\$ @nderscore It's fewer bytes to say nderscore than underscore. \$\endgroup\$
    – wizzwizz4
    Jan 3, 2016 at 18:26
5
\$\begingroup\$

Ruby, 125 124 chars

i=[*[(t=Time.new).month,t.day,t.hour,t.min,t.sec].each_cons(2)].index [3,14];i&&$><<['Pi Day','','Pi Minute','Pi Second'][i]

Alas, the cleverer %i[month day hour min sec].map{|x|Time.new.send x} is longer.

The key here is the use of each_cons to avoid repetition (see the last few lines of the explanation below).

i=                          # send i (index) to...
[*                          # convert to array (splat)...
 [
  (t=Time.new).month,       # the current month...
  t.day,t.hour,t.min,t.sec  # etc... (duh)
 ]
 .each_cons(2)              # each consecutive two elements
]                           # [[month, day], [day, hour], [hour, min], etc]
.index [3,14];              # first occurrence of [3, 14]
i&&                         # shorthand for "if i"...
$><<                        # output...
[
 'Pi Day',                  # [month=3, day=14] is Pi Day
 '',                        # [day=3, hour=14] isn't anything
 'Pi Minute',               # [hour=3, min=14] is Pi Minute
 'Pi Second'                # [min=3, sec=14] is Pi Second
][i]                        # index by index (obviously)
\$\endgroup\$
3
  • \$\begingroup\$ @Cole And what will you do with the second element? \$\endgroup\$
    – nicael
    Jan 2, 2016 at 14:21
  • \$\begingroup\$ Why isn't Pi Hour anything. What's wrong with 2 in the afternoon, tomorrow? \$\endgroup\$
    – Mr Lister
    Jan 2, 2016 at 14:31
  • \$\begingroup\$ @ColeJohnson No, [(p='Pi ')+Day','',p+'Minute',p+'Second'] is longer. \$\endgroup\$
    – Doorknob
    Jan 2, 2016 at 16:17
4
\$\begingroup\$

CJam, 41 bytes

et[3E]#"
Pi Day

Pi Minute
Pi Second
"N/=

Test it here. Alternatively use this link to stub the result of et for easier testing.

Explanation

et   e# Get the current datetime as an array with the following elements:
     e#   - Year
     e#   - Month
     e#   - Day
     e#   - Hour
     e#   - Minute
     e#   - Second
     e#   - Millisecond
     e#   - Weekday
     e#   - Tickrate or something.
[3E] e# Push the array [3 14].
#    e# Find the position of this subarray in the current datetime array. Let's see
     e# what results we can get:
     e#   - Year 3 is in the past and there is no 14th month, so we can't get 0.
     e#   - Pi day will give result 1.
     e#   - Day 3, hour 14 would give 2.
     e#   - Pi minute will give result 3.
     e#   - Pi second will give result 4.
     e#   - Second 3, millisecond 14 would give 5.
     e#   - Weekday and tickrate won't be 14, so we'll never get 6 or 7.
     e#   - If [3 14] isn't found at all we get -1.
"\Pi Day\\Pi Minute\Pi Second\"
     e# Push this string (with linefeeds instead of backslashes.
N/   e# Split into lines.
=    e# Select the corresponding element. The non-existent "pi hour" and "pi millisecond"
     e# would map to empty strings as well as the -1.
\$\endgroup\$
4
\$\begingroup\$

Python 2, 219 186 183 Bytes (198-15)

I tried

Ungolfed:

from datetime import datetime

now = datetime.now()
output = ['Pi Day', 'Pi Minute', 'Pi Second', 'No Pi Time']

if now.month == 3 and now.day == 14:
    print output[0]
elif now.hour == 2 and now.minute == 13:
    print output[1]
elif now.minute = 2 and now.second == 13:
    print output[2]
else:
    print output[3]

Golfed:

from datetime import *
n=datetime.now()
a=n.minute
if n.month==3and n.day==14:print'Pi Day'
elif n.hour==2and a==13:print'Pi Minute'
elif a==2and n.second==13:print'Pi Second'
else:print'No Pi Time'
\$\endgroup\$
5
  • 4
    \$\begingroup\$ from datetime import*;n=datetime.now() is shorter. Also, there's no point in indexing into an array when you're printing constant strings. \$\endgroup\$
    – Doorknob
    Jan 2, 2016 at 1:29
  • \$\begingroup\$ @Doorknob冰 That's true :) \$\endgroup\$
    – Zizouz212
    Jan 2, 2016 at 1:36
  • \$\begingroup\$ Shorter even: paste.ee/p/ebcSh \$\endgroup\$
    – Riker
    Jan 2, 2016 at 1:40
  • \$\begingroup\$ Made by swapping if/elses with [else,if][statement]. \$\endgroup\$
    – Riker
    Jan 2, 2016 at 1:41
  • 1
    \$\begingroup\$ The latter numbers are wrong (2:13 instead of 3:14), and the 12-hour clock requirement isn't met. (Seems to apply to some other answers too) You can also get it shorter by indexing the result of time.localtime(); it comes down to 148-15 bytes (without the 12-hour fix). The 12-hour thing is unfortunate though; without it you could easily get it down to 129-15 bytes: import time;x=3,14;T=time.localtime();print{1:'Pi Day',3:'Pi Minute',4:'Pi Second'}.get((zip(T,T[1:])+[x]).index(x),'No Pi Time') (and 118-15 bytes on Python 3, by converting to bytes and using find, which makes things simpler) \$\endgroup\$ Jan 2, 2016 at 3:49
4
\$\begingroup\$

Japt, 78 - 15 = 63 bytes

D=Ð)g ¥3©Df ¥E?"Pi Day":Dd %C¥3©Dc ¥E?`Pi M©e`:Dc ¥3©Db ¥E?`Pi SeÖ:No Pi Te

Pretty straightforward - just checks the date for every case.

Explanation:

  • D=Ð)g get the current date (Ð), store it in the variable D and get the month (g). Why store it in the variable, if it's already one-letter? Because since then you can dress any part of date with Da, where a is the function, returning year, month, date, etc. But otherwise you'd have to do Ð a, see the space.

  • ¥3 is ==3, checking if the month is March.

  • © is &&, i.e. "and".
  • Df is the day of the month.
  • E is 14
  • ?...:... - typical sets of ternary operators
  • Dd %C the reminder of dividing the hour (Dd) by 12 (C)
  • Dc is the minutes
  • Db are seconds

Try it online!


To emulate Pi Day:

D=Ð"3/14/11 11:11:11";
Dg ¥2©Df ¥E?"Pi Day":Dd %C¥3©Dc ¥E?`Pi M©e`:Dc ¥3©Db ¥E?`Pi SeÖ:No Pi Te

To emulate Pi Minute:

D=Ð"11/11/11 3:14:11";
Dg ¥2©Df ¥E?"Pi Day":Dd %C¥3©Dc ¥E?`Pi M©e`:Dc ¥3©Db ¥E?`Pi SeÖ:No Pi Te

To emulate Pi Second:

D=Ð"11/11/11 00:3:14";
Dg ¥2©Df ¥E?"Pi Day":Dd %C¥3©Dc ¥E?`Pi M©e`:Dc ¥3©Db ¥E?`Pi SeÖ:No Pi Te
\$\endgroup\$
0
3
\$\begingroup\$

TI-BASIC, 124 bytes

Thanks to FlagAsSpam for shaving a few bytes.

"→Str1
getTime
If min({3,14}={Ans(2),Ans(3
"Pi Second→Str1
getTime
If Ans(2)=14 and max(Ans(1)={3,14
"Pi Minute→Str1
getDate
If min({3,14}={Ans(2),Ans(3)
"Pi Day→Str1
Str1
\$\endgroup\$
6
  • \$\begingroup\$ Are you using i (imaginary unit) and e (Euler's constant) as shortcuts? If not, that could also save you some bytes. \$\endgroup\$ Jan 2, 2016 at 19:30
  • \$\begingroup\$ @FlagAsSpam I thought about using those, but I wasn't sure if it counts. \$\endgroup\$ Jan 2, 2016 at 19:39
  • \$\begingroup\$ @FlagAsSpam Whether or not they're valid here, e is actually two bytes! \$\endgroup\$
    – lirtosiast
    Jan 2, 2016 at 21:37
  • \$\begingroup\$ @ThomasKwa Oh, right. \$\endgroup\$ Jan 2, 2016 at 21:39
  • \$\begingroup\$ @FlagAsSpam It is no longer invalid. ^_^ \$\endgroup\$ Jan 2, 2016 at 23:26
3
\$\begingroup\$

Perl, 80 - 15 = 65 bytes

print'No 'x localtime!~/(ar | 15:|03:)14/,'Pi ',(Time,Day,Minute,Second)["@-"/4]

Take 2, parsing the string representation of localtime. At present, this looks something like this:

Sun Jan  3 15:14:15 2016

The position of the matched string is used to determine the correct Pi Time.


Perl, 100 bytes

@t=localtime;$t[2]%=12;3-/3/^{@t[$_,$_+1]}->{14}||exit!print'Pi ',(Second,Minute,_,Day)[$_]for 3,1,0

localtime returns the months zero indexed, hence the need for 3-/3/.

\$\endgroup\$
3
\$\begingroup\$

05AB1e, score: 31 (46 bytes - 15 bonus)

žfžeža12%žbDžc)2ôJƵÖk”€º‚Ž™Ù…Þ”#…Pi ìć…No ìªsè

Try it online or try it online with emulated datetime.

Adding the No Pi Time bonus costed 8 bytes, so it's worth the -15. Here it is without the bonus:
žfžeža12%žbDžc)2ôJƵÖk”‚Ž™Ù…Þ ”#„Pirèðý - Try it online or try it online with emulated datetime.

Explanation:

žf               # Push the current month
  že             # Push the current day
ža               # Push the current hours (24-hours format)
  12%            # Modulo-12 to make it a 12-hours format
     žb          # Push the current minutes
D                # Duplicate the current minutes
 žc              # Push the current seconds
)                # Wrap all values on the stack into a list
 2ô              # Split it into pairs
   J             # Join each pair together
    ƵÖ           # Push compressed integer 314
      k          # Get the first 0-based index of 314 in this list (or -1 if none are)
”€º‚Ž™Ù…Þ”       # Push dictionary string "Time Day Minute Second"
          #      # Split it on spaces: ["Time","Day","Minute","Second"]
           …Pi ì # Prepend "Pi " in front of each:
                 #  ["Pi Time","Pi Day","Pi Minute","Pi Second"]
ć                # Extract head; pop and push remainder-list and first item separately
 …No ì           # Prepend "No " in front of it: "No Pi Time"
      ª          # Append it to the remainder-list:
                 #  ["Pi Day","Pi Minute","Pi Second","No Pi Time"]
s                # Swap so the earlier index of 314 is at the top
 è               # Use it to index into the list of strings,
                 # where -1 would get the last item
                 # (after which the result is output implicitly)

See this 05AB1E tip of mine (sections How to use the dictionary? and How to compress large integers?) to understand why ”€º‚Ž™Ù…Þ” is "Time Day Minute Second" and ƵÖ is 314.

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

Python 3, 137 - 15 = 122 bytes

import time
T=list(time.localtime())
T[3]%=12
print({1:'Pi Day',3:'Pi Minute',4:'Pi Second'}.get(bytes(T[1:6]).find(b'\x03\x0e'),'No Pi Time'))

The 12-hour requirement was unfortunate, as this would've been 118-15=103 bytes without it:

import time
print({1:'Pi Day',3:'Pi Minute',4:'Pi Second'}.get(bytes(time.localtime()[1:6]).find(b'\x03\x0e'),'No Pi Time'))
\$\endgroup\$
2
\$\begingroup\$

AppleScript, 202 190 187 183 181 bytes

Hey, this isn't so bad after all.

set n to current date
set b to n's time string
if n's date string contains"March 14"
log"Pi Day"
else if b contains"3:14:"
log"Pi Minute"
else if b contains"3:14"
log"Pi Second"
end

I actually found a use for AppleScript's method calling. Go figure. Nope. Just turns out that I'm an idiot. Setting a variable is shorter.

(for those wondering, current date command returns a date-type with the contents "Saturday, January 2, 2016 at 2:46:01 PM" or the like)

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

PHP, 85 - 15 = 70 bytes

<?=['No Pi Time','Pi Day','Pi Minute','Pi Second'][strpos(@date(Ymdhi_is),'0314')/4];

The main trick use here is the Ymdhi_is date format, at the time of writing, date('Ymdhi_is') returns 201501030258_5828.

  • md, hi and is are the values who will be replaced by 0314 if it's Pi-something. Note that all those strings will be always be replaced by a 4-character long string.
  • They are put in that specific order since strpos will stop searching at the first occurrence of the needle, so we put them in the order of priority.
  • A separator between hi and is is necessary because we don't want strpos to match a value that would overlap both (thanks to primo for saving bytes here).
  • The needle is 0314 because 314 would wrongly match 10:31:42 as Pi-Second.

The Y part is the trickiest. We need a prefix to to offset the first occurrence of Pi-something, allowing us to distinguish strpos's return values between false (not found, Pi-nothing) and 0 (found at index 0, Pi-day).

And we want this prefix to be either 4 or 5-character long, since we are planning to divide strpos's return value by 4.

Y is 4-character long, but:

  • it will be 5-character long someday, and this will break the program (think about year 10314): the PHP documentation says that Y will be replaced by 4 digits, but it's not true.
  • if you come back in time, at year 314, it will break the program.

Since PHP didn't exist in year 314, and will likely not exist anymore in year 10314, I guess these bugs can be safely ignored.

Note that 0314 can overlap Ymd since:

  • Ymmd configuration: there's no 31st month.
  • YYmm configuration: there's no 14th month.
  • YYYm configuration: there are less than 40 months.

Also, there's a version without the bugs related to the year, which is 86 - 15 = 71 bytes:

<?=['No Pi Time','Pi Day','Pi Minute','Pi Second'][strpos(@date(D_mdhi_is),'0314')/4];
\$\endgroup\$
1
  • \$\begingroup\$ Great answer. If you use underscores rather than dots, you can drop the quotes around Ymd_hi_is. Also, I don't think a separator is necessary between md and hi, as the 12-hour h can never be 14, and never start with 3 or 4. \$\endgroup\$
    – primo
    Jan 3, 2016 at 7:02
1
\$\begingroup\$

Go, 211 - 15 = 196 bytes

import."time"
func f(){N,s:=Now(),"Pi "
M:=N.Minute()
if _,m,d:=N.Date();m==3&&d==14{s+="Day"}else if N.Hour()%12==3&&M==14{s+="Minute"}else if M==3&&N.Second()==14{s+="Second"}else{s="No "+s+"Time"}
println(s)}

Attempt This Online!

Prints to STDERR.

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

Japt, 48 47 45 bytes

:\ I can definitely do better than this! Outputs undefined if it's not a Pi date/time. Second line include a trailing space.

`DÃÕsMÔSSeÖ`qÅæÏgKs6 f"%d+" ã2)e#;ìF
©i"Pi 

Test it, or test:

`...`qÅæÏgKs6 f"%d+" ã2)e#;ìF\n©i"Pi 
`...`                                     :Compressed string "DaysssMinutesSecond"
     q                                    :Split on
      Å                                   :  "s"
       æ                                  :Get first element to return true
        Ï                                 :When its index is passed through the following function
         g                                :  Index into
          K                               :    Date
           s6                             :    To locale string (M/D/Y, h:m:s A/PM)
              f                           :    Match
               "%d+"                      :      RegEx /\d+/
                     ã2                   :    Sub-arrays of length 2
                       )                  :  End indexing
                        e                 :  Is equal to
                         #;               :    59
                           ì              :    Converted to digit array in base
                            F             :      15
                             \n           :Assign to variable U
                               ©          :Logical AND with
                                i"Pi      :  U prepended with "Pi "
\$\endgroup\$
1
\$\begingroup\$

Pascal (FPC), 263 bytes

uses sysutils,RegExpr;var x:array[0..2]of string=('.*:03:14','.* 03:14.*','14-3.*');y:array[0..2]of string=('Second','Minute','Day');p:string;i:word;begin
for i:=0to 2do if ExecRegExpr(x[i],DateTimeToStr(Now))then p:=y[i];if length(p)>0 then writeln('Pi ',p);end.

Try it online!

Might be shortened by using if..then..elseif.. instead of complicated arrays & loops.

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

Pascal, 226 Bytes

See also FreePascal. This program requires a processor complying to ISO standard 10206 “Extended Pascal”.

program p(output);var t:timeStamp;begin getTimeStamp(t);with t do write(subStr('Pi Day   ',1,9*ord(month=3))+subStr('Pi Minute',1,9*ord(hour in[3,15]))+subStr('Pi Second',1,9*ord(minute=3)):9*ord(14 in[day,minute,second]))end.

Ungolfed:

program piDMS(output);
    var
        ts: timeStamp;
    begin
        getTimeStamp(ts);
        { `with t do ` is two characters shorter than six times `t.` }
        with ts do
        begin
            writeLn(
                    { subStr(string, firstCharacterIndex, length) }
                    subStr('Pi Day   ', 1, 9 * ord(month = 3)) +
                    subStr('Pi Minute', 1, 9 * ord(hour in [3,15])) + 
                    subStr('Pi Second', 1, 9 * ord(minute = 3))
                    : 9 * ord(14 in [day, minute, second])
                );
        end;
    end.

216 characters if

  • the implementation-defined value of maxChar has an ordinal value ≥ 59 and
  • neither chr(3) or chr(14) of the implementation-defined set of char values indicate an end of line (Pascal does not permit multiline strings).
program p(output);var t:timeStamp;begin getTimeStamp(t);with t do year:=index(chr(month)+chr(day)+chr(hour mod 12)+chr(minute)+chr(second),'');write(subStr('Pi SecondPi Minute         Pi Day   ',37-9*t.year):9)end.

NB: The string literal '' is chr(3) + chr(14).

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

Python 3, 179 bytes

import functools as F,datetime as D
T,G=D.datetime.now(),getattr
F.reduce(lambda i,j:print("Pi "+i.title())if G(T,i)/G(T,j)==3/14else j,"month day hour minute second".split(" "))
\$\endgroup\$
0
\$\begingroup\$

Zsh*, 93 88 83 (98-15) bytes

case `date` in *Mar\ 14*)t=Day;;*\ 03:14*)t=Minute;;*03:14\ *)t=Second;esac
<<<Pi\ ${t?No Pi Time}

Try it online! (98-15 bytes)
 103-15 bytes  93 bytes  107-15 bytes, using associative array

Used extendedglob for matching the case patterns. If $t wasn't set (${t?}), then it prints "No Pi Time" to stderr.

\$\endgroup\$

Your Answer

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

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