Я бы определенно подошел к этому с dcg s. Идея состоит в том, чтобы создать простую грамматику для ввода и использовать ее для анализа файла.
:- 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
. Они анализируют пробел, включая переводы строк, несколько пробелов, включая переводы строк, и несколько символов пробелов , а не , включая переводы строк и целые числа.
Грамматика гласит, что вход состоит из целого числа 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]] .
Наслаждайтесь!
Edit : Я бы, вероятно, не изменил это, чтобы вернуть line(1,2,3,4,5), line(4,5,6), ...
, потому что вам будет неприятно обрабатывать структуры переменной арности. Но если вы действительно хотите, вы можете заменить правило team//1
на это:
team(Team) --> team_list(TeamList), { Team =.. [list|TeamList] }.
team_list([X|Xs]) --> integer(X), whites, team_list(Xs).
team_list([]) --> [].
Здесь мы используем univ (=..
), чтобы создать термин из списка. Опять же, я бы не стал использовать эту идею здесь, потому что ваша обработка станет более сложной, вероятно, без реальной выгоды.