Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
1K views

Homework Solutions - MATLAB

This document provides MATLAB code solutions to various homework problems. It includes solutions to problems involving matrix indexing and operations, conditional logic, loops, and other MATLAB programming concepts. Multiple solutions are sometimes provided to illustrate alternative approaches. Descriptive comments are included with some solutions to explain the logic and techniques used.

Uploaded by

achueth
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

Homework Solutions - MATLAB

This document provides MATLAB code solutions to various homework problems. It includes solutions to problems involving matrix indexing and operations, conditional logic, loops, and other MATLAB programming concepts. Multiple solutions are sometimes provided to illustrate alternative approaches. Descriptive comments are included with some solutions to explain the logic and techniques used.

Uploaded by

achueth
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Solutions to Homework 3

Problem odd_index:
function out = odd_index(M)
out = M(1:2:end, 1:2:end);
end
Problem int_col:
function v = int_col(n)
v = [n 1:n-1]';
end

Note that this is just one possible solution. There are many others.

Problem rich:
function usd = rich(cent)
usd = [0.01 0.05 0.10 0.25] * cent';
end

We use the fact that matrix multiplication sums up a set of products. Multiplying a row
vector with a column vector will result in a scalar. Here it performs the exact calculations
we need.

Problem light_time:
function [mins km] = light_time(mile)
km = mile * 1.609;
mins = km / 3e5 / 60;
end
Problem pitty:
function c = pitty(ab)
c = sqrt(ab(:,1) .^ 2 + ab(:,2) .^2);
end

Problem pitty (alternative solution):


