Re: Can Maxima Protect Variables Under Recursion?



Maths For Fun And Insight wrote:
If I do a simple factorial recursion, there is no problem whatsoever:

(%i6) facty(x) := if x=1 then 1 else x*facty(x-1);
(%o6) facty(x) := if x = 1 then 1 else x facty(x - 1)
(%i7) facty(5);
(%o7) 120

However - I wrote a program to try to quickly answer the following
question (which defies simple combinatorical solution): if I have a
list of numbers of marbles of different colours, how many different
combinations of colours can I make with n of those marbles? (e.g. if I
have 3 reds, 2 greens and 1 yellow, I can make 6 different combinations
of 3 balls - red red red, red red green, red red yellow, red green
green, red green yellow, green green yellow). This program gives
incorrect results - and the reason is that Maxima is not protecting the
variables under recursion:

reduceColor(fullList,take) := (newList: copylist(fullList), newList[1]:
min(fullList[1],take) - 1, newList);

colors(list, take, taken, startTake) :=
block([],
if list[1] < 0 then
return(0)
else
if length(list) = 2 then
if take < 0 then
return(0)
else
if take = 0 then
return(1)
else
if list[1] + list[2] < take then
return(0)
else
if list[1] + list[2] = take then
return(1)
else
(count: 0,
for i: 0 thru list[1] do
for j: 0 thru list[2] do
if i + j = take then
count: count + 1,
return(count))
else
(if take > list[1] then
ntake: list[1]
else
ntake: take,
return(colors(rest(list), startTake - ntake - taken, taken + ntake,
startTake)
+ colors(reduceColor(list,ntake), ntake, taken, startTake))))$

(%i8) trace(colors);
(%o8) [colors]
(%i9) colors([4,3,2,1],4,0,4);
1 Enter colors [[4, 3, 2, 1], 4, 0, 4]
2 Enter colors [[3, 2, 1], 0, 4, 4]
3 Enter colors [[2, 1], 0, 4, 4]
3 Exit colors 1
3 Enter colors [[- 1, 2, 1], 0, 4, 4]
3 Exit colors 0
2 Exit colors 1
2 Enter colors [[- 1, 3, 2, 1], 0, 0, 4]
2 Exit colors 0
1 Exit colors 1

Reading the part of the manual that refers to functions (
http://maxima.sourceforge.net/docs/manual/en/maxima_40.html#SEC152 ),
it is supposed to be possible to protect variables by putting their
names in the list at the start of the block. However - if I do
something like this:

colors(qlist, qtake, qtaken, startTake) :=
block([list: listcopy(qlist), take: qtake, taken: qtaken],

In the above line, you wrote listcopy instead of copylist (list: qlist
seems to work just as well anyway). That removes the error.

It is still giving the wrong answer for colors([4,3,2,1]4,0,4) - but
that might be due to a programming error - I will study it a bit
more...

if list[1] < 0 then
return(0)
else
if length(list) = 2 then
if take < 0 then
return(0)
else
if take = 0 then
return(1)
else
if list[1] + list[2] < take then
return(0)
else
if list[1] + list[2] = take then
return(1)
else
(count: 0,
for i: 0 thru list[1] do
for j: 0 thru list[2] do
if i + j = take then
count: count + 1,
return(count))
else
(if take > list[1] then
ntake: list[1]
else
ntake: take,
return(colors(rest(list), startTake - ntake - taken, taken + ntake,
startTake)
+ colors(reduceColor(list,ntake), ntake, taken, startTake))))$

I get the following error:

(%i9) colors([3,2,1],4,0,4);
Maxima was unable to evaluate the predicate:
errexp1
#0: colors(qlist=[3,2,1],qtake=4,qtaken=0,starttake=4)
-- an error. Quitting. To debug this try debugmode(true);

Can anyone offer any advice, please?

.



Relevant Pages