找回密码
 注册
Simdroid-非首页
查看: 1172|回复: 65

【讨论】正则系列

[复制链接]
发表于 2013-6-15 23:25:06 | 显示全部楼层 |阅读模式 来自 河北廊坊
本帖最后由 qibbxxt 于 2013-6-16 00:06 编辑

元音第一集
题目如下:
找出字符串中元音字母出现的次数
x='string the MaTLaBiAn'
在这个字符串中,元音字母依次为iaaBiA,一共出现了6次
x='coUnt the vowEl'
在这个字符串中,元音字母依次为oUoEI,一共出现了5次
写一个函数来完成,输入字符串,输出出现元音字符次数
可以用下列例子来测试
  1. 1
  2. %%
  3. x='coUnt the vowEl';
  4. y_correct = 5;
  5. assert(isequal(vowel_counter(x),y_correct))

  6. 2
  7. %%
  8. x='coUnt the vowEl counter';
  9. y_correct = 8;
  10. assert(isequal(vowel_counter(x),y_correct))

  11. 3
  12. %%
  13. x='The fox was the jackle';
  14. y_correct = 6;
  15. assert(isequal(vowel_counter(x),y_correct))

  16. 4
  17. %%
  18. x='Education';
  19. y_correct = 5;
  20. assert(isequal(vowel_counter(x),y_correct))

  21. 5
  22. %%
  23. x='We are the MaTLaBiAns';
  24. y_correct = 8;
  25. assert(isequal(vowel_counter(x),y_correct))
复制代码
题目来源:http://www.mathworks.cn/matlabcentral/cody/problems/1559-count-vowel
发表于 2013-6-15 23:30:24 | 显示全部楼层 来自 新疆乌鲁木齐
Simdroid开发平台
本帖最后由 bainhome 于 2013-6-15 23:46 编辑

先来个非正则的,把楼歪掉,其他同仁再用正则给“正”回来:
  1. function ans = vowel_counter(x)
  2. lower(x);
  3. sum(ans==97|ans==101|ans==105|ans==111|ans==117);
  4. end
