Generator functions

This gives the context for why this challenge came to life. Feel free to ignore.

Generator functions are a nice way of encoding the solution to a problem of combinatorics. You just write some polynomials, multiply them and then your solution is the coefficient of one of the terms.

For example, how many bouquets of 10 flowers can you make if you want to use 3 or more dandelions, really want to use an even number of lilies and cannot afford more than 5 roses? Easy, just find the coefficient of x^10 in

16 Answers
16

J has a nice geometric idiom for multiplying polynomials, which we
represent as lists of coefficients, with explicit zeroes where needed:

+//.@(*/)

Let's see how this works using the example:

1 3 5 +//.@(*/) 5 3 2

First it creates a multiplication table */:

5 3 2
15 9 6
25 15 10

And @: then it computes the sums along each diagonal +//. using the Oblique /. adverb:

This works because moving down a diagonal is equivalent to decrementing the
power of one x while incrementing the power of another, meaning that the
numbers along a diagonal represent all the components of some a factor x^n
for some n.

The rest of the solution is just mechanics for the problem as stated:

{ ::0[: <polynomial idiom> />

Since we can have an arbitrary number of polynomials, we represent them as a list of boxes (each box containing one polynomial) and take that as the right arg. The left arg is the index we want.

Now { ::0 ... is a dyadic hook asking for the index specified by the left arg, after transforming the right arg by everything in .... And, if you can't find the index, return 0 ::0.

Finally [: <polynomial idiom> /> says to first unbox > the right arg lists, filling any missing coefficients with 0. Then reduce / that list using the polynomial multiplication idiom.

An infix function taking a number n and a lists of lists of coefficients with lowest exponents first.

Here's the key recursive idea. Instead of actually multiplying out the polynomials to get one big polynomial, we only just try to extract the coefficient. Algorithmically, this isn't faster than multiplying out coefficient, but in terms of brevity, it saves us from needing to product lists for the intermediate or final product.

When multiply \$p(x)\cdot q(x)\$, we can split up \$p(x)\$ into its constant and remaining terms as \$p(x)=p_0(x) +x \cdot p_{\mathrm{rest}}(x)\$. Then, the coefficient of \$x^n\$ in \$p(x)\cdot q(x)\$ can be written as:

We can continue expanding this out recursively until we get \$p=0\$, where the remaining result is zero. If \$q(x)\$ is itself expressed as a product of polynomials, we continue to extract coefficients from there. The base case is that the empty product is \$1\$, so its \$x^0\$ coefficient is \$1\$ and the rest are zero.

\$\begingroup\$Isn't there an elegant way to gracefully return 0 when the exponent is too high? :/\$\endgroup\$
– RGSFeb 2 at 9:57

1

\$\begingroup\$@RGS I've found a much more elegant way to combine the indexing and the maximal exponent issue (tail from index exponent+1 then take the head, since head for an empty list yields zero)\$\endgroup\$
– Jonathan AllanFeb 2 at 13:17

Takes input like f(3,[1,2,3],[4,5,6]), with the polynomials as separate arguments. The idea for the recursion if the same as in my Haskell answer. But, since Python doesn't have as nice pattern matching, we need to check for empty lists explicitly.

A dyadic link taking k as the left argument and the list of polynomials as a list of lists of coefficients as the right argument. Returns an integer. If k could be 1-indexed, ‘} could be deleted for 13 bytes.

Adapted to use @JonathanAllan’s revised method for dealing with larger k; be sure to upvote his (still shorter) answer too!

First Husk answer. This took so much longer to complete than I thought it would. I'm glad there is a tutorial with good explanation of how the input-order and super-numbers work, otherwise I had to give up. I never programmed in Haskell, and maybe I'm just too used to the left-to-right stack-based 05AB1E, but Husk isn't exactly straight-forward due to its strong-typed nature and right-to-left execution (including input-arguments) imho..
But, it works, which is what counts in the end. :)

First input-argument is a list of lists of coefficients where index encodes exponent, like the third input example in the challenge description. Second argument is the coefficient integer \$k\$.

² # Use the first argument,
G( ) # and left-reduce it by:
Ṫ # Apply double-vectorized:
* # Multiply
# (This basically results in the multiplication table of the lists)
∂ # Take the diagonals of this multiplication table
m # Map over these diagonal-lists:
Σ # And sum each together
→ # Only leave the last list after the reduce-by
∞0 # Push an infinite list of 0s: [0,0,0,...]
+ # Merge the two lists together
⁰ # Push the second argument `k`
→ # Increase it by 1 (since Husk uses 1-based indexing instead of 0-based)
! # And use it to index into the list we created
# (after which the result is output implicitly)

\$\begingroup\$@RGS I'm glad I got it's working in the end. I kept getting the Could not infer valid type for program error almost every step of the way, haha. I should have read that tutorial more thoroughly sooner though, bit my own fault. At first I tried to use implicit inputs, which works with a single argument. Took me a while to realize only the even superscript digits ⁰²⁴⁶⁸ are used to get arguments (odd ones are used to push an argument twice), and also in reversed order.. So with my two argument program, ² is the first argument and ⁰ the second. Ah well..\$\endgroup\$
– Kevin CruijssenFeb 4 at 15:44

\$\begingroup\$if you didn't know husk, why did you go for it?\$\endgroup\$
– RGSFeb 4 at 16:01

1

\$\begingroup\$@RGS To try something new. :) And I remember Husk had a 1-byte diagonals builtin, so I figured it would be pretty short using a rather similar approach as the J answer.\$\endgroup\$
– Kevin CruijssenFeb 4 at 16:15

Definitely not the right language to use for this challenge (no builtins for convolution, polynomials, getting all diagonals of a matrix, etc.).. But with some -rather long- workarounds, it still works (although is too slow for the last test cases).

Input as a list of list of coefficients where index encodes exponent, as well as the integer \$k\$ as second input.

Å» # Left reduce the (implicit) input-list of lists of integers by:
# 1) Calculate the multiplication table of the current two lists:
δ # Apply double-vectorized:
* # Multiply
# 2) Take the sums of each diagonal:
ε # Map each inner list to:
ā # Push a list in the range [1,list-length] (without popping the list itself)
_ # Convert each to 0, so we'll have a list of 0s of the same length
« # Append this list of 0s to the current list
NF # Loop the 0-based map-index amount of times:
Á # And rotate the current list that many times towards the right
}} # End the loop and map
ø # Zip/transpose; swapping rows/columns
# (We now have a list of all diagonals)
O # And take the sum of each inner list
}θ # After the reduce-by is done, pop and push the final resulting list
∞_« # Append an infinite amount of trailing 0s
Iè # And then use the second input to (0-based) index into this list
# (after which the result is output implicitly)

