16
\$\begingroup\$

A listening party is an event where a bunch of people get together to listen to some music (like a viewing party, but for music). In the age of the internet you can do Listening Parties online with friends, where you just all hit play together.

The problem is on the internet everyone is in different time-zones so you can't just say "Let's start at 5:35". As a solution we just type xs in the hours position. So xx:35 means whenever the minute hand is next at 35. If the minute hand is already at that value then the party happens in 1 hour. If you need to specify more than one hour ahead you can add 1+, 2+ etc. to the beginning. So 1+xx:35 is an hour after the next time the minute hand is at 35.

Your task is to take the current local time, and a string representing when the listening party happens in the above format and output when the listening party will occur in local time.

IO

You can take and output the local time either as a 24 hour string with the minutes and hours separated by a colon (e.g. 19:45), as a tuple of the minutes and hours or as some native time type when available. If you take a string you may assume a leading zero when the hour hand is a one digit number otherwise. The two should be the same format. You can take the string representing when the listening party will happen either as a native string type or as a list of chars. The string will always match the following regex:

([1-9]+\d*\+)?xx:[0-5]\d

Scoring

This is so answers will be scored in bytes with fewer being better.

Test cases

5:35 xx:45 -> 5:45
19:12 xx:11 -> 20:11
5:15 1+xx:35 -> 6:35
12:30 1+xx:15 -> 14:15
8:29 3+xx:12 -> 12:12
4:30 xx:30 -> 5:30
23:59 xx:01 -> 0:01
15:30 25+xx:12 -> 17:12
12:09 xx:08 -> 13:08
\$\endgroup\$
11
  • 1
    \$\begingroup\$ Similar question for the other input: is [1, 15] an acceptable format for 1+xx:15? \$\endgroup\$ Sep 6, 2021 at 12:47
  • 9
    \$\begingroup\$ People from, say, Eucla, Australia (UTC+8:45) are still badly out of beat with this method. :-/ \$\endgroup\$
    – Arnauld
    Sep 6, 2021 at 12:54
  • 1
    \$\begingroup\$ Huh? You are the one of the strict users who enforce loose IO rules on each question, and then doing the opposite on your own question. Why [1, 15] isn't acceptable? I don't think it trivializes the challenge so much \$\endgroup\$
    – Wasif
    Sep 6, 2021 at 14:22
  • 1
    \$\begingroup\$ I just asked why [1,15] isn't acceptable from Robin's comment. I didn't intended to be rude, I am sorry if offended you \$\endgroup\$
    – Wasif
    Sep 6, 2021 at 15:18
  • 1
    \$\begingroup\$ May I assume the UTC offset of user's timezone in hour is an integer, and no DST will start / end before the listening party starts? \$\endgroup\$
    – tsh
    Sep 7, 2021 at 1:28

14 Answers 14

5
\$\begingroup\$

Jelly, 22 20 bytes

Ṗ+<¬Ṫɗ+%"24ɓṣ”:f€ØDV

Try it online!

Takes the time as [hh, mm] on the left and the xx string on the right.

-2 bytes thanks to Lynn by a clever exploitation of Jelly's vectorising atoms!

How it works

This uses the ɓ chaining structure to group a series of links to act only on the string, then we run the main links on the result of those links and on [hh, mm]. The ɓ splits the program into two links: Ṗ+<¬Ṫɗ+%"24 and ṣ”:f€ØDV. The first one is dyadic (as two arguments are passed to the program), and the second one is dyadic but with the arguments in the opposite order as the first.

For a program that consists of two dyadic links x (f g) y, we calculate x f (x g y). Non-notationally, this means that we run the second dyad on the two arguments, returning a value z. We then run the first dyad with x on the left and z on the right. The standard way of writing this would be f ð g. Using ɓ however, we reverse the arguments to g, so f ɓ g is x f (y g x).

g is ṣ”:f€ØDV, run dyadically with the string S on the left and the time T on the right. g consists of 5 atoms: , ”:, f€, ØD, V, which can be grouped into ṣ”:, f€ØD, V, a series of dyad-nilad pairs and a monad. This means that the right argument to the link is essentially ignored, and only the left argument is modified. We could try to use a monadic link for this, but by reversing the arguments implicitly with ɓ, we can avoid any quicks to indicate that a monadic link should be run on S.

