Multi-level marketing "legs" investment rule

Multi-level marketing related challenge.

A peer wants to get rewarded. So it attracted N investors (N>=1), each i-th investor invested x[i]. When a total sum exceeds threshold x[0]+x[1]+...+x[N-1] >= T a peer could be rewarded. But only if a following conditions are satisfied:

• Minimum amount of investors should be greater than M, (M<=N)
• For at least one integer k, where k>=M and k<=N, any k investors have to invest at least T/k each;

Given N, x[], T, M you should determine whether the peer's reward is generated or not (boolean result, "yes" or "no"). Shortest code wins.

Examples:

N=5; M=3; T=10000, in order to generate the peer's reward one of the following must be satisfied:

• any 3 invested at least 3334 each
• any 4 invested at least 2500 each
• all 5 invested at least 2000 each

N=6; M=2; T=5000:

• any 2 invested at least 2500 each
• any 3 invested at least 1667 each
• any 4 invested at least 1250 each
• any 5 invested at least 1000 each
• all 6 invested at least 834 each

generalized: for any k, where k>=M and k<=N:

• any k of N investors invested at least T/k each

Test cases:

format:

N, x[], T, M -> correct answer

6, [999, 999, 59, 0, 0, 0], 180, 3 -> 0
6, [0, 60, 0, 60, 60, 0], 180, 3 -> 1
6, [179, 89, 59, 44, 35, 29], 180, 3 -> 0
6, [179, 89, 59, 44, 35, 30], 180, 3 -> 1
6, [179, 89, 59, 44, 36, 29], 180, 3 -> 1
6, [179, 90, 59, 44, 35, 29], 180, 3 -> 0
6, [30, 30, 30, 30, 29, 30], 180, 3 -> 0
6, [30, 30, 30, 30, 30, 30], 180, 3 -> 1

• @JonathanAllan Sure, if your language allows it, and writing len(x) will be shorter than writing N. That is made, because for dynamically allocated array x in C there is no direct len(x) function - so you may always refer to length as N. For convenience, you may consider all input data N, x[], T, M as some externally defined constants, or some language built-ins. Commented Jan 6, 2019 at 16:32
• I don't think those notifications reached them (with the hyphens) as I got them in my inbox. Commented Jan 6, 2019 at 17:03
• @JonathanAllan not quite familar with pinging syntax, and non-latin names.. maybe they will return some day :) Commented Jan 6, 2019 at 17:17
• Also, can output be reversed? A falsey value for true and truthy value for false? Commented Jan 6, 2019 at 23:25
• @WîtWisarhd Code golf is a winning criterion... look at the tags. Commented Jan 8, 2019 at 0:47

Jelly,  12  9 bytes

