Пролог: разбить список на список из N списков, содержащих по N элементов каждый
Я искал множество существующих вопросов о Прологе, касающихся SO, имеющих отношение к расщеплению, но не смог найти такой общий, как тот, который я хочу. Я хотел бы отметить, что мне удалось разделить списки на списки из 2/3/4 элементов, используя 2/3/4 переменные, переданные перед переменной списка. Этот вопрос отличается от этого только своей универсальностью.
Таким образом, мой список всегда будет содержать N*N элементов, причем N заранее неизвестно (обычно они варьируются от 4 до 36, да, N также является идеальным квадратом). Я хочу разделить его на список из N списков, каждый из которых содержит N элементов, потому что это позволит мне рассматривать его как матрицу, что позволяет транспонировать и выполнять определенные операции такого рода. Я действительно не смог зайти слишком далеко с логикой, потому что я относительно новичок в декларативном программировании; см. ниже мою неполную (ошибочную) попытку:
listmodel(1,L):- L = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].
size(L,N) :- length(L,N1), N is round(sqrt(N1)).
% add_tail(+Liste, +Element, -ResultantList)
add_tail([],L,[L]).
add_tail([X|L1],L2,[X|LI]):-add_tail(L1,L2,LI).
% partition the list containing N*N items into a list of N lists containing N elements each.
% part(+Liste, +Size, -ResultantList)
part([],_,DL).
part(L,N,DL) :-
length(P,N), % P(refix) initialized
append(P,S,L), % S(uffix) contains rest of L, using append in (-,-,+) mode
add_tail(DL,P,DL1), %add P(first N elements) as first element of DL.
part(S,N,DL1).
Сейчас работает ?- listmodel(1,L),size(L,N),part(L,N,DL).
будет производить DL=[]
потому что это то, что он инициализируется в первом add_tail
позвонить в part
сказуемое. Кажется, я не могу понять, как сохранить все элементы в списке, который сохранился с помощью рекурсии.
Любая помощь / направление любого рода будут оценены. Я застрял здесь более 23 часов 10 минут.
Благодарю.
2 ответа
Это должно сделать это:
часть([], _, []). часть (L, N, [DL|DLTail]):- длина(DL, N), добавить(DL, LTail, L), часть (LTail, N, DLTail).
Базовый случай - первый / последний аргументы - пустые списки.
Рекурсивный шаг берет новый список из N элементов, берет первые N элементов из L (который будет одним из элементов третьего аргумента) и вызывает рекурсивно.
Хотите совместить универсальность и выгодные свойства терминации? Используйте clpfd!
: - use_module ( библиотека (clpfd)).
Сначала мы определяем list_prefix_n_suffix/4
, list_prefix_n_suffix(Zs,Xs,N,Ys)
логически эквивалентно обоим append(Xs,Ys,Zs), length(Xs,N)
а также length(Xs,N), append(Xs,Ys,Zs)
, но имеет лучшее универсальное поведение завершения, чем 1!
list_prefix_n_suffix (Zs, Xs, N, Ys): - list_prefix_n0_n_suffix (Zs, Xs, 0, N, Ys). list_prefix_n0_n_suffix (Zs, Xs, N0, N, Ys): - zcompare (Order, N0, N), rel_list_prefix_n0_n_suffix (Порядок, Zs, Xs, N0, N, Ys). rel_list_prefix_n0_n_suffix (=, Ys, [], _, _, Ys). rel_list_prefix_n0_n_suffix (<, [Z | Zs], [Z | Xs], N0, N, Ys): - N1 # = N0 + 1, list_prefix_n0_n_suffix (Zs, Xs, N1, N, Ys).
Некоторые примеры запросов для list_prefix_n_suffix/4
:
? - list_prefix_n_suffix ([a, b, c], Xs, -1, Ys). ложь % OK: слишком мало?- list_prefix_n_suffix([a,b,c], Xs, 0, Ys). Xs = [], Ys = [a,b,c]. % успешно определен? - list_prefix_n_suffix ([a, b, c], Xs, 4, Ys). ложь % OK: слишком большой?- list_prefix_n_suffix([a,b,c], Xs, N, Ys). Xs = [], N = 0, Ys = [a,b,c]; Xs = [a], N = 1, Ys = [b,c]; Xs = [a,b], N = 2, Ys = [c]; Xs = [a,b,c], N = 3, Ys = []; ложный. % завершается повсеместно
На основании выше list_prefix_n_suffix/4
мы определяем list_rows_width/3
:
list_rows_width ([], [], _N). list_rows_width ([E | Es0], [[R | Rs] | Rss], N): - list_prefix_n_suffix ([E | Es0], [R | Rs], N, Es), list_rows_width (Es, Rss, N).
Примеры запросов с использованием list_rows_width/3
:
? - list_rows_width ([a, b, c, d, e, f], Rows, 4). ложный. % ОК: 6 не делится на 4?- list_rows_width([a,b,c,d,e,f], Rows, 3). Строки = [[a,b,c],[d,e,f]]. % преуспевает детерминистически?- list_rows_width([a,b,c,d,e,f,g,h,i,j,k,l], Rows, N). N = 1, Rows = [[a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[л]]; N = 2, Rows = [[a, b],[c, d],[e, f],[g, h],[i, j],[k, l]]; N = 3, Rows = [[a, b, c],[d, e, f],[g, h, i],[j, k, l]]; N = 4, Rows = [[a, b, c, d],[e, f, g, h],[i, j, k, l]]; N = 6, Rows = [[a, b, c, d, e, f],[g, h, i, j, k, l]]; N = 12, ряды = [[a, b, c, d, e, f, g, h, i, j, k, l]]; ложный. % завершается повсеместно
Работает так, как должно!
Сноска 1: Не прибегая к использованию альтернативных механизмов управления потоком, таких как пролог-сопрограммирование.