270 likes | 422 Views
Week 11 - Programming IV. Today 1. Vectorization to simplify programs 2. Structured software Definition: array operations versus loops masks ( indicator arrays ) math with masks addressing with masks array functions. Structured Programming. Manage complexity Readable
E N D
Week 11 - Programming IV Today 1. Vectorization to simplify programs 2. Structured software Definition: array operations versus loops • masks (indicator arrays) • math with masks • addressing with masks • array functions
Structured Programming • Manage complexity • Readable • Testable • Reusable • Maintainable
Structured Programming • Hierarchical • Modules are divided into smaller and smaller submodules (functions work well as modules) • functions contain functions • Modular • Simple independent modules with well defined inputs and outputs • Locality • Minimize inputs and outputs • Generate values inside the module where possible
Example 1 – clipping a time plot to [-1,1]: Time (sec.) Time (sec.)
Method 1 – using a loop and branch: for k = 1:length(y) if y(k) > 1 y(k) = 1; elseif y(k) < -1 y(k) = -1; end end
“mask” arrays to indicate locations with relevant characteristics Method 2 – using mask math: p = y>1; n = y<-1; y = (1-p).*(1-n).*y + p - n; or p = y>1; n = y<-1; y = ~p.*~n.*y + p - n; use masks either mathematically or logically
Method 3 – using mask addressing: p = y>1; or n = y<-1; y(p) = 1; y(y>1) = 1; y(n) = -1; y(y<-1) = -1; mask determines which elements to change
size with second argument 1 returns the number of rows Method 1 – loop and branch: for k = 1:size(score,1) if score(k,1) < score(k,2) score(k,:) = score(k,[2 1]); end end
identify which rows to swap Method 2 – using mask addressing: flip = score(:,1)<score(:,2); score(flip,[1 2]) = score(flip,[2 1]) and reverse them
Example 3: sorting (last week) Given N numbers (x1,…xN), sort them into increasing order 3 1 4 5 2 7 1 0 1 2 3 4 5 7
start 3 1 4 5 2 7 0 0 1 4 5 2 7 3 0 1 4 5 2 7 3 0 1 2 5 4 7 3 0 1 2 3 4 7 5 0 1 2 3 4 7 5 0 1 2 3 4 5 7 done Original program employed nested loops:
function array = simpsort(array) % function to sort from smallest to largest for k = 1:length(array)-1 loc = k; for k2 = k:length(array) if array(k2)<array(loc) loc = k2; end end if loc ~= k array([k,loc ]) = array([loc,k]); end end locate the index (loc) of the smallest value swap values, if necessary
Method 2 – using array functions function array = simpsort(array) % vectorized version of simpsort for k = 1:length(array)-1 [ val, loc ] = min( array(k:end) ); array([k,loc+k-1]) = array([loc+k-1,k]); end note offset to loc of k-1 since min( ) works on a subarray
Example 4: matrix sorting (HW 7-15) Sort a 4 by 7 matrix
Method 1 – brute force loop and branch: for r1 = 1:4 for c1 = 1:7 val = inf; for r2 = 1:4 for c2 = 1:7 end end result(r1,c1) = val; mat(rloc,cloc) = inf; end end outer loops (r1,c1) build result inner loops (r2,c2) locate minimum if mat(r2,c2) < val val = mat(r2,c2); rloc = r2; cloc = c2; end after finding minimum (val, rloc, cloc) “erase” it using infinity
Method 2 – simpler loop and branch using min operator: for r = 1:size(mat,1) for c = 1:size(mat,2) [val,loc] = min(mat(:)); result(r,c) = val; mat(loc) = inf; end end loops (r,c) still build result minimum value and location identified by array operation Note mat(:) after finding minimum at (loc) erase it using infinity Note scalar addressing into mat
Example 5: tic-tac-toe winner • Find the winner in a 3-by-3 tic-tac-toe board. Assume representations: • Empty cell = 0 • X = +1 • O = – 1
16 checks in all Problems: tedious not directly expandable no help on next move Method 1 – brute force condition testing if board(1,:)==ones(1,3) disp('X won') elseif board(1,:)==-ones(1,3) disp('O won') elseif board(2,:)==ones(1,3) disp('X won') … elseif [board(1,1),board(2,2),board(3,3)] == … … end
Method 2 – use loops: for k = 1:3 if board(k,:)==ones(1,3) | board(:,k)==ones(3,1) disp('X won') elseif board(k,:)== -ones(1,3) | board(:,k)== -ones(3,1) disp('O won') end end plus tests for diagonals (no loop advantage here)…
Method 3 – use mask and array operations: cols = sum(board); rows = sum(board'); diag1 = trace(board); diag2 = trace(board(:,[3 2 1])) checks = [ cols, rows, diag1, diag2 ]; if any(checks == 3) disp('X won') elseif any(checks == -3) disp('O won') end –1,0,+1 representation is very useful with summing!
Other array functions simplify the diagonal tests: diag1 = sum(sum(board.*eye(3,3))); diag2 = sum(sum(board.*[0 0 1; 0 1 0; 1 0 0])); diag1 = sum(diag(board)); diag2 = sum(diag(fliplr(board))); diag grabs just the diagonal elements fliplr = flips the array left to right (also see flipud)
Summing allows looking for a potential win: if any(checks == 3) disp('X won') elseif any(checks == -3) disp('O won') elseif any(checks == -2) disp('X could win now!') elseif any(checks == 2) disp('O could win now') end
function drawgame %DRAWGAME draws the tic-tac-toe board x = [ -1 -1 4 4]; y = [ -1 4 4 -1]; fill(x,y, 'w'); % Use a white box background. hold on hx1 = [ 0 3 ]; hy1 = [ 1 1 ]; % Horizontal line at y = 1 hx2 = [ 0 3 ]; hy2 = [ 2 2 ]; % Horizontal line at y = 2 vx1 = [ 1 1 ]; vy1 = [ 0 3 ]; % Vertical line at x = 1 vx2 = [ 2 2 ]; vy2 = [ 0 3 ]; % Vertical line at x = 2 plot(hx1,hy1,'k',hx2,hy2,'k',vx1,vy1,'k',vx2,vy2,'k') axis off, axis square return
[n, m] = getmove(player) function [n, m] = getmove(player) %GETMOVE asks a tic-tac-toe player to pick a square. %GETMOVE draws an X on the tic-tac-toe square chosen if player == 1 and a O if player == 2. %GETMOVE returns the indices of the board square selected. [x y]= ginput(1); % Use cursor to pick a square. m = ceil(x); % m is the column index. It corresponds to x. n = 4 - ceil(y); % n is the row index. It corresponds to 4 - y. % Shift and invert so board does not appear up side down if player == 1 % 1 in the array board, X in figure text(ceil(x)-.5, ceil(y)-0.5, 'X', 'fontsize',20,'horizontalalignment','center', 'color',[0 1 0]) end if player == 2 % -1 in the array board, O in figure text(ceil(x)-0.5, ceil(y)-0.5, 'O', 'fontsize',20,'horizontalalignment','center', 'color',[1 0 0]) end return
% Lecture 11 demo board = zeros(3); drawboard player = 1; while any(~all(board)) % Keep going as long as any 0s remain. [n, m] = getmove(player) player = 3 - player; % player toggles between 1 and 2. board(n,m) = 3 - 2*player; % 3-2*player = either -1 or +1 % 3-2 = 1 if player = 1 and 3-4 = -1 if player = 2 end board
winner = check4win(board) function winner = check4win(board) % CHECK4WIN checks the tic-tac-toe board for a win. winner = 0; if any(sum(board)==3) |any(sum(board')==3) | trace(board)==3 |trace(board(:,[3 2 1]))==3 winner = 1; end if any(sum(board)==-3) |any(sum(board')==-3) | trace(board)==-3 |trace(board(:,[3 2 1]))==-3 winner = 2; end return