描述。
有8个球,编号从0到7,其中7个球的重量相同。有一个更重。你的任务是找到它的号码。
你的函数findBall将收到一个参数--scales对象。天平对象包含一个内部存储的8个元素的数组(索引为0-7),每个元素都有相同的值,只有一个元素更大。它还有一个名为getWeight(left, right)的公共方法,该方法接收两个索引数组,并根据在所传递的索引处发现的数值的累加,返回-1、0或1,这些数值是较重、相等或较轻的。
getWeight返回。
如果左盘较重则返回-1
如果右锅较重,则返回1
如果两个平底锅的重量相同,则返回0
scales.getWeight()的用法示例。
scales.getWeight([3], [7]) 如果球3比球7重,则返回-1;如果球7更重,则返回1;如果这些球的重量相同,则返回0。
scales.getWeight([3, 4], [5, 2]) 如果球3和4的重量比球5和2的重量重,返回-1。
那么,你可能会问,问题出在哪里呢?好吧--这个天平非常古老。在天平损坏之前,你只能使用它两次。
注意 - 在Python、Crystal和Ruby版本中使用scales.get_weight()。
def find_ball(scales):
part = [[None, 0, 1], [2, 3, 4], [5, 6, 7]]
res1 = scales.get_weight(part[-1], part[1])
res2 = scales.get_weight([part[res1][-1]], [part[res1][1]])
return part[res1][res2]
难度升级
有n个球,编号从0到n-1(0,1,2,3,等等)。其中大部分球的重量相同,但有一个球比较重。你的任务是找到它。
你的函数将收到两个参数--一个天平对象,和一个球的数量。天平对象只有一个方法。
get_weight(left, right)
其中左和右是分别放在左盘和右盘的球的数量数组。
如果该方法返回-1,则左盘较重。
如果该方法返回1,则右盘更重。
如果该方法返回0,则两个锅的重量相同。
那么,是什么让这个卡塔的 "全能大师 "版本?
首先,它不像以前的版本那样只限于8个球--你的解决方案必须适用于8-500个球。
第二,使用天平的次数不能超过图表中的列表。
小球数量 | 次数
ball count | uses
0-9 | 2
10-27 | 3
28-81 | 4
82-243 | 5
244-500 | 6
def find_ball(scales, n):
select = list(range(n))
while len(select) > 1:
left, right, unused = select[::3], select[1::3], select[2::3]
if len(select) % 3 == 1: unused.append(left.pop())
select = [left, unused, right][scales.get_weight(left, right) + 1]
return select.pop()
这是高手!
分金子的奥秘
在野外,两个程序员A和B同时发现了一些黄金。他们都想得到这些金子,于是他们决定用以下规则来分配金子。
他们把金子分成n堆,并排在一起。每堆的数量和堆的顺序都是随机的。
他们轮流从最左边或最右边取走一堆黄金。
在每一轮中,程序员将用他的智慧来选择对他最有利的黄金。
输入
一个代表黄金的整数的列表*。
输出
计算出的A和B最终获得的黄金数量,以一个元组*(A的数量,B的数量)。
*列表/元组的表示方法因语言而异--见实例测试
注意,我们可以假设A总是先拿,而且每次都使用最佳策略。
例子
对于黄金=[10,1000,2,1],输出应该是[1001,12]。
在第一轮,A可以拿10或1,10比1大。
我们应该选择10吗?不,聪明的程序员不这么认为;-)
因为如果A选择10,下一回合B可以选择1000。
所以,A选择1是最好的选择。
在第二轮,无论B选择10还是2,在第三轮,A总是可以选择1000。
所以,B选择10是最好的选择。
最终结果。
A: 1 + 1000 = 1001
B: 10 + 2 = 12
对于金币=[10,1000,2],输出应该是[12,1000]。
在这个例子中,A面临的选择与前一个例子中的第2个回合相同。
性能算法
代码块
杜德数据挑战赛 3 - 最佳解决方案
在这篇文章中,我将介绍杜德数据挑战赛第3期的 "最佳 "解决方案。关于问题的设置,请参考那篇文章。
天真的解决方案--带应用的自定义函数
在上一篇文章中详细介绍了天真的解决方案。最终的结果是一个庞大的自定义函数,包含许多布尔过滤器,用于寻找特定的数据子集进行聚合。对于每一个组,都会返回一个有11个值的系列。这些值中的每一个都成为结果数据框架中的一个新列。让我们来看看这个自定义函数。
Dunder Data Challenge3 Optimal Solution.png
我们使用这个天真的解决方案的性能需要近4秒。
成为一个专家
如果你想让别人信任你使用pandas做决策,你必须成为专家。我已经完全掌握了pandas,并开发了一些课程和练习,将大量提高你的知识和效率来做数据分析。
用Python掌握数据分析 - 我的综合课程有800多页,350多个练习,多个项目,以及详细的解决方案,将帮助你成为pandas的专家。
通过报名参加免费的Pandas入门课程,获得材料的样本。
最优解决方案
为了大大增加我们的性能,我们需要利用groupby对象的内置方法。上面,我们使用了一个自定义函数来做很多很多的计算。这些计算是在每个组上进行的。让我们得到组的总数。
>>> len(df.groupby(['country', 'region']))
520
len(df.groupby(['国家', '地区']))
520
对于这520个组中的每一个,都调用了大量的f_final函数,重新计算了每个过滤器。为每个组运行这些相同的计算是导致apply性能不佳的主要原因之一。
看一下f_final中的所有过滤器。你会注意到,它们中的每一个都是独立于特定组的。这意味着我们可以在分组之前计算这些过滤器并得到相同的结果。作为一个具体的例子,看一下下面的DataFrame。
df_rev = pd.DataFrame({'state': ['TX', 'TX', 'TX', 'CA', 'CA',
'CA'],
'category': ['tech', 'energy', 'energy',
'tech', 'energy', 'energy'],
'revenue' : [10, 5, 8, 20, 12, 2]})
df_rev = pd.DataFrame({'state': ['TX', 'TX', 'TX', 'CA', 'CA',
'CA']。
'类别': ['科技', '能源', '能源',
'科技', '能源', '能源'],
'收入':[10, 5, 8, 20, 12, 2]})
Dunder Data Challenge3 Optimal Solution2.png
让我们来计算每个州的收入,但只是能源类别的收入。一个天真的解决方案是编写一个自定义函数,每个组将被过滤掉能源类别,然后对收入进行求和。
def f(x):
is_energy = x['category'] == 'energy'.
return x.loc[is_energy, 'revenue'].sum()
使用这个自定义函数和apply返回每个州的能源类别的正确收入。
>>> df_rev.groupby('state').apply(f)
state
CA 14
TX 13
州
加州 14
德克萨斯州 13
相反,我们可以为能源收入创建一个完整的新列。首先,我们创建一个布尔系列,其中True对应于 "能源"。我们把这个系列乘以原来的收入列。因为False的值是0,True的值是1,所以新的列将和原来的列一样,但在类别不是能源的地方有0。
filt = df_rev['category'] == 'energy'
df_rev['energy_revenue'] = filt * df_rev['revenue']
df_rev
Dunder Data Challenge3 Optimal Solution4.png
现在我们可以在分组过程中使用内置的sum方法而不是我们的自定义函数。这里不需要应用。
>>> df_rev.groupby('state')['energy_revenue'].sum()
state
CA 14
TX 13
州
加州 14
德克萨斯州 13
使用where方法
你可能需要将过滤后的数值替换为0,而不是像我们上面所做的那样,将它们变成缺失值。如果你要计算像平均数或中位数这样的东西,这是至关重要的,因为它将考虑到0的值。where方法将把传递的布尔系列的假值替换为NaN。
filt = df_rev['category'] == 'energy'
df_rev['energy_revenue'] = df_rev['revenue'].where(filt)
df_rev
Dunder Data Challenge3 Optimal Solution4-1.png
我们可以调用相同的groupby来获得相同的结果。
df_rev.groupby('state')['energy_revenue'].sum()
state
CA 14.0
TX 13.0
州
加州 14.0
德克萨斯州 13.0
用我们的挑战数据进行过滤
让我们计算一下rev_2019,它被定义为2019年上半年的收入。让我们先用天真的思维方式,定义一个自定义函数。
>>> def get_rev_2019(x):
is_2019H1 = x['date'].between('2019-01-01', '2019-06-30')
return x.loc[is_2019H1, 'revenue'].sum()
>>> df.groupby(['country', 'region']).apply(get_rev_2019).head()
country region
Argentina A 150508
B 139048
C 118035
D 131728
E 146201
df.groupby(['国家', '地区']).apply(get_rev_2019).head()
代码块
国家地区
阿根廷 A 150508
B 139048
C 118035
D 131728
E 146201
现在,让我们使用我们的新方法,首先将过滤器应用于整个DataFrame,创建一个新列,然后使用内置的sum方法。
>>> is_2019H1 = df['date'].between('2019-01-01', '2019-06-30')
>>> df['rev_2019'] = df['revenue'].where(is_2019H1)
>>> df.groupby(['country', 'region'])['rev_2019'].sum().head()
country region
Argentina A 150508.0
B 139048.0
C 118035.0
D 131728.0
E 146201.0
自定义函数与内置方法的性能比较
让我们比较一下这两种方法的性能。
>>> %timeit df.groupby(['country', 'region']).apply(get_rev_2019)
633 ms ± 15.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %%timeit
>>> is_2019H1 = df['date'].between('2019-01-01', '2019-06-30')
>>> df['rev_2019'] = df['revenue'].where(is_2019H1)
>>> df.groupby(['country', 'region'])['rev_2019'].sum()
27.3 ms ± 530 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df.groupby(['国家', '地区']).apply(get_rev_2019)
633毫秒±15.9毫秒/循环(7次运行的平均值±std.dev.,每次1个循环)。
%timeit
is_2019H1 = df['date'].between('2019-01-01', '2019-06-30')
df['rev_2019'] = df['revenue'].where(is_2019H1)
df.groupby(['国家', '地区']) ['rev_2019'].sum()
每循环27.3毫秒±530微秒(7次运行的平均值±std.dev.,每次10循环)
自定义函数比内置方法慢25倍,这只是一个简单的计算。自定义函数越复杂,性能差异就越大。
避免使用apply的技巧
如果你试图避免使用apply,那么你没有选择,只能使用内置的groupby方法。这就限制了可能性,迫使你以不同的方式来处理这个问题。主要的 "技巧 "是在使用groupby方法之前对整个DataFrame执行操作。
不是所有的操作都能在整个DataFrame上执行,只有那些独立于分组的操作。那么,你怎么知道一个操作是否独立于组?该操作不会有特定于当前组的计算。例如,我们正在按国家和地区进行分组。如果一个操作依赖于特定的国家或地区,那么它将不能在整个DataFrame上执行。
一个具体的例子可以在这里提供帮助--如果上半年的定义是希腊从1月到7月,其他国家从1月到6月,那么上半年的收入计算将取决于组。
在这个挑战中,所有的业务都是独立于集团的。不存在基于集团的特殊情况。这意味着我们可以在分组之前,执行我们在自定义函数内使用的所有操作,以在其之外应用。
完整的最优解决方案
现在将给出完整的最优解。我们将为我们的过滤器使用与自定义函数中相同的定义,但改为在整个DataFrame上计算它们。然后我们将创建新的列,在过滤器为False的地方有NaN。
Dunder Data Challenge3 Optimal Solution5.png
现在我们可以只使用内置的groupby方法来聚合数据。
这并不是最终的DataFrame,因为有些列只能从聚合值的结果中计算出来。我们还需要放弃其中一些在结果中不再需要的中间列。
Dunder Data Challenge3 Optimal Solution6.png
让我们来验证一下,这些DataFrame是等价的。
>>> df1 = df.groupby(['country', 'region']).apply(f_final)
>>> df1.equals(df_new1.astype('float'))
True
真
让我们把最优解的所有步骤放到一个单一的函数中,然后我们可以用它来衡量性能。
def optimal():
... all steps
约20倍的速度
由于在整个DataFrame上预先计算新的列,并且只使用内置的groupby方法,最优方案的速度是天真的方案的20倍左右。
>>> %timeit optimal()
201毫秒±2.48毫秒/循环(7次运行的平均值±std.dev.,每次1个循环)。
关于如何取消apply的总结
我建议不惜一切代价避免apply,因为使用它可能会严重影响性能。下面的步骤总结了避免apply的程序。
在分组之前,计算任何独立于每个组的计算结果。这些计算会被应用到整个DataFrame中,作为一个整体
在你的DataFrame中创建新的列,包含步骤1中这些新计算的结果。
分组时,只使用内置的groupby聚合方法。不要使用自定义函数。
你可能会有一些使用groupby聚合结果的聚合(例如,取平均值和中位数的差值)。在groupby之后计算这些列。
掌握Python、数据科学和机器学习
沉浸在我用Python掌握数据科学和机器学习的全面路径中。购买全能通行证,就可以终身享受所有当前和未来的课程。它包含的一些课程。
银行客服的流程挑刺
1、对不起,您换汇需要联系储蓄卡客服,转接过去,
2、储蓄卡客服问需要查看我有没有储蓄卡,
答:可能办过,但没怎么用,也记不得卡号了,但我是贵行多年的白金卡信用卡 客户,客户资料应该比较全,可否再查下
自从,开启迷之对话 ——
3、对不起,先生您查看名下的储蓄卡,也需要开通电话银行
4、Okay,转自动语音,尝试开通电话银行,按提示:
5、输入卡号,身份证号,提示卡号或者密码不对,有点晕
6、平复心情,泡杯茶败火,一百个小心继续输,第8遍放弃
7、再联系客服,只问一个问题:本人贵行预留的手机号码是多少
8、客服回:请先注册电话银行业务
9、我问不注册可以查吗?曾在柜台办过人脸识别或回答个人私密信息
10、不行,转上一级经理,与经理的对话又回到了起点
11、 又提示我回到电话银行注册
问候内心飘过的一万个草原小骆驼,深吸一口气
12、一字一顿给经理讲:“ 给您免费支个招,贵行发一条营销短信,看到哪部手机收到,就是预留的手机号吗?
13、呵呵呵,对面的经理一阵凌乱:啊这,谢谢您
class User:
def __int__(self,name,id,phone):
self.name = name
self.id = id
self.phone = phone
def check_id(self):
NAME = False
ID = False
name = input('您的姓名:')
if name == self.name:
print(f"客户的姓名正确")
NAME = True
else:
id = input('您的身份证号:')
if self.id == id:
ID = True
print(f'身份证号码正确!')
print(f"您现在可以查询的信息:\n"
"1.查询卡号"
"2.查询预留手机号码"
"3.查询还款")
return NAME,ID
def checkDebtCard(self)->int: #身份证或者是卡号
if self.check_id():
print("您输入密码即可查询还款")
else:
return print("您提供的个人信息不正确")
def smstoPhone(self,phone):
phoneNo = input('请输入手机号:')
if self.phone == phoneNo:
return print('已经发送到您的手机')
# 银行录入用户的信息
zhangmin = User()
zhangmin.name = 'zhangmin'
zhangmin.id = '1234'
zhangmin.phone = '18983086450'
#客户张敏打客服电话
zhangmin.check_id()
zhangmin.checkDebtCard()







网友评论