理解程序化思维,需要看清问题怎样转化为数据、规则怎样组织为步骤,以及结论为什么成立。沿着实例手工推演、追踪状态并核对结果,可以将抽象、算法与验证等概念转化为解决问题的方法。
从登记表汇总到路线判断、整数计算和面积近似,不同任务都需要明确输入、保留关键关系、组织处理过程,并建立独立的核验依据。代码示例用于辅助观察,可在学习相应语法后运行和修改。
一、登记表需求与验收实践
1.1 从操作动作提炼需求
把 200 份 Word 登记表汇总到 Excel,表面上是复制与粘贴,实际包含多个判断:哪些文件属于处理范围,字段在哪里,什么情况算缺失,无法处理的文件如何记录。
先选一份完整材料,手工列出动作:打开文档,找到第一张表,识别字段标签,读取对应内容,按规定列序写入汇总表。再检查一份籍贯为空的材料,判断它是否满足有效记录的要求,由此补充“记录来源与原因,继续处理下一份”的规则。
这两个样例可以帮助明确需求的四个要素:
• 输入:指定目录中的文件,只处理当前目录,不递归子目录;其中的 .docx 文件作为目标材料。
• 结构:第一张表每行包含两个单元格,不使用合并单元格;左列为标签,右列为值。必需字段为姓名、性别、出生年月、民族和籍贯。
• 规则:排除以 ~$ 开头的临时文件和非目标格式文件;清除标签和值两端的空白,检查必需标签是否缺失、重复,以及对应值是否为空。额外标签不纳入汇总;保留原文件,不推测补齐内容。
• 输出:一份 Excel 工作簿,分别保存汇总、待核查与排除清单,并保留来源文件名。
重复性、规则性、数据可表示性和可验证性帮助判断是否值得编程;输入、结构、规则和输出用于明确任务。选择方法时,还应结合工作量、现有工具与核验条件。
1.2 明确模板与例外
.docx 与旧版 .doc 属于不同格式。使用 处理登记表时,应提供它支持的 .docx 文件;旧版文件需要先转换,或按非目标格式排除。
Word 表格可能包含合并单元格和不规则行,不能仅凭视觉上“像两列”就认定结构符合约定。程序需要检查实际结构,或在处理前统一模板。
在约定的模板中,程序按标签识别内容,再按固定字段顺序输出,因此五个标签在表中的先后顺序可以变化。列数变化、合并单元格、必需标签重复或必需字段缺失,都应记录为待核查情况。
这一约定限定了程序的适用范围。扫描图像、自由排版文字和其他表格结构,需要另外设计提取方法。标签正确且值非空,只说明满足当前的结构与完整性要求;字段内容是否符合业务规则,还需另行判断。
出生年月可以暂按原文保存。例如,材料写为“2005-03”时保留这一文本;只写“2005”时,也不自动补出月份。若任务要求完整年月,应增加相应的检查规则。
1.3 建立独立预期
可准备三份使用虚构信息的 Word 样表,每份包含规定的五个标签:
• 登记表01.docx:张三,男,2005-03,汉族,北京。
• 登记表02.docx:李四,女,2005-07,汉族,江苏。
• 登记表03.docx:王五,男,2005-11,汉族,籍贯为空。
五个字段均为必需,因此前两份进入汇总,第三份进入待核查。若输入目录中只有这三个文件,排除数应为零。
运行前,先记录预期数量:有效记录两条、待核查记录一条、排除记录零条。再列出有效记录的完整字段,以及第三份材料的缺失原因。这样,检查依据来自材料与规则,独立于程序输出。
数量应满足:
输 入 有 效 待 核 查 排 除
这里的计数单位是输入清单中的文件。工作表标题行和文件夹本身均不计入文件记录。
数量等式用于检查总体是否相符,还应逐一核对来源文件,确保每个输入文件只出现一次。遗漏一个文件并重复处理另一个文件时,总数仍可能相等。
1.4 沿数据流理解实现
登记表程序可以划分为四个相互衔接的部分:
1. 读取与检查:先排除临时文件和非目标格式文件,再读取目标文档,检查表格结构并建立标签与值的对应关系。
2. 分类与记录:将符合要求的文件归入有效类别,将读取失败或不符合要求的文件归入待核查类别;各类记录均保留来源,待核查与排除记录同时注明原因。
3. 保存结果:按规定列序写入工作簿,保持文本字段的表示,拒绝覆盖已有输出。
4. 核对结果:检查文件数量、分类去向和字段内容。
把表格看成“标签—值”的对应关系,是数据抽象;把批量任务拆成读取、检查、分类与保存,是任务分解;对所有文件重复执行同一套规则,是自动化。
处理第三份样表时,发现籍贯为空,就应记录“必需字段为空:籍贯”,并将该文件归入待核查。其他材料仍可继续处理。
异常规则需要明确规定处理结果。例如,字段为空可以进入待核查;输出目录无法写入,则需要报告问题并采取相应处理。不同异常不应一律按“跳过”处理。
1.5 保存与读回检查
保存结果后,应重新打开工作簿,确认三个工作表存在、字段顺序正确,并与前面确定的数量和内容预期逐项比较。
读回检查比较“准备写入的内容”和“实际保存的内容”,有助于发现写入、格式转换或文件保存环节的问题。
提取是否正确,还需要对照原始样表和独立预期检查。若内存中的内容本来就提取错了,写入后再读回仍可能完全一致。
因此,验收至少包含三个层次:
• 文件检查:结果文件能够正常打开。
• 数量检查:数量符合预期,每个输入文件都有唯一、明确的去向。
• 内容检查:字段、值和来源逐项对应。
即使程序交换了两个人的籍贯,文件与数量检查仍可能通过。逐项内容核验才能发现这类错误。
1.6 修改规则与迁移练习
使用样表副本开展以下练习,每次先写出预期,再检查结果:
• 补齐第三份样表的籍贯,预期变为三条有效记录、零条待核查记录。
• 加入一份 说明.txt,预期排除数增加一,原三份样表的分类保持不变。
• 加入一个以 ~$ 开头的 Word 临时文件,预期进入排除清单。
• 删除一个必需标签,或增加重复的必需标签,预期进入待核查。
• 交换两行字段的位置,预期仍能按固定列序输出,检验是否确实按标签读取。
输出文件宜与输入材料分开保存,避免再次运行时把先前输出误纳入输入范围。
三份样表用于验证基本规则。扩大到 200 份材料前,还应检查模板差异、重复材料、损坏文件和实际文件数量。小样本成功只能支持已经覆盖的条件。
二、自然语言与精确表达
2.1 模糊、歧义与语境
“高分学生”没有明确边界,属于模糊表达;“他背着妈妈去看病”可能表示背负着或瞒着,存在不同解释;“这道菜不错”在日常交流与正式评分中承担不同作用,体现语境依赖。
自然语言(Natural Language)允许人们借助共同经验省略细节。把需求交给程序处理时,这些省略的内容需要转化为明确约定。
例如,“整理最新登记表”仍需明确:按文件名中的日期还是修改时间判断,同一人的多份材料怎样取舍,无法确定先后时如何记录。将这些条件说明清楚,有助于减少实现过程中的错误假设。
2.2 规则边界与符号含义
将“选出高分学生”明确为“数学成绩至少 80 分”,就确定了边界。检验时,79 分应排除,80 分与 81 分应保留。
符号含义取决于所在系统的约定。数学中的等号表达相等关系;编程语言则另有赋值与比较规则。
形式化(Formalization)使表达具有明确的结构与规则。语法正确仍需结合任务要求判断:一个程序可以准确执行“大于 80 分”,同时违反“至少 80 分”的需求。
数学公式也需要明确变量与适用条件。例如,圆面积关系为:
其中,半径用 r 表示,面积用 S 表示。若将直径当作半径,公式即使抄写正确,也会得到错误结果。
2.3 伪代码中的完整处理范围
伪代码(Pseudocode)使用接近自然语言的表达描述处理逻辑。
登记表任务可以先写成:
建立输入文件清单
对清单中的每个文件:
如果是临时文件或非目标格式:
记录来源与排除原因
否则:
尝试读取并检查目标文档
如果读取失败或不符合模板与字段要求:
记录来源与待核查原因
否则:
保存字段与来源
输出三个类别的记录
核对文件数量与每条记录的内容
重复范围、判断条件和执行顺序共同构成处理流程。将三份样表逐项代入,可以在编写代码前检查分支是否完整。
若只写“遇到错误就跳过”,被跳过的文件便缺少可回查的去向。记录来源与原因,才能解释它为什么没有出现在有效汇总中。
三、抽象模型与算法推演
3.1 七桥问题的结构判断
3.1.1 从陆地与桥到图
哥尼斯堡七桥问题(Seven Bridges of Königsberg)询问:能否连续行走,恰好经过每座桥一次?
可以先讨论要求回到起点的情形,再讨论允许起点与终点不同的情形。两种要求对应不同的路线条件。
欧拉(Leonhard Euler)通过研究陆地与桥的连接关系分析这一问题。用现代图论语言,可以把陆地表示为顶点(Vertex),桥表示为边(Edge),形成图(Graph)。
桥的长度、颜色和陆地面积可以略去;哪些陆地相连,以及相连的桥有几座,必须保留。
![]()
图 3-1:七桥问题的抽象模型
将四块陆地命名为 A、B、C、D,七座桥的连接关系可以表示为:
• A 与 B 之间两座
• A 与 C 之间两座
• A 与 D 之间一座
• B 与 D 之间一座
• C 与 D 之间一座
同一对陆地之间的两座桥应保留为两条不同的边。若只记录去重后的“陆地对”,就会丢失需要经过两座桥的约束。
3.1.2 度数与成对进出
顶点的度数(Degree)是与该顶点关联的边端数量。自环在同一个顶点上贡献两次;当前七桥图没有自环,可以直接数各块陆地连接的桥数:
• A 的度数为 5。
• B、C、D 的度数均为 3。
每条边有两个端点,因此所有顶点度数之和等于边数的两倍:
其中,V 表示顶点集合,E 表示边集合,竖线表示集合中的元素数量。这一关系提供了独立的计数核对。
行走经过中间顶点时,沿一条边进入,就需要沿另一条尚未使用的边离开。一次完整进出消耗两条关联边,这解释了偶数度的重要性。
3.1.3 回路与开放通路
恰好经过每条边一次的路线称为欧拉通路(Euler Trail);其中回到起点的情形称为欧拉回路(Euler Circuit)。
在回路中,起点的首次离开与最后返回也可以配成一对,因此每个顶点都需要偶数条关联边。
若起点与终点不同,起点可以多一次离开,终点可以多一次进入,因此两者的度数为奇数,其余顶点的度数为偶数。
对于至少含一条边的有限无向图,在所有非孤立顶点相互连通的条件下:
• 存在欧拉回路,当且仅当所有顶点的度数均为偶数。
• 存在起点与终点不同的欧拉通路,当且仅当恰有两个奇度顶点。
• 奇度顶点超过两个时,不存在经过每条边恰好一次的路线。
连通性不能省略。两个互不相连的环,虽然所有顶点度数都是偶数,却无法通过一次连续行走遍历全部边。孤立顶点不影响对已有边的遍历判断。
偶数度与连通性也足以保证欧拉回路存在,可以通过逐步构造回路来理解。从一个有边的顶点出发,连续沿未使用的边行走,直到无法继续。成对进出的关系保证路线在起点闭合。
若还有未使用的边,连通性保证已有回路上存在与剩余边相接的顶点。移除已经使用的边后,各顶点的剩余度数仍为偶数,因此可以从相接点构造另一个回路,再接入原路线。边数有限,重复这一过程即可覆盖全部边。
对于恰有两个奇度顶点的情况,可以临时在它们之间增加一条边,使所有度数变为偶数。得到回路后删去这条临时边,就形成以两个奇度顶点为端点的开放通路。
七桥图有四个奇度顶点,因此两种路线都不存在。
3.1.4 结构检查与条件修改
结构检查需要同时保留每座桥、统计度数并检查连通性。邻接关系可以只记录两个顶点是否相连,但度数计算必须计入重复边。
增建一座 B—C 桥后,B 与 C 变成偶度,A 与 D 仍为奇度,因此新图存在以 A、D 为端点的开放通路。
若分别增建 A—B 与 C—D 两座桥,四个顶点都变成偶度,新图便满足欧拉回路条件。
修改约束可以产生新的可解问题,但必须清楚说明改变了哪些条件。修改后的路线不能作为原七桥问题的解答。
3.2 最大公约数与欧几里得算法
3.2.1 从定义到取余
两个不全为零的整数的最大公约数(Greatest Common Divisor,GCD),是同时整除它们的最大正整数。
求 48 与 18 的最大公约数,可以列出约数后比较。欧几里得算法(Euclidean Algorithm)则通过反复取余,将问题逐步缩小。
设 a 为非负整数,b 为正整数。带余除法给出:
若正整数 d 同时整除 a 和 b,它也整除余数;反过来,若 d 同时整除 b 和余数,它也整除 a:
因此,两对数拥有相同的公约数:
这条关系将原问题转化为同类、规模更小的问题。
3.2.2 手工追踪与终止依据
对 48 与 18,取余过程为:
每一步把原来的除数与余数作为下一对输入,最后得到 6 与 0。每个非零整数都整除 0,因而这两个数的最大公约数为 6。
![]()
图 3-2:欧几里得算法的取余与终止
算法的正确性与终止性分别有不同依据:
• 正确性:每次更新后,两数的公约数集合保持不变。
• 终止性:只要除数非零,新余数就比它小且不为负;非负整数不能无限严格递减。
计算过程中持续保持的性质,称为不变量(Invariant)。识别不变量,有助于解释算法为什么得到正确结果。
3.2.3 Python 实现
对于负整数,可以先取绝对值。一个输入为零、另一个非零时,结果为非零输入的绝对值。
两个输入都为零时,所有正整数都是公约数,按“最大正公约数”的定义不存在最大值。Python 标准库对这种情况约定返回零,上面的示例采用相同的结果约定。数学定义与程序接口约定需要分别理解。
3.3 猴子吃桃的迭代与递归
3.3.1 时间点与递推关系
从第一天到第九天,猴子每天早上吃掉现有桃子的一半,再多吃一个,其余时间桃子数量不变。第十天早上尚未进食时,剩下一个。求第一天早上的数量。
用 a_i 表示第 i 天早上进食前的桃子数。前九天相邻状态之间满足:
已知最后一天的数量,可以反向整理为:
递推关系(Recurrence Relation)描述相邻状态怎样联系;迭代(Iteration)通过重复计算更新状态。迭代可以用于手工计算,也可以用循环实现。
3.3.2 反推与更新次数
由已知状态逐步计算:
从第十天回到第一天,需要跨过九个相邻日期,因此更新九次。若直接把“十天”理解为十次更新,就会多反推一天,得到 3070,与原题的时间点不符。
3.3.3 迭代实现
迭代过程中应保持状态含义清楚:初始数量对应第十天,更新一次对应第九天,更新九次对应第一天。明确状态与日期的对应关系,有助于判断循环边界。
3.3.4 递归调用与逐层返回
递归(Recursion)通过同类子问题的结果完成当前计算。
在这个问题中,求第一天的数量需要第二天的数量,求第二天又需要第三天,直到第十天可以直接使用已知结果。调用过程向已知情形推进:
求第一天 → 求第二天 → …… → 求第九天 → 第十天直接返回 1
随后逐层返回,计算第九天的 4、第八天的 10,最终得到第一天的 1534。
递归需要明确基本情形(Base Case),并使每次调用逐步接近它。缺少基本情形,或状态更新方向错误,都可能使调用无法按计划结束。
这里每次只依赖一个后续状态。分治(Divide and Conquer)通常还涉及多个子问题及其结果组合,不能仅凭程序使用递归,就认定它采用了分治算法。
3.3.5 两种实现的核验
对原题给定的十天情形,两种实现使用相同的递推关系,都进行九次反推。迭代使用少量变量保存当前状态;递归还需要保留尚未完成的函数调用。
整数的位数会随天数增加,因此“只保存一个整数”也不意味着存储需求始终固定。
可以通过代数推导独立核验:
连续使用九次:
还可以从 1534 正向模拟,依次得到:
1534 → 766 → 382 → 190 → 94 → 46 → 22 → 10 → 4 → 1
仅检查两份程序输出相同,可能漏掉两者共同采用的错误规则。代数推导与正向模拟提供了不同的核验依据。
3.4 积分近似与误差分析
3.4.1 从曲线面积到矩形求和
考虑平方函数在零到一区间内与横轴围成的面积:
将区间等分为 n 段,其中 n 为正整数,每段宽度为:
用矩形近似每段面积,需要决定矩形高度的取值位置。左端点法使用各段左端的函数值,右端点法使用各段右端的函数值:
求和符号表示将指定范围内的各项相加。两个式子都包含 n 项,对应 n 个矩形。
在各个子区间内选取一个点,将该点的函数值与子区间宽度相乘,再把这些乘积相加,所得结果称为黎曼和(Riemann Sum)。左、右端点法采用不同的取点位置。
对于这里的连续函数,当分段宽度趋于零时,黎曼和趋于定积分的值。
![]()
图 3-3:左、右端点矩形和与曲线面积
平方函数在这个区间递增,因此左端点和偏小,右端点和偏大:
这一大小关系依赖函数在指定区间内的单调性。更换函数或区间后,应重新分析。
3.4.2 四段时的手算与精确值
取四段时,每段宽度为 0.25。左端点的函数值依次为 0、0.0625、0.25、0.5625:
右端点的函数值依次为 0.0625、0.25、0.5625、1:
精确求值则使用原函数。对于闭区间上的连续函数,若已有相应原函数,牛顿—莱布尼茨公式(Newton–Leibniz Formula)给出:
平方函数的一个原函数为:
因此,精确积分值为:
两种方法得到的结果满足:
原函数法在这里给出精确值;有限矩形求和给出近似值。对于原函数难以用方便的形式表达,或只有离散采样数据的情况,可以考虑数值积分(Numerical Integration)。
3.4.3 平方和公式的推导
为了分析分段数与误差的关系,先整理右端点和:
平方和可以利用相邻立方之差推导:
让 k 从 1 取到 n,两边分别相加。左侧中间项相消,只剩 n 的立方:
利用等差数列求和公式:
移项整理得到:
代回右端点和:
左右端点和的共同项相消,只留下最右与最左两个高度的差:
因此:
这些关系既说明近似值为什么趋近于三分之一,也解释了两种取点方式产生的偏差方向。
3.4.4 误差与计算量
对当前函数、区间和等分右端点法,近似误差为:
分为四段与八段时:
分为一千段时:
对这个函数的等分右端点法,矩形近似误差随分段数增加而单调减小。如果逐段计算矩形面积,计算项数也随之增加;若已推导出专用公式,则可以直接利用公式求值。
程序使用浮点数时,还会引入表示与舍入误差。选择分段数需要同时考虑方法误差、数值计算和资源消耗。对其他积分,应使用相应的误差分析,不能只凭几次结果彼此接近就认定精度足够。
3.4.5 Python 实现与核对
核验可以从四段时的手算结果开始,再检查夹逼关系、左右差值和独立推导的求和公式。多种依据结合,比仅观察输出的小数形式更能发现问题。
四、可计算性与实现条件
4.1 机械规则的逐步执行
图灵机(Turing Machine)使用纸带、读写头、有限控制状态和转移规则描述机械化计算。理论模型允许使用无界的纸带空间;实际计算设备具有有限的存储和运行资源。
可以通过一个简单过程观察机械执行。假定读写头从有限二进制串的最左端开始:
• 读到 0,写成 1,并向右移动。
• 读到 1,写成 0,并向右移动。
• 读到输入末尾的空白,停止。
对输入 0110 逐格执行,得到 1001。输入范围、符号含义、移动方向与停止条件均已确定。
若改为始终向右移动,遇到空白也继续移动,就会形成持续运行的过程。明确规则本身并不保证程序终止。
邱奇—图灵论题(Church–Turing Thesis)认为,直观意义上能够有效机械执行的计算,都可以由图灵机完成。它将直观概念与形式模型联系起来;不同形式化计算模型之间的等价性,则可以在各自定义下证明。
4.2 停机问题的反证思路
停机问题(Halting Problem)询问:给定程序及其输入,程序最终是否会停止。
假设存在一个判断器 H,总能停止,并正确判断任意程序在指定输入上是否停止。
利用 H 构造程序 D。D 接收一段程序的编码,询问 H:“这段程序以自身编码为输入时,会停止吗?”
随后,D 按相反方式行动:
• H 判断会停止,D 就持续运行。
• H 判断不会停止,D 就立即停止。
现在,将 D 自身的编码作为输入交给 D。若 H 判断它会停止,D 就持续运行;若 H 判断它不会停止,D 又立即停止。两种结果都与假设矛盾,因此这样的通用判断器不存在。
这不妨碍分析具体算法。最大公约数可以依据公约数关系和余数递减证明正确性与终止性;登记表程序也可以在明确的输入和环境条件下接受检查。
有限样例测试能够发现错误,但不能自动构成对全部输入的正确性证明。
4.3 求解方法、资源与执行机构
任务能够写出输入与输出,说明需求已有表达,接下来还需要确定可执行的求解方法。一个数学命题尚未得到证明,也不能直接作为已经证明不可计算的例子。
存在算法后,还需考虑时间与存储。枚举一个有限但极大的组合空间,理论上能够结束,实际却可能耗时过长。积分近似同样需要权衡精度与计算量。
若任务涉及“烹制一个汉堡”等物理操作,还需要原料、传感器、执行机构与控制系统。计算可以支持配方安排和动作控制,实际完成任务则依赖设备与环境条件。
因此,应分别检查求解方法是否存在、资源是否足够,以及现实操作条件是否具备。
五、大模型辅助编程与方案验证
5.1 需求转换与程序组织
大语言模型(Large Language Model,LLM)可以协助把需求转化为候选代码。代码的具体执行仍依赖语言实现、程序库和运行环境。
明确描述有助于减少不必要的假设;结果是否正确,还需依据输入、规则与预期进行核验。
程序表达具有不同抽象层次:机器语言(Machine Language)使用处理器能够执行的指令编码;汇编语言(Assembly Language)使用助记符表示指令;高级语言(High-Level Language)提供更接近任务的数据与操作表达。
自然语言辅助编程(Natural Language-Assisted Programming)进一步提供了描述需求、生成和修改代码的交互方式,生成结果仍需遵循相应语言与运行环境的规则。
面向过程(Procedural Programming)与面向对象(Object-Oriented Programming)关注程序怎样组织;自然语言辅助编程关注人与工具怎样协作生成和修改代码。这些方式可以结合使用。
5.2 同一案例的验证与修改
登记表任务可以使用以下请求:
输入为指定目录中的 Word 登记表,格式和字段以提供的三份虚构样表为准。请先列出文件范围、字段结构、缺失与重复标签的处理规则,以及汇总、待核查、排除三个工作表的内容。对不明确的条件先提出问题。确认规则后再给出 Python 实现,保留来源和原文件,拒绝覆盖已有输出。请在代码注释中说明关键操作,并列出测试方法和仍需人工核验的事项。
提供样表时,应同时说明已独立确定的预期结果。模型可以协助补充测试思路,验收依据仍需回到材料和任务规则。
得到候选代码后,应确认它是否实现实际文件读取、分类、保存和结果核对。出现差异时,提供具体材料、原定规则、实际结果与预期结果,例如:
第三份样表的籍贯为空,按规则应进入待核查,但实际进入了有效汇总。请检查必需字段的空值判断,说明原因,并给出最小修改及对应测试。
增加字段、修改日期格式或改变模板时,应同步更新需求、测试材料与验收依据。原样例也应重新检查,防止修正一种情况时影响已有功能。
5.3 从案例迁移到新任务
七桥问题保留连接结构,欧几里得算法保持公约数关系,猴子吃桃利用相邻日期的递推关系,积分近似连接分段、累加与误差。登记表任务则需要保留字段、来源、分类和输出约定。
面对新问题,可以依次检查:
• 哪些对象与关系必须保留?
• 哪些规则需要事先确定?
• 状态怎样变化?
• 过程何时结束?
• 结果依据什么核验?
这些问题把案例中的方法连接起来,使手工推演、程序执行与结果解释形成完整的处理过程。
小结
案例推演将程序化思维落实为可检查的关系:以度数判断路线,以不变量解释取余,以递推连接状态,以误差分析近似。结合材料约定、独立预期和执行核验,可以逐步建立从明确需求到验证方案的完整方法。
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.