2013-08-14 2 views
1

나는 프롤로그 초보자이며 목록에 문자열을 구문 분석하는 데 막혔습니다. 나는 형태프롤로그에서 목록으로 변환 문자열

1..2...3..4 

나는이 기능을 달성 할 수있는 방법

[1, _, _, 2, _, _, _, 3, _, _, 4] 

과 같은리스트로 변환 할 문자열을 가지고?

+0

포인트 또는 정수 사이에 한 자리 숫자가 있습니까? 다시 말해'12.23 '은'[1, 2, _, 2, 3]'또는'[12, _, 23]'로 이동합니까? –

+0

한자리 수입니다. 그래서 12.23은 [1, 2, _, 2, 3]이됩니다. –

답변

2

다른 해결책은 DCG를 사용하는 것입니다. 코드는 간단하다 :

digit(N) --> 
    [ D ], { member(D, ""), number_codes(N, [D]) }. 

dot(_) --> ".". 

token(T) --> digit(T). 
token(T) --> dot(T). 

tokens([T|Ts]) --> token(T), tokens(Ts). 
tokens([]) --> "". 

parse_codes(In, Out):- 
    phrase(tokens(Out), In, ""). 

parse_atom(In, Out):- 
    atom_codes(In, Codes), 
    parse_codes(Codes, Out). 
(실제로는 단지 코드의 목록입니다) "문자열"와 SWI - 프롤로그에

테스트 : 단지 코드로 변환됩니다

?- parse_codes("1..24.4", Out). 
Out = [1, _G992, _G995, 2, 4, _G1070, 4] . 

그리고 원자와 함께 () 같은 술어를 사용하기 전에 : 조금 애호가 표기법

?- parse_atom('1..22.4', Out). 
Out = [1, _G971, _G974, 2, 2, _G1049, 4] . 

SWI-Prolog에 인쇄 익명 변수 (_)하지만 그렇지 않으면 당신이 필요로하는 동일한 결과를해야합니다.

0

수 당신의 문자열에서 문자 및 목록의 요소 사이의 관계를 설명하는 술어 :

char_to_el(DigitChar, Digit) :- % a character between '0' and '9' 
    DigitChar >= 0'0, DigitChar =< 0'9, 
    number_codes(Digit, [DigitChar]). 
char_to_el(0'., _). % the element is the '.' characther 

캐릭터가 참으로 자리하고 정수로 변환 여부를 첫 번째 절을 확인합니다. 문자의 정수 값에서 0'0을 간단히 빼기 때문에 number_code/2를 사용하는 대신 Digit is DigitChar - 0'0을 쓸 수 있습니다.

당신은 사용할 수 있어야 maplist/3 다음은 GNU 프롤로그 설명서에 따라 : 대신

| ?- maplist(char_to_el, "1..2...3..4", L). 

L = [1,_,_,2,_,_,_,3,_,_,4] 

yes 

있지만 (아마도 오래된 GNU 프롤로그 버전?) 내 시스템에 작동하지 않았다, 그래서 :

str_to_list([], []). 
str_to_list([C|Cs], [E|Es]) :- 
    char_to_el(C, E), 
    str_to_list(Cs, Es). 

| ?- str_to_list("1..2...3..4", L). 

L = [1,_,_,2,_,_,_,3,_,_,4] 

yes 
1

또 다른 방법은 0..9의 ascii 숫자가 알려진/고정되어 있다는 사실을 활용하면 형식 변환이나 검사가 필요없고 빼기 만하면됩니다.

% case 1: char is in decimal range 0-9, ie ascii 48,49,50,51,52,53,54,55,56,57 
% so eg. char 48 returns integer 0 
onechar(Char, Out) :- 
    between(48, 57, Char), 
    Out is Char -48. 

% case 2: case 1 failed, dot '.' is ascii 46, use anonymous variable 
onechar(46, _). 

% execution 
go(InString, OutList) :- 
    maplist(onechar, InString, OutList). 

실행 :

?- go("1..2...3..4", X). 
X = [1, _G5638, _G5641, 2, _G5650, _G5653, _G5656, 3, _G5665, _G5668, 4] 

편집 :이 문자열은 ASCII 번호 목록으로 표시되기 때문에 작동하므로 문자열 ""가 [48,49,50로 내부적으로 표현되는 말을 잊었다 , 51,52,53,54,55,56,57].

onechar이 해당 목록 항목 중 1 개에 대해 계산을 수행하면 maplist는 모든 목록 항목에서 동일한 조건자를 호출합니다.

편집 2 : 두번째 규칙은 원래이었다

% case 2: case 1 failed, output is an anon variable 
onechar(_, _). 

이 너무 관대 - 입력이 0.9 점은 다음 조건에 장애가 포함되지 않은 것으로 추정합니다.

+0

직접 아스키 코드 대신에 '0'표기법을 사용해야합니다. 읽기 쉽고 똑같습니다 (매직 넘버는 없습니다). –