Re: Can Maxima Protect Variables Under Recursion?



Hi MFFAI,

I've got it working for you now!

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


colors(qlist, qtake, qtaken, startTake) :=
block([list: qlist, take: qtake, taken: qtaken, ntake],
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
(ntake: min(take,list[1]),
return(colors(rest(list), startTake - ntake - taken, taken +
ntake,startTake)
+ colors(reduceColor(list,ntake), ntake, taken, startTake))))$

I made the following changes:

1. erroneous "listcopy" removed (as previously stated)

2. variable "ntake" added to list of protected variables at start of
block command

3. I replaced your if..then..else statement to select the smaller of
take and list[1] with min(take,list[1]) (no difference to program -
just looks more elegant ;-) )

It's a nice program - I'll be adding it to my archive!

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],
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