我有一个格式为
的文件3
1 2 3 4 5
4 5 6
1 6 2 4 6 7
第一行标识随后的行。这些行反过来只是一系列数字。我需要将其保存到如下所示的列表中:
N = 3,
Teams = [line(1, 2, 3, 4, 5), line(4, 5, 6), line(1, 6, 2, 4, 6, 7)].
到目前为止我要尝试的是:
read_file(File, N, Lines) :-
open(File, read, Stream),
read_line_to_codes(Stream, Line),
atom_codes(Atom, Line),
atom_number(Atom, N),
read_lines(Stream, N, Lines).
read_lines(Stream, N, Lines) :-
( N == 0 -> Lines = []
; N > 0 -> read_line(Stream, N, Line),
Nm1 is N-1,
read_lines(Stream, Nm1, RestLines),
Lines = [Line | RestLines]).
read_line(Stream, N, line()) :-
read_line_to_codes(Stream, Line),
atom_codes(Atom, Line),
atomic_list_concat([N | Atoms], ' ', Atom),
maplist(atom_number, Atoms, []).
但是我认为atomic_list_concat([N | Atoms], ' ', Atom),
似乎存在问题。这是我与序言的第一次接触,所以我不确定发生了什么。如何修复上面的代码?
答案 0 :(得分:2)
我肯定会用dcg来解决这个问题。这里的想法是为您的输入创建一个简单的语法,然后使用它来解析文件。
:- use_module(library(dcg/basics)).
input(N, Teams) --> integer(N), blanks, teams(Teams).
teams([Team|Teams]) --> team(Team), blank, teams(Teams).
teams([]) --> [].
team([X|Xs]) --> integer(X), whites, team(Xs).
team([]) --> [].
库dcg/basics
为我们提供了四个我们在此处使用的实用程序函数:blank
,blanks
,whites
和integer/1
。它们解析包含换行符的空格,包含换行符的多个空格以及包含换行符的多个空格字符 not 和整数。
该语法表示输入由整数N,空行和一些组组成。这些团队可以是一个团队,一个空白团队以及更多的团队,或者我们已经完成了。部署相同的想法可以组建一个团队:我们要么拥有一个整数,再加上一些空格和更多的整数,要么就完成了。请注意,DCG版本比字节处理方法要短得多且更具说明性!
使用它也很容易:
?- phrase_from_file(input(N, Teams), 'input.txt').
N = 3,
Teams = [[1, 2, 3, 4, 5], [4, 5, 6], [1, 6, 2, 4, 6, 7]] ;
false.
如果需要,可以将其提升到实用程序谓词中
parse(Filename, N, Teams) :- phrase_from_file(input(N, Teams), Filename).
?- parse('input.txt', N, Teams).
N = 3,
Teams = [[1, 2, 3, 4, 5], [4, 5, 6], [1, 6, 2, 4, 6, 7]] .
享受!
编辑:我可能不会将其更改为返回line(1,2,3,4,5), line(4,5,6), ...
,因为您会发现处理可变的arity结构不愉快。但是,如果您确实愿意,可以使用以下代替team//1
规则:
team(Team) --> team_list(TeamList), { Team =.. [list|TeamList] }.
team_list([X|Xs]) --> integer(X), whites, team_list(Xs).
team_list([]) --> [].
在这里,我们正在使用univ(=..
)从列表中构建一个词。再说一次,我不会在这里部署这个想法,因为您的处理将变得更加复杂,可能没有任何实际收获。