You are on page 1of 7

4/27/01

Loop Programming Patterns (preliminary)


by John R. Glover A software pattern is a reusable solution to a recurring problem that arises within a certain context and system of forces. Patterns can be described at three levels: architectural patterns, design patterns, and programming patterns. Programming patterns (idioms , coding patterns ) are low-level patterns specific to a programming language. Experienced programmers automatically call upon these patterns when they see that one is appropriate to the task. A pattern has (at least) a name, a problem to be solved, a standard solution, and examples that illustrate it. (For these low-level patterns, we will omit the context and forces.) Let's look at a few. Since these are all loop programming patterns, for simplicity they will be expressed in terms of problems involving values in an array. Name: Loop Condition Problem: A test must be applied to each value in a vector. Solution: Use an if statement to apply the test inside a for loop. Example: % Display all negative values in the vector for n = 1:length(x) if x(n) < 0 disp(x(n)) end end Name: Counter Problem: It is necessary to count occurrences of some condition in the loop. Solution: Maintain a separate counter variable. Example: % Count the negative values counter = 0; %initialize counter for n = 1:length(x) if x(n) < 0 count = count + 1; %increment counter end end

Page 1 of 7

4/27/01 Name: Compute from Index Problem: A value must change with each pass through the loop, but that value is not the loop variable. Solution: Compute the value using the loop variable. Example: % Compute values of sin(t) for n = 1:101 t = (n-1)*2*pi/100; %compute from loop variable y(n) = sin(t); end Name: Separate Index Problem: The loop variable is not suitable for an array index, but one is needed. Solution: Maintain a separate array index. Example: % Compute values of sin(t) n = 1; %initialize separate index for t = 0:2*pi/100:2*pi y(n) = sin(t); n = n + 1; %increment index end Name: Second Index (similar to Separate Index) Problem: It is necessary to index through two arrays at a different rate, so the loop variable can be used for only one. Solution: Maintain a second array index incrementing at the different rate. Example: % Copy just the negative values into a new vector index2 = 1; %initialize second index for n = 1:length(x) if x(n) < 0 y(index2) = x(n); index2 = index2 + 1; %incr second index end end

Page 2 of 7

4/27/01 Name: Flag Variable Problem: It is necessary to mark the occurrence of an event in the loop so that you know it has occurred, either on the next pass through the loop or when you exit the loop. Solution: Maintain a Boolean flag variable. The flag's state indicates whether the event has occurred Example (On exit from loop, the flag indicates whether the event occurred in the loop.): % Look for a specified value in the vector target = input('Enter value to be found:'); found = 0; %not found yet for n = 1:length(x) if x(n)==target found = 1; %found end end if found do something end Example (On each pass through the loop, the flag indicates whether the event occurred on a previous pass through the loop, perhaps putting the code in a different "mode."): % How many times does a positive follow a negative % in the vector x? count = 0; negfound = 0; % flag=1 if negative found last pass for n = 1:length(x) % First, was a negative found on previous pass? if negfound if x(n)>0 %...yes, so is this now a positive? count = count + 1; end end % In any case, set flag for next pass negfound = x(n)<0; % true only if this value negative end disp(count)

Page 3 of 7

4/27/01 Name: Early Exit Problem: Part way through the loop, there is no longer a need to continue it. Solution: Exit early when the exit condition is detected (Flag Variable is probably needed so that you will know that the early exit occurred). Example: % Look for a specified value in the vector target = input('Enter value to be found:'); found = 0; %not found yet for n = 1:length(x) if x(n)==target found = 1; %found break; end end if found do something end

Name: Early Return Problem: Part way through execution of a function, the answer is computed and there is no need to continue the function. Solution: Return immediately without executing the remainder of the code. Example: function result = sumsquares(x) % SUMSQUARES Return avg of squares of x values unless % one of them is negative, in which case return zero total = 0; for n = 1:length(x) if x(n)<0 result = 0; return % oops, a zero, immediate return else total = total + x(n)^2; end result = total/length(x)

Page 4 of 7

4/27/01 Name: Extreme Value Problem: A value must be located that stands out from every other value encountered in the loop. Solution: Maintain a separate extreme so far variable, initialized to the first value. Example: % Find the largest value in the vector maxval = x(1); %largest so far for n = 2:length(x) %continue with 2nd value if x(n) > maxval maxval = x(n); %replace with new max value end end Name: Extreme Initial Value Problem: We want to know which value best meets a condition, but we cannot easily (or do not wish to) initialize to a first candidate. Solution: Initialize the answer to an extreme or impossible value, knowing that it will be updated on the first pass through the loop. Example: % Find the largest absolute value in the vector absmax = -1; %will be changed immediately for n = 1:length(x) %start with the first if abs(x(n)) > absmax absmax = abs(x(n)); %replace end end Name: Save Index Problem: The result desired is the index of the array value meeting the condition. Solution: Use a separate index variable to save the desired index. Example: % Clear the last negative value in the vector to zero saveIndex = 0; %no index yet for n = 1:length(x) if x(n) < 0 saveIndex = n; %save new index end end if saveIndex > 0 x(saveIndex) = 0; %clear value at last index end Note: This is combined with a variation of the Flag Variable pattern, since the nonzero value of saveIndex indicates that a negative value was found.

Page 5 of 7

4/27/01 Name: Factor Out Invariants Problem: In a loop it is necessary to repeatedly use the result of a function call or other computation, although that result does not change. Solution: Improve efficiency by taking the function call or computation outside the loop. Example, inefficient solution: % Find the value closest to target value: cos(pi/5) closest = x(1); %closest so far for n = 2:length(x) %continue with 2nd value if abs(x(n)-cos(pi/5)) < abs(closest-cos(pi/5)) closest = x(n); %save new closest value end end disp(['Closest is:' num2str(closest)]) Example, factoring out the invariant computations : % Find the value closest to target value: cos(pi/5) closest = x(1); %closest so far target = cos(pi/5); distance = abs(closest-target); for n = 2:length(x) %continue with 2nd value if abs(x(n)-target) < distance closest = x(n); %save new closest value distance = abs(closest-target); % and new distance end end disp(['Closest is:' num2str(closest)]) Note: The Extreme Value pattern is also used in this example.

Page 6 of 7

4/27/01 Name: Swap/Exchange Problem: We need to exchange two values in a vector. Solution: Perform the exchange through a separate swap variable. Example: % Reverse the elements in a vector for n = 1:fix(length(x)/2) m = length(x)-n+1; %index backwards from end swap = x(n); x(n) = x(m); x(m) = swap; end Note: The Second Index pattern is also used in this example. Note: Efficiency of this example could be improved by using the Factor Out Invariants pattern: % Reverse the elements in a vector len1 = length(x)+1; %precompute invariant for n = 1:fix(length(x)/2) m = len1-n; %index backwards from end swap = x(n); x(n) = x(m); x(m) = swap; end Name: Two Questions Problem: We want a complex result that is not easily answered by a single pattern. Solution: Recognize that two (or more) questions are really being asked, and devise the appropriate combination of patterns as the solution. Example: % Are there more than 25 values greater than 100? count = 0; %init counter found = 0; %init flag for n = 1:length(x) if x(n) > 100 count = count + 1; if count > 25 found = 1; break; end end end if found disp('Yes, more than 25 values were found.') end Note: Patterns used are Counter, Flag Variable , and Early Exit.

Page 7 of 7