19
\$\begingroup\$

We define the hyper-average of an array / list (of numbers) the arithmetic mean of the sums of its prefixes.

For example, the hyper-average of the list [1, 4, -3, 10] is computed in the following manner:

  • We get the prefixes: [1], [1, 4], [1, 4, -3], [1, 4, -3, 10].

  • Sum each: [1, 5, 2, 12].

  • And now get the arithmetic mean of the elements in this list: (1 + 5 + 2 + 12) / 4 = 5.

A pseudo-element of an array is an element whose value is strictly lower than its hyper-average. Hence, the pseudo-elements of our example list are 1, 4 and -3.


Given a list of floating-point numbers, your task is to return the list of pseudo-elements.

  • You don't have to worry about floating-point inaccuracies.

  • The input list will never be empty and it may contain both integers and floats. If mentioned, integers may be taken as floats (with <integer>.0)

  • You may assume that the numbers fit your language of choice, but please do not abuse that in any way.

  • Optionally, you may take the length of the array as input as well.

  • This is , so standard rules for the tag apply. The shortest code in bytes (in each language) wins!


Test Cases

Input -> Output

[10.3] -> []
[5.4, 5.9] -> [5.4, 5.9]
[1, 4, -3, 10] -> [1, 4, -3]
[-300, -20.9, 1000] -> [-300, -20.9]
[3.3, 3.3, 3.3, 3.3] -> [3.3, 3.3, 3.3, 3.3]
[-289.93, 912.3, -819.39, 1000] -> [-289.93, -819.39]
\$\endgroup\$
2
  • \$\begingroup\$ If some languages are allowed to take the length of the array as additional input, then it should be allowed for all languages. \$\endgroup\$
    – user61980
    Aug 15, 2017 at 22:13
  • 1
    \$\begingroup\$ @ngenisis It is for all languages. If taking the length as well shortens your program, feel free to do it. That spec isn't language restrictive at all. \$\endgroup\$
    – Mr. Xcoder
    Aug 16, 2017 at 5:43

30 Answers 30

8
\$\begingroup\$

05AB1E, 9 8 bytes

-1 bytes thanks to Magic Octopus Urn

ηOO¹g/‹Ï

Try it online!

η        # Get prefixes
 O       # Sum each
  O¹g/   # Get the mean ( length(prefix list) equals length(original list) )
      ‹Ï # Keep only the value that are less than the mean

05AB1E, 6 bytes

Using the new ÅA command.

ηOÅA‹Ï

Try it online!

η      # Get prefixes
 O     # Sum each
  ÅA   # Get the mean
    ‹Ï #  Keep only the value that are less than the mean
\$\endgroup\$
1
  • 2
    \$\begingroup\$ ηOO¹g/›Ï for 8; also it starts with nOO!. \$\endgroup\$ Aug 14, 2017 at 17:30
7
\$\begingroup\$

MATL, 8 bytes

ttYsYm<)

Try it online! Or verify all test cases.

Explanation

tt    % Implicitly input array. Duplicate twice
Ys    % Cumulative sum
Ym    % Arithmetic mean
<     % Less than? (element-wise). Gives an array containing true / false
)     % Reference indexing : use that array as a mask to select entries 
      % from the input. Implicitly display
\$\endgroup\$
7
\$\begingroup\$

Japt v2.0a0 -f, 12 11 10 9 bytes

<Wå+ x÷Wl

Try it

-1 byte thanks to ETH pointing out a redundant character.

<Wå+ x÷Wl     :Implicit filter of each element in input array W
<             :Is less than
 Wå+          :  Cumulatively reduce W by addition
     x        :  Reduce by addition
      ÷Wl     :  Divide by length of W
\$\endgroup\$
0
4
\$\begingroup\$

Python 3 with Numpy, 48 bytes

lambda x:x[x<mean(cumsum(x))]
from numpy import*

Input and output are Numpy arrays. Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ +1 Finally, someone uses cumsum! \$\endgroup\$
    – Mr. Xcoder
    Aug 14, 2017 at 15:24
4
\$\begingroup\$

Haskell, 39 bytes

f l=filter(<sum(scanl1(+)l)/sum(1<$l))l

Try it online!

Unfortunately length is of type Int, so I cannot use it with floating point division / and I have to use a workaround: sum(1<$l).

\$\endgroup\$
4
\$\begingroup\$

Husk, 10 9 bytes

Thanks @Zgarb for golfing off 1 byte!

f</L⁰Σ∫⁰⁰

Try it online!

