Substitution rule on maple - substitution

I am slightly new to maple and I am interested in the following question.
Let's assume I have a map f that sends a to abb and b to a. My first question is how do I define this map on maple? I am also interested in when the map is applied repeated i.e. the iterates of f. Say if I have a seed ab, is there something I can put on maple such that when I apply f, it becomes abba and so on?
Thank you

Hope this helps:
> f(a) := a,b,b;
a, b, b
> f(b) := a;
a
> map(f, [a, b]);
[a, b, b, a]
> map(f, %);
[a, b, b, a, a, a, b, b]

You could also do this using strings.
restart:
g := e->StringTools:-SubstituteAll(StringTools:-CharacterMap("ab","ta",e),"t","abb"):
g("a");
"abb"
g("b");
"a"
g("ab");
"abba"
(g##2)("ab");
"abbaaabb"
subs(["a"=a,"b"=b],StringTools:-Explode(g("ab")));
[a, b, b, a]
f(a) := a,b,b;
f(a) := a, b, b
f(b) := a;
f(b) := a
map(f, [a, b]);
[a, b, b, a]
map(f, %);
[a, b, b, a, a, a, b, b]
F := e->map(f,e):
F([a, b]);
[a, b, b, a]
(F##2)([a, b]);
[a, b, b, a, a, a, b, b]
evalb( subs(["a"=a,"b"=b],StringTools:-Explode(g("ab"))) = F([a, b]) );
true
ans1 := CodeTools:-Usage( (g##20)("ab") ):
memory used=6.01MiB, alloc change=4.01MiB, cpu time=100.00ms, real time=102.00ms, gc time=0ns
ans1list := CodeTools:-Usage( subs(["a"=a,"b"=b],StringTools:-Explode(ans1)) ):
memory used=32.00MiB, alloc change=32.01MiB, cpu time=170.00ms, real time=175.00ms, gc time=0ns
ans2 := CodeTools:-Usage( (F##20)([a, b]) ):
memory used=128.11MiB, alloc change=21.02MiB, cpu time=3.81s, real time=3.82s, gc time=3.46s
evalb( ans1list = ans2 );
true
You could also write either g or F to chew on larger chunks (of length 2, or 4, etc), and to recursively split the argument, etc, and even to learn such patterns.

Related

A predicate that takes a list and repeats each element X amount of times - Prolog

I can get the result to be true, but when I attempt to make it false I feel like it is in an endless loop.
repeat(L,N,Result):-
rHelp(L,N,[],Result).
rHelp(_,_,Result,Result).
rHelp([H|T],N,L1,L2):-
dupe(H,N,[],L3),
append(L1,L3,L4),
rHelp(T,N,L4,L2).
dupe(_,0,L,L).
dupe(H,N,L,Result):-
N1 is N-1,
append(L,[H],L1),
dupe(H,N1,L1,Result).
Example Test:
repeat( [a, b, c], 2, [a, a, b, b, c, c] )
repeat( [1, a, 2, b], 0, [ ] )
repeat( [1, 1, 2], 3, [1, 1, 1, 1, 1, 1, 2, 2, 2] )
which are all True. I am just trying to get a false result.
One reason it's hard to make your program fail is that it describes too many incorrect solutions:
?- repeat([a, b, c], 2, Result).
Result = [] ;
Result = [a, a] ;
Result = [a, a, b, b] ;
Result = [a, a, b, b, c, c] ;
% nontermination
The reason you accept too many solutions is the first clause of rHelp/4:
rHelp(_,_,Result,Result).
Here you say that for any input list, at any point in the computation where you have an intermediate result Result, that is a correct solution. But this is not the case. The intermediate result is only a complete result once you have exhausted the entire input list. This clause should be:
rHelp([], N, Result, Result).
Note that I found this essentially by pattern matching. Adjacent clause heads like
foo(_, Bar).
foo([H|T], Bar) :- ...
simply look incorrect. Why is the _ not an empty list? In most cases a predicate like this would have mutually exclusive patterns in the head, and here that is not the case.
With this fixed, we can try the test again:
?- repeat([a, b, c], 2, Result).
Result = [a, a, b, b, c, c] ;
% nontermination
Better! But it still goes searching for more solutions although there are none. This, too, is a case of clauses not being mutually exclusive:
dupe(_,0,L,L).
dupe(H,N,L,Result):-
N1 is N-1,
...
If the second argument is not 0, the second clause applies. If the second argument is 0, the first clause applies... but so does the second! After finding a solution using the first clause, Prolog will backtrack and execute the second clause with N = 0. Then N1 will become -1, and your program goes off recursively looking for negative infinity.
The fix is to add a guard N > 0 in the second clause. And with these two changes, the test works as desired:
?- repeat([a, b, c], 2, Result).
Result = [a, a, b, b, c, c] ;
false.
One general point to observe here is that it was easier to understand the behavior of your predicate by using less specific queries. There is no need to specify a fixed list for the Result argument: Leave it free and see what Prolog gives you!

Perform replacement in nested predicate using recursion

I'm trying to write a set of predicates that replace terms in nested predicates using recursion; i.e.
Given:
r(a, aa).
r(c, cc).
r(e, ee).
p(a, b, c).
p(a, b, p(d, e, f)).
p(a, p(p(b, c, d), e, f), g).
I want:
p(aa, b, cc)
p(aa, b, p(d, ee, f))
p(aa, p(p(b, cc, d), ee, f), g)
Here is a (probably wildly incorrect) attempt:
inf(p(A, B, C), p(AA, BB, CC)):-
p(A, B, C),
( r(A, AA);
r(B, BB);
r(C, CC)
).
inf(p(A, B, C), p(AA, BB, CC)):-
p(A, B, C),
( r(A, AA);
r(B, BB);
r(C, CC)
),
( inf(A, AA);
inf(B, BB);
inf(C, CC)
).
With a call to inf(X, Y). this yields:
X = p(a, b, c),
Y = p(aa, _1262, _1264)
X = p(a, b, c),
Y = p(_1064, _1066, cc)
X = p(a, b, p(d, e, f)),
Y = p(aa, _1074, _1076)
X = p(a, p(p(b, c, d), e, f), g),
Y = p(aa, _1082, _1084)
false
which is not what I want. I suspect there is something wrong with how my base case combines with the code doing replacements.
Any help would be greatly appreciated!
Thanks/JC
Here's a simplified approach which might have some exception cases for you to examine and explore, but it illustrates a handy use of (=..)/2 and maplist/3. (=..)/2 provides an equivalence between a term and a list (e.g., p(a, b, p(d, e, f)) =.. L results in L = [p, a, b, p(d, e, f)] and Term =.. [foo, x, y] results in Term = foo(x, y)). By getting a list equivalent of a term, you can use recursive list processing to handle arbitrary compound terms.
maplist(foo, List1, List2) exercises a query foo(X1, X2) for every corresponding element X1 of List1 and X2 of List2 and succeeds if each query succeeds and provides argument instantiations for each success as Prolog normally does on a query.
You can use maplist(r, TermList, SubList) to perform a simple substitution using the mapping r as long as r succeeds for every element of the list. However, in this case, you'd want a mapping that succeeds with the same term back again if there is no mapping. For this, you can define map_r as below.
% map_r is the mapping defined by 'r', or term maps to itself
map_r(X, M) :-
r(X, M).
map_r(X, X) :-
\+ r(X, _).
% A functor on its own is just itself after term substitution
term_subst(Term, Functor) :-
Term =.. [Functor]. % Term has no arguments
% A functor with arguments is the same functor with args substituted
term_subst(Term, TermSub) :-
Term =.. [Functor | [Arg|Args]], % Term has at least one arg
maplist(map_r, [Arg|Args], ArgsMap), % mapping of matching args
maplist(term_subst, ArgsMap, ArgsSub), % recursive substitution for sub-terms
TermSub =.. [Functor | ArgsSub].

Move every second element to the back of a list, recursively

I'm looking for a way to shuffle a list of numbers in a specific way.
shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) should return [1, 3, 5, 7, 9, 11, 2, 6, 10, 4, 12, 8]
The recursion would be something like this:
[1,3,5,7,9,11] with remainder [2,4,6,8,10,12]
[2,6,10] with remainder [4,8,12]
[4,12] with remainder [8]
and then you append the result lists and return the wanted answer.
My current code looks like this. How can I adapt it so that it produces the type of recursion I explained above? the mode is shuffle(+,?).
shuffle([], _).
shuffle(List, Shuffled) :- r(List, Shuffled).
r([], []).
r([X], [X]):- !.
r([X,A|Xs], [X|Ys]) :- r(Xs, Ys).
First, a predicate that gets half the work done: reorders the list so that every second element is picked out and appended to the back, keeping the order:
untangle([], []).
untangle([X|Xs], [X|Ys]) :-
untangle_1([X|Xs], [X|Ys], Bs, Bs).
% The rest of the Untangled is the list at the back;
% the list at the back is now empty
untangle_1([], Back, Back, []).
% Keep elements in odd positions at the front
untangle_1([X|Xs], [X|Untangled], Back, Bs) :-
untangle_2(Xs, Untangled, Back, Bs).
% Same as above
untangle_2([], Back, Back, []).
% Move elements in even positions to the back
untangle_2([X|Xs], Untangled, Back, [X|Bs]) :-
untangle_1(Xs, Untangled, Back, Bs).
This is very similar to the interwine/3 defined in this answer. Instead of using two lists for the "unzipped" elements, it puts them at the front and back of the same list.
Now what you need is shuffle the elements that would otherwise be appended to the back:
shuffle([], []).
shuffle([X|Xs], Shuffled) :-
untangle_1([X|Xs], Shuffled, Back, Bs),
shuffle(Bs, Back).
Did I understand that correctly?
?- shuffle([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z], S), write(S).
[a,c,e,g,i,k,m,o,q,s,u,w,y,b,f,j,n,r,v,z,d,l,t,h,x,p]
S = [a, c, e, g, i, k, m, o, q|...].
You will also notice that this shuffle/2 works in modes shuffle(+List, -Shuffled), shuffle(-List, +Shuffled), and shuffle(?List, ?Shuffled). To what I can see, it is identical in semantics (and almost identical in implementation) to the solution of false.
Here is a version using DCGs:
eo([], Ys,Ys) -->
[].
eo([X|Xs], [X|Ys0],Ys) -->
eo2(Xs, Ys0,Ys).
eo2([], Ys,Ys) -->
[].
eo2([X|Xs], Ys0,Ys) -->
[X],
eo(Xs, Ys0,Ys).
list_shuffled(Xs, Ys0) :-
phrase(eo(Xs, Ys0,Ys),Ys).
And here is the most general query showing all possible uses:
?- list_shuffled(Xs,Ys), numbervars(Xs+Ys,0,_).
Xs = Ys, Ys = []
; Xs = Ys, Ys = [A]
; Xs = Ys, Ys = [A, B]
; Xs = [A, B, C], Ys = [A, C, B]
; Xs = [A, B, C, D], Ys = [A, C, B, D]
; Xs = [A, B, C, D, E], Ys = [A, C, E, B, D]
; Xs = [A, B, C, D, E, F], Ys = [A, C, E, B, D, F]
; Xs = [A, B, C, D, E, F, G], Ys = [A, C, E, G, B, D, F]
; ... .
Here's another, somewhat transparent solution using append:
shuffle([], []).
shuffle([X|T], Shuffled) :-
unzip([X|T], Odd, Even),
shuffle(Even, EvenShuffled),
append(Odd, EvenShuffled, Shuffled).
% Split a list into odd and even elements
unzip([], [], []).
unzip([X], [X], []).
unzip([X,Y|T], [X|Tx], [Y|Ty]) :-
unzip(T, Tx, Ty).
For the record, I do prefer Boris' and false's solutions to this one (+1 to both) as both are more efficient. :)

Simple Multiple Choice

I want to ask about my multiple choice program that I made. I confuse how to store a value continuously, so I can take a conclusion in the end of program, based on sum of the value that already store.
start :- program.
program :-
write('This is question number 1'),nl,
write('A'),nl,
write('B'),nl,
write('C'),nl,
read(Choice),nl,
(
%case1
Choice='a'->nl,
=================================
A = A + 1 <--- Right Here,
And then go to Question 2.
=================================
%case2
Choice='b'->nl,
=================================
B = B + 1 <--- Right Here,
And then go to Question 2.
=================================
%case3
Choice='c'->nl,
=================================
C = C + 1 <--- Right Here,
And then go to Question 2.
=================================
%case_default
write('Wrong Code')
).
So I can take a conclusion like this,
===================================
if B < A > C then you're an A.
if A < B > C then you're a B.
if A < C > B then you're a C.
===================================
Thanks you very much before :)
There are many possible ways to store values. What you probably think of - storing some counters and updating them on given answers - can lead to some complicated situations. Example of code working with counters:
question('Choose a, b or c: ').
question('Choose again a, b or c: ').
question('Think before you choose a, b, or c: ').
ask :-
findall(Q, question(Q), Questions),
ask_and_count([0,0,0], [A,B,C], Questions),
max_list([A,B,C], Max),
nth1(Index,[A,B,C],Max),
nth1(Index,[a,b,c],Answer),
print('You''re a(n) '), print(Answer), nl.
ask_and_count(Count, Count, []) :-
print('Thank you, that''s all questions!'), nl, !.
ask_and_count(InCount, OutCount, [Q | Questions]) :-
print(Q),
read_abc(Ans),
increase(Ans, InCount, NewCount),
ask_and_count(NewCount, OutCount, Questions).
read_abc(A) :-
read(A),
member(A, [a,b,c]),
!.
read_abc(A) :-
print('Only a, b and c are accepted! Answer again: '),
read_abc(A).
increase(a, [A, B, C], [X, B, C]) :- X is A + 1.
increase(b, [A, B, C], [A, X, C]) :- X is B + 1.
increase(c, [A, B, C], [A, B, X]) :- X is C + 1.
Sample input and output:
?- ask.
Choose a, b or c: b.
Choose again a, b or c: c.
Think before you choose a, b, or c: c.
Thank you, that's all questions!
You're a(n) c
Maybe I can inspire you to do it another way, which in my opinion is more "prologish" as it relies on lists and leads to simpler code:
question('Choose a, b or c: ').
question('Choose again a, b or c: ').
question('Think before you choose a, b, or c: ').
read_abc(A, Choices) :-
read(A),
member(A, Choices),
!.
read_abc(A, Choices) :-
print('Only '), print(Choices), print(' are accepted! Try again: '),
read_abc(A, Choices).
ask(Answers) :-
findall(Ans, (question(Q), print(Q), read_abc(Ans, [a,b,c])), Answers).
start :-
ask(Answers),
print(Answers).
Sample input and output:
?- start.
Choose a, b or c: c.
Choose again a, b or c: b.
Think before you choose a, b, or c: c.
[c,b,c]
true.
After you have all answers in a list, you can simply count occurences of every answer.
Other way of storing choices is by using assert and retract predicates. Expert systems do that. When using assert and retract you can use some predicates like global variables known from other programming languages.

Parameters as array in Yaml in Symfony2

I'm doing this which works fine:
parameters:
array_name1: [a, b, c, d]
array_name2: [x, y, a, b]
Now I need to add what in PHP would be $array_name3[1] = array("a", "b", "c") etc., so something like this:
parameters:
array_name3[1]: [1, 2, 3]
array_name3[2]: [a, b, c]
array_name3[3]: [x, y, z]
...which of course doesn't work. Nothing I try seems to be accepted.
How do I define multi-dimensional arrays in Yaml (Symfony2)?
Try this
parameters:
array_name3:
- [1, 2, 3]
- [a, b, c]
- [x, y, z]
Or if you want to have it associative:
parameters:
array_name3:
1: [1, 2, 3]
2: [a, b, c]
bla: [x, y, z]
Or if you want more - read documentation

Resources