Given an integer between 0 and 141 (inclusive), list all 24-hour times whose hour, minute, and second units add to that integer.
Rules of addition
Numbers are added by their time units, not by single digits.
For example, take 17:43:59
17+43+59=119
Remember, that is an example of digits being added. In reality, you would enter 119, and 17:43:59 would be one of the results. Output should be given as HH:MM:SS or H:MM:SS.
Also keep in mind the highest number possible is 141, being 23:59:59. This is code golf, so the lowest amount wins. Trial and error is permitted, but there may be a better way to go about this.
Edit: Please specify where in your code the input value is.
-
3\$\begingroup\$ Welcome to Programming Puzzles & Code Golf! If by plugged in you mean made part of the source code, that's usually disallowed. In general, it's a good idea to stick to those defaults. Do we have to display the results as strings? If so, what formats are allowed? \$\endgroup\$Dennis– Dennis2016年12月31日 03:14:22 +00:00Commented Dec 31, 2016 at 3:14
-
\$\begingroup\$ Is the input number guaranteed to be positive? Will there be at least one solution? \$\endgroup\$xnor– xnor2016年12月31日 03:19:56 +00:00Commented Dec 31, 2016 at 3:19
-
\$\begingroup\$ I've edited the question a bit to clarify/answer some things. If your intent was different than my changes, feel free to edit it to match that. \$\endgroup\$Geobits– Geobits2016年12月31日 03:27:14 +00:00Commented Dec 31, 2016 at 3:27
-
1\$\begingroup\$ I only did that because it's the usual way I see times given (in the real world). Nobody ever says it's 13:4:7, but 5:10:30 is almost always acceptable. I don't have an issue with it being changed. \$\endgroup\$Geobits– Geobits2016年12月31日 03:28:59 +00:00Commented Dec 31, 2016 at 3:28
-
3\$\begingroup\$ "Please specify where in your code the input value is." - The convention on PPCG for taking input is using arguments, as well as a few other options. See Default for Code Golf: Input/Output methods on Meta. \$\endgroup\$user2428118– user24281182016年12月31日 09:52:05 +00:00Commented Dec 31, 2016 at 9:52
21 Answers 21
Jelly, (削除) 16 (削除ここまで) (削除) 30 (削除ここまで) (削除) 29 (削除ここまで) 20 bytes
Now with the correct output format! Many thanks to Dennis for his help in debugging this answer. Golfing suggestions welcome. Try it online!
Edit: +14 bytes from using the correct output format. -1 byte from removing an extra space. -3 from changing from 24,60,60 to "ð<<‘. -6 bytes from changing +100DḊ€€ to d5.
"ð<<‘Œp’S=\Ðfd5j€":Y
Explanation
"ð<<‘Œp’S=\Ðfd5j€":Y Main link. Argument: n
"ð<<‘ Jelly ord() the string `ð<<` to get [24, 60, 60]. Call this list z.
Œp Cartesian product of z's items.
Since each item of z is a literal,
Jelly takes the range [1 ... item] for each item.
’ Decrements every number in the Cartesian product
to get lowered ranges [0 ... item-1].
S=\ Create a dyadic link of `sum is equal to (implicit n)`.
Ðf Filter the Cartesian product for items with sum equal to n.
d5 By taking divmod 10 of every number in each item,
we get zero padding for single-digit numbers
and every double-digit number just turns into a list of its digits.
j€": Join every number with a ':'.
Y Join all of the times with linefeeds for easier reading.
Bash, 71
- 8 bytes saved thanks to @hvd
for t in {0..23}+{00..59}+{00..59};{((${t//+0/+}-1ドル))||echo ${t//+/:};}
-
1\$\begingroup\$
printfis costly here. By gettingtcloser to the right format, and fixing it up to make((t-1ドル))work, you can get it down to 71:for t in {0..23}+{00..59}+{00..59};{((${t//+0/+}-1ドル))||echo ${t//+/:};}\$\endgroup\$hvd– hvd2016年12月31日 12:12:38 +00:00Commented Dec 31, 2016 at 12:12
Perl 6, (削除) 62 (削除ここまで) 56 bytes
{map *.fmt('%02d',':'),grep $_==*.sum,(^24 X ^60 X ^60)}
Just checks all possible combinations in the cross product of all hours, minutes, and seconds.
Python 3, 91 bytes
def f(n):
for k in range(86400):t=k//3600,k//60%60,k%60;sum(t)==n!=print('%d:%02d:%02d'%t)
There are shorter solutions using exec (Python 2) or recursion (Python 3), but both require an unreasonable amount of memory.
PowerShell, (削除) 87 (削除ここまで) 77 bytes
Saved 10 bytes thanks to John L. Bevan
$d=date;0..86399|%{$d+=1e7l;"$d".Split()[1]}|?{("{0:H+m+s}"-f$d|iex)-in$args}
Try it online! (this will time out, it's very slow)
Explanation
Pretty simple, starting with the current [datetime], add 1 second 86,399 times, format as a string, then keep only the ones where sum adds up.
-
\$\begingroup\$ FYI: You can replace
10000000with1e7lto save 4 bytes... or even1e7for an extra byte (I think; I had to include theLfor the benefit of the parameter; but suspect your approach avoids that need. \$\endgroup\$JohnLBevan– JohnLBevan2016年12月31日 20:52:31 +00:00Commented Dec 31, 2016 at 20:52 -
1\$\begingroup\$ @JohnLBevan thanks! I struggled with
1e7for at least 30 minutes, and it was theLpostfix I missed; I forgot about it and couldn't figure out a way to get it to int that was shorter than the constant. Who decided that that a[timespan]interprets an[int]as ticks and a[double]as days anyway?? Theiexbit is pretty brilliant, though it makes this whole thing inordinately slower. \$\endgroup\$briantist– briantist2016年12月31日 21:04:51 +00:00Commented Dec 31, 2016 at 21:04 -
1\$\begingroup\$ No worries; I had some help on that one too ;) : stackoverflow.com/q/41408902/361842 \$\endgroup\$JohnLBevan– JohnLBevan2016年12月31日 21:06:44 +00:00Commented Dec 31, 2016 at 21:06
-
1\$\begingroup\$ @JohnLBevan I literally just saw this question before the comment where you linked it! Nice. \$\endgroup\$briantist– briantist2016年12月31日 21:08:29 +00:00Commented Dec 31, 2016 at 21:08
-
1\$\begingroup\$ Also the
iextrick was adapted from a tip here: codegolf.stackexchange.com/a/746/6776 \$\endgroup\$JohnLBevan– JohnLBevan2016年12月31日 21:08:55 +00:00Commented Dec 31, 2016 at 21:08
Haskell, 77 bytes
f x=[tail$(':':).tail.show.(+100)=<<t|t<-mapM(\x->[0..x])[23,59,59],sum t==x]
Haskell, 90 bytes
p x=['0'|x<10]++show x
i=[0..59]
f x=[p h++':':p m++':':p s|h<-[0..23],m<-i,s<-i,h+m+s==x]
Returns a list of HH:MM:SS strings, e.g. f 140 -> ["22:59:59","23:58:59","23:59:58"].
It's three simple loops through the hours, minutes and seconds. Keep and format all values where the sum is the input number x.
Batch, 168 bytes
@for /l %%t in (0,1,86399)do @call:c %1 %%t
@exit/b
:c
@set/ah=%2/3600,m=%2/60%%60,s=%2%%60,n=%1-h-m-s
@set m=0%m%
@set s=0%s%
@if %n%==0 echo %h%:%m:~-2%:%s:~-2%
Outputs single-digit hours.
Mathematica, 79 bytes
Cases[Tuples@{(r=Range)@24-1,x=r@60-1,x},t_/;Tr@t==#:>DateString@TimeObject@t]&
Octave, (削除) 83 (削除ここまで) , 87 bytes
@(a){[H,M,S]=ndgrid(0:23,s=0:59,s);printf("%d:%02d:%02d\n",[H(x=H+M+S==a),M(x),S(x)]')}
QBIC, (削除) 82 (削除ここまで) 72 bytes
:[0,23|[0,59|[0,59|~b+c+d=a|?!b$+@:`+right$(@0`+!c,2ドル)+A+right$(B+!d,2ドル)
This hits an unfortunate spot in QBasic, with casting to number, trimming and prepending a 0 when necessary is really costly.
Sample output:
Command line: 119
1:59:59
2:58:59
2:59:58
3:57:59
[... SNIP 270 lines ...]
23:58:38
23:59:37
(削除) Explanation (削除ここまで) I wrote a novel about it:
: Get N, call it 'a'
[0,23| Loop through the hours; this FOR loop is initialised with 2 parameters
using a comma to separate FROM and TO, and a '|' to delimit the argument list
[0,59| Same for the minutes
[0,59| And the seconds
QBIC automatically creates variables to use as loop-counters:
b, c, d (a was already taken by ':')
~b+c+d=a IF a == b+c+d
| THEN
? PRINT
! CAST
b 'b'
$ To String; casting num to str in QBasic adds a space, this is trimmed in QBIC
+@:` Create string A,ドル containing ":"
+right$ This is a QBasic function, but since it's all lowercase (and '$' is
not a function in QBIC) it remains unaltered in the resulting QBasic.
(@0`+!c,2ドル) Pad the minutes by prepending a 0, then taking the rightmost 2 characters.
+A Remember that semicolon in A$? Add it again
+right$ Same for the seconds
(B+!d,2ドル) Reusing the 0-string saves 2 bytes :-)
-
\$\begingroup\$ QBIC looks interesting. Did you create it just for #code-golf!? :) \$\endgroup\$kodybrown– kodybrown2017年01月01日 02:15:35 +00:00Commented Jan 1, 2017 at 2:15
-
\$\begingroup\$ @wasatchwizard Yup :-) \$\endgroup\$steenbergh– steenbergh2017年01月01日 06:01:35 +00:00Commented Jan 1, 2017 at 6:01
PowerShell, 67 (削除) 79 (削除ここまで) Bytes (nasty version)
Since the rules say nothing about completing in a certain time (or at all), and nothing about no duplicates, here's a horrific solution:
for(){if(("{0:H+m+s}"-f($d=date)|iex)-in$args){"{0:H:mm:ss}"-f$d}}
-
1\$\begingroup\$ I can't find the relevant meta post, but i'm pretty sure a submission have to halt to be valid, unless specified by the challenge \$\endgroup\$Sefa– Sefa2017年01月03日 10:24:28 +00:00Commented Jan 3, 2017 at 10:24
-
\$\begingroup\$ Thanks @Sefa... if that's the case I can't find a nice way to get my nasty version to work in less characters than Briantist's clean version... Tempted to delete this answer, but I'm kind of proud of how bad it is ;) \$\endgroup\$JohnLBevan– JohnLBevan2017年01月03日 12:18:07 +00:00Commented Jan 3, 2017 at 12:18
Racket 39 bytes
(for*/sum((h 24)(m 60)(s 60))(+ h m s))
Ungolfed:
(for*/sum ; loop for all combinations; return sum of values for each loop
((h 24) ; h from 0 to 23
(m 60) ; m from 0 to 59
(s 60)) ; s from 0 to 59
(+ h m s)) ; sum of all 3 variables
MATL, 29 bytes
24:q60:qt&Z*t!si=Y)'%i:'8:)&V
Explanation
24:q % Push [0 1 ... 23]
60:q % Push [0 1 ... 59]
t % Duplicate
&Z* % Cartesian product of the three arrays. This gives a matrix with each
% on a different row Cartesian tuple
t! % Push a transposed copy
s % Sum of each column
i= % Logical mask of values that equal the input
Y) % Select rows based on that mask
'%i:' % Push this string
8:) % Index (modularly) with [1 2 ... 8]: gives string '%i:%i:%i'
&V % Convert to string with that format specification. Implicitly display
JavaScript, (削除) 122 (削除ここまで) 120 bytes
Takes one additional empty string as input, (削除) which I presume doesn't count towards the size (削除ここまで). Updated bytecount (including historical) to add two bytes for the string's initialization.
console.log((
//Submission starts at the next line
i=>o=>{for(h=24;h--;)for(m=60;m--;)for(s=60;s--;)if(h+m+s==i)o+=`${h}:0${m}:0${s} `;return o.replace(/0\d{2}/g,d=>+d)}
//End submission
)(prompt("Number:",""))(""))
-
\$\begingroup\$ If you need to initialize a string to empty, the initialization must be counted \$\endgroup\$edc65– edc652017年01月01日 10:50:14 +00:00Commented Jan 1, 2017 at 10:50
-
\$\begingroup\$ @edc65 Done.··· \$\endgroup\$user2428118– user24281182017年01月01日 11:04:06 +00:00Commented Jan 1, 2017 at 11:04
JavaScript (ES6), 110
v=>eval("o=[];z=x=>':'+`0${x}`.slice(-2);for(m=60;m--;)for(s=60;s--;h>=0&h<24&&o.push(h+z(m)+z(s)))h=v-m-s;o")
Less golfed
v=>{
o=[];
z=x=>':' + `0${x}`.slice(-2);
for(m = 60; m--;)
for(s = 60; s--; )
h = v - m - s,
h >= 0 & h < 24 && o.push(h + z(m) + z(s))
return o
}
Test
F=
v=>eval("o=[];z=x=>':'+`0${x}`.slice(-2);for(m=60;m--;)for(s=60;s--;h>=0&h<24&&o.push(h+z(m)+z(s)))h=v-m-s;o")
function update() {
O.textContent=F(+I.value).join`\n`
}
update()
<input id='I' value=119 type=number min=0 max=141 oninput='update()'><pre id=O></pre>
JavaScript, 96 bytes
v=>{for (i=86399;i;[a,b,c]=[i/3600|0,i%3600/60|0,i--%60]){v-a-b-c?0:console.log(a+":"+b+":"+c)}}
Expanded view:
v => {
for (i = 86399; i;
[a, b, c] = [i / 3600 | 0, i % 3600 / 60 | 0, i-- % 60]) {
v - a - b - c ? 0 : console.log(a + ":" + b + ":" + c)
}
}
Loop through all possible times by looping 86399 to 1,
- convert the integer to time by dividing by 3600 to get the first digit
- the 2nd digit by taking the integer mod 3600 and then dividing by 60
- and the last digit is the integer mod 60
Subtract all 3 numbers from the input value to return a falsey value if the three numbers add up to the input value. If the value is falsey, output the value.
bash, 78 bytes (using a BSD utility) or 79 bytes (non-BSD also)
This is a little longer than @DigitalTrauma and @hvd's nice 71-byte bash solution, but I kind of liked the idea here of using numbers in base 60; I'm curious if anybody can golf this down a little more.
With the BSD-standard jot utility:
jot '-wx=`dc<<<60do3^%d+n`;((`dc<<<$x++'1ドル'-n`))||tr \ :<<<${x:3}' 86400 0|sh
With the more universally available seq utility:
seq '-fx=`dc<<<60do3^%.f+n`;((`dc<<<$x++'1ドル'-n`))||tr \ :<<<${x:3}' 0 86399|sh
The idea is to generate the numbers from 0 to 83699 and use dc to convert them into base 60. The "digits" in dc's base-60 output are 2-digit numbers from 00 to 59, with spaces separating the "digits", so this lists all the desired times from 00 00 00 to 23 59 59 in almost the format needed.
If you literally carry that out, though, numbers below 60^2 aren't 3-digit numbers in base 60, so the initial 00 or 00 00 is missing. For that reason, I'm actually generating the numbers from 60^3 to 60^3+83699; this ensures that all the numbers generated are exactly 4 digits long in base 60. This is OK as long as I eventually throw away the extra first digit (01) that isn't needed.
So, once the desired times are generated, I just take each quadruple from 01 00 00 00 to 01 23 59 59, add the last three numbers and subtract the argument 1ドル. If that's 0, I then take everything in the quadruple from the 3rd character on (throwing away the "01 "), use tr to convert spaces to colons, and print the result.
PowerShell, 91 (削除) 97 (削除ここまで) bytes (including input)
param($x)1..864e3|%{($d=date($_*1e7l))}|?{("{0:H+m+s}"-f$_|iex)-eq$x}|%{"{0:H:mm:ss}"-f$_}
(削除) param($x)0..23|%{$h=$_;0..59|%{$m=$_;0..59|?{$h+$m+$_-eq$x}|%{"{0:0}:{1:00}:{2:00}"-f$h,$m,$_}}} (削除ここまで)
or
param($x)0..23|%{$h=$_;0..59|?{($s=$x-$h-$_)-le59-and$s-ge0}|%{"{0:0}:{1:00}:{2:00}"-f$h,$_,$s}} <\s>
Expanded & commented
param($x)
#loop through the hours
0..23 | %{
$h=$_
#loop through the minutes
0..59 | %{
$m=$_
#loop through the seconds
0..59 | ?{ #filter for those where the sum matches the target
$h + $m + $_ -eq $x
} | %{
#format the result
"{0:#0}:{1:00}:{2:00}" -f $h, $m, $_
}
}
}
NB: Surpassed by @Briantist's version: https://codegolf.stackexchange.com/a/105163/6776