function [newCountVec, newCount, hitFlag, hitIndex] = ...
vectorCounter(xEnd, xStart, hitList, oldCountVec, oldCount)
% Updates an iterator over a variable number of variable length vectors (specified by first and last elements).
% it is useful to travel over the vertices of multidimensional lists, flow graphs, hypercubes and so on.
%
% vecCount() updates a counter from an initial vector to a final vector.
% Optionally, a list of count values can be compared to the current count and if one matches, a flag is set.
% When the current count matches the final count, it is flagged as done.
%
% inputs: (all 5 are required)
% xEnd - vector of final values to compare against the current vector count (can be negative)
% xStart - initial vector of count values (can be negative)
% hitList - optional list of count values (not vectors) to compare against the current count
% oldCountVec - vector of the last count vector returned by this function (last values fed back in)
% oldCount - old scalar count returned by this function (last values fed back in)
%
% outputs: newCountVec - (required) new vector of count values
% newCount - (optional) new scalar count
% hitFlag - (optional) true of scalar count matches any of hitList OR current and end vector counts match
% hitIndex - (optional) index of hitList member matching the current count. 0 if function is done.
%
% demo:
% vectorCounter; % <== no input arguments
%
% This function does NOT provide an enumerated list of values, rather you call it iteratively
% from within a loop. If you want such a list, follow the example and wrap this function in a loop
%
% example:
% ---------------- cut and paste --------------
% clc
% doneFlag = false; % not done
% lastVec = [2 3 4]; % end vector
% firstVec = [1 1 1]; % start vector (default for a 3-element vector)
% thisCount = 0; % start (scalar) count is usually 0 or 1 (c vs matlab)
% thisVec = firstVec; % first vector is usually set to start
% hitList = [12, 14, 50]; % want to find the 12th, 14th and 50th count elements flagged
%
% while(doneFlag == false)
%
% [thisVec, thisCount, hitFlag, hitIndex] = vectorCounter(lastVec, firstVec, hitList, thisVec, thisCount);
%
% fprintf('[');
% fprintf('%3d ', thisVec);
% fprintf(']');
% if(~isempty(thisCount)), fprintf('%3d ', thisCount); else fprintf(' -- '); end
% fprintf('%3d ', hitFlag);
% fprintf('%3d\n', hitIndex);
% if(hitFlag == true)
% if(hitIndex == 0),
% break;
% end
% end
% end
% ------------end cut and paste ---------------
%
%
% --- Iterative call results ---
% thisVec thisCount hitFlag hitIndex
% ------------------------------------------------
% [1 1 1] 0 0
% [2 1 1] 1 0
% [1 2 1] 2 0
% [2 2 1] 3 0
% [1 3 1] 4 0
% [2 3 1] 5 0
% [1 1 2] 6 0
% [2 1 2] 7 0
% [1 2 2] 8 0
% [2 2 2] 9 0
% [1 3 2] 10 0
% [2 3 2] 11 0
% [1 1 3] 12 1 1 <- first flag (flag at 12)
% [2 1 3] 13 0
% [1 2 3] 14 1 2 <- second flag (flag at 14)
% [2 2 3] 15 0
% [1 3 3] 16 0
% [2 3 3] 17 0
% [1 1 4] 18 0
% [2 1 4] 19 0
% [1 2 4] 20 0
% [2 2 4] 21 0
% [1 3 4] 22 0
% [2 3 4] 23 1 0 <- done flag (3rd flag at 50 was never encountered)
% ---------------------------------------------------
%
% (C) michaelB brost Feb 2009
%
% algorithm
if(nargin == 0),
% demo mode?
doDemo;
return;
end
% initialize potential outputs for early function termination
newCountVec = [];
newCount = [];
hitFlag = true;
hitIndex = 0;
if(nargin ~= 5),
error('must have 5 inputs\n');
return;
end
if(nargout < 1),
error('must use at least 1 output\n');
return;
end
%check lengths
if(length(xStart) ~= length(xEnd))
error('start and end vectors must have same lengths');
end
if(length(xStart) ~= length(oldCountVec))
error('count, start and end vectors must have same lengths');
end
% check end >= start
for k1=length(xEnd):-1:1,
if(xStart(k1) > xEnd(k1)),
error(sprintf('start > end at index %d', k1));
end
end
% check start <= current count
for k1=length(xStart):-1:1,
if(oldCountVec(k1) < xStart(k1)),
error(sprintf('count < start at index %d', k1));
end
end
% check end >= current count
for k1=length(xEnd):-1:1,
if(oldCountVec(k1) > xEnd(k1)),
error(sprintf('count > end at index %d', k1));
end
end
% increment the counter checking for various conditions
newCountVec = oldCountVec;
newCountVec(1) = newCountVec(1) + 1;
hitFlag = false;
hitIndex = [];
carryFlag = false;
for k1=1:length(newCountVec),
if(newCountVec(k1) > xEnd(k1)),
newCountVec(k1) = xStart(k1);
if(k1 < length(newCountVec))
newCountVec(k1+1) = newCountVec(k1+1) + 1;
carryFlag = true;
else,
carryFlag = true;
break;
end
else,
carryFlag = false;
end
end
% are we done?
if(carryFlag == true),
hitFlag = true;
hitIndex = 0;
% done
return;
end
% update overall count - assume it is correct
newCount = oldCount + 1;
% check overall count against count list we look for
hitIndex = find(newCount == hitList);
hitFlag = false;
if(~isempty(hitIndex)),
hitFlag = true;
end
% ------------------------------------- demo -----------------------------------
function doDemo
clc
fprintf('least significant count component is to the left\n');
fprintf('-----------------------------------------\n');
xStart = [-3 2 -1];
xEnd = [ 2 3 1 ];
hitList = [ 2 3 5 7 10 12 30 33];
fprintf('start condition: ');
fprintf('%3d ', xStart);
fprintf('\n');
fprintf('end condition: ');
fprintf('%3d ', xEnd);
fprintf('\n');
fprintf('hit conditions: ');
fprintf('%3d ', hitList);
fprintf('\n');
fprintf('pseudo code:\n');
fprintf(' do:\n');
fprintf(' [newVec, newCount, doneFlag, hitIndex] = vectorCounter(xEnd, xStart, hitList, oldVec, oldCount)\n');
fprintf(' oldVec = newVec\n');
fprintf(' oldCount = newCount\n');
fprintf('\n do something here .... \n\n');
fprintf(' until(doneFlag == true)\n');
fprintf('\n-----------------------------------------\n');
% I don't line infinite loops....
maxIter = 1e5;
nIter = 1;
newCountVec = xStart;
newCount = 0;
fprintf('old (scalar) count----old (vector) count-------hit index\n');
while(nIter < maxIter),
fprintf('%5d ', nIter);
fprintf(' [');
fprintf('%3d, ', newCountVec(1:(end-1)));
fprintf('%3d', newCountVec(end));
fprintf(']');
% iterative update of various quantities.....
[newCountVec, newCount, hitFlag, hitIndex] = vectorCounter(xEnd, xStart, hitList, newCountVec, newCount);
if(hitFlag == true),
fprintf(' %3d ', hitIndex);
if(hitIndex == 0),
fprintf(' <== DONE\n');
break;
else,
fprintf('\n');
end
else,
fprintf('\n');
end
nIter = nIter + 1;
end
fprintf('\n-----------------------------------------\n');
return;