Вопрос по clpfd, dcg, prolog, numbers, roman-numerals – Пролог преобразовать числа в римские цифры
у меня есть этот код, который преобразует целые числа в римские цифры, мне нужно добавить функцию, которая сравнивает целое число с вводом римских цифр и показать, если это '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
напишите грамматику (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).
Увидетьэтот ответ для большего.
IIL
который я недавно нашел в моей библиотеке.
false
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
объединяется с вашей римской цифрой интереса.