改进我们的Hidoku拼图解决算法

时间:2019-06-13 12:23:32

标签: prolog

Hidoku(Hidato)是一个日语逻辑难题:在图中找到一条路径,该路径以正确的顺序恰好一次穿过所有字段。 -交互式/在线解决或打印出许多难题,包括解决方案,各种难度和图表大小,解决方案技术,链接,文献。

该学生项目的状态是我们已经执行了这些规则,但是正在努力加快prolog程序的速度。我们认为我们必须实施其他规则和启发式方法,但不知道应该使用哪种策略。

您可以在这里找到我们给定的难题:

http://translate.google.com/translate?u=https%3A//www.janko.at/Raetsel/Hidoku/index.htm&langpair=auto|en&tbb=1&ie=utf-8

我们定义了hidoku规则

/*-----------------Libraries-------------------------------------*/

:-use_module(library(clpfd)). % loading library
:-use_module(library(lists)). % loading library

/*---------create a list with all possible consecutive pairs of numbers of a given hidoku----------------------------*/

% clear element at X position of a list
    remove_at(X,[X|Xs],1,Xs).
    remove_at(X,[Y|Xs],K,[Y|Ys]) :- K > 1, 
        K1 is K - 1, remove_at(X,Xs,K1,Ys).

% create a list with numbers between I and K with every number two times
    range(I,I,[I]).
    range(I,K,[I,I|L]) :- I < K,I1 is I + 1, range(I1,K,L).

% create list P with all possible consecutive pairs between St and End 
% List: [E1,E2,E3,E4,E5,...](E1,E2 -> 1.pair; E3,E4 -> 2.pair)

listeF1(St,End,P) :- 
    range(St,End,P_n),
    remove_at(_,P_n,1,P).

%e.g.:listeF1(1,9,P).-> result:P= [1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9].


/*--------------test if neighbour --------------------------------------------------*/

indexOf([Element|_], Element, 1).   % We found the element
indexOf([_|Tail], Element, Index):-
  indexOf(Tail, Element, Index1),   % Check in the tail of the list
  Index is Index1+1.                % and increment the resulting index

% changing the mod function that gives the divisor instead of the case 0
mod2(Z,M,X):- 
    Zn is mod(Z,M),
    Zn=:=0,
    X = M,
    !. 
mod2(Z,M,X):- X is mod(Z,M),Zn is mod(Z,M), Zn=\=0.


% testing if number 'ZahlA' and number 'ZahlB' of matrix are neighbours ('Cols' is the matrix size)
nachbarM(ZahlA,ZahlB,Matrix,Cols):-
    flatten(Matrix, NewList),
    indexOf(NewList,ZahlA,A),
    Ax_id is ceiling(A/Cols),
    mod2(A,Cols,Ay_id),         
    indexOf(NewList,ZahlB,B),
    Bx_id is ceiling(B/Cols),
    mod2(B,Cols,By_id),
    C is abs(Ax_id-Bx_id),
    D is abs(Ay_id-By_id),
    E is C*C+D*D,
    E<3.

/*-----------test if all consecutive numbers are neighbours--------------------------------------------------*/



alle_benachbart(L,Matrix,Cols) :-
    [A1,A2|T]=L,
    nachbarM(A1,A2,Matrix,Cols),
    alle_benachbart(T,Matrix,Cols).
alle_benachbart([],Matrix,Cols).

% e.g. alle_benachbart([1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9],[[9,3,2],[8,1,4],[7,6,5]],3). % true
% e.g. alle_benachbart([1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9],[[1,2,3],[4,5,6],[7,8,9]],3). % false  
% e.g. alle_benachbart([1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9],[[1,2,3],[6,5,4],[7,8,9]],3). % true




/* ----------hidoku rules for a 3x3 puzzle---------------------------------------------------------------*/
hidoku(Rows) :- 
    length(Rows,3),maplist(same_length(Rows), Rows),
    append(Rows, Vs),
    Vs ins 1..9,        % ist eine Zahl von 1~N×M einzutragen
    all_distinct(Vs),   % jede Zahl genau einmal verwendet
    listeF1(1,9,L_fol),
    alle_benachbart(L_fol,Rows,3).



/*----------CMD-------how to try it---------------------------------------------------*/
% hidoku(Rows), maplist(label, Rows). %-> generate a solved hidoku without any given conditions
% hidoku(Rows), maplist(label, Rows),Rows=[[_,2,_],[6,_,8],[_,_,_]]. %-> solve the given problem 'Rows'

直到现在,我们的代码仅适用于3x3矩阵。对于我们的作业,对于每个给定的问题(最大大小为10 x 10),prolog求解器应该少于30秒。

0 个答案:

没有答案