元ネタ:https://twitter.com/puzzlegiver_bot/status/217544145630281729
ただし、解はアルファベットではなく、与えたリストの中での位置を返す。
元ネタ:https://twitter.com/puzzlegiver_bot/status/217544145630281729
ただし、解はアルファベットではなく、与えたリストの中での位置を返す。
append([], List, List). append([Head|Tail], List, [Head|TailR]) :- append(Tail, List, TailR). 部分リスト(List, (I, I), []). 部分リスト(List, (0, End), SubList) :- number(End), End > 0, 部分リスト_(List, End, SubList). 部分リスト([Head|Tail], (Bgn, End), SubList) :- number(Bgn), Bgn > 0, Bgn1 is Bgn - 1, number(End), End > 0, End1 is End - 1, 部分リスト(Tail, (Bgn1, End1), SubList). 部分リスト_(_, 0, []). 部分リスト_([Head|Tail], Cnt, [Head|TailAcc]) :- Cnt > 0, Cnt1 is Cnt - 1, 部分リスト_(Tail, Cnt1, TailAcc). 整数閉区間(L, L, R) :- L =< R. 整数閉区間(N, L, R) :- L =< R, L1 is L + 1, 整数閉区間(N, L1, R). 和([Head|Tail], Sum) :- 和_acc(Tail, Sum, Head). 和_acc([], Sum, SumAcc) :- Sum is SumAcc. 和_acc([Head|Tail], Sum, SumAcc) :- 和_acc(Tail, Sum, Head + SumAcc). 弧(List, (I, I), []). 弧(List, (0, End), Arc) :- 部分リスト(List, (0, End), Arc). 弧(List, (Bgn, 0), Arc) :- length(List, N), 部分リスト(List, (Bgn, N), Arc). 弧(List, (Bgn_, End_), Arc) :- number(Bgn_), number(End_), Bgn_ =\= 0, End_ =\= 0, length(List, N), Bgn is ((Bgn_ mod N) + N) mod N, % 非負最小剰余 End is ((End_ mod N) + N) mod N, ( Bgn < End -> 部分リスト(List, (Bgn, End), Arc) ; 弧(List, (Bgn, 0), ArcLead), 部分リスト(List, (0, End), ArcTrail), append(ArcLead, ArcTrail, Arc) ). 輪の等和分割(List, [X|Answer], Div) :- 和(List, ListSum), ArcSum is ListSum / Div, length(List, N), 整数閉区間(X, 0, N), % 第一の切断点(の右) 輪の等和分割(List, [X|Cut], Div, ArcSum, N, N), append(Answer, [X], Cut). 輪の等和分割(_, [_], 0, _, _, 0). 輪の等和分割(List, [Bgn, End|Cut], Div, Sum, LenFull, LenRemain) :- 整数閉区間(Len, 1, LenRemain), End is (Bgn + Len) mod LenFull, 弧(List, (Bgn, End), Arc), 和(Arc, Sum), Div1 is Div - 1, LenRemain1 is LenRemain - Len, 輪の等和分割(List, [End|Cut], Div1, Sum, LenFull, LenRemain1). % 例題 ?- 輪の等和分割( [1, 12, 5, 8, 10, 3, 11, 9, 6, 7, 4, 2], Answer, 3 ). /* Answer = [2,6,9]. % つまり 5, 11, 7 の左側 B, F, I で切断する */ % --------------------- % おまけ:特殊バージョン (3分割、数値に重複がないことが条件) between(L, L, R) :- L < R. between(N, L, R) :- L < R, L1 is L + 1, between(N, L1, R). 隣接(1, 12). 隣接(12, 5). 隣接(5, 8). 隣接(8, 10). 隣接(10, 3). 隣接(3, 11). 隣接(11, 9). 隣接(9, 6). 隣接(6, 7). 隣接(7, 4). 隣接(4, 2). 隣接(2, 1). 区間(X, R) :- 隣接(X, R) ; (X \== R, 隣接(R1, R), 区間(X, R1)). 弧和(X, R, Sum) :- 区間(X, R), 弧和_acc(X, R, Sum, 0). 弧和_acc(X, X, Sum, SumAcc) :- !, Sum is SumAcc. 弧和_acc(X, R, Sum, SumAcc) :- 隣接(X, X1), 弧和_acc(X1, R, Sum, SumAcc + X). 3分割( [X, Y, Z], Sum ) :- between(X, 1, 13), 弧和(X, Y, Sum), 弧和(Y, Z, Sum), 弧和(Z, X, Sum). ?- Sum is ((12*(12 + 1))/2) / 3, 3分割(A, Sum). % A = [5,11,7] % B, F, I