g, given S, extracts the offset and minutes from the string, returning [offset, mins] as a pair of integers. f is then run as a dyadic link, with T (the time) on the left and [offset, mins] on the right.

Lynn noticed a clever exploitation of Jelly's vectoriser that allows us to save 2 bytes here. Essentially, if we have a list and an integer, [a, b] + x will vectorise across that list, yielding [a+x, b+x], and if we have two lists [a,b,c] + [x,y], we'll get [a+x,b+y,c]. The " (vectorise) quick will take a dyad h and force this behaviour.

Therefore, if we want to apply a dyad to just the first element of a list, we can use " and turn the right argument into a singleton list. For example: [a, b] +" x ⁼ [a+x, b]. Here, we calculate whether or not the mins is already past the current minutes of T. If so, we add 1 to hours. Therefore, we remove minutes from T, yielding [hours] and add this to the comparison, to yield [hours + (mins ≥ minutes)]. We then add this to [offset, mins], to yield [hours + (mins ≥ minutes) + offset, mins]. Finally, we use " on %24 so that we only modulo the first element by 24.

How it works, in detail

Ṗ+<¬Ṫɗ+%"24ɓṣ”:f€ØDV - Main link. Takes [h, m] on the left and S on the right
           ɓṣ”:f€ØDV - Dyadic chain with S on the left, [h,m] on the right:
            ṣ”:      -   Split S on ”:
                €    -   Over each half:
               f ØD  -     Only keep digits
                   V -   Evaluate each as integers, [a, b]
Ṗ+<¬Ṫɗ+%"24ɓ         - Links to the left as a dyadic chain g([h,m], [a,b]):
Ṗ                    -   Pop; Yield [h]
     ɗ               -   Last 3 links as a dyad f([h,m], [a,b]):
  <¬                 -     [¬(h < a), ¬(m < b)]
    Ṫ                -     ¬(m < b)
 +                   -   [h + ¬(m < b)]
      +              -   [h + ¬(m < b) + a, b]
       %"24          -   [(h + ¬(m < b) + a) % 24, b]
\$\endgroup\$
2
  • 1
    \$\begingroup\$ It seems like the left half can be Ṗ+<¬Ṫɗ+%"24 to save two bytes. The idea is to make [h+¬(m<b)] (a list of length 1), then add this to [a, b], and then mod only the first element by 24. \$\endgroup\$
    – Lynn
    Sep 6, 2021 at 20:44
  • \$\begingroup\$ @Lynn Thanks, that's a clever trick with the lists + vectorisation! \$\endgroup\$ Sep 6, 2021 at 22:25
4
\$\begingroup\$

JavaScript (ES6), 52 bytes

I/O format: tuple of integers

([h,m],s)=>[([H,M]=s.split(/\D+/),h-~H-(M>m))%24,+M]

Try it online!

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

Haskell, 77 bytes

(h,m)%s|[(b,_:c)]<-reads s=(h+b,m)%c|n<-read$drop 3s=(mod(h+sum[1|m>=n])24,n)

Try it online!

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

Perl 5 (-p), 56 bytes

s/(.+):(.+) (.+\+)?xx:(.+)/(($1+$3+($4<=$2))%24).":$4"/e

Try it online!

We match the input regex and do some fun math. The minute hand of the result is always $4 (the fourth capture group). The hour hand is the initial hour hand ($1), plus the time offset ($3), plus one extra if we've already passed the minute in the current hour ($4<=$2), mod 24.

Perl's numerical coercion rules help us a lot here. $4<=$2 coerces to zero or one, which is the exact number we need to add to the hour hand. $3 is the offset value, such as 2+, which coerces to 2 under numerical coercion. If there's no offset, then $3 is undefined which conveniently coerces to zero.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ If you trust the input to be well behaved, and use $', 11 bytes can be shaved off: Try it online! \$\endgroup\$
    – Kjetil S
    Sep 7, 2021 at 11:10
