Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Learning Prolog: solving a crossword scheme

I'm trying to learn Prolog following the tutorials on this site and I can't find a solution to an exercise (and there's no solution on the site).

Here's what I have to do:

Here are six Italian words:

astante , astoria , baratto , cobalto , pistola , statale .

They are to be arranged, crossword puzzle fashion, in the following grid:

scheme

The following knowledge base represents a lexicon containing these 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).

Write a predicate crossword/6 that tells us how to fill in the grid. The first three arguments should be the vertical words from left to right, and the last three arguments the horizontal words from top to bottom.

Now, the same question has been asked there but each given solution uses things that I don't know (and I'm not supposed to know to solve this).

To clarify, while the things in the linked question are surely working, they use stuff that hasn't been explained yet in the guide that I'm following, and this means that I need to solve the exercise without using that kind stuff, so no maplist and things like that.

My idea was to fill the board with the letters from the given words, with some constraints:

  • the word in V1 must have, as its second character, the second character of the word in H1
  • the word in V1 must have, as its fourth character, the second character of the word in H2
  • the word in V1 must have, as its sixth character, the second character of the word in H3

and so on..

So here's my code:

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). 

crossword(V1,V2,V3,H1,H2,H3):- word(V1, V11,V12,V13,V14,V15,V16,V17),
                               word(H1, H11,V12,H13,H14,H15,H16,H17),
                               word(H2, H21,V14,H23,H24,H25,H26,H27),
                               word(H3, H31,V16,H33,H34,H35,H36,H37),

                               word(V2, V21,V22,V23,V24,V25,V26,V27),
                               word(H1, H11,H12,H13,V22,H15,H16,H17),
                               word(H2, H21,H22,H23,V24,H25,H26,H27),
                               word(H3, H31,H32,H33,V26,H35,H36,H37),

                               word(V3, V31,V32,V33,V34,V35,V36,V37),
                               word(H1, H11,H12,H13,H14,H15,V32,H17),
                               word(H2, H21,H22,H23,H24,H25,V34,H27),
                               word(H3, H31,H23,H33,H34,H35,V36,H37). 

(I'm sorry if this is not formatted well but I still don't know what's the correct indentation style for Prolog).

Of course, event if my idea seems correct (at least to me), this code returns No and I don't know why.

Any hint on this?

EDIT:

Following @mbratch's comment, I've tried using the code found in this solution.

Here's the code:

crossword(V1, V2, V3, H1, H2, H3) :-
   word(V1, V1a, V1bH1b, V1c, V1dH2b, V1e, V1fH3b, V1g), 
   word(V2, V2a, V2bH1d, V2c, V2dH2d, V2e, V2fH3d, V2g), 
   word(V3, V3a, V3bH1f, V3c, V3dH2f, V3e, V3fH3f, V3g), 
   word(H1, H1a, V1bH1b, H1c, V2bH1d, H1e, V3bH1f, H1g), 
   word(H2, H2a, V1dH2b, H2c, V2dH2d, H2e, V3dH2f, H2g), 
   word(H3, H3a, V1fH3b, H3c, V2fH3d, H3e, V3fH3f, H3g).

The code works, but it has a problem with duplicates which I don't mind.

What I'd like to understand is why this one works while mine returns No.

like image 643
StepTNT Avatar asked Jan 19 '14 18:01

StepTNT


2 Answers

crossword(V1,V2,V3,H1,H2,H3) :-
 word(V1, _, V12, _, V14, _, V16, _),
 word(V2, _, V22, _, V24, _, V26, _),
 word(V3, _, V32, _, V34, _, V36, _),
 word(H1, _, V12, _, V22, _, V32, _),
 word(H2, _, V14, _, V24, _, V34, _),
 word(H3, _, V16, _, V26, _, V36, _),
 V1 \= H1.
like image 81
Arik Avatar answered Nov 04 '22 23:11

Arik


After few tries, and based on @joel76's comment, I noticed that my first code was wrong because I declared H1,H2 and H3 multiple times, so the result computed in the second line was being changed in the sixth and this led to the No returned by Prolog.

So, instead of doing things in multiple lines, I merged them with this result:

crossword(V1,V2,V3,H1,H2,H3):- word(V1, V11, V12, V13, V14, V15, V16, V17),
                               word(V2, V21, V22, V23, V24, V25, V26, V27),
                               word(V3, V31, V32, V33, V34, V35, V36, V37),
                               word(H1, H11, V12, H13, V22, H15, V32, H17),
                               word(H2, H21, V14, H23, V24, H25, V34, H27),
                               word(H3, H31, V16, H33, V26, H35, V36, H37).

and now it's working.

like image 27
StepTNT Avatar answered Nov 05 '22 01:11

StepTNT