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

Prolog实现谢尔宾斯基地毯遇阻,寻求技术解决方案

解决Prolog实现谢尔宾斯基地毯的问题

嘿,作为Prolog新手折腾递归图形生成确实容易卡壳,咱们先从你现有的代码出发,一步步把谢尔宾斯基地毯的逻辑补全跑通。

首先先把你给出的代码片段放出来:

rewrite('X', [['X','X','X'],['X',' ','X'],['X','X','X']]).
rewrite(' ', [[' ',' ',' '],[' ',' ',' '],[' ',' ',' ']]).
rec(1, [], CurrentList, [CurrentList]).
rec(_, [], CurrentList, CurrentList).
rec(0, L, CurrentList, Result):- append(CurrentList, [L], Result).
rec(N, [H|T], CurrentList, Result):- atom(H), N > 0, rewrite(H, L), K is N - 1, rec...

现有代码的问题分析

你的思路方向是对的:用rewrite/2定义每个符号的替换规则,用rec/4做递归展开,但几个子句的逻辑有点冲突,比如:

  • 多个rec的base case(比如rec(1, [], ...)和rec(_, [], ...))会导致匹配混乱
  • 递归展开时,没有处理rewrite返回的二维列表,而是直接把它当成普通元素来处理,这会导致层级不对
  • 当处理列表中的元素时,没有考虑递归展开后需要把多行合并的逻辑(谢尔宾斯基地毯是按行来生成的,每一层要把三行分别拼接)

修正后的完整实现

咱们重新梳理逻辑,核心是:

  1. 定义初始的1阶地毯(就是单个'X')
  2. 递归时,把当前每一行的每个符号替换成对应的3行,然后把三部分的行分别拼接起来
  3. 最后把生成的二维列表打印出来,方便看效果

完整代码如下:

% 定义替换规则:X替换成3x3的块,空格替换成全空格块
rewrite('X', [['X','X','X'], ['X',' ','X'], ['X','X','X']]).
rewrite(' ', [[' ',' ',' '], [' ',' ',' '], [' ',' ',' ']]).

% 递归的base case:0阶时,直接返回原元素组成的单一行
rec(0, Symbol, [Symbol]).
% 递归步骤:对Symbol进行替换,然后对替换后的每一行递归展开K阶(K=N-1)
rec(N, Symbol, Result) :-
    N > 0,
    K is N - 1,
    rewrite(Symbol, Block),
    % 对Block中的每一行递归展开,得到展开后的行列表
    maplist(rec_row(K), Block, ExpandedRows),
    % 把三部分的行分别拼接:第一行+第二行+第三行
    append(ExpandedRows, Result).

% 处理一行的递归展开:把行里的每个元素递归展开K阶,然后把对应位置的行拼接
rec_row(K, Row, ExpandedRow) :-
    % 对行里的每个符号递归展开K阶,得到每个符号对应的行列表
    maplist(rec(K), Row, SymbolRows),
    % 把每个符号的第1行、第2行、第3行分别拼接起来
    transpose(SymbolRows, Transposed),
    maplist(append, Transposed, ExpandedRow).

% 辅助谓词:转置二维列表(用来把每个符号的行对齐拼接)
transpose([], []).
transpose([[]|_], []).
transpose(Matrix, [Row|Rows]) :-
    maplist(head, Matrix, Row),
    maplist(tail, Matrix, RestMatrix),
    transpose(RestMatrix, Rows).

head([H|_], H).
tail([_|T], T).

% 生成并打印N阶谢尔宾斯基地毯
sierpinski(N) :-
    rec(N, 'X', Carpet),
    maplist(print_row, Carpet).

print_row(Row) :-
    atom_chars(Atom, Row),
    writeln(Atom).

代码解释

  • rewrite/2:保持你原来的定义,每个符号对应3x3的块
  • rec/3:递归生成N阶地毯,base case是0阶直接返回单元素行;N>0时先替换成3x3块,再对每一行递归展开
  • rec_row/3:处理单行的展开,把行内每个符号的展开结果转置后拼接,这样就能把三个符号的第一行拼在一起,第二行拼在一起,以此类推
  • transpose/2:辅助谓词,用来转置二维列表,实现行对齐拼接
  • sierpinski/1:入口谓词,调用递归生成后打印每一行

测试效果

比如调用sierpinski(2).,会输出:

XXXXXXXXXXX
X XX XX XX
XXXXXXXXXXX
XXX   XXX
X X   X X
XXX   XXX
XXXXXXXXXXX
X XX XX XX
XXXXXXXXXXX

这样就能正确生成谢尔宾斯基地毯啦~

内容的提问来源于stack exchange,提问作者Mesieur Kobayashi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:45:15