Edit: -2 bytes because I ended with ;\n}
when I could just end with a }
, silly mistake.
Edit 2: -22 more bytes by reading about general JS golfing tips. I managed to take out parentheses from my nested ternaries in the r
rounding function, and used bitwise math operations to avoid using Math.floor
and Math.ceil
Edit 3: -13 bytes because I was able to replace the a.length
shortcut function with just direct calls to a.length
to save 4 bytes. I also moved the g() function directly into the return statement, since it was only used once, which removed the rest of the bytes.
a=>{s=i=>a.splice(i,1)
e=_=>a.reduce((t,i)=>t+=i)/a.length
r=n=>(m=n%1,m<0.75?m>0.25?~~(n)+0.5:~~(n):n%1?-~n:n)
return a.length>2?r((a.sort((x,y)=>x-y),s(0),s(-1),e())):r(e())}
Try it online!
I'm sure it can be improved as I'm fairly new, but it was fun to solve this one. I believe the main things that could be improved are my rounding logic/methods, and the fact that the main function uses a function body ({ }
and return
).
There was one thing in the question that was inconsistent with the examples and I wasn't really sure how to handle it. I implemented it so that it's consistent with the examples, but it doesn't exactly reflect the specified rounding rules, here is the example I found to be inconsistent:
6.5, 9 -> 8
You say it should be 8, although the average is 7.75. In the rounding rules you say it has to be at least .76 to go +1. I chose to reflect the examples instead of your rounding rules, so >=0.75 to go +1, and <=0.25 to go -1, between 0.25 and 0.75 (exclusive) for .5. If the rounding specifications change, my code should be able to adapt without changing the number of bytes, by just changing the numbers in the rounding function r
, and maybe the order of the ternary statement depending on the rules.
Slightly ungolfed with explanation (the math operations were changed to bitwise operations and g() is directly in the return statement)
a => { // a is the input array
s = i=>a.splice(i, 1); // shortcut to remove index i for 1 element
e = _=>a.reduce((t, i) => t += i) / a.length; // get array avg
g = _=>(a.sort((x,y)=>x-y), s(0), s(-1), e()); // what to execute when > 2: sort, remove 1st/last, get avg
t = n=>Math.floor(n); // Math.floor shortcut
// apply olympic rounding to number by checking the value of n%1
r = n=>(m=n%1,m < 0.75 ? (m > 0.25 ? t(n) + 0.5 : t(n)) : Math.ceil(n));
// if arr length > 2: round g(), otherwise round e()
return a.length > 2 ? r(g()) : r(e());
}
6.5, 9
disagrees with your spec which indicates that x.75 rounds to x.5. \$\endgroup\$