SWI- 프롤로그, 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
. 보다 많은 필드에서는 사용할 수 없습니다 . 내가 멍청한 짓을하거나 답이 없으면 다른 사람들도 성공하지 못했음을 의미합니다.