Вопрос по clpfd, dcg, prolog, numbers, roman-numerals – Пролог преобразовать числа в римские цифры

6

у меня есть этот код, который преобразует целые числа в римские цифры, мне нужно добавить функцию, которая сравнивает целое число с вводом римских цифр и показать, если это 's #ry или false, например: roman (v, 5). правда

#oroman(0).
#oroman(N) :- N &l#; 4, pu#("I"), M is N - 1, #oroman(M).
#oroman(N) :- N = 4, pu#("I"), pu#("V").
#oroman(N) :- N = 5, pu#("V").
#oroman(N) :- N &l#; 9, pu#("V"), M is N - 5, #oroman(M).
#oroman(N) :- N = 9, pu#("I"), pu#("X").
#oroman(N) :- N &l#; 40, pu#("X"), M is N - 10, #oroman(M).
#oroman(N) :- N &l#; 50, pu#("X"), pu#("L"), M is N - 40, #oroman(M).
#oroman(N) :- N &l#; 90, pu#("L"), M is N - 50, #oroman(M).
#oroman(N) :- N &l#; 100, pu#("X"), pu#("C"), M is N - 90, #oroman(M).
#oroman(N) :- N &l#; 400, pu#("C"), M is N - 100, #oroman(M).
#oroman(N) :- N &l#; 500, pu#("C"), pu#("D"), M is N - 400, #oroman(M).
#oroman(N) :- N &l#; 900, pu#("D"), pu#("D"), M is N - 500, #oroman(M).
#oroman(N) :- N &l#; 1000, pu#("C"), pu#("M"), M is N - 900, #oroman(M).
#oroman(N) :- N &l#; 4000, pu#("M"), M is N - 1000, #oroman(M).



roman(N) :- #oroman(N).
Пытатьсяtoroman(-1): Ты получаешьIVXXLXCCDCM, Это то же значение, что и.toroman(0+9) false

Ваш Ответ

2   ответа
5

напишите грамматику (DCG) связать целое число и список символов, обозначающих римские цифры. Вот начало:

:- use_module(library(clpfd)).

roman(0) --> "".
roman(N0) --> "I", { 1 #=< N0, N0 #=< 3, N1 #= N0-1}, roman(N1).

Вы можете использовать это так:

?- phrase(roman(3), L).
L = "III" ;
false.

или же

?- phrase(roman(N), "II").
N = 2 ;
false.

или, если вы нене знаю, что спросить, просто задайте самый общий вопрос:

?- phrase(roman(N), L).
N = 0,
L = [] ;
N = 1,
L = "I" ;
N = 2,
L = "II" ;
N = 3,
L = "III" ;
false.

Чтобы получить ответы компактно, какL = "III"использовать:- set_prolog_flag(double_quotes,chars). Увидетьэтот ответ для большего.

@ joel76: Спасибо. Что очень печально, так это то, что люди не понимают, что есть много хороших ярлыков, таких какIIL который я недавно нашел в моей библиотеке. false
Да, это'здорово иметь CLP (FD) на простом прологе. Спасибо Маркус! CapelliC
использование CLP (FD) для выражения семантики в DCG кажется действительно интересным! CapelliC
@chac: большинство реализаций CLP (FD) имеют серьезную корректность и другие ограничения, которые делают их непригодными для замены. false
1

toroman/1 процедура что-то вродеtoroman/2 который возвращает римскую цифру, а не просто печатает ее.

Тогда вы сможете легко сравнить римскую цифру с результатом вызоваtoroman/2 в целое число.

Также обратите внимание, что ваша текущая процедура будет повторяться до тех пор, пока не будет получено переполнение стека, если вы вернетесь к другому решению. Вы должны либо защищать каждое предложение, которое рекурсивно вызывает себя для рекурсии, только если параметр вызова неотрицателен, либо добавить в качестве первого предложения проверку, которая завершается неудачно, например:

roman(N):- N < 0, !, fail.

После изменения toroman / 1 для возврата римского литерала вы получите что-то вроде этого (просто немного измените ваш код, чтобы возвращать литерал в качестве второго аргумента):

toroman(N, _):- N < 0, !, fail.
toroman(0, []).
toroman(N, ['I'|Roman]) :- N < 4, M is N - 1, toroman(M, Roman).
toroman(4, ['IV']).
toroman(5, ['V']).
toroman(N, ['V'|Roman]) :- N < 9, M is N - 5, toroman(M, Roman).
toroman(9, ['IX']).
toroman(N, ['X'|Roman]) :- N < 40, M is N - 10, toroman(M, Roman).
toroman(N, ['XL'|Roman]) :- N < 50, M is N - 40, toroman(M, Roman).
toroman(N, ['L'|Roman]) :- N < 90, M is N - 50, toroman(M, Roman).
toroman(N, ['XC'|Roman]) :- N < 100, M is N - 90, toroman(M, Roman).
toroman(N, ['C'|Roman]) :- N < 400, M is N - 100, toroman(M, Roman).
toroman(N, ['CD'|Roman]) :- N < 500, M is N - 400, toroman(M, Roman).
toroman(N, ['DD'|Roman]) :- N < 900, M is N - 500, toroman(M, Roman).
toroman(N, ['CM'|Roman]) :- N < 1000, M is N - 900, toroman(M, Roman).
toroman(N, ['M'|Roman]) :- N < 4000, M is N - 1000, toroman(M, Roman).

roman(N, R) :- toroman(N, L), atomic_list_concat(L, R).

roman(N) :- roman(N, R), write(R).

Тогда вы могли бы просто позвонитьroman(N, R) и проверить,R объединяется с вашей римской цифрой интереса.

я получил это просто нужно было изменить все заглавные буквы на маленькие Muhsag
спасибо, что было действительно полезно. Список это то, что мне нужно. Я пытался изменить ваш код, чтобы получить результат true или false с такими вопросами, как:? - Роман (5, V). правда. ? - роман (5, р). R = V. что я должен изменить? Muhsag
Вы должны заключить римский литерал в одинарные кавычки (потому что вы хотите использовать атом, а не переменную). Так, например, вы могли бы спросить? - Роман (5, 'V'). gusbro

Похожие вопросы