解决把两个数字的和、积分别告诉两个人猜两个数字组合的问题

本文通过编程解决了一道有趣的数学对话题,两个学生通过对话逐步缩小数字范围,最终确定了老师给出的两个数字。文章提供了完整的Python代码实现,并详细解释了每一步的逻辑。
部署运行你感兴趣的模型镜像

原题:一个老师从2到9中取两个数字,给甲说了和,给乙说了积, 甲说我不知道,乙说我也不知道,甲说你不知道那我就知道了, 乙说你知道了那我也知道了, 这两个数分别是多少?


题目很有趣,直接上python代码,欢迎指正:


# -*- coding: utf-8 -*-
 
# 原题:一个老师从2到9中取两个数字,给甲说了积,给乙说了和,
# 甲说我不知道,乙说我也不知道,甲说你不知道那我就知道了,
# 乙说你知道了那我也知道了
# 这两个数分别是多少?
 
# ========================================================
# 为了方便表示,记两个数字的组合为字符串i&j,如2&3这种格式
# 以下是工具函数
# ========================================================
# 通过数字i和j生成组合(注意i&j和j&i其实是一样的)
def genij(i, j):
    return '%d&%d'%(i, j) if i >=j else '%d&%d'%(j, i)
 
# 获得组合的和
def add_ij(ij):
    v = ij.split('&')
    return int(v[0]) + int(v[1])
 
# 获得组合的积
def mul_ij(ij):
    v = ij.split('&')
    return int(v[0]) * int(v[1])
 
# ========================================================
# 以下开始计算
# ========================================================
def find_ijs(begin, end):
    end = end + 1
 
    # 生成两个begin-end数字所有可能的和、积
    a = {}
    b = {}
    for i in range(begin, end):
        for j in range(begin, end):
            v = genij(i, j)
 
            if i+j in a:
                a[i+j].add(v) 
            else:
                a[i+j] = set()
                a[i+j].add(v)
 
            if i*j in b:
                b[i*j].add(v)
            else:
                b[i*j] = set()
                b[i*j].add(v)
 
    # print u'----------两个%d-%d数字和的可能组合a-------------------\n'%(begin, end), a
    # print u'----------两个%d-%d数字积的可能组合b-------------------\n'%(begin ,end), b
 
    # 排除和是唯一的组合(如果是唯一,甲第一次就应该知道这两个数字)
    a1 = {k: v for k, v in a.items() if len(v) == 1}
    a1 = reduce(lambda x, y: x | y, [k for k in a1.values()]) 
    # print u'----------甲第一次不知道后可以排除的组合a1-------------------\n',list(a1)
 
    # 排除积是唯一的组合(如果是唯一,乙第一次就应该知道这两个数字)
    b1 = {k: v for k, v in b.items() if len(v) == 1}
    b1 = reduce(lambda x, y: x | y, [k for k in b1.values()]) 
    # print u'----------乙第一次不知道后可以排除的组合b1-------------------\n',list(b1)
 
    # 排除a1、b1后剩下的数字组合
    c = set()
    for i in range(begin, end):
        for j in range(begin, end):
            v = genij(i, j)
            if v not in a1 and v not in b1:
                c.add(v)
    # print u'----------甲乙第一次不知道后的可能组合c-------------------\n',list(c)
 
    # 甲第二次知道了,是因为他能够排除和为m数字中其他非正确答案的组合
    # 那就是说和为m的可能的数字组合除正确答案之外都在不可能的数字组合a1和b1里面
    c1 = []
    for i in c:
        v = add_ij(i)
        test = True
        for j in a[v]:
            if j != i:
                if j in c:  # 相当于 if j not in a1 and j not in b1:
                    test = False
        if test:
            c1.append(i)
    # print u'----------甲第二次知道后的可能组合c1-------------------\n',c1
 
    # 乙第二次知道了,是因为他能够排除积为n数字中其他非正确答案的组合
    # 他的依据是甲既然知道,那么这个数字组合肯定是c1中的一种
    # 然后他再根据c1做一下排除, 积为n的可能的数字组合除正确答案之外都在不可能的数字组合c1里面
    c2 = []
    for i in c1:
        v = mul_ij(i)
        test = True
        for j in b[v]:
            if j != i:
                if j in c1:
                    test = False
        if test:
            c2.append(i)
    # print u'----------乙第二次知道后答案c2-------------------\n',c2
    return c2
 
for i in range(3, 20):
    for j in range(2, i):
        print '%d-%d'%(j, i), find_ijs(j, i)


