14
\$\begingroup\$

I have a colleague at work that works from home every Tuesday and Thursday. At around 8:00 AM he sends us a message with the following text:

Hello today I'm working from home

In order to relieve him from the burden of doing this every day he stays at home, we would like to automate this task for him.

The challenge

Write in as few bytes as possible a piece of code that:

  • Receives the current time: your code may receive values for the current year, month (1-12), day of month (1-31), hour (0-23) and minute (0-59) and the day of the week (you can choose whether this number starts from 0 or 1, and if 0/1 means Sunday, Monday or any other day); alternatively you may receive a structure such as Date, DateTime, Calendar or any other time-related structure, if your language allows it. You can also receive a string with the date in yyyyMMddHHmm if you want, or two separate strings for date and time, and then an integer with the day of week. Feel free.
  • Returns two consistent truthy and falsey values, indicating if the message must be sent to the work chat or not.

Rules

  • This piece of code is assumed to be invoked periodically. The exact periodicity is irrelevant, nonetheless.
  • The truthy value must be returned if the day of week is Tuesday or Thursday and the time is 8:00 AM with an error margin of 10 minutes (from 7:50 to 8:10 inclusive).
  • The truthy value must be sent only if it is the first time the code is invoked between those hours for the specified day. We don't want the bot to send the same message several times in a row. The way you manage this restriction will be entirely up to you.
  • Your code may be an independent program executed repeatedly or it may be part of a bigger code that is always running. Your choice.
  • You may assume that there will be no reboots between executions of the code.
  • You may assume that the date will always be correct.
  • Explanations about your code and specifically about the method used to achieve persistence are encouraged.

Examples

(Week starts on Monday: 1, the following invokations will be made in succession)
2018,08,27,08,00,1 = falsey (not Tuesday or Thursday)
2018,08,28,07,45,2 = falsey (out of hours)
2018,08,28,07,55,2 = truthy (first time invoked this day at the proper hours)
2018,08,28,08,05,2 = falsey (second time invoked this day at the proper hours)
2018,08,28,08,15,2 = falsey (out of hours)
2018,08,29,08,00,3 = falsey (not Tuesday or Thursday)
2018,08,29,18,00,3 = falsey (not Tuesday or Thursday)
2018,08,30,07,49,4 = falsey (out of hours)
2018,08,30,07,50,4 = truthy (first time invoked this day at the proper hours)
2018,08,30,07,50,4 = falsey (second time invoked this day at the proper hours)
2018,08,30,08,10,4 = falsey (third time invoked this day at the proper hours)
2018,08,30,08,11,4 = falsey (out of hours)
2018,09,04,08,10,2 = truthy (first time invoked this day at the proper hours)

This is , so may the shortest code for each language win!

\$\endgroup\$
12
  • \$\begingroup\$ This comes from the sandbox. \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 13:59
  • \$\begingroup\$ Is there any restriction in the input format? Can I take the date as a single parameter like YYYYmmdd and the time as well HHss? \$\endgroup\$ Aug 28, 2018 at 14:13
  • 1
    \$\begingroup\$ @LuisfelipeDejesusMunoz yes, if you want you may receive the date and time in that format. I have updated the question to make that clear. \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 14:17
  • 1
    \$\begingroup\$ @KamilDrakari the program must check the date given as parameter, you cannot take the current date. If you do so it will be impossible to make the code pass a test battery like the one I propose in the question. \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 16:07
  • 2
    \$\begingroup\$ So, you're polling a script regularly to be useful at most once a day, 2/7th of the days? If you automate all your tasks like that... \$\endgroup\$
    – Mast
    Aug 28, 2018 at 18:23

11 Answers 11

15
\$\begingroup\$

JavaScript (ES6), 43 bytes

f=(D,t,d)=>5>>d&t>749&t<811&&!f[D]*(f[D]=1)

Try it online!

Input

  • the date as a string in yyyymmdd format
  • the time as a string in hhmm format
  • the day of week as a 0-indexed integer, with 0 = Tuesday, 1 = Wednesday, ..., 6 = Monday

Output

Returns 0 or 1.

Commented

