从CSDN的趣味题学Python

转自:http://www.cnblogs.com/chagel/archive/2009/02/01/1381820.html

最近在论坛闲逛,先后参与了两题算法趣味题目。

  1. 题目1是要求算一任意长度字符串中不同的字符以及它的个数。
  2. 题目2是把一段字符串用“右起竖排”的古文格式输出。

题目难度不大,都是针对字符串的操作,逻辑比较简单,灵活在对不同语言、语法的掌握程度。(原文分别在:12。)

看了大家用C++、C#、Java等语言的实现,总感觉牛刀杀鸡太麻烦,有兴趣的朋友可以自己写写看或者直接看原文的网友回复。我最近一段时间Python写的比较多,读到这些题目时候,就有一种跃跃欲试的冲动。因为我知道用Perl,Python,Ruby等动态语言来做这类题目,会是非常理想的。后来我做了这两道题目,结果也令人满意,代码之简洁保持在所有答案的前列。

先看第一题Python解答:

dic = {}
for s in "abcdefgabc":
    dic[s] = 1 if s not in dic else (dic[s]+1)
print '\n'.join('%s,%s' % (k, v) for k, v in dic.items())

输出结果:

a,2
c,2
b,2
e,1
d,1
g,1
f,1

Python的四行代码分别做了dictionary的声明,赋值,字符串的遍历,以及高效拼接。

如果还没有看出它的简洁和强大的话,请看第二题的解法:

def main(offset=6):
    string = u'静夜思 李白床前明月光,疑似地上霜。举头望明月,低头思故乡。090131'
    a = [[' ']*offset for row in xrange(offset)]
    for i in xrange(offset):
        for j in xrange(offset):
            a[i][j] = string[j + i*offset]
    b = [[r[col] for r in a[::-1]] for col in xrange(len(a[0]))]
    print '\n'.join([u'┊'.join(unicode(c) for c in row)for row in b])

输出结果:

0┊低┊举┊疑┊床┊静
9┊头┊头┊似┊前┊夜
0┊思┊望┊地┊明┊思
1┊故┊明┊上┊月┊
3┊乡┊月┊霜┊光┊李
1┊。┊,┊。┊,┊白

这题如果用C#等实现,代码要在20行以上。下面我简单介绍一下这几行代码:

  1. 第3行,在Python里面二维“数组”通过嵌套list来实现,这里初始化一个6行6列的二维数组;
  2. 第7行,我们把“矩阵”顺时针旋转了90度(行列置换,并且对置换后的行首尾对调-这里的::-1就是用来置换一个list的trick);
  3. 最后一行,我们把数组里的每行中元素,每行之间分别用两个不同字符拼接起来。join方法以及for..in..语句在python中是相当常见的用法。

通过这两题,我们看到Python在处理字符串时候的十分灵活方便,虽然一种语言的好坏不应完全靠是否简洁来衡量,但对于我个人而言,Python是目前我用过的最好的语言。而且对于趣味题来说,这不就是我们解题的趣味所在吗?

----------------------------------------------------------------

Feedback

#1楼   回复  引用  查看    

2009-02-01 09:50 by Jeffrey Zhao      
从CSDN的趣味题学C# 3.0
http://www.cnblogs.com/JeffreyZhao/archive/2009/02/01/1381867.html

#2楼   回复  引用  查看    

2009-02-01 10:24 by JimLiu      
老赵的代码不错,我改进下
第二个
static void Count(string message) {
message
.GroupBy(c => c)
.ToList()
.ForEach(p => Console.WriteLine("{0}, {1}", p.Key, p.Count()));
}

这样似乎更爽一些,呵呵

#3楼   回复  引用  查看    

2009-02-01 10:26 by Jeffrey Zhao      
@JimLiu
那个select的确可以省,我是习惯于先搞出数据来,然后添加行为,而不是在行为里继续计算

#4楼   回复  引用  查看    

2009-02-01 10:34 by JimLiu      
@Jeffrey Zhao
呵呵,是因为先select了好重复用吧,习惯问题,我的喜欢就根据题目变化。

#5楼 122.4.212.*   回复  引用    

2009-02-01 11:59 by young5335[未注册用户]
a="abcdefgabc"
myset=set(a)
for s in myset:
print(str(a.count(s))+" "+s)

2 a
2 c
2 b
1 e
1 d
1 g
1 f

#6楼 122.4.212.*   回复  引用    

