# A nice solution on MATLAB Cody problem #73

MATLAB Cody is a useful place not only for having the compelling to solve different interesting problems in the smartest way, but for learning from the solutions of others. Now a very clever solution on Cody problem #73 is discussed. The task is:

Replace NaNs with the number that appears to its left in the row. If there are more than one consecutive NaNs, they should all be replaced by the first non-NaN value to the immediate left of the left-most NaN. If the NaN is in the first column, default to zero.

An example input and output pair is:

x = [NaN 1 2 NaN NaN 17 3 -4 NaN] y = [ 0 1 2 2 2 17 3 -4 -4]

The straightforward solution is to use a cycle while each NaNs are replaced. In the example below we put first a zero to the beginning of the array to handle the case of the NaNs at the front. Then in a cycle we find the position of the first NaN, and replace it with the previous element:

function x = replace_nans(x) x = [0 x] % put a zero into the first position

while any(isnan(x)) % loop until there is any NaN NaNList = isnan(x) % get a logical list of NaNs NaNPos = min(find(NaNList)) % find the position of the first NaN x(NaNPos) = x(NaNPos - 1) % new value: the value on the left end x(1) = [] % remove the zero from the first position end % an example usage of the function replace_nans([NaN 1 2 NaN NaN 17 3 -4 NaN]);

The output of the function is:

x = 0 NaN 1 2 NaN NaN 17 3 -4 NaN NaNList = 0 1 0 0 1 1 0 0 0 1 NaNPos = 2

x = 0 0 1 2 NaN NaN 17 3 -4 NaN NaNList = 0 0 0 0 1 1 0 0 0 1 NaNPos = 5

x = 0 0 1 2 2 NaN 17 3 -4 NaN NaNList = 0 0 0 0 0 1 0 0 0 1 NaNPos = 6

x = 0 0 1 2 2 2 17 3 -4 NaN NaNList = 0 0 0 0 0 0 0 0 0 1 NaNPos = 10

x = 0 0 1 2 2 2 17 3 -4 -4 x = 0 1 2 2 2 17 3 -4 -4

Most of the solutions use this approach, but Ankur Pawar had another way of thinking. See his code first, it has been modified a bit for better understanding:

function x = replace_nans(x) NotNaNs = ~isnan(x) % positions of non-NaN elements indices = cumsum(NotNaNs) % indexing based on non-NaN positions

% filter for non-NaN elements and put a zero into the first position NotNaNList = [0 x(NotNaNs)] x = NotNaNList(indices + 1) % do the re-indexing of the vector end % an example usage of the function x = [NaN 1 2 NaN NaN 17 3 -4 NaN] replace_nans(x);

The output of the function is:

x = NaN 1 2 NaN NaN 17 3 -4 NaN NotNaNs = 0 1 1 0 0 1 1 1 0 indices = 0 1 2 2 2 3 4 5 5 NotNaNList = 0 1 2 17 3 -4 x = 0 1 2 2 2 17 3 -4 -4

This is a very clever solution using no loops:

- First a logical array is generated indicating the non-NaN elements.
- The next step is the key: the cumulated summation. The result of this operation is a list of indices, showing that which non-NaN element shall stay at the given position: in the
*indices*vector from the left to the right the index is inceremented only, when we reach a non-NaN element otherwise it remains the same. - Then we collect the non-NaN elements and add a zero to handle the case of the first-placed NaNs.
- The re-indexing is left only: we are ready.

A simple but great and useful approach: thanks, Ankur!