f = (            // named function, as the underlying object will be used as storage
  D,             // D = date (string)
  t,             // t = time (string)
  d              // d = day of week (integer)
) =>             //
  5              // 5 is 0000101 in binary, where 1's are set for Tuesday and Thursday
  >> d &         // test the relevant bit for the requested day of week
  t > 749 &      // test whether we are in the correct time slot
  t < 811        //
  && !f[D] *     // make sure that this date was not already invoked at a correct time
  (f[D] = 1)     // and store it in the underlying object of f()
\$\endgroup\$
3
  • 7
    \$\begingroup\$ Javascript (and your mastery of it) will always amaze me. \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 14:31
  • 1
    \$\begingroup\$ ES6 is fun to golf with :) Is the 2nd input format valid? \$\endgroup\$
    – Arnauld
    Aug 28, 2018 at 14:36
  • \$\begingroup\$ Yes, I already specified that in the text of the question. \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 14:37
5
\$\begingroup\$

Python 3, 69 bytes

f=lambda w,r,*t,l={0}:r not in l!=w in(2,4)<(7,49)<t<(8,11)!=l.add(r)

Try it online!

Takes input as f(day of the week, date, hours, minutes), where date can be in any consistent format.

\$\endgroup\$
5
\$\begingroup\$

APL (Dyalog Unicode), 61 53 50 48 37 36 bytesSBCS

Anonymous infix lambda. Called with YYYYMMDD f hhmm and then prompts for weekday number; 2 and 4 are Tuesday and Thursday. Redefines the global D to remember dates.

D←⍬
{≢D,←⍺/⍨(⎕∊2 4)∧(⍺∊D)<30≥|780-⍵}

Try it online!

D←⍬ initialise D to be an empty set

{} anonymous lambda; is YYYYMMDD, is hhmm
780-⍵ difference between 780 (mean of 0750 and 0810) and the time
| absolute value of that
30≥ is 30 greater or equal to that?
()< and it is not true that:
  ⍺∊D the date is a member of D
()∧ and it is true that:
  ⎕∊2 4 the prompted for weekday is a member of the set {2,4}
⍺/⍨ use that to compress the date (i.e. gives {} if false, {date} if true)
D,← append that to D
 and return its tally (i.e. 0 or 1, which are APL's false and true)

\$\endgroup\$
4
\$\begingroup\$

Excel formula, 85 bytes

=IF(AND(MID(WEEKDAY(A1)/0,684;3;1)="3";A1-INT(A1)>=0,32638;A1-INT(A1)<=0,34028);TRUE)

Weekday with no parameters are from 1 (Sunday) to 7 (Saturday). The days we want are 3 and 5. Dividing all numbers from 1 to 7 for 0,648, only 3 and 5 gives a result where the first decimal is 3 (Got it by dividing with rand())

Input is inserted on Cell A1

\$\endgroup\$
1
  • \$\begingroup\$ You could use MID(WEEKDAY(A1)/0,29;5;1)="4" and also ;1;) instead of ;TRUE) \$\endgroup\$
    – adebunk
    Aug 28, 2018 at 21:01
4
\$\begingroup\$

Clean, 343 326 303 279 216 bytes

Clean is so ill-suited to this it's like trying to paint a fence with a chainsaw.

import StdEnv,System.Environment,System._Unsafe
?(y,x,z)=y*480+x*40+z
$y h m d=(d-3)^2==1&&((h-8)*60+m)^2<121&&appUnsafe(setEnvironmentVariable"l"(fromInt(?y)))(maybe 0toInt(accUnsafe(getEnvironmentVariable"l")))< ?y

Try it online!

Golfing then explaination.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1 Just for the painting a fence with a chainsaw reference! :D \$\endgroup\$ Sep 27, 2018 at 18:44
4
\$\begingroup\$

R, 114 106 bytes

function(D,y=D:"%D",u=D$h==7&D$mi>49|D$h==8&D$mi<11&D$w%in%2^4&!y%in%L,`:`=format,`^`=c){L<<-L^y[u];u}
L=F

Try it online!

Persistence:

Date is checked against L, the list of dates where the code returned TRUE. When the code returns TRUE, today's date is appended to this list. Otherwise the list is not modified.

Saved 6 bytes thanks to @Giuseppe!

Made the code actually work and saved 2 bytes thanks to @digEmAll!

