您的位置:首页 > 编程语言 > MATLAB

[matlab]mathworks上的cody challenge题解及一些常用函数的总结(7)

2013-08-27 22:06 633 查看
Part 7. Problem 61 - Problem 70.

Problem 61. Find state names that end with the letter A

% Given a list of US states, remove all the states that end with the letter A.
%
% Example:
%
%  Input  s1 = 'Alabama Montana Nebraska Vermont Nevada';
%  Output s2 is '   Vermont ';

function s2 = refcn(s1)
s2 = [];
s1 = regexp(s1, 'New \w*a\>|North \w*a\>|West \w*a\>|\w*a\>', 'split');
for k = 1:length(s1)
s2 = [s2 s1{k}];
end

UPD: 用regexprep改写。

function ans = refcn(s)
regexprep(s, '\<((New|North|West) )?\w*a\>', '');
end


Problem 62. Elapsed Time

% Given two date strings d1 and d2 of the form yyyy/mm/dd HH:MM:SS (assume hours HH is in 24 hour mode), determine how much time, in decimal hours, separates them. Assume d2 is always later than d1.
%
% Example:
%
%  Input d1 = '2010/12/14 12:00:00'
%  Input d2 = '2010/12/14 13:06:36'
%  Output elapsed is 1.11

function elapsed = elapsed_time(d1, d2)
elapsed = 24*(datenum(d2) - datenum(d1));

datenum可以将一个日期格式的字符串转换为距离0/0/0 0:00:00的时间,单位是小时。

Problem 63. Encode Roman Numerals

% Create a function taking a non-negative integer as its parameter and returning a string containing the Roman Numeral representation of that integer.
%
% By convention, "modern" Roman numerals are written by expressing each digit separately starting with the leftmost digit and skipping any digit with a value of zero.
%
% Examples
%
%     If n is 1990 then romStr = 'MCMXC' since 1000=M, 900=CM, 90=XC.
%     If n is 2008 then romStr = 'MMVIII' since 2000=MM, 8=VIII.
%     If n is 1666 then romStr = 'MDCLXVI'.
%     If n is 0 then romStr is empty ([] and '' are both acceptable)
%
% n will always be an integer between 0 and 3999 (inclusive).
%
% This problem is adapted from Rosetta Code.

function romStr = dec2rom(n)
roman = {'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'};
num = {1000 900 500 400 100 90 50 40 10 9 5 4 1};
romStr = [];
for k = 1:length(num)
while (n >= num{k})
romStr = [romStr roman{k}];
n = n - num{k};
end
end

Problem 64. The Goldbach Conjecture, Part 2

% The Goldbach conjecture asserts that every even integer greater than 2 can be expressed as the sum of two primes.
%
% Given the even integer n, return c, the number of different ways two primes can be added to result in n. Only count a pair once; the order is unimportant.
%
% Example:
%
%  Input  n = 10
%  Output c is 2
%
% because of the prime pairs [3 7] and [5 5].
%
%  Input  n = 50
%  Output c is 4
%
% because of [3 47], [7 43], [13 37], and [19 31].

function c = goldbach2(n)
hn = floor(n/2+0.1); c = 0;
for k = 2:hn
if isprime(k) && isprime(n - k)
c = c + 1;
end
end

UPD: 用sum和all改写。

function ans = goldbach2(n)
sum(arrayfun(@(x) all([isprime(x) isprime(n-x)]), 1:floor(n/2+0.1)));
end


Problem 65. Word Counting and Indexing

% You are given a list of strings, each being a list of words divided by spaces. Break the strings into words, then return a master word table of all the words and an indexed version of each string.
%
% The master list should have no repeated entries and should be sorted in alphabetical order.
%
% Example
%
% If str_list = {'one two three','two one four zero'}
%
% then
%
%     word_table = {'four','one','three','two','zero'}
%     str_index_list = {[2 4 3],[4 2 1 5]}.
%
% Notice that no words are repeated in word_table, and each string in the string_list can be regenerated by referencing into the word_table using the string_index_list.

function [word_table,str_index_list] = word_index(str_list)
table = containers.Map();
for k = 1:length(str_list)
now = regexp(str_list{k}, ' ', 'split');
for l = 1:length(now)
if ~table.isKey(now{l})
table(now{l}) = 1;
end
end
end
word_table = table.keys();
str_index_list = {};
mpidx = containers.Map();
for k = 1:length(word_table)
mpidx(word_table{k}) = k;
end
for k = 1:length(str_list)
now = regexp(str_list{k}, ' ', 'split');
nowret = [];
for l = 1:length(now)
key = mpidx(now{l});
nowret = [nowret key];
end
str_index_list = [str_index_list nowret];
end

UPD: 循环套循环...改进后也挺复杂的...看看有没更好的方法...

function [table idx] = word_index(list)
a = cellfun(@(x) regexp(x, ' ', 'split'), list, 'UniformOutput', false);
table = unique([a{:}]);
idx = cellfun(@(x) arrayfun(@(y) find(strcmp(y, table)), x), a, 'UniformOutput', false);
end


Problem 66. Find the two-word state names

% Given a list of states, remove all the states that have two-word names.
%
% If
%
%  s1 = 'Alabama Montana North Carolina Vermont Nevada';
%
% then
%
%  s2 = 'Alabama Montana  Vermont Nevada';

