Replies: 2 comments 2 replies
-
I have now implemented this, using the DCG non-terminal :- use_module(library(error)). :- meta_predicate(if__(1, 2, 2, ?, ?)). if__(If_1, Then, Else) --> { call(If_1, T) }, ( { T == true } -> Then ; { T == false } -> Else ; { must_be(boolean, T) } ). With this building block, we can write: :- use_module(library(dcgs)). :- use_module(library(reif)). :- use_module(library(clpz)). clpz:monotonic. compression([]) --> []. compression([L|Ls]) --> compression_(Ls, L). compression_([], L) --> [#L]. compression_([L|Ls], L0) --> if__(clpz_t(#L #= #L0 + 1), more_compression(Ls, L, L0), ([#L0], compression([L|Ls]))). more_compression([], L, L0) --> finish_run(L0, L). more_compression([M|Ms], L, L0) --> if__(clpz_t(#M #= #L + 1), more_compression(Ms, M, L0), (finish_run(L0, L), compression([M|Ms]))). finish_run(L0, L) --> if__(clpz_t(#L #= #L0 + 1), [#L0,#L], [L0-L]). Yielding for example: ?- phrase(compression([3,4,6,7,8,9,10,15,16,17,20,22,23,24,25]), Cs). Cs = [#3,#4,6-10,15-17,#20,22-25]. |
Beta Was this translation helpful? Give feedback.
1 reply
-
This was a fun puzzle! I tried solving the problem in reverse, using your :- use_module(library(reif)).
:- use_module(library(clpz)).
:- use_module(library(dcgs)).
:- use_module(library(lists)).
:- use_module(library(error)).
clpz:monotonic.
if__(If_1, Then, Else) -->
{ call(If_1, T) },
( { T == true } -> Then
; { T == false } -> Else
; { must_be(boolean, T) }
).
range(X, Y) --> { #X #=< #Y }, [X], if__(#=(X, Y), [], ({#X1 #= #X + 1}, range(X1, Y))).
expansion([]) --> [].
expansion([L|Ls]) --> expand_(L, _, I), expansion_(Ls, I).
expansion_([], _) --> [].
expansion_([L|Ls], I0) --> expand(L, I0, I), expansion_(Ls, I).
expand(Item, I0, I) --> expand_(Item, X, I), { #X #\= #I0 + 1 }.
expand_(#X, X, X) --> [X].
expand_(X-Y, X, Y) --> { #X #< #Y }, range(X, Y). It seems to work mostly the same, though my implementation doesn't quite work when trying to use iterative deepening: ?- length(X, L), phrase(expansion(X), Y).
X = [], L = 0, Y = []
; X = [#_A], L = 1, Y = [_A]
; ^C error('$interrupt_thrown',repl/0). Addendum: made this cmp(X, Y, Lt, Eq, Gt) --> if__(#<(X, Y), Lt, if__(#=(X, Y), Eq, Gt)). |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Dear all,
today I came across an interesting question: https://stackoverflow.com/questions/78401978/prolog-compress-a-list-that-contains-segments-of-continuous-numbers-to-a-list-w
It is phrased quite imperatively and a bit hard to understand as "Compressing a list of integers to a compressed list. List contains segments of continuous integers. A segment with length greater than 2 will be encoded to list
[start, end]
, end is inclusive. If the length is not greater than 2 will be kept no change."An example is also specified:
I used this opportunity to try out a few of the constructs we have available in Scryer Prolog, as currently the only Prolog system that provides them by default, notably
library(reif)
and the new predicateclpz_t/2
thanks to @librarianmage.The solution I came up with is:
Note that I am using a clean representation for the second argument: I use the prefix operator
#
to mark integers, so that we can symbolically distinguish them from ranges of the formStart-End
. With this representation, I get:One very nice property of the code is that we can also use it in other directions and modes, for instance we can ask the most general query:
We can also try different search strategies, for example iterative deepening:
Using iterative deepening, we can use the same code to find a list that results in a given "compressed" list:
We get all this generality by construction, because only pure monotonic constructs are used in the code. This ensures that the code yields correct results in all usage modes.
I leave finding a better name for the predicate as a challenge.
One other point I noticed: I think this solution would benefit from a DCG non-terminal
if__//3
that is analogous toif_/3
, except that it can be used within DCGs. I think such a non-terminal would yield a shorter and more elegant solution in this case, and I would greatly appreciate any feedback and help with these issues.Thank you a lot, and enjoy!
Markus
Beta Was this translation helpful? Give feedback.
All reactions