Ungolfed/Explanation

           -- argument is ⁰ (list) 
f       ⁰  -- filter the original list with
 <         --   element strictly smaller than
     Σ∫⁰   --   sum of all prefixes
  /L⁰      --   averaged out
\$\endgroup\$
1
  • 3
    \$\begingroup\$ f</L⁰Σ∫⁰⁰ is 9 bytes, but three lambda arguments feels clunky. \$\endgroup\$
    – Zgarb
    Aug 14, 2017 at 17:28
4
\$\begingroup\$

Java 8, 81 bytes

This lambda expression accepts a List<Float> and mutates it. The input list's iterator must support removal (ArrayList's does, for example). Assign to Consumer<List<Float>>.

a->{float l=0,t=0,u;for(float n:a)t+=n*(a.size()-l++);u=t/l;a.removeIf(n->n>=u);}

Ungolfed lambda

a -> {
    float l = 0, t = 0, u;
    for (float n : a)
        t += n * (a.size() - l++);
    u = t / l;
    a.removeIf(n -> n >= u);
}

Try It Online

Acknowledgments

  • -3 bytes thanks to Kevin Cruijssen
  • -17 bytes thanks to Nevay
\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can save 3 bytes by removing t/=l; and change if(n<t) to if(n<t/l). \$\endgroup\$ Aug 15, 2017 at 12:17
  • 1
    \$\begingroup\$ You can use a list instead of an array to be able to modify the provided argument rather than printing the resulting values a->{float l=0,t=0,u;for(float n:a)t+=n*(a.size()-l++);u=t/l;a.removeIf(n->n>=u);} (81 bytes). \$\endgroup\$
    – Nevay
    Aug 15, 2017 at 14:19
3
\$\begingroup\$

Jelly, 9 bytes

+\S÷L<Ðf@

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Maybe <Ðf@ should instead be <Ðḟ@? \$\endgroup\$ Aug 14, 2017 at 15:04
  • \$\begingroup\$ @EriktheOutgolfer but it passes all the testcases. \$\endgroup\$
    – Leaky Nun
    Aug 14, 2017 at 15:08
  • 1
    \$\begingroup\$ Still something doesn't seem good to me...first of all +\S÷L calculates the hyper-average, then <Ðf@ puts it as its right argument and < will return 1 if an element is a pseudo-element, essentially filtering for the pseudo-elements instead of filtering them out. \$\endgroup\$ Aug 14, 2017 at 15:15
  • 1
    \$\begingroup\$ @EriktheOutgolfer In this context, filtering out means filtering for. \$\endgroup\$
    – Leaky Nun
    Aug 14, 2017 at 15:22
3
\$\begingroup\$

Python 2, 78 76 71 66 bytes

-7 bytes thanks to Mr. Xcoder.

lambda l:[x for x in l if x<sum(sum(l[:i])for i in range(len(l)))]

Try it online!

\$\endgroup\$
6
3
\$\begingroup\$

Perl 6, 31 bytes

{.grep(flat([\,] $_).sum/$_>*)}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 56 55 52 bytes

a=>a.filter(x=>x<t/a.length,a.map(x=>t+=s+=x,s=t=0))

Test it

o.innerText=(f=

a=>a.filter(x=>x<t/a.length,a.map(x=>t+=s+=x,s=t=0))

)(i.value=[1,4,-3,10]);oninput=_=>o.innerText=f(i.value.split`,`.map(eval))
<input id=i><pre id=o>

\$\endgroup\$
0
3
\$\begingroup\$

R, 31 bytes

function(l)l[l<mean(cumsum(l))]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

C# (Mono), 95 bytes

using System.Linq;a=>a.Where(d=>d<new int[a.Length].Select((_,i)=>a.Take(i+1).Sum()).Average())

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3, 72 bytes

lambda x:[*filter((sum(-~a*b for a,b in enumerate(x))/len(x)).__gt__,x)]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Very clever solution! I never thought filter would win over the usual list comprehension. \$\endgroup\$
    – Mr. Xcoder
    Aug 14, 2017 at 15:14
2
\$\begingroup\$

Python 3, 76 bytes

lambda x:[w for w in x if w<sum(u*v+v for u,v in enumerate(x[::-1]))/len(x)]

Input and output are lists of numbers. Try it online!

This works in Python 2 too (with the obvious replacement for print syntax in the footer).