ṢṚ×J$ṫ⁵<Ṃ  A full program which accepts x T M and prints 0 if the peer is rewarded and 1 if not. Try it online! How? ṢṚ×J$ṫ⁵<Ṃ - Main Link: list of numbers, x; number, T   e.g. [100, 50, 77, 22, 14, 45], 180
Ṣ         - sort x                                          [ 14, 22, 45, 50, 77,100]
Ṛ        - reverse                                         [100, 77, 50, 45, 22, 14]
$- last two links as a monad: J - range of length [ 1, 2, 3, 4, 5, 6] × - multiply [100,154,150,180,110, 84] ṫ - tail from index: ⁵ - 5th argument (3rd input), M (e.g. M=3) [ 150,180,110, 84] < - less than T? [ 1, 0, 1, 1] Ṃ - minimum 0  • seems not working: tio.run/##y0rNyan8///hzkWHp/uoHJ5wbMnDnasfNW61ebiz6dCah7sW/P//… Commented Jan 6, 2019 at 18:08 • in example third investor invested less than 1/3rd of T (less than 33), but result still counted as positive ("any k invested at least T/k each" failed) Commented Jan 6, 2019 at 18:10 • Yeah, I created it using prefixes of reverse-sorted values and thought I could change it to postfixes of sorted, but actually couldn't because I'm then tailing... reverted :) Commented Jan 6, 2019 at 18:12 • Yeah, now I've finished golfing I'm writing an explanation. Commented Jan 6, 2019 at 18:29 • It now "prints 0 if the peer is rewarded and 1 if not". (i.e. 0 is "yes"). It saves 1 byte :) Commented Jan 6, 2019 at 18:43 05AB1E, 9 bytes {Rƶ.ssè›ß  Port of @JonathanAllan's Jelly answer, so also takes the inputs x T M and outputs 0 for "yes" and 1 for "no". If this is not allowed, and it should be inverted, a trailing _ can be added. Explanation: { # Sort the (implicit) input x # i.e. x=[100,50,77,22,14,45] → [14,22,45,50,77,100] R # Reverse it # i.e. [14,22,45,50,77,100] → [100,77,50,45,22,14] ƶ # Multiply it by it's 1-indexed range # i.e. [100,77,50,45,22,14] → [100,154,150,180,110,84] .s # Get all the suffices of this list # i.e. [100,154,150,180,110,84] # → [[84],[110,84],[180,110,84],[150,180,110,84],[100,154,150,180,110,84]] s # Swap to take the (implicit) input T è # Get the prefix at index T # i.e. [[84],[110,84],[180,110,84],[150,180,110,84],[100,154,150,180,110,84]] # and T=3 → [150,180,110,84] › # Check for each list-value if the (implicit) input M is larger than it # i.e. [150,180,110,84] and M=180 → [1,0,1,1] ß # And pop and push the minimum value in the list (which is output implicitly) # i.e. [1,0,1,1] → 0  Alternative for .ssè: sG¦}  Explanation: s # Swap to take the (implicit) input T G } # Loop T-1 times: ¦ # Remove the first item from the list that many times # i.e. [100,154,150,180,110,84] and T=3 → [150,180,110,84]  • I didn't stated on "how should you map output", just that it have to be boolean (to has only 2 states). So yes, definetely you may use 0 for "yes" and 1 for "no" :) Commented Jan 7, 2019 at 9:04 JavaScript, 54 52 bytes (x,t,m,n)=>x.sort((a,b)=>a-b).some(i=>i*n-->=t&n>=m)  Try it online • Also 35-40% more performant that 72-byted solution. Lovely code, felt like its ready to be embedded in production MLM-related web projects :^) Commented Jan 7, 2019 at 9:12 • Just noticed. Test case #2 [0, 60, 0, 60, 60, 0], 180, 3 -> true seems to be not working! 72 byted bersion handles it ok. Bug or feature?) Commented Jan 24, 2019 at 14:23 Retina, 79 bytes \d+ * O^_+(?=.*]) _+(?=.*])(?<=(\W+_+)+)$#1*$& +\W+_+(.*_)_$
$1 (_+).*], \1,  Try it online! Takes input in the format [x], T, M. Link includes test cases. Explanation: \d+ *  Convert to unary. O^_+(?=.*])  Sort [x] in descending order. _+(?=.*])(?<=(\W+_+)+)$#1*$&  Multiply each element of [x] by its index. +\W+_+(.*_)_$
$1  Delete the first M-1 elements of [x]. (_+).*], \1,  Test whether any remaining element of [x] is greater or equal to T. Perl 6, 46 33 29 bytes {$^b>all $^a.sort Z*[...] @_}  Try it online! Anonymous code blocks that takes input in the form list, amount, length of list, minimum amount of investors and returns a truthy/falsey all Junction, where truthy is failed and falsey is success. Explanation: { } # Anonymous code block all # Are all of$^a.sort                # The sorted list
Z*             # Zip multiplied by
[...] @_    # The range from length of list to the minimum amount
\$^b>                          # Not smaller than the given amount?


05AB1E, 6 bytes

Input taken in the order T, N, x[], M
Output is 0 for peer reward and 1 if not

Ÿs{*›W


Try it online! or as a Test Suite

Explanation

Ÿ        # push the range [N ... T]
s{      # push the list x[] sorted ascending
*     # elementwise multiplication (crops to shortest list)
›    # for each element, check if M is greater than it
W   # push min of the result
# output implicitly

• Nice trick of using * with the range to implicitly crop the list! Commented Jan 7, 2019 at 14:03

C# (.NET Core), 129, 89 bytes

EDIT: Thanks to Kevin Cruijssen for golfing off 40 bytes while explaining the mechanics as to why!

(n,q,t,m)=>{int c=0,j;for(;m<=n&c<1;c=c<m++?0:1)for(j=n;j-->0;)c+=q[j]<t/m?0:1;return c;}


Try it online!

• 106 bytes Some of the things I've changed: Removed the input n since you don't use it anywhere; removed k since you can use m itself; added a variable l for q.Length since you use it twice; combined the variables int c=0,l=q.Length,j; so you don't need the additional var; removed the unnecessary brackets by putting everything in the for-loop body; changed the c>=k check to c<k; and changed the if(c>0)break; to m=c>0?l+1:m;, since the loop stops if m<=l, changing m to l+1 saves a byte over break (and it also saves on 2 brackets). :) Commented Jan 8, 2019 at 16:09
• If you haven't seen it yet, Tips for golfing in C# and Tips for golfing in <all languages> might be interesting to read, through. Commented Jan 8, 2019 at 16:10
• 89 bytes Some additions to the golfs in my first comment. The m=c>0?l+1:m can be removed completely and a &c<1 check can be added to the loop instead. And by taking the input n again, you don't need the q.Length anymore but can use n instead. Commented Jan 8, 2019 at 16:46

C# (Visual C# Interactive Compiler) with flag /u:System.Linq.Enumerable, 69 bytes

(n,x,t,m)=>Range(0,n-m+1).Where(b=>x.Count(a=>a>=t/(b+m))>=b+m).Any()


Try it online!

// Takes in 4 parameters as input
(n,x,t,m)=>
// Create a new array with the length of all the numbers from m to n, inclusive
Range(0,n-m+1)
// And filter the results by
.Where((_,b)=>
// If the number of people that invested more than the total amount divided by the index plus m
x.Count(a=>a>=t/(b+m))
// Is greater than the index plus m
>= b+m)
// And check if there is at least one value in the filtered IEnumerable<int>, and if there is, return true
.Any()


Without any flags, 73 bytes

(n,x,t,m)=>new int[n-m+1].Where((_,b)=>x.Count(a=>a>=t/(b+m))>=b+m).Any()


Try it online!

• I thought of that, and stated in the description that N>=1, and M<=N So you may shorten your solution a bit :) Commented Jan 7, 2019 at 9:02

JavaScript, 72 bytes

Code

(x,T,M)=>x.sort(t=(d,e)=>e-d).map((s,i)=>s*i+s).slice(M-1).sort(t)[0]>=T


Try it online!

Accepts input in format (x[],T,M)

Explanation

x.sort(t=(d,e)=>e-d)     \\sort numbers in reverse numerical order
.map((s,i)=>s*i+s)       \\Multiply each number in array by position(1 indexed) in array
.slice(M-1)              \\Remove the first M-1 elements (at least M people)
.sort(t)[0]              \\Get the maximum value in the array
>=T                      \\True if the maximum value is >= the threshold

• Commented Jan 6, 2019 at 22:26
• (Or 53 bytes if the meaning of the Boolean value can be inverted.) Commented Jan 6, 2019 at 22:52
• @Arnauld, 52 bytes ;) Commented Jan 6, 2019 at 23:23
• (By the way, I came up with my solution independently of your comment, in case you were wondering - it's a port of my Japt solution. On mobile so can't see timestamps properly to tell who posted first.) Commented Jan 6, 2019 at 23:40