\$\endgroup\$
7
  • \$\begingroup\$ This method takes the current time instead of receiving it as a parameter, doesn't it? \$\endgroup\$
    – Charlie
    Aug 28, 2018 at 15:25
  • \$\begingroup\$ @Charlie looks I I should have read the challenge more carefully... would have made my life easier ! I will update. \$\endgroup\$
    – JayCe
    Aug 28, 2018 at 15:27
  • \$\begingroup\$ ^ has higher precedence than %any% but * has lower precedence than %any%, so using ^ you can get rid of some parentheses, and I golfed a few more down, too! Pretty sure it works for 108 bytes \$\endgroup\$
    – Giuseppe
    Aug 28, 2018 at 15:41
  • 1
    \$\begingroup\$ You could also use : instead of ^, for the fun of it, and so your code has a million : in it. \$\endgroup\$
    – Giuseppe
    Aug 28, 2018 at 15:41
  • \$\begingroup\$ @Giuseppe It does have a ton of : now! \$\endgroup\$
    – JayCe
    Aug 28, 2018 at 16:23
2
\$\begingroup\$

Batch, 109 bytes

@if %3 neq 2 if %3 neq 4 exit/b1
@if %2 geq 07:50 if %2 leq 08:10 if .%1 neq .%l% set l=%1&exit/b0
@exit/b1

Takes input in the form date time dow e.g. 2018-09-04 08:10 2 and outputs via exit code. Explanation: The environment variable l (or any other single letter would work) is used to store the last successful date that passes the test. (The date format itself does not matter as long as it is consistent and does not contain spaces.)

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

Perl 6, 33 bytes

{811>$^t>749>5+>$^w%2>(%){$^d}++}

Try it online!

Heavily inspired by Arnauld's solution. Uses the same input format.

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

C (gcc),  78   50  49 bytes

D;f(d,w,t){w=d-D&&w<4&&w%2&&t>749&&t<811&&(D=d);}

Try it online!

The expected inputs are:

  • d: the date, as a single number yyyymmdd
  • w: the day of the week, starting with Monday (0)
  • t: the time, as a single number hhmm

Explanation

D;                                      // the date we last said hello.
f(d,                                    // date
    w,                                  // day of the week
      t)                                // time
{
  w=                                    // replaces return
    d-D                                 // if we did not say hello today
       &&w<4&&w%2                       // and we are Tuesday(1) or Thursday(3)
                 &&t>749&&t<811         // and time is between 7:50 and 8:10, inclusive
                               &&(D=d); // then we say hello (evaluated to true) and update D
}

Edits

  • Saved 28 bytes thanks to Adám
  • Saved 1 more byte, since abs() was actually not helping with the new version
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Why not take YYYYMMDD and hhmm as single numbers? \$\endgroup\$
    – Adám
    Aug 28, 2018 at 15:51
  • \$\begingroup\$ @Adám Indeed... I'll try that when I have some time \$\endgroup\$
    – Annyo
    Aug 30, 2018 at 6:27
  • \$\begingroup\$ Suggest w<4&w%2&t>749&t<811 instead of w<4&&w%2&&t>749&&t<811 \$\endgroup\$
    – ceilingcat
    Sep 22, 2018 at 9:59
1
\$\begingroup\$

C#, 121 Bytes

int[] d=new int[]{2,4};
double s=>Now.TimeOfDay.TotalSeconds;
bool h=>d.Contains((int)Now.DayOfWeek)&&s>=470&&s<=490;

Moving all three to the same line reduces size to 117 bytes. h is used as a property, just read the value prior to sending the message:

if (h) SendMessage();
\$\endgroup\$
1
\$\begingroup\$

F#, 119 bytes

let f w d h m l = if not(l|>Seq.contains d)&&[3;5]|>Seq.contains w&&(h=7&&m>49||h=8&&m<11)then(l@[d],true)else(l,false)

let f w d h m l =

declare function called f with parameters w (day of week) d (date) h (hour) m (minute) l (list of dates it's run on)

if not(l|>Seq.contains d) if the list of dates doesn't contain the passed date

&&[3;5]|>Seq.contains w and the day is Tuesday (3) or Wednesday (5)

&&(h=7&&m>49||h=8&&m<11) and the time is between (exclusive) 7:49 and 8:11

then(l@[d],true) then return a tuple containing the list of dates with the current date appended, and true

else(l,false) else return a tuple containing the list of dates without today and false

\$\endgroup\$

Your Answer

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

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