Sledgehammer, 6 bytes

⣈⠲⡎⡒⢢⣑

Only works in the interactive app (that requires excessive amounts of tinkering to get it to actually decompress the Braille code itself, but it's possible), because of a bug where the console app doesn't call postprocess and ends up replacing all occurrences of #, #1, #2, ## by s1, s2, s3, ss1.

Obtained from the Mathematica code Coefficient[ToExpression@#, z, #2] (where ToExpression is eval and Coefficient simply gets the right coefficient, and z gets replaced by x1 as part of the compression).

Takes as inputs k and then polynomials as a list of lists of coefficents [c0, c1, c2, ...]. Forms all tuples of indexes into the polynomials that sum to the desired coefficent; and then sums up the products of the corresponding coefficients.

Takes input as a list of lists of [coefficient, exponent] pairs, paired with k. Could be trivially modified to accept index-as-exponent coefficient lists by replacing ∋ with i, which is in fact what I did originally before I made an error writing out the test cases and switched for my own convenience.

⟨ ⟩ Call the first element of the input L and the last element k.
ᶠ Find every
∋ selection of a [coefficient, exponent] pair
ᵐ from each polynomial in L
{ } such that k is
+ the sum of
tᵐ the exponents.
hᵐ² Extract the coefficients from each selection,
×ᵐ multiply the coefficients extracted from each selection,
+ and output the sum of the products.

{⟨∋ᵐ{tᵐ+}⟩hᵐ×}ᶠ+ is an equally valid solution at the same length, but I'm not sure I remember ever superscripting ᵐ before this, so I'm just going with the version that does that.

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).

Code Golf Stack Exchange is a site for recreational programming competitions, not general programming questions. Challenges must have an objective scoring criterion, and it is highly recommended to first post proposed challenges in the Sandbox.