5
\$\begingroup\$

I know there must be an easier way to write this but I'm stuck in over-complicating mindset instead of just following the Zen of Python. Please help me simplify this.

Given a day of the week encoded as 0=Sun, 1=Mon, 2=Tue, ...6=Sat, and a boolean indicating if we are on vacation, return a string of the form "7:00" indicating when the alarm clock should ring. Weekdays, the alarm should be "7:00" and on the weekend it should be "10:00". Unless we are on vacation -- then on weekdays it should be "10:00" and weekends it should be "off".

alarm_clock(1, False) → '7:00'
alarm_clock(5, False) → '7:00'
alarm_clock(0, False) → '10:00'
def alarm_clock(day, vacation):

    weekend = "06"
    weekdays = "12345"
    if vacation:
        if str(day) in weekend:
            return "off"
        else:
            return "10:00"
    else:
        if str(day) in weekend:
            return "10:00"
        else:
            return "7:00"
\$\endgroup\$
4
\$\begingroup\$

I don't think it can get much simpler than this (Pythonic, easy to read, performance great enough to never be a bottleneck):

def alarm_clock(day, vacation):
    weekend = int(day) in (0, 6)
    if weekend and vacation:
        return 'off'
    elif weekend or vacation:
        return '10:00'
    return '7:00'

I came up with this after creating a weekend boolean value and then checking the return values alarm_clock should have:

return_values = {
    # (weekend, vacation): Return value,
    (True, True): 'off',
    (True, False): '10:00',
    (False, True): '10:00',
    (False, False): '7:00'
}

As you can see, if both are True (if weekend and vacation:), we should return 'off', and if one of them is True (if weekend or vacation:), we should return 10:00 regardless of which one. Else return 7:00

\$\endgroup\$
  • \$\begingroup\$ I see you omitted the word "else", is that Pythonic? \$\endgroup\$ – noob81 Jul 10 '15 at 16:43
  • \$\begingroup\$ @noob81 That's everyone's personal preference, but it's often considered more pythonic to emit the "else" \$\endgroup\$ – Markus Meskanen Jul 10 '15 at 16:46
  • 1
    \$\begingroup\$ @noob81 Actually, I take that back. It's just everyone's personal preference, there's absolutely no guidelines to whether you should emit it or not. Often depends on the situation :) \$\endgroup\$ – Markus Meskanen Jul 10 '15 at 17:25
7
\$\begingroup\$
  1. You don't use weekdays.
  2. You can have two return statements. (Shown below).

This keeps the same logic, it just removes the need for so meany return statements.

def alarm_clock(day, vacation):
    weekend = "06"
    if vacation:
        return "off" if str(day) in weekend else "10:00"
    else:
        return "10:00" if str(day) in weekend else "7:00"

I would improve it further by adding a check, that you enter a number 0-6.

if not (0 <= day <= 6):
    return "-:--"
\$\endgroup\$
2
\$\begingroup\$

What about:

  1. using 10:00 as default:
  2. only check for weekend
  3. you might replace (str(day) in weekend) by (0 == day %6) but it is harder to understand

Code:

def alarm_clock(day, vacation):
    weekend = "06"
    if vacation and (str(day) in weekend):
        return "off"
    else:
        if not (str(day) in weekend):
            return "7:00"
    return "10:00"

The bit more cryptic version:

def alarm_clock(day, vacation):
    if vacation and 0 == day % 6:
        return "off"
    else:
        if 0 != day % 6:
            return "7:00"
    return "10:00"
\$\endgroup\$
  • 1
    \$\begingroup\$ if str(day) not in weekend would be the preferred construction according to PEP8. \$\endgroup\$ – Jaime Jul 10 '15 at 15:54
2
\$\begingroup\$

Building on @Joe Wallis' answer, I would shorten it as follows:

def alarm_clock(day, vacation):
    weekend = "06"

    times = {"weekend": "10:00", "weekday": "7:00"}
    if vacation:
        times = {"weekend": "off", "weekday": "10:00"}

    return times['weekend'] if str(day) in weekend else times['weekday']

Which could be further shortened to (detrimental to readability though):

def alarm_clock(day, vacation):
    times = {"weekend": "off", "weekday": "10:00"} if vacation \
            else {"weekend": "10:00", "weekday": "7:00"}

    return times['weekend'] if str(day) in "06" else times['weekday']

The advantages are that you have a dict with the weekend/weekday times, so you only need one generic return statement. The magic/hardcoded string in the further shortened version is a no-no though. Furthermore, you could extend the function to allow for custom times to be passed in, as such:

def alarm_clock(day, vacation, times={}):
    times = times.get('regular', {"weekend": "10:00", "weekday": "7:00"})
    if vacation:
        times = times.get('vacation', {"weekend": "off", "weekday": "10:00"})

    return times['weekend'] if str(day) in "06" else times['weekday']

You can then call it as such:

times = {'regular': {'weekend': "9:00", "weekday": "7:00"}, "vacation": {"weekend": "12:00", "weekday": "6:00"}}
alarm_clock(2, False, times)
\$\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.