인덱스 연산 및 루프를 사용할 수있는 간단하지 효율적인 방법 : 라이브러리의 documentation에서
...
Sq = 3,
findall(B, (between(1, Sq, R),
between(1, Sq, C),
block(M, Sq, R, C, B)), Bs).
cell(M, R,C, V) :-
nth1(R,M,Row), nth1(C,Row,V).
block(M, Sq, R,C, B) :-
findall(V, (between(1, Sq, X),
between(1, Sq, Y),
I is (R-1) * Sq + X,
J is (C-1) * Sq + Y,
cell(M, I, J, V)), B).
은 (clpfd)는 알려진 표준 크기 제한보다 효율적인 방법이 있습니다. 당신은 그 코드를 일반화하려고 할 수 있습니다.
편집 여기가 내 테스트 사례입니다. 위조 된 행렬에 유의하십시오. 블록이 어디에 있는지 쉽게 이해할 수 있습니다. 이 명령을
q(Bs) :-
M = [[1,2,3,4,5,6,7,8,9],
[a,b,c,d,_,3,_,8,5],
[x,y,z,_,2,_,_,_,_],
[u,v,z,e,t,y,_,_,_],
[b,b,b,e,t,y,1,_,_],
[c,c,c,e,t,y,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]],
Sq = 3,
findall(B, (between(1, Sq, R),
between(1, Sq, C),
block(M, Sq, R, C, B)), Bs).
cell(M, R,C, V) :-
nth1(R,M,Row), nth1(C,Row,V).
block(M, Sq, R,C, B) :-
findall(V, (between(1, Sq, X),
between(1, Sq, Y),
I is (R-1) * Sq + X,
J is (C-1) * Sq + Y,
cell(M, I, J, V)), B).
및 테스트 :
?- q(Bs),maplist(writeln,Bs).
[1,2,3,a,b,c,x,y,z]
[4,5,6,d,_G928,3,_G934,2,_G940]
[7,8,9,_G895,8,5,_G904,_G907,_G910]
[u,v,z,b,b,b,c,c,c]
[e,t,y,e,t,y,e,t,y]
[_G796,_G799,_G802,1,_G808,_G811,_G814,_G817,_G820]
[5,_G769,_G772,_G775,_G778,2,_G784,_G787,_G790]
[_G736,_G739,_G742,_G745,1,_G751,_G754,4,_G760]
[_G706,7,3,_G715,_G718,_G721,_G724,_G727,9]
Bs = [[1, 2, 3, a, b, c, x, y|...], [4, 5, 6, d, _G928, 3, _G934|...], [7, 8, 9, _G895, 8, 5|...], [u, v, z, b, b|...], [e, t, y, e|...], [_G796, _G799, _G802|...], [5, _G769|...], [_G736|...], [...|...]].
대단히 감사합니다! 당신이 아마도 좀 더 잘 어울리는 것을 이해하는데 도움이된다면 궁금합니다. findall 내에서 중첩 된 betweens는 나에게 약간의 혼란을주고있는 것처럼 보인다! 그러나 Bs는 '블록'목록을 포함하는 목록이어야합니다 (뭔가 빠졌을 수도 있습니다). 그러나 항상 [[], [], [], []]로 끝나는 것 같습니다. . 어떤 생각이 거기에서 진행되고 있을지 모릅니다. 도움에 다시 한번 감사드립니다 - 정말 고맙습니다! – user1257768
테스트 케이스를 추가했습니다. 편집을 참조하십시오. – CapelliC