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

Prolog中实现唯一绑定的更优方法咨询

Simplifying Uniqueness Constraints in Your Prolog Crossword Solver

Hey there! Great job getting that crossword solver up and running—even if all those manual not(X=Y) checks feel clunky and repetitive. Let's fix that and make your code more concise, readable, and aligned with declarative programming principles.

The Problem with Manual Uniqueness Checks

Writing out every pair-wise not(X=Y) is not only tedious, but it's also error-prone (easy to miss a pair!) and doesn't scale well if you ever expand the crossword size. Instead of telling Prolog how to check uniqueness, we can declare what we want: all words in the crossword must be distinct.

A Clean Solution: A Reusable all_unique Predicate

Most Prolog implementations don't have a built-in predicate for checking uniqueness of arbitrary terms, but we can easily build one using two basic Prolog tools: sort/2 and length/2. Here's how it works:

  • sort/2 takes a list and returns a sorted version where duplicate elements are removed.
  • If the original list has all unique elements, the sorted list will have the same length as the original.

Here's the helper predicate:

all_unique(List) :-
    sort(List, SortedList),
    length(List, OriginalLength),
    length(SortedList, OriginalLength).

Updated Crossword Code

Now we can replace all those repetitive not(X=Y) lines with a single call to all_unique/1, passing in a list of all our crossword words:

word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).

% Helper to check all elements in a list are unique
all_unique(List) :-
    sort(List, SortedList),
    length(List, OriginalLength),
    length(SortedList, OriginalLength).

crossword(V1,V2,V3,H1,H2,H3):-
    word(V1,V1a,V1b,V1c,V1d,V1e,V1f,V1g),
    word(V2,V2a,V2b,V2c,V2d,V2e,V2f,V2g),
    word(V3,V3a,V3b,V3c,V3d,V3e,V3f,V3g),
    word(H1,H1a,H1b,H1c,H1d,H1e,H1f,H1g),
    word(H2,H2a,H2b,H2c,H2d,H2e,H2f,H2g),
    word(H3,H3a,H3b,H3c,H3d,H3e,H3f,H3g),
    % Grid intersection constraints
    V1b = H1b, V1d = H2b, V1f = H3b,
    V2b = H1d, V2d = H2d, V2f = H3d,
    V3b = H1f, V3d = H2f, V3f = H3f,
    % Clean, scalable uniqueness check
    all_unique([V1,V2,V3,H1,H2,H3]).

Why This Works

  • Declarative Style: Instead of manually enumerating every pair of words to compare, we're telling Prolog "all these words must be unique"—which is exactly what we mean, without getting bogged down in implementation details.
  • Scalability: If you ever add more words to the crossword (e.g., V4, H4), you just add them to the list passed to all_unique/1—no need to write dozens more comparison lines.
  • Reliability: No risk of missing a pair-wise check, which is easy to do with 6+ variables.

Bonus: Efficiency Tip (Optional)

For a small performance boost, you can reorder your goals to apply the intersection constraints earlier. This lets Prolog prune invalid word choices sooner, instead of generating all possible word combinations first:

crossword(V1,V2,V3,H1,H2,H3):-
    word(V1,V1a,V1b,V1c,V1d,V1e,V1f,V1g),
    word(H1,H1a,V1b,H1c,H1d,H1e,H1f,H1g), % Bind V1b to H1b immediately
    word(H2,H2a,V1d,H2c,H2d,H2e,H2f,H2g), % Bind V1d to H2b immediately
    word(H3,H3a,V1f,H3c,H3d,H3e,H3f,H3g), % Bind V1f to H3b immediately
    word(V2,V2a,H1d,V2c,V2d,V2e,V2f,V2g), % Bind V2b to H1d immediately
    word(V3,V3a,H1f,V3c,V3d,V3e,V3f,V3g), % Bind V3b to H1f immediately
    V2d = H2d, V2f = H3d,
    V3d = H2f, V3f = H3f,
    all_unique([V1,V2,V3,H1,H2,H3]).

This isn't strictly necessary for your current problem, but it's a good habit to pick up as you dive deeper into declarative programming and optimization.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:35:55