Python 3, 136 bytes

Just tests the conditions to make sure they are met. 1 if the reward is given, 0 if not.

lambda N,x,T,M:(sum(x)>=T)*(M<=N)*any(any(all(j>=T/k for j in i)for i in combinations(x,k))for k in range(M,N+1))
from itertools import*


Try it online!

Python,  71  65 bytes

lambda x,T,M:all(i*v<T for i,v in enumerate(sorted(x)[-M::-1],M))


Try it online!

An unnamed function; port of my Jelly answer. As such "yes" is False and "no" is True. Here, however, we discard test-cases as a part of the reversal and take advantage of the ability to initiate the enumerate count to M. (min would also work in place of all)

R, 43 42 bytes

-1 bytes by implementing the approach even more closely

function(N,x,S,M)min(sort(x,T)[M:N]*M:N<S)


Try it online!

Simple R implementation of Jonathan's Jelly approach. I tried a bunch of variations but this pips the best I could think of by a few bytes.

1 implies failure, 0 implies success.

Japt, 161413 11 bytes

ñ í*WõX)d¨V


Try it

ñ í*WõX)d¨V
:Implicit input of array U=x and integers V=T, W=M & X=N
ñ                 :Sort U
í               :Interleave with
WõX           :  Range [W,X]
*              :  And reduce each pair of elements by multiplication
)          :End interleaving
d         :Any
¨V       :  Greater than or equal to V


Java 8, 91 (or 89?) bytes

(N,x,T,M)->{int c=0,j;for(;M<=N&c<1;c=c<M++?0:1)for(j=N;j-->0;)c+=x[j]<T/M?0:1;return c;}


Port of @Destroigo's C# .NET answer (after I golfed it some more), so make sure to upvote him!

Takes inputs N,x,T,M and outputs true/false for "yes"/"no" respectively.

Since the challenge specifically asks for boolean results, I can't return the 1/0 as is, since those aren't valid truthy/falsey values in Java. If any two distinct output values for "yes"/"no" is valid for this challenge instead, the >0 in the return can be dropped to save two bytes, in which case it'll return 1/0 for "yes"/"no" respectively.

Try it online.

Explanation:

(N,x,T,M)->{           // Method with the four parameters and boolean return-type
int c=0,             //  Count integer, starting at 0
j;               //  Temp index integer
for(;M<=N            //  Loop as long as M is smaller than or equal to N
&c<1            //  and c is not 1 yet:
;                //    After every iteration:
c=c<M++?        //     If M is smaller than c:
//     (and increase M by 1 afterwards with M++)
0            //      Set c to 0
:             //     Else:
1)           //      Set c to 1
for(j=N;j-->0;)    //   Inner loop j in the range (N,0]:
c+=             //    Increase the counter c by:
x[j]         //     If the j'th value in x
<T/M?    //     is smaller than T divided by M:
0   //      Leave the counter c unchanged by adding 0
:    //     Else:
1;  //      Increase the counter c by 1
return c>0;}         //  Return whether the counter c is 1


C# (Visual C# Interactive Compiler), 66 bytes

(n,x,t,m)=>Enumerable.Range(m,n-m+1).Any(k=>x.Count(y=>y>=t/k)>=k)


Try it online!

(n,x,t,m)=>[m..n-m+1].Any(k=>x.Count(y=>y>=t/k)>=k)

One thing I changed was the x and t values are decimals. This handles the case where t is not divisible by k a little better.