少儿Python每日一题(10):手机键盘

文章介绍了如何使用Python编程解决一个关于老式手机键盘字母输入统计的问题,给出了三种不同的解题方法,包括多分支结构、成员运算符和键值对匹配,并提供了样例代码。此外,还提及了类似的字符统计题目,强调了解题时需要注意的细节和数据类型运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题解答

本次的题目如下所示(原题出处:NOC)

一般的手机的键盘是这样的:


要按出英文字母就必须要按数字键多下。例如要按出 x 就得按 9 两下,第一下会出 w,而第二下会把 w 变成 x。0 键按一下会出一个空格。
你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘。
输入格式
一行句子,只包含英文小写字母和空格,且不超过 200 个字符。
输出格式
一行一个整数,表示按键盘的总次数。
输入样例
i have a dream
输出 样例
23

本道题本身并不是很难,而且解题的方法也有多种,关键在于能不能读懂题目,有没有思路。这总键盘对于现在的孩子来说相对较为陌生,是诺基亚时代的手机输入方式。

我们先解释一下如何通过“i have a dream”得到23这个结果的。键盘上2到9折八个数字每个数字各对应3到4个字母,如果我们要键入第一个字母,只要按一下对应的数字键;键入第二个字母则要连续按两下这个数字键。也就是键入一个字母最多可能要按4下,比如字母s和字母z。以下是这句话中各个字母需要按键盘的次数:

ihaveadream
31213211113211

通过相加可以得到,总和为23。

下面我们看一下通过程序如何实现。

方法一:多分支结构 + 逻辑语句

我们将每个字母需要按键几下写到分支结构中,然后通过遍历字符串中的字符进行累加,其实很容易得到程序的代码:

s = input()
n = 0
for i in s:
    if i == 'a' or i == 'd' or i == 'g' or i == 'j' or i == 'm' or i == 'p' or i == 't' or i == 'w' or i == ' ':
        n += 1
    elif i == 'b' or i == 'e' or i == 'h' or i == 'k' or i == 'n' or i == 'q' or i == 'u' or i == 'x':
        n += 2
    elif i == 'c' or i == 'f' or i == 'i' or i == 'l' or i == 'o' or i == 'r' or i == 'v' or i == 'y':
        n += 3
    elif i == 's' or i == 'z':
        n += 4
print(n)

方法二:多分支结构 + 成员运算符

刚刚的代码确实解决了问题,但是如果相对来说代码较为零散,并且很容易写错。如果我们将需要按一下、按两下、按三下和按四下的字母分别放入四个序列中,可大幅度提高代码的可阅读性。我们看看如何书写:

s = input()
one = 'adgjmptw ' # 注意还有空格
two = 'behknqux'
three = 'cfilorvy'
four = 'sz'
n = 0
for i in s:
    if i in one:
        n += 1
    elif i in two:
        n += 2
    elif i in three:
        n += 3
    elif i in four:
        n += 4
print(n)

方法三:键值对匹配

除了上述的方法外,我们还可以利用字典类型对字母的按键次数进行匹配。此方法代码是所有解决方法中最简的,较繁琐的是字典的定义。

s = input()
alpha = {'a': 1, 'b': 2, 'c': 3,
         'd': 1, 'e': 2, 'f': 3,
         'g': 1, 'h': 2, 'i': 3,
         'j': 1, 'k': 2, 'l': 3,
         'm': 1, 'n': 2, 'o': 3,
         'p': 1, 'q': 2, 'r': 3, 's': 4,
         't': 1, 'u': 2, 'v': 3,
         'w': 1, 'x': 2, 'y': 3, 'z': 4,
         ' ': 1
         }
n = 0
for i in s:
    n += alpha.get(i)
print(n)

本题拓展

本题考查的是字符统计问题,题目难度★

本类题型的特点是未涉及任何复杂的算法问题,想要做出来也非常容易。但是要将代码写到最优是需要动脑筋的,需要我们对Python的各种数据类型和运算符有较为熟练的掌握。