您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think> 嗯,用户这次问的是鸿蒙系统中关于字符计算规则的具体实现问题。之前用户提到过"两个字母等于一个字符,两个数字等于一个字符"的规则,现在特别关注12字符限制的应用场景。 用户可能正在开发鸿蒙应用,遇到了输入框长度限制的实际问题。ta特意强调"12个字符限制",明这个数字对ta很重要,可能是某个特定功能的要求。ta需要知道系统如何计算字符长度,以及输入内容超出时的处理方式。 这个问题涉及系统底层的字符处理逻辑,需要从几个维度分析:首先确认鸿蒙确实存在这种特殊计算规则(根据官方文档),然后解释规则细节(特别是中英文混合时),最后明12字符限制的实际表现(比如截断机制)。用户很可能在开发表单验证功能,需要精确控制输入长度。 注意到用户没有提供具体代码或错误信息,明ta还处于设计阶段。应该强调测试的重要性,因为半角全角符号、emoji等边缘情况可能影响计算结果。用户可能需要知道如何监听输入事件并实时计算字符数。 上次回答提到过基础规则,这次要更深入:比如单个数字或字母的异常情况处理(系统会补成完整单位吗)、组合字符如何统计(如带音调的字母)。还要提醒用户,同鸿蒙版本可能有差异,建议检查系统API文档。 </think> 在鸿蒙系统中,"两个字母等于一个字符,两个数字等于一个字符" 是 **长度计算规则**,常用于输入框字符限制(如用户名、验证码等)。以下是具体解析: --- ### 一、规则详解 1. **字母计数** - 每个 **半角字母**(如 `a, B, c`)按 **0.5字符** 计算 - 例如:`"Hello"`(5字母) = `5 × 0.5 = 2.5字符` → **系统按3字符计算**(向上取整) 2. **数字计数** - 每个 **半角数字**(如 `1, 2, 3`)同样按 **0.5字符** 计算 - 例如:`"2024"`(4数字) = `4 × 0.5 = 2字符` 3. **汉字与全角字符** - 每个汉字(如 `中, 文`)或全角符号(如 `!, @`)直接计为 **1字符** 4. **混合输入示例** | 输入内容 | 计算方式 | 总字符数 | |----------------|------------------------------|----------| | `ab12中文` | `ab`(2×0.5) + `12`(2×0.5) + `中文`(2×1) = 1+1+2 | **4字符** | | `Tech2024!` | `Tech`(4×0.5) + `2024`(4×0.5) + `!`(1×0.5) = 2+2+0.5 | **4.5→5字符** | --- ### 二、12字符限制的临界值 1. **最大允许输入**(按规则计算 ≤12): - 纯字母:**最多24个**(如 `abcdefghijklmnopqrstuvwx`) - 纯数字:**最多24个**(如 `123456789012345678901234`) - 纯汉字:**12个** - 混合内容:需动态计算(见下表) 2. **常见混合组合上限**: | 内容类型 | 示例 | 实际字符数 | |------------------|---------------------|------------| | 8字母 + 8数字 | `abcd1234efgh5678` | (8×0.5)+(8×0.5)=**8字符** | | 6汉字 + 6字母 | `中国ab民cd` | (6×1)+(6×0.5)=**9字符** | | 10数字 + 1汉字 | `1234567890中` | (10×0.5)+1=**6字符** | --- ### 三、开发注意事项 1. **系统处理逻辑**: ```java // 伪代码:鸿蒙输入框字符计算 int calculateLength(String input) { int total = 0; for (char c : input.toCharArray()) { if (isHalfWidthAlpha(c) || isDigit(c)) { // 半角字母或数字 total += 0.5; } else { // 汉字、全角符号等 total += 1; } } return (int) Math.ceil(total); // 向上取整 } ``` 2. **用户界面提示**: 输入框通常会动态显示: `已输入:X/12字符`(如输入 `apple` 显示 `3/12`) 3. **超出限制的处理**: - 键盘输入:第13字符**无法输入**(无提示) - 粘贴文本:**自动截断**至前12字符 --- ### 四、实际场景验证 1. **测试案例**: - 输入 `a1b2c3d4e5f6g7h8`(16字母数字混合) → 系统计算:`16×0.5=8字符` → **允许输入** - 输入 `北京Shanghai2024!`(2汉字+8字母+4数字+1符号) → 计算:`2×1 + (8+4+1)×0.5 = 2+6.5=8.5→9字符` → **允许输入** 2. **边界测试**: - 输入24个数字 `123...24` → 计算:`24×0.5=12字符` → **允许** - 输入25个字母 `abc...y` → 计算:`25×0.5=12.5→13字符` → **第25字母被拦截** --- ### 五、为什么这样设计? 1. **兼容性**:统一处理ASCII字符(半角)与Unicode字符(全角) 2. **空间优化**:半角字符在显示宽度上约为全角字符的一半 3. **防滥用**:防止通过长串字母/数字绕过限制(如垃圾注册) > ⚠️ **注意**:同鸿蒙版本可能微调规则(如部分EMUI兼容模式将数字按1字符计),需以真机测试为准[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值