function c = pitty(ab)
c = sqrt(sum(ab' .^ 2))';
end

Here we use the fact that the function sum works column by column. So, transposing and
then squaring every element will put the squares of the corresponding a-s and b-s into
columns. The function sum then adds them up, and sqrt computes each element's
square root. Finally, we need to transpose the result back into a column vector.

Problem bottom_left:
function M = bottom_left(N,n)
M = N(end-n+1:end, 1:n);
end

We need the last n rows and the first n columns. The only trick here is that we need endn+1, because end-n:end would get us n+1 indexes and not n as required.

Problem mean_squares:
function mm = mean_squares(nn)
mm = mean((1:nn).^2);
end
Problem hulk:
function H = hulk(v)
H = [v' (v').^2 (v').^3];
end

Solutions to Homework 4
Problem quadrants:
function Q = quadrants(n)
a = ones(n);
Q = [a 2*a ; 3*a 4*a];
end

Problem checkerboard:
function b = checkerboard(n,m)
b = ones(n,m);
b(1:2:n,2:2:m) = 0;
b(2:2:n,1:2:m) = 0;
end

Problem randomness:
function r = randomness(limit,n,m)
r = fix(limit * rand(n,m)) + 1;
end
Problem mtable:
function [t s] = mtable(n,m)
t = (1:n)' * (1:m);
s = sum(t(:));
end

If we matrix multiply a column vector of length N by a row vector of length M, each


element of the resulting N-by-M matrix will be the product of one element from each
vector. Therefore, we can create a multiplication table by setting the column vector to 1:N
and the row vector to 1:M and using matrix multiplication.

Problem identity:
function I = identity(n)
I = zeros(n);
I(1 : n+1 : n^2) = 1;
end

Here we index into a matrix with a single index and MATLAB handles it as if it was a
vector using column-major order. Putting ones at the first position and jumping n+1 every
time, will put them exactly in the diagonal.

Solutions to Homework 5
Here are the "official" solutions. Note that there are multiple ways to solve any non-trivial problem,
so these are just representative examples.

Problem generationXYZ
function gen = generationXYZ(year)
if year < 1966
gen = 'O';
elseif year < 1981
gen = 'X';
elseif year < 2000
gen = 'Y';
elseif year < 2013
gen = 'Z';
else
gen = 'K';
end
end

Problem generationXYZ (alternative solution)


Using no if-statements
function gen = generationXYZ(yr)
opts = {'O','X','Y','Z','K'}; % Create cell array of options
idx = 1 + sum(yr >= [1966,1981,2000,2013]); % Calculate index by comparing year
to edge values
gen = opts{idx};
end

Problem letter_grade
function G = letter_grade(score)
if score >= 91
G = 'A';
elseif score >= 81
G = 'B';
elseif score >= 71
G = 'C';
elseif score >= 61
G = 'D';
else
G = 'F';
end
end

Problem sort3
Using no built-in functions
function v = sort3(a, b, c)
if a <= b
v = [a b];
else
v = [b a];
end
if c >= v(2)
v = [v c];

% a and b in v are ordered. Where to insert c?


% at the end

elseif c <= v(1)


v = [c v];
else

% at the beginning

v = [v(1) c v(2)]; % in the middle


end
end

Problem sort3
Using no if-statements.
function v = sort3 (a,b,c)
v = [a b c];

% unordered

v = [min(v(1),v(3)) v(2) max(v(1),v(3))]; % the 1st and 3rd are in order


v = [min(v(1),v(2)) max(v(1),v(2)) v(3)]; % move 2nd left if necessary
v = [v(1) min(v(2),v(3)) max(v(2),v(3))]; % move 2nd right if necessary
end

Problem classify
function c = classify(x)
[row, col] = size(x);
if row == 0 || col == 0

% any dim == 0 -> empty

c = -1;
elseif row == 1 && col == 1

% both dim == 1 -> scalar

c = 0;
elseif row == 1 || col == 1

% none of the above, but one dim == 1 -> vector

c = 1;
else
c = 2;
end
end

Problem classify (alternative solution)


function c = classify(x)
mindim = min(size(x));

maxdim = max(size(x));
if mindim == 0

% if one dim == 0, it must be empty

c = -1
elseif maxdim == 1 % otherwise, both dim == 1 (since max == 1) -> scalar
c = 0;
elseif mindim == 1 % otherwise, if the smaller dim == 1 -> vector
c = 1;
else
c = 2;
end
end

Problem classify (alternative solution)


Using no if-statements
function y = classify (x)
d = size(x);
p = prod(d);

% multiplies the two dims

y = -1 +(p>=1) +(p>1) +(min(d)>1) % each added condition increases the answer


by one
end

% Note that the first two solutions are longer but easier to read and understand than this
one.

Problem older
function a = older(y1,m1,d1,y2,m2,d2)
a = 1;
if y1 == y2 && m1 == m2 && d1 == d2
a = 0;
elseif (y1 > y2) || (y1 == y2 && m1 > m2) || (y1 == y2 && m1 == m2 && d1 > d2)

a = -1;
end
end

Problem older (alternative solution)


Using no if-statements
function a = older(y1,m1,d1,y2,m2,d2)
a1 = y1 * 366 + m1 * 31 + d1;

% does not have to be exact date in days...

a2 = y2 * 366 + m2 * 31 + d2;

% it simply makes a1 and a2 comparable

a = sign(a2 - a1);

% sign() returns -1, 0 or 1, just what is needed

end

% multiplying by 366 or greater is needed because of leap years

Problem movies
function cando = movies(hr1,min1,durmin1,hr2,min2,durmin2)
cando = false;
endtime = hr1*60 + min1 + durmin1;

% convert times to minutes

starttime = hr2*60 + min2;


if endtime <= starttime && endtime + 30 >= starttime % so we can compare them
cando = true;
end
end

Problem movies (alternative solution)


Using no if-statement
function cando = movies(h1,m1,d1,h2,m2,d2)
end1 = h1*60 + m1 + d1;
st2 = h2*60 + m2;

cando = (end1 <= st2 && end1+30 >= st2);


end

Problem sines
function [s1 s2 sums] = sines(pts,amp,f1,f2)
if nargin < 1, pts = 1000;

end

if nargin < 2, amp = 1;

end

if nargin < 3, f1 = 100;

end

if nargin < 4, f2 = f1*1.05; end


t = 0 : 2*pi/(pts-1) : 2*pi;
s1 = amp * sin(f1*t);
s2 = amp * sin(f2*t);
sums = s1 + s2;
end

% The sin() function has a full period between 0 and 2*pi.


% To set up the vector t, dividing by (pts-1) is needed
% because n points in a line define (n-1) consecutive segments
% and not n. For example, two points define a single line segment.
% The function call sin(f1*t) will create exactly f1 full periods
% using vector t defined above.

Problem moving average


function a = moving_average(x)
persistent xp;
if isempty(xp)
xp = x;

% first time, the buffer simply contains x

elseif length(xp) < 25


xp(end+1) = x;
else

% while fewer than 25 elements, keep adding x to the buffer

xp = [xp(2:end),x];
end

% replace first (oldest) element by shifting to the left

% and inserting x at the end

a = mean(xp);
end

Problem moving average (alternative solution)


Using no if-statement
function avg = moving_average (in)
persistent buffer;
buffer = [in buffer(1:end-(length(buffer) == 25))];
avg = mean(buffer);
end

% This is an illustration of a short, but tricky solution. However,


% a longer, but more readable solution is always preferred, therefore,
% the first solution is better!
%
% This one works by realizing that we do not need to check whether the
% buffer is empty or not, since [x buffer] will work either way.
% The tricky part is how the length is handled. While the buffer is
% shorter than 25, buffer(1:end) is used. Once it reaches 25, it turns
% into buffer(1:end-1), exactly what is needed.

Solutions to Homework 6

Problem neighbor
function w = neighbor(v)
w = [];
if min(size(v)) == 1

% must be a vector

for ii = 1:length(v)-1

% if length is less than 2, loop won't do anything

w(ii) = abs(v(ii+1) - v(ii));


end
end
end

Problem neighbor (alternative solution)


no explicit loop
function w = neighbor(v)
if length(v) < 2 || min(size(v)) ~= 1 % must be a vector of at least two elements
w = [];
else
w = abs(v(1:end-1)-v(2:end));
end

% take the difference of two subvectors

% of length (n-1)

end

Problem replace_me
builds up the output one element at a time
function w = replace_me(v,a,b,c)
if nargin < 3
b = 0;

end
if nargin < 4
c = b;
end
w = [];
for k = 1:length(v);
if v(k) == a

% if a is found,

w = [w,b,c];
else

% we insert b and c at the end of the current w

% otherwise,

w = [w,v(k)]; % we insert the original element of v


end
end
end

Problem replace_me (alternative solution)


only changes the output vector when an instance of a is found
function w = replace_me(v,a,b,c)
if nargin < 3
b = 0;
end
if nargin < 4
c = b;
end
w = v;

% make w the same as v

wi = 1;

% wi is used to index into w

for vi = 1:length(v)
if v(vi) == a
w = [w(1:wi-1) b c w(wi+1:end)];
wi = wi + 1;

% insert b and c at position wi

% increment wi

end
wi = wi + 1;

% wi is incremented in either case

end
end

Problem halfsum
using nested loops
function s = halfsum(A)
[row col] = size(A);
s = 0;
for ii = 1:row
for jj = ii:col

% the column index only starts at the current row index

s = s + A(ii,jj);
end
end
end

Problem halfsum (alternative solution)


using a single loop and sum
function s = halfsum(A)
[nr,~] = size(A);
s = 0;
for r = 1:nr

% for each row

s = s + sum(A(r,r:end));

% sum adds up the elements right of the diagonal

(inclusive)
end

% in the current row

end

Problem large_elements
function found = large_element(A)

[row col] = size(A);


found = [];
for ii = 1:row
for jj = 1:col
if A(ii,jj) > ii + jj

% if the element is larger than the sum of its indexes

found = [found; ii jj]; % add a new row to the output matrix


end
end
end
end

problem one_per_n
using while-loop
function n = one_per_n(x)
n = 0;
sum = 0;
while sum < x && n <= 10000
n = n + 1;
sum = sum + 1/n;
end
if n > 10000
n = -1;
end
end

problem one_per_n (alternative solution)


using for-loop
function n = one_per_n(x)
s = 0;

for n = 1:1e4
s = s + 1/n;
if s >= x
return;
end
end
n = -1;
end

Problem approximate_pi
function [a,k] = approximate_pi(delta)
k = 0;
f = sqrt(12);
a = f;

% compute sqrt(12) only once


% the value of a for k == 0

while abs(pi-a) > delta


k = k + 1;

% while we are further away than delta


% increment k

a = a + f*(-3)^(-k)/(2*k+1);

% add increment to current value of a

end
end

Problem separate_by_two
using division and rounding
function [even,odd] = separate_by_two(A)
even = A(fix(A/2) == A/2)'; % if A is even, rounding does not do anything to A/2
odd = A(fix(A/2) ~= A/2)'; % if A is odd, it gets rid of the .5 part, so they won't be
equal
end
% note that this will put non-integers into odd

Problem separate_by_two (alternative solution)


using mod (or rem)
function [even, odd] = separate_by_two(A)
even = A(mod(A,2) == 0)'; % mod gives 0 if even
odd = A(mod(A,2) == 1)'; % mod gives 1 if odd
end
% note that this one will not put non-integers in any of the outputs

Problem separate_by_two (alternative


solution)
using mod (or rem)
function [even,odd] = separate_by_two(A)
mod2 = logical(mod(A,2));
even = A(~mod2)';

% modulo 2 is zero for even numbers (logical false), so we

need to negate it
odd = A(mod2)';

% modulo 2 is non-zero for odd numbers, that is, logical true

end
% note that this will put non-integers into odd

Problem divvy
function A = divvy (A,k)
L = (mod(A,k) ~= 0);
A(L) = k * A(L);

% creates a logical matrix based on divisibility by k

% changes only the non-divisible elements of A by multiplying

them by k
end
% uses A as both input and output, so we only need to modify some elements of A

Problem divvy (alternative solution)


single line solution
function I = divvy(I,k)
I(mod(I,k) ~= 0) = I(mod(I,k) ~= 0) * k;
end
% same solution as above, but it repeats the modulo computation

Problem square_wave
using a for-loop
function sq = square_wave(n)
t = 0 : 4*pi/1000 : 4*pi;

% setup vector according to the specs

sq = zeros(1,length(t));

% initialize output to 0

for ii = 1:2:2*n

% run for first n odd numbers (2k-1)

sq = sq + cos(ii*t-pi/2)/ii;

% add the next cosine term

end
end

Problem square_wave (alternative solution)


tricky code with no explicit loops
function s = square_wave(n)
t = 0 : 4*pi/1000 : 4*pi; % setup vector according to the specs
idx = (2*(1:n)' - 1);

% make column vector of fist n odd numbers (2k-1)

% idx*t makes a matrix; each row is (2k-1)*t, for a given k


% idx*ones(size(t)) also makes a matrix; each element of row k is just (2k-1)
% sum down the columns
s = sum(sin(idx*t) ./ (idx*ones(size(t))),1);
end

% the second argument to sum is needed in case n is 1


% remember that sum(x) sums x along columns unless x is a row vector!

Problem my_prime
using a for-loop
function a = myprime(n)
a = false;
if n > 1

% 1 is by definition not prime

for ii = 2:sqrt(n)

% see explanation below

if ~mod(n,ii)
return;
end
end
a = true;
end
end
% x is prime if it is NOT divisible by all integers from 2 to sqrt(x)
% because factors have to come in pairs -- one bigger than sqrt(x) and
% one smaller (or both equal)

Problem my_prime (alternative solution)


with no explicit loops
function prim = myprime(p)
v = 2:sqrt(p);
v = v(rem(p,v) == 0);

% if p is prime, none of the remainders can be 0

prim = ~length(v) && (p ~= 1); % so if v has any elements, p is not prime


end

% 1 is handled by the (p ~= 1) condition

Solutions to Homework 7

Problem integerize
traditional solution with a single if-elseif-statement
function name = integerize(A)
mx = max(A(:));
name = 'NONE';
if mx <= intmax('uint8')
name = 'uint8';
elseif mx <= intmax('uint16')
name = 'uint16';
elseif mx <= intmax('uint32')
name = 'uint32';
elseif mx < intmax('uint64')
name = 'uint64';
end
end

Problem integerize (alternative solution)


using a cell vector of strings and a for-loop instead
function cl = integerize(A)
cls = {'uint8'; 'uint16'; 'uint32'; 'uint64'};
cl = 'NONE';
mx = max(A(:));
for ii = 1:length(cls)
if intmax(cls{ii}) >= mx
cl = cls{ii};

break;
end
end
end

Problem integerize (alternative solution)


using a cell vector of strings and vector indexing instead
function iclass = integerize(A)
c = {'uint8','uint16','uint32','uint64','NONE'};
% Array of maximum values for each class
x = 2.^[8,16,32,64] - 1;
% Index into names, based on size of largest element of A
iclass = c{sum(max(A(:))>x)+1};
end

Problem May2015
function sub_May2015
days = ['Thu'; 'Fri'; 'Sat'; 'Sun'; 'Mon'; 'Tue'; 'Wed' ];
for ii = 1:31
m(ii).month = 'May';
m(ii).date = ii;
m(ii).day = days(rem(ii,7)+1,:); % +1 is needed because 0 is an invalid index
end
end

Problem June2015
traditional solution with a for-loop
function m = June2015
days = [ 'Sun'; 'Mon'; 'Tue'; 'Wed'; 'Thu'; 'Fri'; 'Sat'];

for ii = 1:30
m{ii,1} = 'June';
m{ii,2} = ii;
m{ii,3} = days(rem(ii,7)+1,:);
end
end

Problem June2015 (alternative solution)


using MATLAB built-in functions instead
function x = June2015
% Make vector of dates for June 2015
t = datetime(2015,6,1:30);
% Make a cell array from the components of t
x = cat(1,month(t,'name'),num2cell(day(t)),day(t,'shortname'))';
end

Problem codeit
traditional solution, looking at one char at a time
function out = codeit(in)
for ii = 1:length(in)
if in(ii) <= 'z' && in(ii) >= 'a'
out(ii) = 'a' + 'z' - in(ii);

% lower case
% encrypt it

elseif in(ii) <= 'Z' && in(ii) >= 'A' % upper case
out(ii) = 'A' + 'Z' - in(ii);
else
out(ii) = in(ii);
end
end
end

% encrypt it
% everything else
% no change needed

Problem codeit (alternative solution)


using logical indexing instead, the input and the output arguments are the same
function txt = codeit (txt)
U = txt > 64 & txt < 91;

% identify uppercase

L = txt > 96 & txt < 123; % identify lowercase


txt(U) = char(155-txt(U)); % encrypt uppercase
txt(L) = char(219-txt(L)); % encrypt lowercase
end

Problem dial
translating the actual requirements straight to code works, but it is pretty long and somewhat
awkward
function ph = dial(str)
code = {'ABC'; 'DEF'; 'GHI'; 'JKL'; 'MNO'; 'PRS'; 'TUV'; 'WXY'};
ph = str;

% set the output to the input

for ii = 1:length(str)
c = str(ii);

% the current char from the input

if c == ' ' || c == '-' || c == '(' || c == ')'


ph(ii) = ' ';

% these characters need to turn into spaces

continue;
elseif (c >= '0' && c <= '9') || c == '#' || c == '*'
continue;

% these need to remain unchanged

else
n = -1;
for jj = 1:length(code)
if ~isempty(strfind(code{jj},c)) % looking for legal letters
n = jj + 1;
break;

% Found it! ABC on the dial maps to 2 not 1, hence the +1

end
end
if n == -1
ph = [];

% if we did not find a valid letter


% need to return []

return;
end
ph(ii) = char('0' + n); % otherwise, add the char for the right number
end
end
end

Problem dial (alternative solution)


no loop and a single if-statement
function ph = dial(str)
% the variable code has the characters' required mapping starting from space, ending
with Y
% x is for illegal input (e.g., see how Q maps to x in-between 7-s)
code = ' xx#xxxx *xx xx0123456789xxxxxxx2223334445556667x77888999';
ph = [];

% default return value in case of illegal input

n = str-' '+1; % creates a vector of indexes into code from the input characters
% the first two sum()-s check for out-of-range input (smaller than space or larger than
Y)
% the third sum() checks for any input char mapping to x, that is, illegal input
if ~((sum(n <= 0) + sum(n > length(code))) || sum(code(n) == 'x'))
ph = code(n); % a single assignment does the actual transformation of the input
string
end
end

Problem replace
using a for-loop and logical indexing
function strs = replace(strs,c1,c2);
for ii=1:length(strs)
strs{ii}(strs{ii} == c1) = c2;

% for each string in the cell vector


% replace all c1-s with c2-s at once

end
end

Problem roman
problem size is small, so it is easier to simply enumerate all 20 numbers
function num = roman(rom)
romans = { 'I' 'II' 'III' 'IV' 'V' 'VI' 'VII' 'VIII' 'IX' 'X' ...
'XI' 'XII' 'XIII' 'XIV' 'XV' 'XVI' 'XVII' 'XVIII' 'XIX' 'XX'};
num = uint8(0);
for ii = 1:20
if strcmp(rom,romans{ii})
num = uint8(ii);
break
end
end
end

Problem roman (alternative solution)


using find() instead of a loop
function ar = roman(str)
allstr = {'I','II','III','IV','V','VI','VII','VIII','IX','X',...
'XI','XII','XIII','XIV','XV','XVI','XVII','XVIII','XIX','XX'};
ar = find(strcmp(allstr,str)); % find() returns the indexes of non-zero elements

if isempty(ar)
ar = 0;

% if no match, input is bad


% no need to convert to uint8 yet

end
ar = uint8(ar);

% convert to uint8

end

Problem censor
function out = censor(strs,str)
out = {};
for ii = 1:length(strs)

% creates the output from scratch


% for each string in the cell vector

if isempty(strfind(strs{ii},str)) % if the substring is not found


out = [out strs{ii}];
end
end
end

% the current string goes into the output

You might also like