You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Black Box Component Builder求解Advent of Code的方法与思路咨询

使用Black Box Component Builder解决Advent of Code 2023第1天问题

解题思路与BBCB环境适配

BBCB基于Component Pascal,核心特点是强类型、模块化结构,文本处理依赖内置标准模块,思维方式和你熟悉的Lisp、Forth、C有明显差异:

  • 无动态类型或栈式操作,需用静态变量、循环、条件判断处理逻辑
  • 所有代码需封装在MODULE中,依赖的系统模块必须显式导入
  • 字符串、文件操作依赖Strings、Files等内置模块,过程式风格更突出

第一部分:提取数字字符求和

核心逻辑

读取每行文本,分别找到第一个和最后一个数字字符,组合成两位数后累加总和。

BBCB代码实现

MODULE AoC2023Day1Part1;
IMPORT Files, Strings, Chars, Out;

PROCEDURE ComputeSum*(inputPath: ARRAY OF CHAR): INTEGER;
VAR
  f: Files.File;
  line: Strings.String;
  first, last: CHAR;
  sum, num: INTEGER;
  i: INTEGER;
BEGIN
  sum := 0;
  IF Files.Open(f, inputPath, Files.Read) THEN
    WHILE Files.ReadLn(f, line) DO
      first := #0; last := #0;
      (* 查找第一个数字字符 *)
      FOR i := 0 TO Strings.Length(line)-1 DO
        IF Chars.IsDigit(Strings.Get(line, i)) THEN
          first := Strings.Get(line, i);
          EXIT;
        END;
      END;
      (* 查找最后一个数字字符 *)
      FOR i := Strings.Length(line)-1 DOWNTO 0 DO
        IF Chars.IsDigit(Strings.Get(line, i)) THEN
          last := Strings.Get(line, i);
          EXIT;
        END;
      END;
      (* 计算当前行数值并累加 *)
      IF first # #0 THEN
        num := (ORD(first) - ORD('0')) * 10 + (ORD(last) - ORD('0'));
        sum := sum + num;
      END;
    END;
    Files.Close(f);
  END;
  RETURN sum;
END ComputeSum;

PROCEDURE Run*;
VAR
  total: INTEGER;
BEGIN
  total := ComputeSum("input.txt");
  Out.String("第一部分总和:"); Out.Int(total, 0); Out.Ln;
END Run;

END AoC2023Day1Part1.

代码说明

  • 导入Files处理文件读写,Strings操作字符串,Chars判断字符类型,Out实现控制台输出
  • 两次遍历每行文本分别定位首尾数字,逻辑直观符合BBCB的过程式风格
  • 通过ORD函数将字符转换为对应数值,这是Component Pascal处理字符转数字的标准方式

第二部分:识别数字单词

核心调整

新增数字单词(one-nine)的识别逻辑,遍历文本时需同时检查单个字符和子串是否匹配数字单词。

BBCB代码实现

MODULE AoC2023Day1Part2;
IMPORT Files, Strings, Chars, Out;

CONST
  numWords: ARRAY 9 OF ARRAY OF CHAR = ("one", "two", "three", "four", "five", "six", "seven", "eight", "nine");
  numVals: ARRAY 9 OF INTEGER = (1, 2, 3, 4, 5, 6, 7, 8, 9);

PROCEDURE GetNumAtPos(line: Strings.String; pos: INTEGER): INTEGER;
VAR
  i: INTEGER;
  sub: Strings.String;
BEGIN
  (* 检查单个数字字符 *)
  IF Chars.IsDigit(Strings.Get(line, pos)) THEN
    RETURN ORD(Strings.Get(line, pos)) - ORD('0');
  END;
  (* 检查是否匹配数字单词 *)
  FOR i := 0 TO 8 DO
    IF pos + Strings.Length(numWords[i]) <= Strings.Length(line) THEN
      Strings.Sub(line, pos, Strings.Length(numWords[i]), sub);
      IF Strings.Equal(sub, numWords[i]) THEN
        RETURN numVals[i];
      END;
    END;
  END;
  RETURN -1; (* 未找到有效数字 *)
END GetNumAtPos;

PROCEDURE ComputeSum*(inputPath: ARRAY OF CHAR): INTEGER;
VAR
  f: Files.File;
  line: Strings.String;
  first, last, current: INTEGER;
  sum, i: INTEGER;
BEGIN
  sum := 0;
  IF Files.Open(f, inputPath, Files.Read) THEN
    WHILE Files.ReadLn(f, line) DO
      first := -1; last := -1;
      (* 单次遍历定位首尾有效数字 *)
      FOR i := 0 TO Strings.Length(line)-1 DO
        current := GetNumAtPos(line, i);
        IF current <> -1 THEN
          IF first = -1 THEN first := current; END;
          last := current; (* 持续更新最后一个数字 *)
        END;
      END;
      IF first <> -1 THEN
        sum := sum + first * 10 + last;
      END;
    END;
    Files.Close(f);
  END;
  RETURN sum;
END ComputeSum;

PROCEDURE Run*;
VAR
  total: INTEGER;
BEGIN
  total := ComputeSum("input.txt");
  Out.String("第二部分总和:"); Out.Int(total, 0); Out.Ln;
END Run;

END AoC2023Day1Part2.

代码说明

  • 用常量数组存储数字单词与对应数值,符合BBCB静态类型的设计思路
  • GetNumAtPos封装位置数字识别逻辑,职责单一,便于维护
  • 单次遍历即可完成首尾数字的定位,优化了第一部分的重复遍历逻辑

BBCB解题思维总结

  1. 模块化封装:所有功能拆分为独立过程,放在MODULE中,便于复用和调试
  2. 依赖标准模块:优先使用内置的Strings、Files等模块,避免自定义基础操作
  3. 静态类型约束:提前明确变量类型,减少运行时错误,这和C的思路类似,但模块化边界更清晰
  4. 过程式逻辑:用循环、条件判断处理字符流,无函数式高阶操作,逻辑直观易读

内容的提问来源于stack exchange,提问作者Ala'a Mohammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:38:16