读取文件并保存到列表

时间:2018-07-06 08:58:31

标签: prolog swi-prolog

我有一个格式为

的文件
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),似乎存在问题。这是我与序言的第一次接触,所以我不确定发生了什么。如何修复上面的代码?

1 个答案:

答案 0 :(得分:2)

我肯定会用来解决这个问题。这里的想法是为您的输入创建一个简单的语法,然后使用它来解析文件。

:- 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为我们提供了四个我们在此处使用的实用程序函数:blankblankswhitesinteger/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(=..)从列表中构建一个词。再说一次,我不会在这里部署这个想法,因为您的处理将变得更加复杂,可能没有任何实际收获。