SWI-Prolog、536 441 1バイト
1 UNIX行末、最後の新しい行はカウントされません
すべての最適化が削除されたバージョン(441バイト):
:-[library(clpfd)].
m(G,L):-maplist(G,L).
l(L,A):-length(A,L).
y(A,E,(X,Y)):-nth1(X,A,R),nth1(Y,R,F),var(F),F=E.
a(A,S):-l(L,A),X#>0,X#=<L,Y#>0,Y#=<L,h(S,(X,Y),A).
h(0,_,_).
h(L,(X,Y),A):-(B=A;transpose(A,T),B=T),y(B,s,(X,Y)),M#=L-1,Z#=Y+1,h(M,(X,Z),B).
e([],_,[]).
e([H|R],I,O):-J#=I+1,e(R,J,P),l(H,Q),Q ins I,append(P,Q,O).
r(R):-m(c,R),nl.
c(E):-var(E)->put(@);put(E).
g(L,H,S):-l(L,A),m(l(L),A),m(y(A,\),S),e(H,1,G),!,m(a(A),G),!,m(r,A).
コードはバイト数を最小化するように変更されているため、重複したショットのリストを受け入れなくなります。
基本的に最適化され、完全にゴルフされたバージョン(536→506バイト)
:-[library(clpfd)].
m(G,L):-maplist(G,L).
l(L,A):-length(A,L).
x(A,I,E):-X=..[a|A],arg(I,X,E).
y(A,E,(X,Y)):-x(A,X,R),x(R,Y,E).
a(A,S):-l(L,A),X#>0,X#=<L,Y#>0,Y#=<L,(B=A;transpose(A,T),B=T),h(S,(X,Y),B).
h(0,_,_).
h(L,(X,Y),A):-y(A,E,(X,Y)),var(E),E=s,M#=L-1,Z#=Y+1,h(M,(X,Z),A).
e([],_,[]).
e([H|R],I,O):-J#=I+1,e(R,J,P),l(H,Q),Q ins I,append(P,Q,O).
r(R):-m(c,R),nl.
c(E):-var(E)->put(@);put(E).
g(L,H,S):-l(L,A),m(l(L),A),sort(S,T),m(y(A,\),T),e(H,1,G),!,l(E,T),sumlist(G,D),L*L-E>=D,m(a(A),G),!,m(r,A).
明らかに不可能な場合にコードをより速く終了させるために、いくつかの基本的なチェック(必要な出荷ブロックの数をカウント)を実装します。このコードは、これまでのショットのリストに重複することもありません。
詳細なコメント付きの(多少)読みやすいバージョンを以下に示します。
:-[library(clpfd)].
% Shorthand for maplist, which works like map in high order function
m(G,L):-maplist(G,L).
% Creating a square matrix A which is L x L
board(L,A):-l(L,A),m(l(L),A).
% Shorthand for length, with order of parameters reversed
l(L,A):-length(A,L).
% Unification A[I] = E
x(A,I,E):-X=..[a|A],arg(I,X,E).
% Unification A[X][Y]=E
idx2(A,E,(X,Y)):-x(A,X,R),x(R,Y,E).
% Mark positions that have been shot
markshot(A,S):-m(idx2(A,\),S).
% Place all ships on the board
placeships(H,A):-m(placeship(A),H).
% Place a length S ship horizontal/vertical forward on the board
placeship(A,S):-
l(L,A), % Get length
X#>0,X#=<L,Y#>0,Y#=<L, % Constraint X and Y coordinates
transpose(A,T), % Transpose to work on columns
(placeship_h(S,(X,Y),A) ; placeship_h(S,(Y,X),T)).
% Place ship horizontal, forward at (X,Y)
placeship_h(0,_,_).
placeship_h(L,(X,Y),A):-
idx2(A,E,(X,Y)),var(E),E=s, % Make sure position is unassigned, then mark
L2#=L-1,Y2#=Y+1, % Do this for all blocks of the ship
placeship_h(L2,(X,Y2),A).
% Expand the list of ships
% e.g. [2,3,1] --> [3,2,2,2,1,1]
shipexpand(S,O):-shipexpand(S,1,O).
shipexpand([],_,[]).
shipexpand([H|R],I,O):-
I2#=I+1,shipexpand(R,I2,O2), % process the rest
l(H,O1),O1 ins I, % duplicate current ship size H times
append(O2,O1,O). % larger ship size goes in front
% Print the result
pboard(A):-m(prow,A).
prow(R):-m(pcell,R),print('\n').
pcell(E):-var(E)->print(@);print(E).
game(L,H,S):-
board(L,A), % create board
sort(S,SS), % remove duplicates
markshot(A,SS), % mark positions that have been shot
shipexpand(H,HH),!, % make a list of ships
l(SC,SS),sumlist(HH,BC),L*L-SC>=BC, % check to speed-up, can be removed
placeships(HH,A),!, % place ships
pboard(A). % print result
クエリ形式:
game(Board_Size, Ships_List, Shots_List).
サンプルクエリ(質問のサンプルを使用):
?- game(4,[1,1,1],[(2,1),(3,2),(3,3),(4,1),(4,3),(4,4)]).
ssss
\ss@
@\\@
\@\\
true.
?- game(4,[2,2,0,1],[(2,1),(3,2),(3,3),(4,1),(4,3),(4,4)]).
ssss
\sss
s\\s
\s\\
true.
26x26
?正規表現と再帰に基づいてソリューションをスケッチしましたが、非常に遅くなります=以上のフィールドでは使用できません6x6
。私が非常に愚かなことをするか、答えが足りないということは、他の人も成功しないことを意味します。