I am using Luxon and would like to compute the start of the current half hour. Currently, to get a Luxon DateTime, I am doing:
const startOfHalfHour = millis => DateTime.fromMillis(millis - (millis % (30 * 60 * 1000)))
Am I missing a simpler, more idiomatic way? DateTime#startOf() does not have a "half hour" unit.
Luxon doesn't have a half-hour unit, so no, there's no built-in way to do that. I would do something like this:
DateTime.prototype.startOfHalfHour = function() {
let result = this.startOf("hour");
if (this.minute >= 30)
result = result.set({ minute: 30 });
return result;
};
var dt = DateTime
.fromISO("2020-05-25T10:35:12")
.startOfHalfHour();
console.log(dt.toISO());
What is the simplest and correct way to round the time and dateTime in XPath?
For example, how to define a function local:round-time-to-minutes in such way that the following test-case:
let $t1 := xs:time( "12:58:37" )
let $t2 := local:round-time-to-minutes( $t1 )
return format-time( $t2, '[H01]:[m01]:[s01]' )
will return "12:59:00".
Don't sure what is better in case of "23:59:31" — to return "00:00:00" or to raise a dynamic error.
And similar function local:round-datetime-to-minutes to handle dateTime?
(it doesn't have such edge case as above)
Let these functions use "round half towards positive infinity" rule, where half is 30.0 seconds.
This is how the solution proposed by #michael.hor257k would look in XQuery:
declare variable $ONE_MIN := xs:dayTimeDuration("PT1M");
declare variable $MIDNIGHT := xs:time("00:00:00");
declare function local:round-time-to-minutes($time) {
$MIDNIGHT + round(($time - $MIDNIGHT) div $ONE_MIN) * $ONE_MIN
};
Another solution is to subtract the number of second from the given dateTime and add one minute (60 seconds) if the number of seconds is not less than 30.
To convert a number of seconds into duration we multiple it on 1S duration (actually, this operation can be eliminated by a compiler).
declare function local:round-time-to-minutes ( $time as xs:time ) {
let $s := seconds-from-time( $time )
return $time - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};
declare function local:round-dateTime-to-minutes ( $dt as xs:dateTime ) {
let $s := seconds-from-dateTime( $dt )
return $dt - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};
This solution is uniform for the cases of xs:time and xs:dateTime types.
Let's say I have a nested hash describing money quantities:
my %money = (coins => {'50c' => 4}, notes => {'10' => 1, '20' => 5});
My desired format is a record list:
my #money = [
(:type('coins'), :subtype('50c'), value => 4),
(:type('notes'), :subtype('10'), value => 1),
(:type('notes'), :subtype('20'), value => 5),
];
The most obvious answer is loops:
my #money;
for %money.kv -> $type, %sub-records {
for %sub-records.kv -> $subtype, $value {
#money.push: (:$type, :$subtype, :$value);
}
}
But I'm allergic to separating a variable from the code that populates it. Next, I tried to create the variable with functional transformations on the input hash:
%money.kv.map: -> $k1, %hsh2 { :type($k1) X, %hsh2.kv.map(->$k2, $v2 {:subtype($k2), :$v2, :value($v2)}) }
But I didn't get the nesting right. I want a list of flat lists. Plus, the above is a mess to read.
The compromise is the gather/take construct which lets me construct a list by iteration without any temporary/uninitialized junk in the main scope:
my #money = gather for %money.kv -> $type, %sub-records {
for %sub-records.kv -> $subtype, $value {
take (:$type, :$subtype, :$value);
}
};
But I'm curious, what is the right way to get this right with just list transformations like map, X or Z, and flat? ("key1", "key2", and "value" are fine field names, since an algorithm shouldn't be domain specific.)
Edit: I should mention that in Perl 6, gather/take is the most readable solution (best for code that's not write-only). I'm still curious about the pure functional solution.
my #money = %money.map:
-> ( :key($type), :value(%records) ) {
slip
:$type xx *
Z
( 'subtype' X=> %records.keys )
Z
( 'value' X=> %records.values )
}
You could do .kv.map: -> $type, %records {…}
-> ( :key($type), :value(%records) ) {…} destructures a Pair object
:$type creates a type => $type Pair
:$type xx * repeats :$type infinitely (Z stops when any of it's inputs stops)
('subtype' X=> %records.keys) creates a list of Pairs
(Note that .keys and .values are in the same order if you don't modify the Hash between the calls)
Z zips two lists
slip causes the elements of the sequence to slip into the outer sequence
(flat would flatten too much)
If you wanted them to be sorted
my #money = %money.sort.map: # 'coins' sorts before 'notes'
-> ( :key($type), :value(%records) ) {
# sort by the numeric part of the key
my #sorted = %records.sort( +*.key.match(/^\d+/) );
slip
:$type xx *
Z
( 'subtype' X=> #sorted».key )
Z
( 'value' X=> #sorted».value )
}
You could do .sort».kv.map: -> ($type, %records) {…}
Advent of Code Day 1 requires looping, in one form or another, over a long string of parentheses like ((((())(())(((()))(( etc. The idea is that ( goes up one "floor", ) goes down one floor, and the objectives are to print
the first index in the string where the floor number is negative and
the final floor when the end of the string is found.
The imperative solution with a for loop is simple (Python as an example):
def main():
flr = 0
basement = False
for idx, elt in enumerate(text):
flr += {
"(": 1,
")": -1
}.get(elt)
if flr < 0 and not basement:
print("first basement pos:", idx + 1)
basement = True
print("final floor:", flr)
The recursive functional solution is a little more complex, but still not too hard.
def worker(flr, txt, idx, basement):
flr += {"(": 1, ")": -1}[ txt[0] ]
if not (len(txt) - 1): return flr
if flr < 0 and not basement:
print("first basement floor index: ", idx + 1)
basement = True
return worker(flr, txt[1:], idx + 1, basement)
def starter(txt):
flr, basement, idx = 0, False, 0
return worker(flr, txt, idx, basement)
if __name__ == '__main__':
__import__("sys").setrecursionlimit(int(1e5))
print("final floor:", starter(text))
Both of these give the correct output of
first basement floor index: 1795
final floor: 74
when run against my challenge input.
except the second one is dumb because Python doesn't have tail call optimisation but never mind that
How can I implement either of these in Factor? This is something I've been confused by ever since I started using Factor.
We can't just use a for loop because there's no equivalent that allows us to keep mutable state between iterations.
We could use a recursive solution:
: day-1-starter ( string -- final-floor )
[ 0 ] dip 0 f day-1-worker 3drop "final floor: %s" printf ;
: day-1-worker
( floor string index basement? -- floor string index basement? )
day-1-worker ! what goes here?
; recursive
Great, that's a skeleton, but what goes in the body of day-1-worker? Factor doesn't have any way to "early return" from a recursive call because there's no way to run the program in reverse and no concept of return -- that doesn't make any sense.
I get the feeling maybe recursion isn't the answer to this question in Factor. If it is, how do I stop recursing?
First of all, recursion is always the answer :)
Since this is a challenge (and I don't know factor), just a hint:
in your python solution you have used the side effect to print the first basement level. Quite unnecessary! You can use basemet argument to hold the floor number too, like this:
def worker(flr, txt, idx, basement):
flr += {"(": 1, ")": -1}[ txt[0] ]
if not (len(txt) - 1): return [flr, basement] # <- return both
if flr < 0 and not basement:
#print("first basement floor index: ", idx + 1) # side effects go away!
basement = idx+1 # <- a number in not False, so that's all
return worker(flr, txt[1:], idx + 1, basement)
So now you get
final,first_basement = worker(0, txt, 0, False)
Or, alternatively you can write 2 functions, first one seeks the index of first basement floor, the other one just computes the final floor. Having <2000 additional small steps is not a big deal even if you do care about performance.
Good luck!
Edit: as of your question concerning recursion in factor, take a look at the Ackermann Function in Factor and the Fibonacci sequence in Factor and you should get the idea how to "break the loop". Actually the only problem is in thinking (emancipate yourself from the imperative model :)); in functional languages there is no "return", just the final value, and stack-based languages you mention are other computational model of the same thing (instead of thinking of folding a tree one thinks about "pushing and poping to/from the stacks" -- which is btw a common way to implement the former).
Edit: (SPOILER!)
I installed Factor and started playing with it (quite nice), for the first question (computing the final score) a possible solution is
: day-1-worker ( string floor -- floor )
dup length 0 =
[ drop ]
[ dup first 40 =
[ swap 1 + ]
[ swap 1 - ]
if
swap rest
day-1-worker ]
if ;
: day-1-starter ( string -- floor )
0 swap day-1-worker ;
So now you can either write similar one for computing basement's index, or (which would be more cool!) to modify it so that it also manages index and basement... (Probably using cond would be wiser than nesting ifs).
You could use the cum-sum combinator:
: to-ups/downs ( str -- seq )
[ CHAR: ( = 1 -1 ? ] { } map-as ;
: run-elevator ( str -- first-basement final-floor )
to-ups/downs cum-sum [ -1 swap index 1 + ] [ last ] bi ;
IN: scratchpad "((())))(())(())(((()))((" run-elevator
--- Data stack:
7
2
EDIT
I originally misread how your were computing the basement value. I've updated the answers below
Here's a JavaScript solution. Sorry I have no idea how this converts to Factor. reduce is an iterative process
const worker = txt=>
txt.split('').reduce(({floor, basement}, x, i)=> {
if (x === '(')
return {floor: floor + 1, basement}
else if (basement === null && floor === 0)
return {floor: floor - 1, basement: i}
else
return {floor: floor - 1, basement}
}, {floor: 0, basement: null})
let {floor, basement} = worker('((((())(())(((()))((')
console.log(floor) //=> 6
console.log(basement) //=> null; never reaches basement
The answer above relies on some some .split and .reduce which may not be present in your language. Here's another solution using Y-combinator and only the substring built-in (which most languages include). This answer also depends on your language having first-class functions.
const U = f=> f (f)
const Y = U (h=> f=> f (x=> h (h) (f) (x)))
const strhead = s=> s.substring(0,1)
const strtail = s=> s.substring(1)
const worker = Y (f=> ({floor, basement})=> i=> txt=> {
// txt is empty string; return answer
if (txt === '')
return {floor, basement}
// first char in txt is '(', increment the floor
else if (strhead (txt) === '(')
return f ({floor: floor + 1, basement}) (i+1) (strtail (txt))
// if basement isn't set and we're on floor 0, we found the basement
else if (basement === null && floor === 0)
return f ({floor: floor - 1, basement: i}) (i+1) (strtail (txt))
// we're already in the basement, go down another floor
else
return f ({floor: floor - 1, basement}) (i+1) (strtail (txt))
}) ({floor: 0, basement: null}) (0)
{
let {floor, basement} = worker('((((())(())(((()))((')
console.log(floor) //=> 6
console.log(basement) //=> null; never reaches basement
}
{
let {floor, basement} = worker(')(((((')
console.log(floor) //=> 4
console.log(basement) //=> 0
}
{
let {floor, basement} = worker('((())))')
console.log(floor) //=> -1
console.log(basement) //=> 6
}
Now my code is as follows:
common_timestamps = NULL
tapply(data$timestamps, data$date,
function(x, common_timestamps ) {
if(length(common_timestamps ) == 0) {
common_timestamps = x
} else {
date_time = intersect(common_timestamps, x)
}
return(common_timestamps)
},
common_timestamps
)
I want to get the common timestamps from the code in the above. I found each time in the loop, the common_timestamp is null and it did not return common_timestamp. What is wrong with code? I think my concept about passing
variables into function for R language might be right.
Could you correct my error and explain my error?
Thank you very much for your help.