function newnumbers = randomlyChangeNumbers(numbers)
% Returns a 1d-list of randomly generated numbers where each number is 
% guaranteed to be (1) drawn from among the same numbers that appear in the 
% original list but (2) different from the corresponding original number.
% The draw is uniform within the set of distinct numbers. No special 
% distribution is preserved.
%
% I use this to certainly corrupt a definite percentage of training labels.
% 
% Input:
%   numbers - 1d-array of numbers
%
% Return:
%   newnumbers - random numbers such that newnumbers(ind) ~= numbers(ind)
%                for any index.
%
% Example: 
%   An original list [1 1 4 5 4] could become for example [4 5 1 4 5] or
%   [4 5 5 4 5] but never [1 5 1 4 5].
%
allNums = unique(numbers);
if numel(allNums) == 1
    warning('mutil:randomlyChangeNumbers', 'Degenerate input with only one number');
end

newnumbers = zeros(size(numbers));
for num = allNums
    nowChanging = (numbers == num);
    shuffleBag = allNums(allNums ~= num);
    %randInts = randi(numel(shuffleBag), [1 sum(nowChanging)]);
    %Octave has no randi..
    randInts = ceil(rand(1, sum(nowChanging)) * numel(shuffleBag));
    newnumbers(nowChanging) = shuffleBag(randInts);
end
