Marquee in Prolog

335 views Asked by At

Well known from , is clearly the pinnacle of the Semantic Web. Or rather its nadir side by side with the blink tag. In any case, how can we represent marquee in Prolog? In other words, how to define a relation marquee/2 such that the following holds:

?- marquee("Prolog is marquee ready! ",M).
   M = "Prolog is marquee ready! "
;  M = "rolog is marquee ready! P"
;  M = "olog is marquee ready! Pr"
;  M = "log is marquee ready! Pro"
;  M = "og is marquee ready! Prol"
;  M = "g is marquee ready! Prolo"
;  M = " is marquee ready! Prolog"
;  M = "is marquee ready! Prolog "
;  M = "s marquee ready! Prolog i"
;  M = " marquee ready! Prolog is"
;  M = "marquee ready! Prolog is "
;  ... .
?- M=[m|_],marquee("Prolog is marquee ready! ",M).
   M = "marquee ready! Prolog is "
;  M = "marquee ready! Prolog is "
;  M = "marquee ready! Prolog is " % infinitely many redundant answers
;  ... .

So how can I define marquee/2 in ISO Prolog just using the Prolog prologue? The double quotes above assume set_prolog_flag(double_quotes, chars), and the answer write option max_depth(0) needs to be set to get the entire string.

What I have tried is member/2 but it only describes the characters and then I tried nth0/3 and nth1/3 but they only described two characters in sequence as in:

?- T = "Prolog is marquee ready! ", nth1(I,T,A),nth0(I,T,B).
   T = "Prolog is marquee ready! ", I = 1, A = 'P', B = r
;  T = "Prolog is marquee ready! ", I = 2, A = r, B = o
;  ... .

Edit: one clarification about the repetitions. They should fit together seamlessly, as in

?- marquee("! ",M).
   M = "! "
;  M = " !"
;  M = "! "
;  M = " !"
;  M = "! "
;  M = " !"
;  M = "! "
;  M = " !"
;  M = "! "
;  M = " !"
;  ... .
6

There are 6 answers

2
repeat On BEST ANSWER

First, hat tip to this answer and the author, @brebs.

I looked at marquee_/3 ... and append/3 looked back at me—with shuffled arguments.

So here's the minimally updated version of marquee/2:

marquee(L,M) :-
   append(L,R,LD),
   append(R,M,LD).   % was: marquee_(LD,R,M)

Sample queries:

?- marquee("prolog",Xs).
   Xs = "prolog"
;  Xs = "rologp"
;  Xs = "ologpr"
;  Xs = "logpro"
;  Xs = "ogprol"
;  Xs = "gprolo"
;  Xs = "prolog"
;  Xs = "rologp"
;  ... .

?- marquee("",Xs).
   Xs = []
;  Xs = []
;  ... .
3
Lospix On

Im not sure this satisfy all your requisites, hope so

marquee(Ls, M):- 
    length(Ls, Len), 
    Max is Len-1,
    between(0, Max, Roll),
    roll(Ls, M, Roll).

lis_pos_elem(Lis, Pos, Elem) :- nth1(Pos, Lis, Elem).

new_index(Shift, Max, I1, I2):-
    I is I1 - Shift,
    ( 
        I < 1,
        I2 is Max + I
    ;
        I2 = I
    ), !.

roll(L,L,0).
roll(L1,L2,R):-
    R > 0,
    length(L1, Len),
    numlist(1, Len, Index),
    maplist(new_index(R, Len), Index, ShiftedIndexes), 
    maplist(lis_pos_elem(L1), ShiftedIndexes, L2).
?-
marquee("Prolog is marquee ready! ", M); true.
M = ['P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' '] ;
M = [' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !] ;
M = [!, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y] ;
M = [y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d] ;
M = [d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a] ;
M = [a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e] ;
M = [e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r] ;
M = [r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' '] ;
M = [' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e] ;
M = [e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e] ;
M = [e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u] ;
M = [u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q] ;
M = [q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a, r] ;
M = [r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m, a] ;
M = [a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' ', m] ;
M = [m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' '] ;
M = [' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s] ;
M = [s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i] ;
M = [i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' '] ;
M = [' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g] ;
M = [g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o] ;
M = [o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l] ;
M = [l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o] ;
M = [o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r] ;
M = [r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P'] ;
true.
3
damianodamiano On

this is an alternative solution (updated after a suggestion in the comments), hope this solves the task

marquee(String,String).
marquee([H|T],R):-
    append(T,[H],NewEl),
    marquee(NewEl,R).


?- marquee("Prolog is marquee ready! ", M).
M = ['P', r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' '];
M = [r, o, l, o, g, ' ', i, s, ' ', m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P'];
...

?- M=[m|_],marquee("Prolog is marquee ready! ",M).
M = [m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' '];
M = [m, a, r, q, u, e, e, ' ', r, e, a, d, y, !, ' ', 'P', r, o, l, o, g, ' ', i, s, ' '];
...
1
Lospix On

This is my updated answer:

marquee_right(S0, M):- 
    length(S0, Len),
    length(_, Roll), 
    Shift is Len - (Roll mod Len),
    length(P1, Shift),
    append(P1, P2, S0),
    append(P2, P1, M).

marquee_left(S0, M):- 
    length(S0, Len),
    length(_, Roll), 
    Shift is Roll mod Len,
    length(P1, Shift),
    append(P1, P2, S0),
    append(P2, P1, M).

@damianodamiano answer seems really good and declarative, maybe my answer follow more a procedural style. Comments and notes are appreciated.

7
brebs On

This feels fairly intuitive, but not super-short:

marquee(L, M) :-
    % Convert to List-Remainder difference list
    append(L, R, LD),
    marquee_(LD, R, M).

marquee_(M, [], M).
% Move from head to tail
marquee_([H|T], [H|R], M) :-
    marquee_(T, R, M).

Result in swi-prolog:

?- marquee([a,b,c,d], L).
L = [a, b, c, d] ;
L = [b, c, d, a] ;
L = [c, d, a, b] ;
L = [d, a, b, c] ;
L = [a, b, c, d] ;
L = [b, c, d, a] ;
...

I suspect there's a trick to convert that into a short DCG that I'm missing...

1
Will Ness On

Rolling rolling rolling ...

marquee([],[]) :- repeat, true.
marquee([H|T],X) :- m(T,R,[H|R],X).
m([H|T],[H|R],Y,X) :- m(T,R,Y,X).
m([],[],Y,Y).
m([],[H|Z],[H|R],X) :- m([],Z,R,X).

Testing:

8 ?- marquee([],X).
X = [] ;
X = [] ;
X = [] ;
X = [] ;
X = [] ;
X = [] 
......

9 ?- marquee([1,2,3,4],X).
X = [1, 2, 3, 4] ;
X = [2, 3, 4, 1] ;
X = [3, 4, 1, 2] ;
X = [4, 1, 2, 3] ;
X = [1, 2, 3, 4] ;
X = [2, 3, 4, 1] ;
X = [3, 4, 1, 2] ;
X = [4, 1, 2, 3] ;
X = [1, 2, 3, 4] ;
X = [2, 3, 4, 1] ;
X = [3, 4, 1, 2] ;
X = [4, 1, 2, 3] 
......