Prolog - 打印带有 format/2 的列表列表
Prolog - Print list of lists with format/2
这是我使用的代码:
printElement(L/C) :- format('~t~a - ~a~t~20+|', [L, C]).
printElement(L) :- format('~t~a~t~20+|~t', L).
printList([]) :- format('~n', []).
printList([H|T]) :-
printElement(H),
printList(T).
printLists([], _).
printLists([H|T], N) :-
M is N + 1,
format('~d- |', M),
printList(H),
printLists(T, M).
作为 BL 列表的列表我将谓词称为 printLists(BL, 0).
我的目标是将 BL 显示为 9x9 网格,单元格大小相同。
相反,我得到了这个:
我希望所有列都显示为图像中的第一列,我的意思是我希望所有其他单元格具有相同的宽度。
为什么我的代码不适用于第二列等等?
此机制的问题在于,在这种情况下,出于某种原因,format/2
列定位在多次调用 format/2
之间似乎无法按预期工作。但是,如果您使用 ~@
格式说明符,它实际上会起作用 [好吧,它 可能 起作用,因为我只能在 SWI Prolog 上尝试它具有相同的format/2
个选项]。
~@
格式选项告诉 format
调用下一个参数作为 Prolog 谓词。
这是一个例子。而不是这个:
printElement(L/C) :- format('~t~a - ~a~t~20+|', [L, C]).
printElement(L) :- format('~t~a~t~20+|~t', L).
试试这个:
printElement(L) :-
( L = A/B
-> format('~@', print2(A, B))
; format('~@', print1(L))
).
print2(L, C) :- format('~t~a - ~a~t~20+|', [L, C]).
print1(L) :- format('~t~a~t~20+|', L). % Not sure why you have the extra '~t'
% in your format; I removed it
请注意,我放入 if-else
结构是为了避免第二个 printElement/1
匹配 L/C
形式。
这是一种不同的方法,它使用构建格式字符串(实际上是一个原子)的谓词和基于输入行的更新数据列表。这通过为整行构建单一格式字符串来规避每行多种格式的问题,以便可以为每一行调用单个 format/2
。
% makeFormat/4
% makeFormat(-RowData, -FormatPrefix, +NewRowData, +Format)
%
makeFormat([], F0, [], F) :-
atom_concat(F0, '~n', F).
makeFormat([E|Es], F0, L, F) :-
( E = A/B
-> atom_concat(F0, '~t~a - ~a~t~20+|', F1),
L = [A,B|Ls]
; atom_concat(F0, '~t~a~t~20+|', F1),
L = [E|Ls]
),
makeFormat(Es, F1, Ls, F).
printLists([], _).
printLists([H|T], N) :-
M is N + 1,
makeFormat(H,'~d- |', H1, Format), % make format starting with '~d- |'
format(Format, [M|H1]), % write out the list with prefix
printLists(T, M).
这是在 SWI Prolog 中有效的另一种方法。您需要在 SICSTUS Prolog 中尝试它,看看它是否也能在那里工作。只需对您的原始解决方案进行以下谓词更新:
printElement(L/C) :- format('~0+~t~a - ~a~t~20+|', [L, C]). % added '~0+'
printElement(L) :- format('~0+~t~a~t~20+|', L). % added '~0+'
printList([]) :- format('~n'). % [] argument unnecessary in format, so removed
在 printElement
中,我在每个格式字符串(原子)的开头添加了一个 ~0+
以在其余格式发生之前建立相对列位置。如果这在 SICSTUS 下不起作用,您可以尝试 ~1+
。但是在 SWI 中,我使用 ~0+
获得了预期的输出。我更喜欢这个解决方案,而不是将任意长的格式字符串粘贴在一起。
原码测试:
?- printList([a,b,c]).
a |b|c|
true.
更新代码测试:
?- printList([a,b,c]).
a | b | c |
true.
这是我使用的代码:
printElement(L/C) :- format('~t~a - ~a~t~20+|', [L, C]).
printElement(L) :- format('~t~a~t~20+|~t', L).
printList([]) :- format('~n', []).
printList([H|T]) :-
printElement(H),
printList(T).
printLists([], _).
printLists([H|T], N) :-
M is N + 1,
format('~d- |', M),
printList(H),
printLists(T, M).
作为 BL 列表的列表我将谓词称为 printLists(BL, 0).
我的目标是将 BL 显示为 9x9 网格,单元格大小相同。 相反,我得到了这个:
我希望所有列都显示为图像中的第一列,我的意思是我希望所有其他单元格具有相同的宽度。
为什么我的代码不适用于第二列等等?
此机制的问题在于,在这种情况下,出于某种原因,format/2
列定位在多次调用 format/2
之间似乎无法按预期工作。但是,如果您使用 ~@
格式说明符,它实际上会起作用 [好吧,它 可能 起作用,因为我只能在 SWI Prolog 上尝试它具有相同的format/2
个选项]。
~@
格式选项告诉 format
调用下一个参数作为 Prolog 谓词。
这是一个例子。而不是这个:
printElement(L/C) :- format('~t~a - ~a~t~20+|', [L, C]).
printElement(L) :- format('~t~a~t~20+|~t', L).
试试这个:
printElement(L) :-
( L = A/B
-> format('~@', print2(A, B))
; format('~@', print1(L))
).
print2(L, C) :- format('~t~a - ~a~t~20+|', [L, C]).
print1(L) :- format('~t~a~t~20+|', L). % Not sure why you have the extra '~t'
% in your format; I removed it
请注意,我放入 if-else
结构是为了避免第二个 printElement/1
匹配 L/C
形式。
这是一种不同的方法,它使用构建格式字符串(实际上是一个原子)的谓词和基于输入行的更新数据列表。这通过为整行构建单一格式字符串来规避每行多种格式的问题,以便可以为每一行调用单个 format/2
。
% makeFormat/4
% makeFormat(-RowData, -FormatPrefix, +NewRowData, +Format)
%
makeFormat([], F0, [], F) :-
atom_concat(F0, '~n', F).
makeFormat([E|Es], F0, L, F) :-
( E = A/B
-> atom_concat(F0, '~t~a - ~a~t~20+|', F1),
L = [A,B|Ls]
; atom_concat(F0, '~t~a~t~20+|', F1),
L = [E|Ls]
),
makeFormat(Es, F1, Ls, F).
printLists([], _).
printLists([H|T], N) :-
M is N + 1,
makeFormat(H,'~d- |', H1, Format), % make format starting with '~d- |'
format(Format, [M|H1]), % write out the list with prefix
printLists(T, M).
这是在 SWI Prolog 中有效的另一种方法。您需要在 SICSTUS Prolog 中尝试它,看看它是否也能在那里工作。只需对您的原始解决方案进行以下谓词更新:
printElement(L/C) :- format('~0+~t~a - ~a~t~20+|', [L, C]). % added '~0+'
printElement(L) :- format('~0+~t~a~t~20+|', L). % added '~0+'
printList([]) :- format('~n'). % [] argument unnecessary in format, so removed
在 printElement
中,我在每个格式字符串(原子)的开头添加了一个 ~0+
以在其余格式发生之前建立相对列位置。如果这在 SICSTUS 下不起作用,您可以尝试 ~1+
。但是在 SWI 中,我使用 ~0+
获得了预期的输出。我更喜欢这个解决方案,而不是将任意长的格式字符串粘贴在一起。
原码测试:
?- printList([a,b,c]).
a |b|c|
true.
更新代码测试:
?- printList([a,b,c]).
a | b | c |
true.