2009-02-01 13:24 by young5335[未注册用户]
import math
colSize=6
string="静夜思 李白床前明月光,疑似地上霜。举头望明月,低头思故乡。0901311"
iLen=math.ceil(len(string)/colSize)
l=list(reversed(([string[i*colSize:i*colSize+colSize].ljust(colSize,' ') for i in range(0,iLen)])))
for i in range(colSize):
for j in range(iLen):
print(l[j][i],end=" ")
print()

python语法我真的快忘光光了.

#7楼 122.4.212.*   回复  引用    

2009-02-01 13:28 by young5335[未注册用户]
要改成跟楼主一样的分隔符,把end="┊"

#8楼 122.4.212.*   回复  引用    

2009-02-01 13:44 by young5335[未注册用户]
PHP的:
$a="abcdefgabc";
$result=count_chars($a,1);
array_walk($result,create_function('$v,$k','echo chr($k)." ".$v."<br/>";'));

a 2
b 2
c 2
d 1
e 1
f 1
g 1

#9楼   回复  引用  查看    

2009-02-02 00:00 by Icebird      
JavaScript:

var s = "hello";
var arr = s.split('');
var o = {};
var c;
for (var i = 0; i < arr.length; i++)
{
o[arr[i]] = (o[arr[i]] ? o[arr[i]] : 0) + 1;
}

var result = "";
for (var p in o)
{
result += p + ", " + o[p] + "\r\n";
}

alert(result);

#10楼 119.32.87.*   回复  引用    

2009-02-02 10:22 by 赖勇浩[未注册用户]
>>> from collections import defaultdict
>>> adict = defaultdict(int)
>>> for s in "abcdefgabc":
... adict[s] += 1
...
>>> print '\n'.join('%s,%s' % (k, v) for k, v in adict.iteritems())
a,2
c,2
b,2
e,1
d,1
g,1
f,1

#11楼 122.4.239.*   回复  引用    

2009-02-02 11:21 by young5335[未注册用户]
a="abcdefgabc"
b={}
a.each_char { |x|b.store(x,a.count(x)) }
b.each {|k,v| puts k+" "+v.to_s}

#12楼 119.161.174.*   回复  引用    

2009-02-02 15:18 by hehehe[未注册用户]
试试Groovy:

('abcdefgabc' as List).groupBy{it}.each{k, v -> println "$k, ${v.size()}"}

#13楼 119.161.174.*   回复  引用    

2009-02-02 15:37 by hehehe[未注册用户]
试试Groovy(第二题):

def a = '床前明月光 疑似地上霜 举头望明月 低头思故乡'.tokenize(' ')

5.times{row ->
println a.collect{it[row]}.reverse().join('|')
}


低|举|疑|床
头|头|似|前
思|望|地|明
故|明|上|月
乡|月|霜|光

#14楼 203.110.175.*   回复  引用    

2009-02-02 16:04 by zealtea[未注册用户]
txt = u"静夜思 李白床前明月光,疑似地上霜。举头望明月,低头思故乡。"
offset = 6

a =[i[::-1] for i in zip(*[txt[i:i+offset] for i in range(0, len(txt), offset)])]

for i in a:
print "|".join(i)

#15楼 125.34.166.*   回复  引用    

2009-02-05 17:36 by tocer[未注册用户]
s = "abcdefgabc"
dic = dict.fromkeys(s, 0)
for x in s:
dic[x] += 1
print '\n'.join('%s,%s' % (k, v) for k, v in dic.items())

和 赖勇浩 的差不多,但不用引入库

或者这个
dic = {}
for x in "abcdefgabc":
dic.setdefault(x, []).append(x)
print '\n'.join('%s,%d' % (k, len(v)) for k, v in dic.items())

#16楼[楼主]   回复  引用  查看    

2009-02-05 23:39 by Chagel      
@zealtea
赞!比我写的更pythonic!

#17楼 221.6.44.*   回复  引用    

2009-02-14 23:07 by 新手学习[未注册用户]
@zealtea
在 python 3k中试了一下,好像在不是刚好6倍数长度时处理不好,zip会截断

#18楼 221.6.44.*   回复  引用    

2009-02-14 23:32 by 新手学习[未注册用户]
@zealtea
加这个就可以了
txt=txt.ljust(((len(txt)-1)//offset+1)*offset,' ')

#19楼   回复  引用  查看    

2009-09-01 17:12 by BuzzLightyear      
第一题:
s=’abcdefgabc‘
print '\n'.join('%s,%d'%(c,s.count(c)) for c in list(set(s)))
原文地址:https://www.cnblogs.com/nsnow/p/1769554.html