Но то, что действительно меня сейчас раздражает, так это то, что в конце нужно вставить треугольную матрицу «не дублируйте никакие привязки».
Мы можем получить лучшеерешение с предикатом all_dif/1
отсюда: https://stackoverflow.com/a/47294595/4391743
all_dif([]).
all_dif([E|Es]) :-
maplist(dif(E), Es),
all_dif(Es).
Этот предикат принимает список элементов, которые отличаются друг от друга.Пока не беспокойтесь о том, чтобы не понять его, вы можете пока рассматривать его как черный ящик.
Вы можете использовать это, чтобы заменить большой блок not
целей в конце определения предиката:
crossword(V1,V2,V3,H1,H2,H3):-
... % unchanged code here
all_dif([V1, V2, V3, H1, H2, H3]).
С этим вы вернетесь только к двум решениям, в которых используются все слова.
Я не чувствую, как пометить привязки как "не волнует "(например, 1-я, 3-я, 5-я и 7-я буквы слов совершенно не имеют значения).
Это действительно очень важный вопрос!А Пролог должен предупредить вас о переменных, которые вы используете только один раз (так называемые "одиночные"), потому что они являются частым источником ошибок:
Singleton variables: [V1a,V1c,V1e,V1g,V2a,V2c,V2e,V2g,V3a,V3c,V3e,V3g,H1a,H1c,H1e,H1g,H2a,H2c,H2e,H2g,H3a,H3c,H3e,H3g]
Вы явно помечаете переменную как "все равно", даваяэто имя, начинающееся с символа подчеркивания _
, или просто с именем _
в целом.Различные вхождения _
помечают разные переменные "все равно".Таким образом, мы получаем:
crossword(V1,V2,V3,H1,H2,H3):-
word(V1,_,V1b,_,V1d,_,V1f,_),
word(V2,_,V2b,_,V2d,_,V2f,_),
word(V3,_,V3b,_,V3d,_,V3f,_),
word(H1,_,H1b,_,H1d,_,H1f,_),
word(H2,_,H2b,_,H2d,_,H2f,_),
word(H3,_,H3b,_,H3d,_,H3f,_),
V1b = H1b,
V1d = H2b,
V1f = H3b,
V2b = H1d,
V2d = H2d,
V2f = H3d,
V3b = H1f,
V3d = H2f,
V3f = H3f,
all_dif([V1, V2, V3, H1, H2, H3]).
Предупреждения исчезли и , нам легче читать программу, потому что подчеркивания оставляют «дыры» в неинтересных местах, и мы более четко видим, какие переменные имеют значение.
Это оставляет нам задачу удалить все эти уравнения.Общий совет по Прологу: За исключением, может быть, иногда по соображениям наглядности, никогда не нужно писать уравнение вида Var1 = Var2
, где обе стороны являются переменными.Просто используйте одно и то же имя для обеих переменных во всем предложении, и вы получите один и тот же результат!
Так что давайте заменим V1b
и H1b
на одну и ту же переменную с именем A
, V1d
и H2b
по той же переменной B
и т. Д.:
crossword(V1,V2,V3,H1,H2,H3):-
word(V1,_,A,_,B,_,C,_),
word(V2,_,D,_,E,_,F,_),
word(V3,_,G,_,H,_,I,_),
word(H1,_,A,_,D,_,G,_),
word(H2,_,B,_,E,_,H,_),
word(H3,_,C,_,F,_,I,_),
all_dif([V1, V2, V3, H1, H2, H3]).
Это эквивалентно вашему первоначальному решению и, я надеюсь, довольно дружественному для новичков.
Надеюсь, это даст вам понять, чтоПрограммы Prolog могут быть немного менее неуклюжими, чем ваша первая попытка.Пожалуйста, останьтесь здесь, мы здесь, чтобы помочь, если вы застряли, и, надеюсь, у вас будет несколько менее неприятных переживаний и вы увидите магию Пролога.