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
。我做一些非常愚蠢的事情,或者缺乏答案意味着别人也没有成功。