此类题型在竞赛,尤其是初赛的前两题中经常会出现。

我们看下面这一道题:

输入一句英文,统计各个字母在句子中出现的次数(不区分大小写,仅统计字母,不统计空格和标点符号等)。

输入格式:在一行中输入一句英文

输出格式:分多行输出,每行输出一个字母和出现的次数

输入样例:

This is my sister

输入样例:

T 2
H 1
I 3
S 4
M 1
Y 1
E 1
R 1

本题也不算难,但是要想做对了,是需要细心的。首先要考虑不区分大小写的问题,其次要考虑不统计标点符号和空格。这道题我们可以充分利用字典类型统计。

s = input()
d = {}
s = s.upper() # 全部转换为大写字母
for i in s:
    if i.isalpha(): # 只统计字母,不是字母不统计
        if i not in d: 
            d[i] = 1 # 字典中没有个数为1
        else:
            d[i] += 1 # 字典中已存在的个数+1
for k, v in d.items():
    print(k, v)

大家可以自己思考本题还有其他什么思路解答。

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有 28 28 个按键,分别印有 26 26 个小写英文字母和 B、P 两个字母。经阿狸研究发现,这个打字机是这样工作的: 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。 按一下印有 B 的按键,打字机凹槽中最后一个字母会消失。 按一下印有 P 的按键,打字机会在纸上打印凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。 例如,阿狸输入 aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印来的字符串从 1 1 开始顺序编号,一直到 � n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数 ( � , � ) (x,y)(其中 1 ≤ � , � ≤ � 1≤x,y≤n),打字机会显示第 � x 个打印的字符串在第 � y 个打印的字符串中现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么? 输入格式 输入的第一行包含一个字符串,按阿狸的输入顺序给所有阿狸输入的字符。 第二行包含一个整数 � m,表示询问个数。 接下来 � m 行描述所有由小键盘输入的询问。其中第 � i 行包含两个整数 � , � x,y,表示第 � i 个询问为 ( � , � ) (x,y)。 输格式 输 � m 行,其中第 � i 行包含一个整数,表示第 � i 个询问的答案
06-09
这道题可以使用字符串和前缀和的思路来解决,具体步骤如下: 1. 读入字符串,用一个数组记录下每个字符串打印后的结果,同时用另一个数组记录下每个字符串的长度。 2. 读入询问个数 m,然后读入 m 行询问,每次查询时先找到第 x 个字符串和第 y 个字符串,然后枚举第一个字符串中的所有子串,判断该子串是否在第二个字符串中现过。如果现过,则将答案加 1。 3. 最后输所有询问的答案。 下面是详细的代码实现: ```c++ #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110; int n, m; char str[N]; char s[N][N]; int len[N]; int sum[N][N]; int main() { cin >> str + 1; n = strlen(str + 1); int cur = 0; for (int i = 1; i <= n; i ++ ) { if (str[i] == &#39;B&#39;) cur = max(0, cur - 1); else if (str[i] == &#39;P&#39;) { s[++ m][0] = cur; for (int j = 1; j <= cur; j ++ ) s[m][j] = s[m][j - 1] + str[i - cur + j]; len[m] = cur; } else s[m + 1][++ cur] = str[i]; } for (int i = 1; i <= m; i ++ ) for (int j = 0; j <= len[i]; j ++ ) for (int k = 1; k <= m; k ++ ) for (int l = 0; l <= len[k]; l ++ ) if (strncmp(s[i] + j, s[k] + l, len[i] - j + 1) == 0) sum[i][k] ++ ; cin >> m; while (m -- ) { int x, y; cin >> x >> y; int res = 0; for (int i = 0; i <= len[x]; i ++ ) for (int j = 1; j <= m; j ++ ) if (strncmp(s[x] + i, s[j], len[x] - i + 1) == 0) res += sum[j][y]; cout << res << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤城老人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值