复制代码
祁工提供了一个相同思路但更高效的代码:
  1. nnz(bsxfun(@eq,lower(x),['aeiou']'))
复制代码
回复 不支持

使用道具 举报

发表于 2013-6-16 00:19:30 | 显示全部楼层 来自 英国
  1. sum(arrayfun(@(x0) numel(x0),regexp(x,'[aeoiu]')))
复制代码

点评

考虑了大小写,贴上来时漏掉了,更改一下:sum(arrayfun(@(x0) numel(x0),regexpi(x,'[aeoiu]'))) 与楼下相比,sum和arrayfun显得多余了,呵呵。  发表于 2013-6-16 06:05
回复 不支持

使用道具 举报

发表于 2013-6-16 04:56:09 | 显示全部楼层 来自 英国
本帖最后由 nwcwww 于 2013-6-16 05:37 编辑
  1. function ans = vowel_counter(x)
  2.   numel(regexpi(x, '[aeiou]'));
  3. end
复制代码
再小就要用dynamic了吧。
另:lin兄的答案好像没有考虑大小写?
回复 不支持

使用道具 举报

发表于 2013-6-16 05:52:49 | 显示全部楼层 来自 英国
补充一个用dynamic regular expression的解:
  1. function y = vowel_counter(x)
  2.   regexp('','(?@ y=numel(regexpi(x, ''[aeiou]''));)');
  3. end
复制代码
回复 不支持

使用道具 举报

 楼主| 发表于 2013-6-16 08:26:55 | 显示全部楼层 来自 河北廊坊
来了非正则的
  1. nnz(ismember(lower(x),'aeiou'))
复制代码
回复 不支持

使用道具 举报

发表于 2013-6-16 13:52:30 | 显示全部楼层 来自 北京
曲线救国一把
  1. numel(x)-numel(regexprep(lower(x),'[aeiou]',''))
复制代码

点评

正则系列的意思是,主题就不系列了,一个主题里,让题目系列吧,这样好管理也便于查找。最后再在1楼出个索引即可。  发表于 2013-6-16 20:30
嗯,英雄所见略同,后面还会一点一点的出的  发表于 2013-6-16 18:02
perfect,这个正则系列是不是标题可以写正则系列之【一】,可以出很多期  发表于 2013-6-16 16:29
不错,应该也可以这样 numel(regexprep(lower(x),'[^aeiou]',''))  发表于 2013-6-16 15:13
回复 不支持

使用道具 举报

发表于 2013-6-16 20:39:47 | 显示全部楼层 来自 新疆乌鲁木齐

题目2——All Capticals?

本帖最后由 bainhome 于 2013-6-17 02:01 编辑

让正则再飞一会儿:
cody练习原题见:Pro.129:All Capticals?
  1. Are all the letters in the input string capital letters?
  2. Examples:
  3. 'MNOP' -> 1
  4. 'MN0P' -> 0
复制代码
测试例子如下:
  1. 1 %%
  2. x = 'MNOP';
  3. y_correct = 1;
  4. assert(isequal(your_fcn_name(x),y_correct))

  5. 2 %%
  6. x = 'MN0P';
  7. y_correct = 0;
  8. assert(isequal(your_fcn_name(x),y_correct))

  9. 3 %%
  10. x = 'INOUT1NOUT';
  11. y_correct = 0;
  12. assert(isequal(your_fcn_name(x),y_correct))

  13. 4 %%
  14. x = 'UPANDDOWN';
  15. y_correct = 1;
  16. assert(isequal(your_fcn_name(x),y_correct))

  17. 5 %%
  18. x = 'RUaMATLABPRO';
  19. y_correct = 0;
  20. assert(isequal(your_fcn_name(x),y_correct))
复制代码
但是在评论中有个建议不错:
  1. Des Mc Manuson 6 Dec 2012:
  2. the description of the problem is misspecified. "Are all the letters in the input string capital letters?" Numbers are not letters. The tests treat numbers as lower case.
复制代码
可以做做。

正则类,至少意图正则的题目最大特点是灵活和多解,这个系列自然要多弄几个,等告一段落我们再总结讨论吧。
回复 不支持

使用道具 举报

 楼主| 发表于 2013-6-16 20:49:42 | 显示全部楼层 来自 河北廊坊
本帖最后由 qibbxxt 于 2013-6-16 20:51 编辑
bainhome 发表于 2013-6-16 20:39
让正则再飞一会儿:
cody练习原题见:Pro.129:All Capticals?测试例子如下:但是在评论中有个建议不错:可 ...
  1. function y = your_fcn_name(x)
  2.   y =  length(regexp(x,'[A-Z]{1}')) == length(x);
  3. end
复制代码
大致解释一下:逐个匹配大写字母,每次匹配一个,这样计算出大写字母的个数和字符串的个数如果相等,则全是大写字符,否则,不是
回复 不支持

使用道具 举报

发表于 2013-6-16 20:56:08 | 显示全部楼层 来自 英国
  1. function y = your_fcn_name(x)
  2.   regexp('','(?@ y = all(x-lower(x)));)');
  3. end
复制代码
这个其实不是正则了。。

点评

其实我们都不是囿于正则的字面意思的,后面还有后续题目,这只是个开始。  发表于 2013-6-16 22:21
嗯,非正则的写法也可以的,比如all(isstrprop(x,'upper'))  发表于 2013-6-16 21:40
回复 不支持

使用道具 举报

发表于 2013-6-16 21:12:47 | 显示全部楼层 来自 北京
本帖最后由 liuyalong008 于 2013-6-16 21:22 编辑

bainhome 发表于 2013-6-16 20:39
让正则再飞一会儿:
cody练习原题见:Pro.129:All Capticals?测试例子如下:但是在评论中有个建议不错:可 ...
  1. numel(regexp(x,'[^A-Z]'))==0
复制代码
  1. isempty(regexprep(x,'[A-Z]',''))
复制代码
回复 不支持

使用道具 举报

发表于 2013-6-17 11:54:07 | 显示全部楼层 来自 北京
本帖最后由 liuyalong008 于 2013-6-17 11:55 编辑

题目三:找出电话区号
Problem 91. Get the area codes from a list of phone numbers
问题描述:

  1. Given a string of text with phone numbers in it, return a unique'd cell array of strings that are the area codes.
  2. s = '508-647-7000, (508) 647-7001, 617-555-1212';
  3. then
  4. a = {'508','617'}
复制代码

  1. % 验证:
  2. %%
  3. s = '508-647-7000, (508) 647-7001, 617-555-1212, 1-800-323-1234, 704 555-1212';
  4. a = {'508','617','704','800'};
  5. assert(isequal(refcn(s),a))
  6. %%
  7. s = '212-657-0260; (888) 647-7001; 336 565-1212; +1-800-323-1234';
  8. a = {'212','336','800','888'};
  9. assert(isequal(refcn(s),a))
复制代码
回复 不支持

使用道具 举报

发表于 2013-6-17 17:21:18 | 显示全部楼层 来自 英国
  1. areacode = regexp(s,'\(?(\d{3})\)?(?=[ -]\d{3}\-\d{3,4})','tokens');
  2. areacode_unique = unique([areacode{:}])
复制代码

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2013-6-17 18:19:16 | 显示全部楼层 来自 英国
  1. function y = refcn(s)
  2.   '(\d{3})(?=\D+\d{3}-\d{4})';
  3.   regexp('','(?@ y=unique(regexp(s, ans, ''match''));)');
  4. end
复制代码

点评

抱歉抱歉,弱智错误:居然直接F9,忘了这是带输入输出的函数,可运行.正写读书笔记,动态正则最后出一个section做专题,暂时不放在前面的解题思路中。  发表于 2013-6-29 02:05
试了下,可以跑啊。这个就是solution 262252, cody上也通过了的。 www.mathworks.cn/matlabcentral/cody/problems/91-get-the-area-codes-from-a-list-of-phone-numbers/solutions/262252  发表于 2013-6-29 00:29
代码无法通过,nwcwww兄检查一下?  发表于 2013-6-28 13:28
个人深深觉得look around 是regexp的精华之一,变数很多,以后可以多做讨论  发表于 2013-6-18 22:05
另外我这两个解只是利用了dynamic这种“作弊”手段而已,称不上真正的leading  发表于 2013-6-18 06:09

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2013-6-17 20:45:07 | 显示全部楼层 来自 河北
  1. unique(feval(@(x)x(1:3:end),regexp(s,'\d{3}','match')));
复制代码

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2013-6-19 18:38:54 | 显示全部楼层 来自 河北廊坊

题目四: Count letters

原题目见Count letters occurence in text, specific to words with a given length.
  1. Build a function with two input arguments: a string and a word length (number of letters), that outputs a vector of counts of the 26 letters of the alphabet, specific to words with a given length.

  2. Case insensitive.
  3. Words contain only letters a-zA-Z, but the string can contain punctuation.
  4. Example

  5. >> txt = 'Hello World, from MATLAB' ;
  6. >> nl  = 5 ;                              % Number of letters.
  7. >> nlWords_getCounts(txt, nl)
  8. ans =
  9.      0  0  0  1  1  0  0  1  0  0  0  3  0  0  2  0  0  1  0  0  0  0  1  0  0  0
  10. here, two 5 letters words are found: 'Hello' and 'World'. The output vector is the count of letters (1 to 26) in these two words taken together. For example, letter 12 is 'l/L' and we see that it appears 3 times, hence the count of 3.
复制代码
题目的大致意思是:找出指定长度的字符串,统计其中26个字母的频率

测试函数如下:
  1. 1
  2. %%
  3. txt = 'Hello World, from MATLAB' ;
  4. nl  = 5 ;
  5. counts_correct = [0 0 0 1 1 0 0 1 0 0 0 3 0 0 2 0 0 1 0 0 0 0 1 0 0 0];
  6. assert(isequal(nlWords_getCounts(txt, nl),counts_correct))

  7. 2
  8. %%
  9. txt = 'UPPER converts any lowercase characters in the string str to the corresponding uppercase characters and leaves all other characters unchanged.'
  10. nl  = 9 ;
  11. counts_correct = [3 0 3 1 5 0 1 1 0 0 0 1 0 2 1 2 0 2 2 0 2 0 1 0 0 0];
  12. assert(isequal(nlWords_getCounts(txt, nl),counts_correct))

  13. 3
  14. %%
  15. txt = 'UPPER converts any lowercase characters in the string str to the corresponding uppercase characters and leaves all other characters unchanged.'
  16. nl  = 10 ;
  17. counts_correct = [6 0 6 0 3 0 0 3 0 0 0 0 0 0 0 0 0 6 3 3 0 0 0 0 0 0];
  18. assert(isequal(nlWords_getCounts(txt, nl),counts_correct))
复制代码
回复 不支持

使用道具 举报

发表于 2013-6-19 23:03:05 | 显示全部楼层 来自 英国
本帖最后由 nwcwww 于 2013-6-20 11:46 编辑

dynamic无节操。
  1. function y = nlWords_getCounts(txt, nl)
  2.     regexp(lower(txt), '\<\w+\>','match');
  3.     regexp('', '(?@ y=arrayfun(@(x) length(regexp(strcat(ans{cellfun(@numel, ans)==nl}), char(96+x))), 1:26);)')
  4. end
复制代码
--------------------

祁工在18楼的点评甚是。我在楼下大概描述下思路吧。
另:想起来当时为何在这里没有用\w{5}一步到位了,因为nl是可变的。。建议大家借鉴祁工sprintf的实现方式。


点评

dynamic不错,不过有空nwc兄可以展现另外两种用法  发表于 2013-6-20 09:02
回复 不支持

使用道具 举报

发表于 2013-6-20 01:37:50 | 显示全部楼层 来自 英国
本帖最后由 nwcwww 于 2013-6-20 01:39 编辑

多用一次dynamic替换,size从楼上的20减到17:
  1. function y = nlWords_getCounts(txt, nl)
  2.     regexp('','(?@ z=strsplit(lower(txt), {'' '', '','', ''.''}))');
  3.     regexp('', '(?@ y=arrayfun(@(x) length(regexp(strcat(z{cellfun(@numel, z)==nl}), char(96+x))), 1:26);)')
  4. end
复制代码

点评

dynamic无疑是减少代码size比较好的选择之一,不过本次讨论,本意是想给大家一个学习的平台,不以代码size为评价指标,在写代码时,最好能写下思路  发表于 2013-6-20 09:04
回复 不支持

使用道具 举报

发表于 2013-6-20 04:37:00 | 显示全部楼层 来自 英国
晚饭过后来个完全不可读的。size = 12,但是我自己都看不懂写的是啥了。
  1. function y = nlWords_getCounts(txt, nl)
  2.   regexp('', '(?@ y=arrayfun(@(x) length(subsref(regexp(cellstr(cell2mat(subsref(strsplit(lower(txt), {'' '', '','', ''.''}),struct(''type'',''()'',''subs'',{{cellfun(@length, strsplit(lower(txt), {'' '', '','', ''.''}))==nl}})))), char(96+x)),struct(''type'',''{}'',''subs'',{{1}}))), 1:26);)')
  3. end
复制代码

点评

确实,按祁工说的在dynamics里加入多条语句即可。那么subref就不必要了,可以直接索引。  发表于 2013-6-27 01:53
1.dynamic里面应该可以写多条语句 2.subref构造麻烦,不如用直接索引的方式 仅供参考  发表于 2013-6-20 09:05

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2013-6-20 10:03:11 | 显示全部楼层 来自 新疆乌鲁木齐
nwcwww功力火候相当老道啊,赞一个!
你自己看着费劲,我们就更云里雾里了,呵呵。可以给些提示,增加一定讨论的操作空间。
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Simapps系列直播

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-9-22 09:22 , Processed in 0.075682 second(s), 23 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表