function ans = refcn(s1)
regexprep(s1, '\<(New|North|West|South|Rhode) \w*\>', '');

今天看别人的代码,发现了一个比regexp更好用的函数,就是regexprep。

它可以将匹配到的正则表达式替换为需要的字符串。这里把它替换为空串。

Problem 67. Find common elements in matrix rows

% Given a matrix, find all elements that exist in every row.
%
% For example, given
%
%  A =
%      1 2 3 5
%      9 2 5 9
%      3 2 5 9
%      1 2 1 5
%      5 1 3 2
%
% the answer would be the vector '2 5'. Elements should be returned sorted ascending.
%
% Note there is no guarantee that there are any such elements; if there are none, the routine should return the empty set. Also, the matrix might contain NaNs, repeats, or very large or very small elements.

function y = common_by_row(x)
sx = size(x); y = [];
for k = 1:sx(2)
now = x(1,k);
flag = 1;
for l = 2:sx(1)
if isempty(find(x(l,:) == now, 1))
flag = 0;
end
end
if ~isempty(find(y == now, 1))
flag = 0;
end
if flag
y = [y now];
end
end
y = sort(y);

UPD: 1*0的矩阵和0*0的矩阵是不同的...

function u = common_by_row(x)
u = unique(x)';
u = u(arrayfun(@(y) all(any(y == x, 2)), u));
if isempty(u) u = []; end
end


Problem 68. Kaprekar Steps

% 6174 is the Kaprekar constant. All natural numbers less than 10,000 (except some with same digits) can be reduced to 6174 in the following steps:
%
% Order the digits of the number in descending and ascending order and compute the difference. Repeat the process till you get 6174.
%
% Example
%
% n = 2376
%
% Digits in descending order = 7632
%
% Digits in ascending order = 2367
%
% Step1:
%
%  >> 7632 - 2367
%  ans = 5265
%
% Step 2:
%
%  >> 6552 - 2556
%  ans = 3996
%
% Step3:
%
%  >> 9963 - 3699
%  ans = 6264
%
% Step4
%
%  >> 6642 - 2466
%  ans = 4176
%
% Step5
%
%  >> 7641 - 1467
%  ans = 6174
%
% Total number of steps = 5.
%
% Your function should return the number of Kaprekar steps for a given input. Numbers such as 2222 will end in zero. These numbers will never result in 6174. They should return Inf.

function y = KaprekarSteps(x)
step = 0; now = x;
while now ~= 0 && now ~= 6174
now = num2str(now);
first = sort(now, 'ascend');
4000

second = sort(now, 'descend');
if length(now) < 4
first = [zeros(1, 4-length(now))+'0', first];
second = [second, zeros(1, 4-length(now))+'0'];
end
% first, second
now = abs(str2num(first) - str2num(second));
step = step + 1;
end
if now == 0
y = Inf;
else
y = step;
end

UPD: num2str可以控制转换格式,在这里可以用'%04d'来控制。利用这个功能可以写得简洁多了。

function y = KaprekarSteps(x)
y = 0;
while x ~= 0 && x ~= 6174
x = abs(str2double(sort(num2str(x, '%04d'), 'ascend')) - str2double(sort(num2str(x, '%04d'), 'descend')));
y = y + 1;
end
if x == 0
y = Inf;
end
end


Problem 69. Find the peak 3n+1 sequence value

% A Collatz sequence is the sequence where, for a given number n, the next number in the sequence is either n/2 if the number is even or 3n+1 if the number is odd. See Problem 21 for more information.
%
% Let c(n) be the sequence for n, and p(n) be the peak value of that sequence. For a given threshold nmax, find the highest peak value max(p(n)) for all Collatz sequences starting with integers between 1 and nmax.

function pmax = peakOfPeaks(nmax)
pmax = nmax;
for k = 1:nmax
now = k;
while now ~= 1
if mod(now, 2) == 0
now = now/2;
else
now = 3*now + 1;
end
pmax = max(pmax, now);
end
end

Problem 70. Alphabetize by last name

% Given a list of names in a cell array, sort the list by the last name. So if
%
%  list = {'Barney Google','Snuffy Smith','Dagwood Bumstead'};
%
% then the output is
%
%  alpha_list = {'Dagwood Bumstead','Barney Google','Snuffy Smith'}

function alpha_list = alphabetize(list)
sl = size(list);
tmp = cell(length(list), 2);
for k = 1:length(list)
now = list{k};
tmp{k, 1} = now;
now = regexp(now, '\w*$', 'match');
tmp{k, 2} = now{1};
end
tmp = sortrows(tmp, 2);
alpha_list = cell(1, length(list));
for k = 1:length(list)
alpha_list{k} = tmp{k, 1};
end
if sl(1) ~= 1
alpha_list = alpha_list';
end


UPD: 一开始用sortrows做不出来,后来发现可以先用sort排序,然后原数组按排序后的下标组合。

function ans = alphabetize(list)
cellfun(@(x) regexp(x, '\w*$', 'match'), list, 'UniformOutput', false);
[~, ans] = sort([ans{:}]);
list(ans);
end


今天看了不少leading solutions,发现自己的代码就是渣渣。往后考虑看一下以前的代码,如果有更好的方法会修改一下。

如果有更为简单的方法,请给我留言,谢谢!

允许转载,转载请注明出处: http://blog.csdn.net/lkjslkjdlk/article/details/10364415
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息