4
\$\begingroup\$

Retina 0.8.2, 81 76 bytes

\d+
$*
:(1*) (1*).*:((?!1\1))?
$#3$*1$2:
+`1{24}:
:
1*
$.&
\B0\b

\b\d\b
0$&

Try it online! Link includes test cases. Edit: Saved 5 bytes thanks to @user41805. Explanation:

\d+
$*

Convert to unary.

:(1*) (1*).*:((?!1\1))?
$#3$*1$2:

Add the extra hours, plus check whether the minutes are behind and if not add another hour.

+`1{24}:
:

Reduce the hours modulo 24.

1*
$.&
\B0\b

Convert the hours and minutes to decimal. Due to the way 1* matches again at the end of a row of 1s, this actually ends up multiplying the result by 10, so the trailing 0 needs to be deleted in this case (but not in the 0 case, as that just becomes 0 as expected).

\b\d\b
0$&

Add leading zeros to single digits.

\$\endgroup\$
4
  • \$\begingroup\$ The x seems extraneous. In that regex, I think you can use (1(?!\1))? instead so that in the substitution you have $3$2:$3. To convert back to decimal, using 1* $.& seems to append a 0 to the answer, but fixing it seems to still be shorter. \$\endgroup\$
    – user41805
    Sep 21, 2021 at 13:55
  • \$\begingroup\$ @user41805 The second suggestion fails for xx:00. The back conversion via 1* $.& will also give a different result in that case. I think I see your point about the x, but I'll let you double-check the other two before updating my answer. \$\endgroup\$
    – Neil
    Sep 21, 2021 at 19:16
  • \$\begingroup\$ You're right, I can't get the second suggestion to work with fewer bytes. But the third one still seems to work. Try it online! (didn't remove the x). But the last two substitutions seem lengthy, I don't know how to shorten them. \$\endgroup\$
    – user41805
    Sep 22, 2021 at 8:13
  • \$\begingroup\$ @user41805 I had a go but I couldn't find anything better either. \$\endgroup\$
    – Neil
    Sep 22, 2021 at 18:27
3
\$\begingroup\$

Python 3, 62 bytes

lambda t,s:(str((eval(s[:-5]+t[0])+(t[1]>=s[-2:]))%24),s[-2:])

Try it online!

Inputs and outputs a tuple of strings.

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

05AB1E, 19 18 bytes

':¡€þø``©@ªþO24%®‚

Try it online or verify all test cases.

I/O of the times as pairs of [HH,mm]; input-order is the string followed by the pair.

Explanation:

':¡               '# Split the first (implicit) input-string on ":"
   €þ              # Only leave the digits of both parts (will be "" for "xx")
     ø             # Zip the pair with the second (implicit) input-pair
      `            # Pop and push both pairs separated to the stack
       `           # Pop and push both minutes separated to the stack
        ©          # Store the minutes of the string in variable `®` (without popping)
         @         # Check if the minutes from the input-pair are larger than or equal
                   # to the minutes of the input-string
          ª        # Append this 1 or 0 to the pair of hours
           þ       # Only leave the numbers (to potentially remove the "")
            O      # Sum this list
             24%   # Modulo-24
                ®‚ # And pair it with minutes `®`
                   # (after which the result is output implicitly)
\$\endgroup\$
3
\$\begingroup\$

jq, 123 bytes

.[2]|=[scan("\\d+")|tonumber]|.[0]+=((.[2][-1]>.[1]//1)?+0//0)+(.[2]|length-1|./.?//0)*.[2][0]|.[1]=.[2][-1]|.[0]%=24|.[:2]

Try it online!

Takes input as [hh,mm,string] and returns [hh,mm].

jq does not have a way to cast a boolean, so the try statements are used(thanks ovs). The modification ops are quite convenient, though.

-5 bytes from ovs.

\$\endgroup\$
4
  • \$\begingroup\$ I think length==1 can be shortened to .==.[:1]. And then, going back to length, (.[2]|length-1|try././/0)*.[2][0] saves two more bytes \$\endgroup\$
    – ovs
    Sep 7, 2021 at 10:03
  • \$\begingroup\$ The first if statement can be shortened to (try(.[2][-1]>.[1]//1)+0//0) \$\endgroup\$
    – ovs
    Sep 7, 2021 at 10:13
  • \$\begingroup\$ try is quite great in this problem. You might want to add it to the tips thread. \$\endgroup\$
    – Razetime
    Sep 7, 2021 at 10:20
  • \$\begingroup\$ Posted it \$\endgroup\$
    – ovs
    Sep 7, 2021 at 13:04
2
\$\begingroup\$

Vyxal, 19 bytes

0p\:€⌊Z÷÷:£≥J∑24%¥"

Try it Online!

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

R, 111 108 105 102 bytes

function(t,x,k=scan(t=el(regmatches(s<-paste0(0,x),gregexpr("\\d+",s)))))c(el(t+k+rev(t>=k))%%24,k[2])

Try it online!


Slightly different solution with the same byte-count:

R, 102 bytes

function(t,x,k=scan(t=el(regmatches(s<-paste0(0,x),gregexpr("\\d+",s)))))c(k,(t+k+rev(t>=k))%%24)[3:2]

Try it online!


R is terrible in string challenges...

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

V (vim) -v calling bc, 105 bytes

Thanks to caird coinheringaahing for filling in some V documentation gaps.
One could reduce the byte count by using raw byte source code instead of -v: 81 bytes courtesy of Aaroneous Miller.
As user41805 pointed out in chat, using bc is most likely inferior to V's built-ins.

f:x"adt x"bdt:s
<esc>"cddo<esc>"apA+1<esc>"cpA+0<esc>Vk:sort
dd0dt+k"bPhxxJI(<esc>A)%24<esc>:.!bc
"cpkJr:

Try it online!, Test it online!

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

C (gcc), 144 143 bytes

n;h;m;o;x,y;f(t,p)char*p,*t;{x=sscanf(p,"%d+xx:%d"+y*3,(y=*p>58)?&m:&o,&m);sscanf(t,"%d:%d",&h,&n);printf("%d:%02d",(h+(y?x:o+1)-(n<m))%24,m);}

Try it online!

Saved a byte thanks to ceilingcat!!!

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

Python 2, 83 65 bytes

a,b=input();print(eval(b[:-5]+a[:-3])+(a[-2:]>=b[-2:]))%24,b[-2:]

Try it online!

pretty simple

Thanks @caird for changing language and saving 18 bytes! (That's a lot of bytes!)

\$\endgroup\$
4
  • \$\begingroup\$ Note that this will error with leading zeros on the hour hand. \$\endgroup\$
    – Wheat Wizard
    Sep 7, 2021 at 7:16
  • \$\begingroup\$ @WheatWizard I used the exact same format as example. \$\endgroup\$
    – okie
    Sep 7, 2021 at 8:07
  • \$\begingroup\$ Yep. It's fine, which is why I'm saying "Note that". \$\endgroup\$
    – Wheat Wizard
    Sep 7, 2021 at 8:08
  • \$\begingroup\$ 65 bytes by switching to Python 2. Outputs space separated, and inputs as a list of strings \$\endgroup\$ Sep 7, 2021 at 20:04
0
\$\begingroup\$

Charcoal, 32 bytes

≔⪪S:θ≔⪪S:ηI﹪⁺¬›⊟θ§η¹Σ⁺§η⁰⊟θ²⁴:⊟η

Try it online! Link is to verbose version of code. Could output in HH:mm format at a cost of 4 bytes. Explanation:

≔⪪S:θ

Input the local time and split on :.

≔⪪S:η

Input the party time and split on :. This means that the hours still contains the xx.

I﹪⁺¬›⊟θ§η¹Σ⁺§η⁰⊟θ²⁴

Compare the two sets of minutes. Concatenate the party hours with the local time, resulting in something like 1+xx5. Because it contains non-digit characters, taking its sum actually extracts all of the embedded integers and sums those, giving us the resulting local hour (after the potential minutes adjustment).

:⊟η

Output the : and party minutes.

\$\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.