Specification: Return index of the first element you can remove that does not change the mean of the list by more than 0.1
Example input/output:
Input:
vals| id | value |
|---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 1 |
Output:
1Python - Imperative
def get_mean(ls):
sum = 0
for e in ls:
sum += e['value']
return sum/len(ls)
def changing_mean(vals):
start_mean = get_mean(vals)
for i,elem in enumerate(vals):
new_ls = vals[:i] + vals[i+1:]
mean = get_mean(new_ls)
if abs(mean - start_mean) < 0.1:
return i
return None
Python - Functional
def changing_mean(vals):
start_mean = sum([l['value'] for l in vals])/len(vals)
diff = lambda m, sm: abs(m - sm)
for i,elem in enumerate(vals):
new_ls = [x['value'] for x in vals if x != elem]
mean = sum(new_ls)/len(new_ls)
if diff(mean,start_mean) < 0.1:
return i
return None
Python - Pandas
def changing_mean(vals): mean = vals.value.mean() mean_without = vals.apply(lambda row: vals[vals.id != row.id].value.mean(), axis=1) return vals[(mean_without - mean).abs() < 0.1].id.tolist()
R - Tidyverse
library(data.table)
changing_mean <- function(vals) {
global_mean <- mean(vals$value)
setDT(vals)[,
mean_change := abs(global_mean - mean(vals[id != .BY, value])),
by = id] %>%
filter(mean_change < 0.1) %>%
slice(which.min(id)) %>%
pull(id)
}SQL - SQLite
SELECT id FROM vals v1 WHERE ABS(( SELECT AVG(value) FROM vals v2 WHERE v1.id != v2.id ) - (SELECT AVG(value) FROM vals)) < 0.1
Datalog - Souffle
.decl avg_except(I:number, Avg:float)
avg_except(I, Avg) :-
vals(I, _),
N = sum 1.0 : { vals(J, _), I != J },
Total = sum V : { vals(J, V), I != J },
Avg = Total / N.
changing_mean(I) :-
vals(I, _),
N = sum 1.0 : vals(_, _),
Total = sum V : vals(_, V),
Avg = Total / N,
avg_except(I, AvgExcept),
((Avg > AvgExcept, Avg - AvgExcept < 0.1);
(Avg < AvgExcept, AvgExcept - Avg < 0.1)).Q - kdb+
diffs:
{abs avg vals[`value] - avg (vals[`value] where vals[`id] <> x)}
each vals[`id];
changing_mean: first vals[`id] where diffs < 0.1