\$\endgroup\$
4
  • \$\begingroup\$ Do you need to reverse the list? \$\endgroup\$
    – 0xffcourse
    Aug 14, 2017 at 15:28
  • \$\begingroup\$ @officialaimm I think so, because enumeration values 1,2,3,... must go with x[0], x[-1], x[-2]. But in all cases the result seems to be the same, hmm... \$\endgroup\$
    – Luis Mendo
    Aug 14, 2017 at 15:35
  • 2
    \$\begingroup\$ I found a counterexample which shows that reversing is indeed necessary \$\endgroup\$
    – Luis Mendo
    Aug 14, 2017 at 15:37
  • \$\begingroup\$ Ah, never mind.. I just thought so because it passed all the test cases... :P \$\endgroup\$
    – 0xffcourse
    Aug 14, 2017 at 15:39
2
\$\begingroup\$

Pyth - 10 bytes

<#.OsM._QQ

Try it online here.

\$\endgroup\$
2
\$\begingroup\$

Mathematica, 35 bytes

Cases[#,x_/;x<#.Range[#2,1,-1]/#2]&

Function which expects a list of numbers as the first argument # and the length of the list as the second argument #2. #.Range[#2,1,-1]/#2 takes the dot product of the input list # and the the list Range[#2,1,-1] == {#2,#2-1,...,1}, then divides by the length #2. Then we return the Cases x_ in the input list # which are less than the hyper-average.

Without the length as a second argument, we need 6 more bytes:

Cases[#,x_/;x<#.Range[h=Tr[1^#],1,-1]/h]&
\$\endgroup\$
2
\$\begingroup\$

TI-Basic, 9 bytes

Ans*(Ans<mean(cumSum(Ans
\$\endgroup\$
2
\$\begingroup\$

Factor, 36 bytes

[ dup cum-sum mean '[ _ < ] filter ]

Try it online!

Explanation:

It's a quotation (anonymous function) that takes a sequence from the data stack as input and leaves a sequence on the data stack as output. Assuming { 1 4 -3 10 } is on the data stack when this quotation is called...

  • dup Duplicate an object.

    Stack: { 1 4 -3 10 } { 1 4 -3 10 }

  • cum-sum Take the cumulative sum.

    Stack: { 1 4 -3 10 } { 1 5 2 12 }

  • mean Take the mean.

    Stack: { 1 4 -3 10 } 5

  • '[ _ < ] filter Take the elements from a sequence that are less than the number on top of the stack.

    Stack: { 1 4 -3 }

\$\endgroup\$
1
\$\begingroup\$

Pyth, 12 11 bytes

f<T.OsM._QQ

-1 byte thanks to Mr. Xcoder

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 11 bytes: f<T.OsM._QQ \$\endgroup\$
    – Mr. Xcoder
    Aug 14, 2017 at 15:06
  • \$\begingroup\$ You can replace f<T with <# to save a byte. This may have been added to Pyth after this answer was posted, not sure. \$\endgroup\$
    – hakr14
    Apr 29, 2021 at 3:24
1
\$\begingroup\$

Perl 5, 51 + 1 (-a) = 52 bytes

$a+=$_*(@F-$c++)for@F;for(@F){print$_,$"if$_<$a/@F}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PHP, 84 bytes

for($i=--$argc;$i;)$s+=$i--/$argc*$r[]=$argv[++$k];foreach($r as$x)$x<$s&&print$x._;

takes input from command line arguments. Run with -nr or try it online.


summing up the partial lists is the same as summing up each element multiplied with the number of following elements +1 → no need to juggle with bulky array functions. It´s still long, though.

\$\endgroup\$
1
\$\begingroup\$

Röda, 46 41 39 bytes

f l{l|[_]if[_1*#l<seq(1,#l)|l[:_]|sum]}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

J, 15 bytes

#~[<[:(+/%#)+/\

Try it online! Expects a J-style array (negatives represented using _ instead of - and elements separated by spaces -- see the TIO link for examples).

I don't know if there's a way to remove the parentheses around the mean (+/%#) but removing that and the cap would be the first thing I'd try to do to golf this further.

Explanation

Sometimes J reads like (obfuscated) English.

#~ [ < [: (+/ % #) +/\
                   +/\  Sum prefixes
                     \   Get prefixes
                   +/    Sum each
          (+/ % #)      Mean
           +/            Sum of array
              %          Divided by
                #        Length of array
   [ <                  Input array is less than?
                         (gives boolean array of pairwise comparisons)
#~                      Filter by
\$\endgroup\$
3
  • 1
    \$\begingroup\$ you beat me to it by 3 mins :) \$\endgroup\$
    – Jonah
    Aug 15, 2017 at 0:46
  • \$\begingroup\$ 12 bytes with #~]<1#.+/\%# \$\endgroup\$
    – miles
    Aug 15, 2017 at 2:08
  • \$\begingroup\$ @miles Unless you think it's similar enough, I think your comment might warrant its own answer. EDIT: I think it's very clever myself. \$\endgroup\$
    – cole
    Aug 15, 2017 at 2:11
1
\$\begingroup\$

K (oK), 26 bytes

Solution:

x@&x<(+/+/'x@!:'1+!#x)%#x:

Try it online!

Examples:

> x@&x<(+/+/'x@!:'1+!#x)%#x:1 4 -3 10
1 4 -3
> x@&x<(+/+/'x@!:'1+!#x)%#x:-289.93 912.3 -819.39 1000
-289.93 -819.39

Explanation:

Interpretted right-to-left. Struggled with a short way to extract prefixes:

x@&x<(+/+/'x@!:'1+!#x)%#x: / the solution
                        x: / store input in x, x:1 4 -3 10
                       #   / count, return length of x, #1 4 -3 10 => 4
     (               )     / do everything in the brackets together
                   #x      / count x
                  !        / til, range 0..x, !4 => 0 1 2 3
                1+         / add 1 vectorised, 1+0 1 2 3 => 1 2 3 4
             !:'           / til each, e.g. !1, !2, !3, !4
           x@              / index into x at these indices (now we have the prefixes)
        +/'                / sum (+ over) each, e.g. 1 5 2 12
      +/                   / sum over, e.g. 20
                      %    / right divided by left, 20%4 => 5 (now we have the hyper average)
   x<                      / boolean list where x less than 5
  &                        / indices where true, &0111b => 1 2 3
x@                         / index into x at these indices (now we have the filtered list)

Notes:

Alternative version taking length of input as parameter (25 byte solution):

> {x@&x<(+/+/'x@!:'1+!y)%y}[1 4 -3 10;4]
1 4 -3
\$\endgroup\$
1
\$\begingroup\$

Jelly, 6 bytes

<ƇÄS÷ɗ

Try it online!

Takes the list on the left and its length on the right, as explicitly permitted.

With newer builtins, Leaky Nun's +\S÷L<Ðf@ becomes ÄS÷L<Ƈ@ (which may as well be ÄS÷L>x@, using one less piece of the present, but that's besides the point), but taking the length as the right argument trades an L and an @ for one ɗ.

 Ƈ        Filter the left argument to elements which
<         are less than
   S ɗ    the sum of
  Ä       the cumulative sums of the left argument
    ÷     divided by the right argument.
\$\endgroup\$
1
\$\begingroup\$

Arturo, 42 bytes

$[a][select a'x[0x<average map a=>[dup+]]]

Try it

$[a][                      ; a function taking an argument a
    select a 'x [          ; select numbers from a and assign current number to x
        0                  ; push 0 to the stack
        x <                ; is x less than...
        average            ; ...the mean...
        map a => [dup +]   ; ...of the cumulative sum of a?
    ]                      ; end select
]                          ; end function
\$\endgroup\$
1
\$\begingroup\$

Julia 0.5, 24 bytes

~x=x[x.<mean(cumsum(x))]

Try it online!

In modern Julia, mean was moved from Base to the Statistics module:

Julia 1.0, 33 bytes

~x=x[x.<sum(cumsum(x))/length(x)]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Nibbles, 5.5 bytes (11 nibbles)

|$-/+`\@+,@

Nibbles uses only integers, so I'm "assuming that the numbers fit my language of choice" by omitting decimal points from fractional inputs & padding with zeros where needed. I hope that this is not construed as "abusing" the lenient input rule in any way.

|$              # filter input to retain only those that are truthy when:
  -             #   subtracting them from
    +           #     the sum of 
     `\@+       #     the cumulative sums of the input
   /            #     divided by
         ,@     #     the length of the input

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Pip, 19 bytes

_<$+$+*(aH\,b)/bFIa

Makes use of the optional length input.

How?

_<$+$+*(aH\,b)/bFIa  : -xp; Two args: array and length
        a         a  : First input; array
            b  b     : Second input; length
                FIa  : Filter: keep items from iterable 'a' which return truthy
_                    : Passed element
 <                   : Is less then
        aH           : Get prefix of a that is # elements long
          \,b        : Range from one to length
    $+*              : Sum of each list
  $+                 : Sum list
              /b     : Divide by length

Try It Online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.