-
-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add more itertools: cartesianPower, combinations, combinationsRepeat #4026
Conversation
|
I forgot: I didn't know where to put binomial, actually I was quite surprised it wasn't there. Would |
|
@bbasile thanks for reviewing my code - I will try harder next time to stick to the coding style ;-) Updates
|
|
IMO, |
| _max_states = length; | ||
| if (_length > 0 && _max_states > 0) | ||
| { | ||
| _state = new size_t[repeat]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Why don't you use the .length array property here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do admit this is very confusing - the number of elements (r.length) is cached (in the documentation I read that it is not guaranteed to be constant) and it is used quite often (in the while loop of popFront.
Moreover max_states computes the all possible states as this makes computations a lot easier and provides the user with a nice .length property.
To avoid this confusion I also renamed lengthComputed to isNrStatesComputed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I meant _state.length = repeat;, but maybe I miss something here (that why I've added the Q before).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh never mind - better naming doesn't hurt ;-)
@bbasile you didn't miss anything - your comment is absolutely valid and changed it to this makes absolutely sense.
I am still not entirely used to D. Sorry & thanks!
02d2575 to
55a2ade
Compare
I renamed it to |
| @@ -11,11 +11,21 @@ $(T2 cache, | |||
| Eagerly evaluates and caches another range's $(D front).) | |||
| $(T2 cacheBidirectional, | |||
| As above, but also provides $(D back) and $(D popBack).) | |||
| $(T2 cartesianPower, | |||
| Lazily computes the Cartesian product of $(D r) for a number of | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the text is confusing, e.g. you want "Lazily computes the Cartesian product of r with itself..." The example should show a power of 3.
Also, I'd like more in terms of motivation. From the few people who need Cartesian products at all, a fraction would need the power of a range, and those could write 'cartesianProduct(r, r, r)`. True, that can't be done if the exponent is a variable. But how often does that happen?
8b1cbb6 to
bde2d10
Compare
I also added a wrapper around Moreover I updated the code in regards to all your concerns (@andralex) - sorry about violating the code style. |
At least for my use cases it is nearly always an variable. I can argue that at least |
|
Does anyone know why autotester is failing randomly with this message?
@braddr ? |
370bf72 to
9430c0d
Compare
|
Updates:
|
|
ping @andralex - what is your opinion on this addition? What is blocking this PR? |
| @@ -4257,6 +4267,11 @@ struct Permutations(Range) | |||
|
|
|||
| next(2); | |||
| } | |||
|
|
|||
| @property bool empty() pure nothrow @safe | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this change is doing in this PR, but attributes for member functions of type templates are inferred, so explicit attributes are not necessary here (also @nogc is conspicuous by absence)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please just use attribute inference. Explicit attributes are nice for documentation but we don't generally document range primitives.
Yes. In the same time, would you mind to place this functions to mir instead? |
| size_t binomial(size_t n, size_t k) pure nothrow @safe @nogc | ||
| in | ||
| { | ||
| assert(n > 0, "binomial: n must be > 0."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assert is unnecessary because n == 0 is also valid (as documented above).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It now checks for n >= 0, there is a generalization of the binomial coefficient for negative integers which is seldomly used - should it be added too?
| void popFront() | ||
| { | ||
| // check whether we have reached the end | ||
| if (empty) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally we use assert(!empty); in popFront, making it a logic error to call popFront on an empty range
|
I'm no math guy but is there really no way to do these in constant space? |
AFAIK having this state array (aka pools) is the most common way to do this - have a look at the implementation in Python: Allocation: https://github.com/python/cpython/blob/520c7a75f1a600b3b3a57ced782dfd046ddff678/Modules/itertoolsmodule.c#L2041 (all other comments are addressed & updated) |
|
Could someone add the @andralex label? Thanks ;-) |
|
Please add algorithms complexity overview |
| } | ||
| body | ||
| { | ||
| if (k < 0 || k > n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k is unsigned
|
@greenify We need time for experiments with this functions before including them into Phobos. |
|
In addition, it is possible to compute FP |
Done - even though I would prefer to have these iteration algorithms in |
|
Update: 15 days and a lot of review & help (thanks so much @9il) later - an initial version of See combinatorics at mir |
As you might have realized I started to enjoy D and come from a Python background (sorry about the contribution "spam"), so I missed some functionality from Python's itertools in Phobos.
This adds a couple of useful combinatoric generators. They are all lazy and provide a length.
product: Cartesian product ofrwith repetitions.For example
"AB".combinationsRepeat(2).arrayreturns["AA", "AB", "BA", "BB"]`.This is different to cartesianProduct in setopts as it allows repeats and avoids to duplicates the input range.
combinations: All k-combinations ofrwith repetitions.For example
"AB".combinations(2).arrayreturns["AB"]`.combinationsRepeat: All k-combinations ofrwith repetitions.For example
"AB".combinationsRepeat(2).arrayreturns["AA", "AB", "BB"]`.There is also a version which combines the three generators in one struct with statics ifs if you prefer this.