Skip to content

Instantly share code, notes, and snippets.

@mndrix
Created July 10, 2015 20:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mndrix/0b14fcd4a8ab873b2016 to your computer and use it in GitHub Desktop.
Save mndrix/0b14fcd4a8ab873b2016 to your computer and use it in GitHub Desktop.
Roman numerals in Prolog
:- use_module(library(clpfd)).
dcg(Arabic) -->
{ Arabic in 1..3999 },
roman(Arabic),
!.
roman(Total) -->
{ Rest #>= 0 },
{ Total #= Value + Rest },
digit(Value),
roman(Rest).
roman(0) --> "".
digit(1000) --> "M".
digit(900) --> "CM".
digit(500) --> "D".
digit(400) --> "CD".
digit(100) --> "C".
digit(90) --> "XC".
digit(50) --> "L".
digit(40) --> "XL".
digit(10) --> "X".
digit(9) --> "IX".
digit(5) --> "V".
digit(4) --> "IV".
digit(1) --> "I".
@mndrix
Copy link
Author

mndrix commented Jul 10, 2015

For example,

?- phrase(dcg(N),`CCXCVIII`).
N = 298.

?- phrase(dcg(388),Roman).
Roman = "CCCLXXXVIII".

@triska
Copy link

triska commented Jul 19, 2015

Thank you for sharing! Example with the most general query:

?- phrase(dcg(N), Rs).
N = 3999,
Rs = [77, 77, 77, 67, 77, 88, 67, 73, 88].

suggesting that this is the only solution, which it of course isn't. For logically sound behaviour, you can throw an instantiation error if the arguments are not sufficiently instantiated. Regarding naming, consider using arabic_roman//1 instead of dcg//1. Very nice idea, thank you again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment