-4

一般的な問題:マップ8 * 8があり、空の正方形に1から6までの数字を入力する必要があります。ただし、各列と生の数字は1回だけ満たす必要があります。各行と列の2つの正方形は空のままです。上と下の両側の数字は、表示されるはずの最初の数字を示しています(ただし、2つの空の正方形の後に表示される場合があります)。

だから、今私はこのコードを持っています、それは最終的に4*4マップのswi-prologで動作します。

:- module(ab, [ab/0]).
:- [library(clpfd)].

gen_row(Ls):-length(Ls, 4), Ls ins 0..3.

transpose(Ms, Ts) :-
    %must_be(list(list), Ms),
    (   Ms = [] -> Ts = []
    ;   Ms = [F|_],
        transpose(F, Ms, Ts)
    ).

transpose([], _, []).
transpose([_|Rs], Ms, [Ts|Tss]) :-
    lists_firsts_rests(Ms, Ts, Ms1),
    transpose(Rs, Ms1, Tss).

lists_firsts_rests([], [], []).
lists_firsts_rests([[F|Os]|Rest], [F|Fs], [Os|Oss]) :-
    lists_firsts_rests(Rest, Fs, Oss).

ab :-
Rows = [R1,R2,R3,R4],
maplist(gen_row, Rows),
transpose(Rows, [C1,C2,C3,C4]),

maplist(all_distinct, [R1,R2,R3,R4]),
maplist(all_distinct, [C1,C2,C3,C4]),

start(R2, 3),
start(R3, 3),
finish(R3, 2),

start(C3, 1),
finish(C2, 2),

maplist(writeln, [R1,R2,R3,R4]).

finish(X, V) :-
reverse(X, Y),
start(Y, V).

start([0,Y|_], Y).
start([Y|_], Y).

しかし、8 * 8パズルのように、より大きな領域に2つの空の場所があるという問題はサポートされていません。ヒントはありますか?

4

1 に答える 1

0

他の質問から transpose/2 を取得し、all_distinct/1 を fd_all_distinct/2 に置き換える必要があります。

また、writeln を取得し、write here を置き換えますmaplist(write, [R1,R2,R3,R4]).

編集簡単な解決策は、有限ドメインの「エンコーディング」を拡張し、0 だけでなく2桁を空白として予約し、他の質問に投稿された回答に既に見られるロジックを拡張することです。

類推のために、私は third_end_view を呼び出します。これは ( Gnu Prolog では)

/*  File:    third_end_view_puzzle.pl
    Author:  Carlo,,,
    Created: Oct  10 2012
    Purpose: help to solve extended Second End View puzzle
             https://stackoverflow.com/q/12797708/874024
*/

:- include(transpose) .

third_end_view_puzzle :-

    length(Rows, 8),
    maplist(gen_row(8), Rows),
    transpose(Rows, Cols),

    maplist(fd_all_different, Rows),
    maplist(fd_all_different, Cols),

    Rows = [R1,R2,R3,R4,R5,R6,R7,R8],
    Cols = [C1,C2,C3,C4,C5,C6,C7,C8],

    start(R1, 4),
    start(R2, 2),
    start(R3, 3),
    start(R4, 5),
    start(R5, 3),
    finish(R1, 6),
    finish(R2, 4),
    finish(R3, 2),
    finish(R5, 1),
    finish(R7, 2),


    start(C2, 3),
    start(C3, 4),
    start(C4, 3),
    start(C5, 5),
%   start(C6, 4),
    start(C7, 1),
%   finish(C1, 3),
%   finish(C2, 2),
    finish(C3, 5),
    finish(C4, 5),
    finish(C5, 6),
    finish(C6, 1),
    finish(C7, 4),

    maplist(fd_labeling, Rows),
    nl,
    maplist(out_row, Rows).

gen_row(N, Ls) :-
    length(Ls, N),
    fd_domain(Ls, 1, N).

out_row([]) :- nl.
out_row([H|T]) :-
    (H >= 7 -> write('-') ; write(H)),
    write(' '),
    out_row(T).

% constraint: Num is max third in that direction
start(Vars, Num) :-
    Vars = [A,B,C|_],
    A #= Num #\/ (A #>= 7 #/\ B #= Num) #\/ (A #>= 7 #/\ B #>= 7 #/\ C #= Num).

finish(Var, Num) :-
    reverse(Var, Rev), start(Rev, Num).

「方向からの第 3 のビュー」を述べるために、具体化せずに、より単純な条件を使用しました。

前述のように、何らかの制約 (コメント アウトされているもの) によってパズルが解けないことがわかります。

テスト:

| ?- third_end_view_puzzle.  

4 3 - - 5 2 1 6 
2 1 - 3 - 5 6 4 
3 5 4 1 - 6 2 - 
5 4 6 2 1 3 - - 
- - 3 6 2 4 5 1 
1 6 2 4 3 - - 5 
6 - 1 5 4 - 3 2 
- 2 5 - 6 1 4 3 

true ? 
于 2012-10-09T10:19:55.653 に答える