2019/9/28_codewars自虐_杜鹃的有趣问题

Magpies are my favourite birds
Baby ones even more so…

It is a little known fact^ that the black & white colours of baby magpies differ by at least one place and at most two places from the colours of the mother magpie.

So now you can work out if any two magpies may be related.

…and Quardle oodle ardle wardle doodle the magpies said

Kata Task
Given the colours of two magpies, determine if one is a possible child or grand-child of the other.

Notes
Each pair of birds being compared will have same number of colour areas
B = Black
W = White
Example:
Given these three magpies

Magpie 1 BWBWBW
Magpie 2 BWBWBB
Magpie 3 WWWWBB
You can see:

Magpie 2 may be a child of Magpie 1 because there is only one difference
Magpie 3 may be child of Magpie 2 because there are two differences
So Magpie 3 may be a grand-child of Magpie 1
On the other hand, Magpie 3 cannot be a child of Magpie 1 because there are three differences

这道题好像没有什么能够学习的地方,主要就是一个比较有趣的算法,先理解一下题意:作为child的两只喜鹊必须要有1-2处的颜色不同,而如果A和B互为child,B和C互为child,那么A和C就是grandchild,现在给出两只喜鹊,判断他们可不可能是child或者grandchild。
child的问题似乎比较好解决,只需要判断两个bird的颜色不同的地方是否是1-2个即可。
而grand的判断比较复杂一点,还是需要静下来想一想的。首先,他只给出了两只鸟,而根据他的题目,grand是三代之间的关系,我们就要假设中间代的颜色情况,由于三代两两之间都是1-2处颜色不同,我第一个想到的是如果要是grand,那么最多有4处不同,最少有0处不同(A和B有两处不同,B和C仍然是这两处不同即可),然后紧接着,想到如果有1,2,3处不同时,依然可以找到一个中间代,使得他们两两为child。
然而到这时,有一个问题我们没有考虑到,就是喜鹊颜色的格数,例题中给出的是6个,而假如例题的颜色个数只有1个,问题就不一样了,如果是1个,那必须这两只喜鹊的颜色是相同的(即W和W或者B和B)才能够是grand!,即不同处为0
如果颜色个数为2,就没有这样的问题了,不管不同的是0,1,还是2都可以找到中间的child。
个人觉得就是这里有点意思- -
附上最初的代码

def child(bird1, bird2):
    difference = 0
    length = len(bird1)
    if bird1==bird2:
        print('False')
        return False
    for n in range(0, length, 1):
        if bird1[n] != bird2[n]:
            difference += 1
    if difference <= 2:
        print('True')
        return True
    else:
        print('False')
        return False


def grandchild(bird1, bird2):
    difference = 0
    length = len(bird1)
    if length==1:
        return False
    if bird1==bird2:
        print('False')
        return False
    for n in range(0, length, 1):
        if bird1[n] != bird2[n]:
            difference += 1
    print(difference)
    if difference <= 4:
        print('True')
        return True
    else:
        print('False')
        return False

同样,评论区有比较简单的代码,但是那种把return和if语句写在一行的写法,个人感觉看起来不是很舒服。可能是之前学C留下的后遗症吧…

def diffs(bird1, bird2):
    return sum(c1 != c2 for c1, c2 in zip(bird1, bird2))

def child(bird1, bird2):
    return diffs(bird1, bird2) in [1, 2]

def grandchild(bird1, bird2):
    return diffs(bird1, bird2) in [0, 1, 2, 3, 4] if len(bird1) > 1 else bird1 == bird2

评论区第一的大佬是这么写的,我觉得有一些可取的,首先他另外定义了一个函数用来返回两喜鹊之间的颜色个数差,这里用到了zip函数,我们最后讲。然后他使用了return和if else在一行的写法,***

“return diffs(bird1, bird2) in [0, 1, 2, 3, 4] if len(bird1) > 1 else bird1 == bird2”

***这种的意思是:如果bird1的长度大于1,那么返回“diffs(bird1, bird2) in [0, 1, 2, 3, 4] ”,这是一个逻辑段,指的是diffs函数返回值在0-4中间,如果在,返回Ture,如果不在,返回False,而如果bird1长度不大于1,即为1,那么就返回bird1==bird2的逻辑结果,如果不等,那么就不是grand,如相等,那就是Ture。
这一段等于:

if len(bird1)>1:
	if diffs(bird1,bird2) in [0,1,2,3,4]:
		return True
	else:
		return False
else:
	if bird1==bird2:
		return True
	else:
		return False

这么写,还是比较简洁的。

最后,说一下zip的用法,zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b)     # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c)              # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]

zip的对象是一个个可以迭代的对象(字符串,元祖,列表,字典等等),然后把每一个对象的相应位上的元素组合成一个新的元祖,py3.x以后zip函数直接返回的对象是一个是个无法解读的zip型对象,要用list/dict/tuple等关键词转换他才可读,另外如果是dict要注意被合成的只能有2个可迭代对象
zip(*name)就是反过来的过程了,对于一个已经zip过的对象(dict,tuple,list)等等,他取每一个对象每一位的对应位组成一个新的对象,对象的类型和原来的类型相同。
zip反过程可以用来做矩阵的转置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值