Choose Language Hide Translation Bar
Challenge 5

jmp-challenge-v2.pngWorking with matrices is both convenient and fast. Many functions that work on a single value can also be applied to an entire matrix. In addition, functions such as V Max, V Mean, and V Quantile can be applied to a function of the matrix (columns, in these situations). This month’s challenge aims to take this to the next level. We’ll be looking to extend this functionality to functions that aren’t available in JSL, and to do it for both matrices and lists.

  1. Write a function named mad that takes a vector as an input and returns the median absolute deviation (the median of the absolute differences from median of the data). For example, mad([1,2,3,1000]) returns 1. If there are an even number of observations, take the average value in the middle to calculate the median.
  2. Write a function trimmedMean(vecIn,pctLo,pctHi) that takes a vector (vecIn) and value between 0 and 0.5 corresponding to the percent of observations below (pctLo) and above (pctHi) the mean that are removed before the mean is calculated. The percent of trimmed values should be the largest number that does not exceed the input percent.
  3. Write a function listContains(listIn,valueString) that takes a list of strings (listIn) and a string (valueString) and returns a list of matrix values where each element of the matrix corresponds to a starting position of valueString in the jth item of listIn (i.e., an item of listIn may contain valueString more than once). Return the missing value if the item does not contain the string.
  4. Write a function applyFunction(listIn,fn,argList) that takes an input list (listIn) and applies the function fn with arguments argList to it. Assume the list will only contain numbers or strings. The function should work for both built-in and user-supplied functions. It could return a single value, matrix, or list of value depending on the input function. For simplicity, assume any function supplied to applyFunction will only need to operate on a character, string, numbers, matrix, or list (restricted to character, string, number, matrix, or list items).

Scoring: Two points for items 1 and 2, six points for items 3 and 4. Four extra points if you can write item 3 or 4 without using a loop (of any sort) or data table.

Deadline for entries is 11:59 PM Eastern US Time on Monday, August 17.

 

11 Aug 2020: There's been a bit of confusion over a few aspects of the challenge. Let me see if I can clear things up:

  • For trimmedMean, pctLo and pctHi are frational values bounded below by 0 and above by 0.5. If, for example, pctLo = 0.23, then the 23% of the values from the lower tail are removed.
  • For listContains, if listIn = {"ABCD","DEFG", "GHIJ"} and valueString = "D", then [4,1,.] is returned.
  • For applyFunction, both listIn and argList are arguments to fn. The main difference is that listIn will never be empty, but argList may be empty. For example, if listIn = {"ABCD","DEFG","GHIJ"} and fn = Contains, then argList should be a list that contains at least one substring to search for. If fn = Length, however, argList would be empty. In cases where fn can be applied to the individual elements, do so. For instance, if fn = Char, rather than returning the quoted list, quote the individual elements of the list.

Hope this makes things clearer. If not, please let me know.

7 Comments
Super User

Thanks for the clarifications Don.  For applyFunction, is fn expressed as a string?  If fn can be any function, how do we know whether or not it can applied to individual elements? - applyFunction just sees a function name as an input parameter, it has no knowledge of what the function is capable of doing?  And if ListIn is a list of numbers then it would make sense to sum the entire list, but alternatively each item might be a list in which case it might make sense to return a list of sums.

Staff

Thanks David,

Let's use the following assumptions:

  1. fn is a string.
  2. listIn is a list composed entirely of numbers or entirely strings. If numbers, fn will perform its operation on the entire vector of input values. If character, it will perform the operation on the individual elements.
  3. The order in which the arguments appear in argList is the same order to be used in fn.

Hopefully that makes things a bit clear. Again, if not, please let me know.

Super User

That is perfectly clear, and I'm happy to work with those assumptions.

 

However (sorry!) I can immediately think of a counter-scenarios: the JMP functions Concat Items and Contains process entire lists rather than individual elements.  And whereas I would want Sum to apply to the entire list, I would want Round to apply to elements.  (Could we not have a flag parameter to indicate whether the function operates at the list level or at the level of individual elements).

 

Sorry again, I feel like I am being a pain.

Staff

No problems! This helps elucidate the issues with trying to do this. Let's add a flag as the last argument to applyFunction to indicate whether it should be applied list-wise or element-wise.

applyFunction(inList,fn,argList,flag)

Super User

Just time to maybe squeeze one last question.  ArgList - is is a list of arguments or an actual JMP list:

 

applyFunction(inList,fn,a,b,c,flag)

or

applyFunction(inList,fn,{a,b,c},flag)

If I don't hear from you I will assume it can be either!

Staff

@David_Burnham I was assuming the 2nd.

Super User

Thanks!