13
\$\begingroup\$

Given an array of integers, find "the next to the middle".

The next to the middle is the smallest integer greater than the smallest among mean, median and mode of the given numbers, that is neither the mean, median or mode and is also contained in the array.

For example, in the following array

[ 7, 5, 2, 8, 0, 2, 9, 3, 5, 1, 2 ]

Mean: 4
Median: 3
Mode: 2

The next to the middle is 5, because:

  • It's greater than 2 (the smallest of the three)
  • It is not any of the mean, median, mode
  • It's present in the input array
  • It's the smallest number matching the above requirements

Another example, given this array

[ 2, 5, 1, 11, -1, 2, 13, 5, 1, 0, 5 ]

Mean: 4
Median: 2
Mode: 5

The next to the middle is 11.

Input

An array containing a sequence of integers.

  • You don't need to handle integers larger than those that your language's data type can handle

  • The mean could be a floating point number and that's just fine.

  • If the number of elements in the input array is even, you need to handle 2 medians, rather than doing the average of the two values.

  • If more than one integer occurs with the highest frequency, you need to handle multiple values for the mode.

Output

The next to the middle.

If such number doesn't exist you can output either 3.14, an empty string or any other value that cannot be mistaken for an element of the array (be consistent with that value throughout your program).

Standard rules apply for your answer, with standard I/O conventions, while default Loopholes are forbidden.

It would be nice if you could provide an easy way to try your program and possibly an explanation of how it works.

This is , the shortest wins.

Test cases

[ 7, 5, 2, 8, 0, 2, 9, 3, 5, 1, 2 ]
5

[ 2, 5, 1, 11, -1, 2, 13, 5, 1, 0, 5 ]
11

[ 528, -314, 2, 999, -666, 0, 0, 78 ]
78

[ 528, -314, 2, 999, -666, 0, 0, 79 ]
79

[ 528, -314, 2, 999, -666, 5, -5, 42 ]
NaN

[ -845, 2021, 269, 5, -1707, 269, 22 ]
5

[ -843, 2021, 269, 5, -1707, 269, 22 ]
2021

[-54,-22,-933,544,813,4135,54,-194,544,-554,333,566,566,-522,-45,-45]
333

[95444,-22668,834967,51713,321564,-8365542,-962485,-253387,-761794,-3141592,-788112,533214,51713,885244,522814,-41158,-88659176,654211,74155,-8552445,-22222]
-3141592

[ 1, 2, 3, 9, 8, 7, 9, 8, 5, 4, 6, 0, 6, 7 ]
NaN

[ ] // empty array
NaN
You don't need to handle an empty array.

Answers to comments

  • Is any normal floating point accuracy acceptable?
    Yes. Since you will compare the mean with integers, considering 9,87654321 as mean is the same thing of considering 9.8 as mean.

  • "If such number doesn't exist", can we error?
    Since there's a reusability rule for functions, if you are writing a function, a program needs to be able to call that function multiple times. If you are writing a program, then you can exit on error, but you have to be consistent with this output: you have to exit on error every time that there is no next to the middle.

\$\endgroup\$
24
  • 2
    \$\begingroup\$ @Razetime, thank you. Here it is the Sandbox link. Even if it's not that interesting. \$\endgroup\$ – Sheik Yerbouti Feb 7 at 12:36
  • 7
    \$\begingroup\$ @Razetime Why?⠀ \$\endgroup\$ – Adám Feb 7 at 13:08
  • 4
    \$\begingroup\$ @Adám Especially for newer users, linking to the Sandbox post discourages “You should use the Sandbox first” comments, which can be quite annoying if you have used the Sandbox \$\endgroup\$ – caird coinheringaahing Feb 7 at 13:22
  • 2
    \$\begingroup\$ But it's true that there is not enough people reviewing the sandbox. \$\endgroup\$ – user202729 Feb 7 at 15:52
  • 2
    \$\begingroup\$ In addition to @cairdcoinheringaahing's comment: all of this general error handling isn't normal for this type of challenge. It just distracts from the main points. Much better to either say whether an input is valid or not or just compute the answer. \$\endgroup\$ – Noodle9 Feb 7 at 17:37
4
\$\begingroup\$

Jelly, 20 bytes

