function [J, grad] = coFiCoFu(params, Y, R, n_users, n_movies, n_features, L)
 % [J, grad] = COFICOSTFUNC(params, Y, R, n_users, n_movies, n_features, L)
 % returns the cost and gradient for the collaborative filtering problem.
 %
 % Unfold the U and W matrices from params
 X = reshape(params(1:n_movies * n_features), n_movies, n_features);
 Q = reshape(params(n_movies * n_features + 1:end), n_users, n_features);
	
 J = 0;
 X_grad = zeros(size(X));
 Q_grad = zeros(size(Q));

 J = 0.5 .* sum(sum(((X*Q').*R - Y.*R).^2)) + ...
    (L./2.*sum(sum(Q.^2))) + (L./2.*sum(sum(X.^2)));
 % Only predict rating X*Q' if user has rated (i.e. R=1)

 X_grad = (((X*Q').* R * Q - Y .* R * Q) + L .* X);

 Q_grad = ((X' * ((X*Q') .*R ) - X' * (Y .*R )))' + L .* Q;
	
 grad = [X_grad(:); Q_grad(:)];
end