МАТЛ, 30 28 26 24 байта
Mean/@N@Partition[#2,UpTo[2#+1],1,{-#-1,#+1}]&
Проверено на Matlab и Octave. Использование текущая версия (9.1.0) языка/компилятора.
Ввод: сначала число, управляющее длиной окна, затем массив с форматом. ćU˜©ε®NX@iX·>£ÅAV®¦©YëN>X+£ÅA}
ć Head extract (get n)
U Save in variable X
˜ Flat the list
© Save the list in register c
ε } Map
® Get the list from register c
NX@ Is the iteration greater than or equal to n
i if true
ë if false
X·> push (n*2)+1
£ extract (n*2)+1 elements from head
ÅA Arithmetic mean
V Save the result in variable Y
® Push the list from register c again
¦ remove head (first element)
© save the new list in register c
Y get variable Y (to apply on map returned value)
N>X+ push i+1+n (i=iteration index, loop count)
£ extract i+1+n elements from head
ÅA Arithmetic mean
.
РЕДАКТИРОВАТЬ (20 мая 2016 г.): Попробуйте онлайн! Код по ссылке имеет [n,[list_m]]
replaced by ćU˜©ε®NX@iX·>£ÅAV®¦©YëN>X+£ÅA}
чтобы соответствовать версии 18.0.0 языка.
Пример
F=(n,a)=>a.map((e,i)=>(s=a.slice(i<n?0:i-n,i+n+1))&&s.reduce((l,c)=>l+c)/s.length)
document.write('<pre>' +
[
[1, [12, 6, 3, 9], [9, 7, 6, 6] ],
[1, [1, 4, 5, 7, 10], [2.5, 3.333, 5.333, 7.333, 8.5] ],
[1, [1, 3, 3, 7, 4, 2, 4, 2], [2, 2.333, 4.333, 4.667, 4.333, 3.333, 2.667, 3] ],
[2, [1, 3, 5, 9, 10, 14, 15, 16, 23], [3, 4.5, 5.6, 8.2, 10.6, 12.8, 15.6, 17, 18] ],
[3, [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1] ],
[3, [1, 2, 3, 4, 5, 6, 7, 8], [2.5, 3, 3.5, 4, 5, 5.5, 6, 6.5] ]
].map(t => {
var [n, m, e] = t;
var r = F(n, m);
// verify to precision of 3 decimals
var test = r.every((v, i) => v.toPrecision(3) === e[i].toPrecision(3));
return 'F(' + n + ', [' + m + '])\t' + (test ? 'Pass' : 'Fail') +
'\n\t{' + r + '} ' + (test ? '=' : '≠') + ' {' + e + '}';
}).join('\n\n') +
'</pre>');
Объяснение
Эквивалентный код Matlab будет
F=(n,a)=>a.map((e,i)=>(s=a.slice(i<n?0:i-n,i+n+1))&&s.reduce((l,c)=>l+c)/s.length)
Код MATL использует недавно добавленные функции неявного ввода и автоматического буфера обмена для ввода функций:
<pre id=O></pre>
||answer||
f=(n,l,p=0)=>l.map((v,i)=>(p+=~l[i-n-1]-~l[i+n])/(n+1+Math.min(n,l.length-1-i,i)),l.map((v,i)=>p+=i<n&&v))
console.log=x=>O.textContent+=x+'\n';
;[
[1,[12,6,3,9],[9,7,6,6]]
, [1,[1,4,5,7,10],[2.5,3.333,5.333,7.333,8.5]]
, [1,[1,3,3,7,4,2,4,2],[2,2.333,4.333,4.667,4.333,3.333,2.667,3]]
, [2,[1,3,5,9,10,14,15,16,23],[3,4.5,5.6,8.2,10.6,12.8,15.6,17,18]]
, [3,[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]]
, [3,[1,2,3,4,5,6,7,8],[2.5,3,3.5,4,5,5.5,6,6.5]]
].forEach(t=>{
var n=t[0],l=t[1],x=t[2],r=f(n,l)
// verify (limited to 3 decimals)
var ok = r.every((v,i)=>v.toFixed(3)==x[i].toFixed(3))
console.log((ok?'OK ':'Fail ')+n+' '+l+' -> '+r+' ('+x+')')
})
Попробуйте онлайн!
@ngn предложил средний трюк, используя (l, n) => {
p = 0;
for (i = 0; i < n; i++) p += v;
r = [];
for (i = 0; i < l.length; i++) {
p += (l[i + n] || 0) - (i > n ? l[i - n - 1] : 0);
r.push(p / Math.min(n, l.length - i - 1, i);
}
return r;
}
, и я пошел еще дальше, сократив его на два байта, устранив необходимость (l,n,p=0)=>l.map((v,i)=>(p+=~l[i-n-1]-~l[i+n])/(n+1+Math.min(n,l.length-1-i,i)),l.map((v,i)=>p+=i<n&&v))
.
Поскольку входные данные представляют собой положительные целые числа, а заполнение Stencil дает только нули, достаточно усреднить ненулевые записи.
Трюк по умолчанию для среднего использования .OM sM .: + Means of flattens of sublists of length 2K+1 of
+ J *
] Y J is E copies of [].
K E Save E to a variable to use it later.
]MQ the input
J Put J on both sides of ]MQ.
h y K 2K+1
(matrix divide/solve linear equation/least squares fit) is "divide a vector by its all ones version", which solves the least squares of something like this:
.OMsM.:++J*]YKE]MQJhyK
где решение наименьших квадратов является в точности средним. Я изменил его, чтобы игнорировать нули при вычислении среднего значения:
t<-2*n+1 -- assign t to the maximum number of elements of a
-- of sublist
take t(inits x) -- build the sublists from t elements of the inits
++tails x -- of the input and the tails of the input,
-- e.g. x=[1,2,3,4], t=3:
-- [[],[1],[1,2]] ++ [[1,2,3,4],[2,3,4],[3,4],[4],[]]
a<-take t<$> -- take at most t elements from every sublist
,length a>n -- keep those with a minimum length of n+1
sum a/sum(1<$a) -- calculate average, "sum(1<$a)" is the length of a
Альтернативно, Extended может сделать то же самое в 15 байтах, используя тот факт, что левый аргумент всегда равен нулю (в отличие от «размера заполнения» в обычной версии Dyalog):
[3.0,4.5,5.6,8.2,10.6,12.8,15.6,17.0,18.0]
Попробуйте онлайн!
2 # [1,3,5,9,10,14,15,16,23]
Попробуйте эквивалентную программу 17.x онлайн!
Какой достойный вызов для трафарета Dyalog APL import Data.List
n#x|t<-2*n+1=[sum a/sum(1<$a)|a<-take t<$>take t(inits x)++tails x,length a>n]
.
Оператор Stencil извлекает движущееся окно из массива точно так, как описано в задаче. В частности, для нечетного размера окна окно центрируется над каждым элементом, при необходимости дополняется нулями вне массива, а затем величина заполнения задается в качестве дополнительной информации, так что один Drop f(n,m)=[mean(m[max(1,i-n):min(end,i+1)])for i=1:endof(m)]
will remove such padding. The rest is just specifying the right window size and taking average m.O:vzeS,0-dQh+dQUvz
по каждому подмассиву.
Иллюстрация
2n+1
Также возможен подход умножения матриц, но он недостаточно короткий:
n
Попробуйте онлайн!
Как это работает
n [m1 m2 ... mx]
||answer||
CJam, 31 30 байт
ri_S*l~1$++\2*)ew{S-_:+\,d/}%`
Формат ввода: {÷/⍵1+.ר⊂⍺≥|∘.-⍨⍳≢⍵} ⍝ Left:n, Right:m
⍳≢⍵ ⍝ 1..length of m
∘.-⍨ ⍝ Self outer product by difference
⍺≥| ⍝ 1 if abs diff is at most n, 0 otherwise
⍝ which gives the band matrix
⍵1+.ר⊂ ⍝ Inner product with m and all-one vector
÷/ ⍝ Divide left by right
.
Запустите все тестовые случаи. (Автоматически преобразует набор тестов в необходимый входной формат.)
Это работает путем предварительного и добавления {÷/⍵1+.ר⊂⍺≥|∘.-⍨⍳≢⍵}
spaces, then taking all substrings of length Input array: 12 6 3 9
Input n: 1
Window size: 3 (1+2×n)
Arguments to left operand of Stencil:
Left Right
1 0 12 6 ⍝ Zero padding 1 unit to the left; 1↓ drops 0 from the front
0 12 6 3
0 6 3 9
¯1 3 9 0 ⍝ Zero padding 1 unit to the right ¯1↓ drops 0 from the back
и снова удаляя пробелы перед вычислением их средних значений.