L‘HịṢ;Æm;ÆṃµṂ³>Ƈḟȯ.Ṃ

A full program accepting a list of numbers which prints the next to the middle or 0.5 if there is none.

Try it online!

Or see the test-suite (uses a functional form which uses the register atoms, © and ®, to replace the use of the program argument atom, ³).

How?

L‘HịṢ;Æm;ÆṃµṂ³>Ƈḟȯ.Ṃ - Main Link: list, A
L                    - length (A)
 ‘                   - increment
  H                  - halve
    Ṣ                - sort (A)
   ị                 - index into (if A has an even number of elements we get the two in
                                   the middle, due to Jelly's fractional indexing magic)
      Æm             - mean (A)
     ;               - concatenate
         Æṃ          - mode (A)
        ;            - concatenate
           µ         - start a new monadic chain, f(X=medians+[mean,mode])
             ³       - programs argument, A
            Ṃ        - minimum (X)
               Ƈ     - filter (A) keeping if:
              >      -   greater than (minimum (X))
                ḟ    - filter - discard those which are in (X)
                  .  - a half
                 ȯ   - logical OR (replace an empty list with 0.5)
                   Ṃ - minimum
\$\endgroup\$
1
  • \$\begingroup\$ Saves no bytes but I did replace ạÐṂÆṁ with L‘HịṢ to cater for it. \$\endgroup\$ – Jonathan Allan Feb 7 at 18:07
3
\$\begingroup\$

J, 76 bytes

Returns an empty list '' if there is no element.

(0{ ::''-./:~@#~-.><./@])({./.~#~[:(=>./)#/.~),(>.@<:@-:@#(-@[}.}.)/:~),+/%#

Try it online!

  • +/%# mean: sum divided by length
  • >.@<:@-:@#(-@[}.}.)/:~ median(s): sort, drop first and last floor(length % 2 - 1) elements (can this be shorter?)
  • #/.~ mode(s): group the list by itself, get the length of each group
  • [:(=>./) the maximum length
  • {./.~#~ take the groups' first element that have the maximum length
  • <./@] minimum of mean, medians and modes
  • -. #~-.> get every element that is not in (mean, medians, modes), but also larger,
  • /:~@ sort them and
  • 0{ ::'' get the first element – if there is none and an error would occur, return '' instead
\$\endgroup\$
0
3
\$\begingroup\$

Jelly, 22 bytes

L‘HịṢ;Æm;Æṃ
ḟÇ>ƇÇṂ$ȯ.Ṃ

Try it online!

Returns 0.5 for an invalid input.

Explanation

L‘HịṢ;Æm;Æṃ   Auxiliary monadic link
L             Length
 ‘            Increment
  H           Half
   ị          Index into
    Ṣ           the sorted array
     ;        Join with
      Æm        the mean
        ;     Join with
         Æṃ     the mode(s)

ḟÇ>ƇÇṂ$ȯ.Ṃ   Main monadic link
ḟ            Filter out
 Ç             the results of the previous link
   Ƈ         Filter
  >            greater than
      $        (
    Ç            The results of the previous link
     Ṃ           Maximum
      $        )
       ȯ     Logical OR (non-vectorizing) with
        .    0.5
         Ṃ   Minimum
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I ended up with L‘HịṢ too after discovering ạÐṂÆṁ errors with an empty list. \$\endgroup\$ – Jonathan Allan Feb 7 at 17:46
3
\$\begingroup\$

05AB1E, 21 bytes

¢ZQÏIÅAI{Ås)˜WUKʒX›}ß

Try it online or verify all test cases.

Explanation:

        #Mode:
¢       # Count how many times each value occurs in the (implicit) input-list
 Z      # Get the maximum of these counts (without popping the list)
  Q     # Check for each if it's equal to this maximum count
   Ï    # Only leave the values in the (implicit) input-list at the truthy indices
        #Mean:
IÅA     # Push the input; pop and push its mean
        #Median:
I{      # Push the input; sort it
  Ås    # Pop and push the middle (one or two) values
)       # Wrap all three into a list
 ˜      # And flatten it
W       # Push the minimum of this list
 U      # Pop and store it in variable `X`
  K     # Remove all medium, mean, and mode values from the (implicit) input-list
   ʒ    # Filter the remaining values by:
    X›  #  Check if it's larger than `X`
   }ß   # After the filter: pop and push the minimum
        # (after which it is output implicitly)

Although 05AB1E does have builtins for all three: mean (ÅA); median (Åm); and mode (.M), the median takes the average of the two values for even-length lists, and the mode only results in a single most frequent value instead of all, which is why we'll do those manually. In the legacy 05AB1E version the .M mode builtin did result in all most frequent values instead of just one, but unfortunately the legacy version doesn't have a median nor middle builtin, and doing that manually would be even longer.

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

JavaScript (ES6), 165 bytes

Returns undefined if no valid answer is found.

a=>a.sort((a,b)=>a-b).map(c=v=>(n++,t+=v,i=c[v]=-~c[v],i<m?0:m=i,v),m=t=n=0).find(v=>v>Math.min(...A=[t/n,a[n>>1],a[n-1>>1],...a.filter(v=>c[v]==m)])&!A.includes(v))

Try it online!

Commented

a =>                     // a[] = input array
  a.sort((a, b) =>       // sort a[] from lowest to highest
    a - b                // so that we can compute the median value(s)
  )                      //
  .map(c = v =>          // for each value v in a[]:
    ( n++,               //   increment the total number of values n
      t += v,            //   add v to the sum t of all values
      i = c[v] = -~c[v], //   update the number i of occurrences of v
      i < m ? 0 : m = i, //   update m to max(m, i)
      v                  //   yield v so that the array is unchanged
    ),                   //   and we can chain with .find()
    m = t = n = 0        //   start with m = t = n = 0
  )                      // end of map()
  .find(v =>             // find the first value v that satisfies:
    v > Math.min(        //   1) it's greater than the minimum of ...
      ...A = [           //        the values stored in A[], which are:
        t / n,           //          - the mean
        a[n >> 1],       //          - the 1st median value
        a[n - 1 >> 1],   //          - the 2nd median value (if any)
        ...a.filter(v => //          - all mode values
          c[v] == m      //            i.e. values that appear m times
        )                //        
      ]                  //        end of array
    ) &                  //      end of Math.min()
    !A.includes(v)       //   2) it's not one of the values defined above
  )                      // end of find()
\$\endgroup\$
1
  • \$\begingroup\$ Arnauld vs Charcoal, J, 05AB1E, Jelly, and Mathematica :) \$\endgroup\$ – Wzl Feb 18 at 21:32
2
\$\begingroup\$

Wolfram Language (Mathematica), 81 bytes

Min@Cases[#,a_/;a>Min@#&&#~FreeQ~a&@{Mean@#,Sort@#//._[_,a__,_]:>a,Commonest@#}]&

Try it online!

Returns Infinity if such a number does not exist.

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

Charcoal, 61 bytes

W⁻θυF№ι⌊ι⊞υ⌊ι≔✂υ⊘⊖Lθ⊕⊘Lθ¹υ≔Eθ№θιηF⌕Aη⌈η⊞υ§θι⊞υ∕ΣθLθI⌊Φ⁻θυ›ι⌊υ

Try it online! Link is to verbose version of code. Outputs None if no suitable value exists. Explanation: Not an ideal challenge for Charcoal.

W⁻θυ

While the sorted list does not contain all of the input values...

F№ι⌊ι⊞υ⌊ι

... push the next value to the sorted list according to the number of times it appears.

≔✂υ⊘⊖Lθ⊕⊘Lθ¹υ

Slice the middle element(s) from the sorted list.

≔Eθ№θιη

Tabulate how many times each element appears in the list.

F⌕Aη⌈η

Loop over the indices of maximum counts, ...

⊞υ§θι

... pushing the original value to the list of averages.

⊞υ∕ΣθLθ

Finally, push the mean to the list of averages.

I⌊Φ⁻θυ›ι⌊υ

Remove all of the averages from the input, then also filter out values lower than all of the averages, and print the minimum of the remainder (if any).

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

Stax, 33 bytes

Ç∞♫ÑÄ‼ú╘màk■g5øg◘U½¢┴Åû)*ç╨£╨├╡óà

Run and debug it

Getting the middle two elements takes most of the space here. Reducing that would significantly improve the score.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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