Endless Subroutine

For questions regarding programming in the EViews programming language.

Moderators: EViews Gareth, EViews Moderator, EViews Jason, EViews Matt

jxwong
Posts: 6
Joined: Mon Nov 14, 2016 3:12 am

Endless Subroutine

Postby jxwong » Mon Nov 14, 2016 3:18 am

Hi,

I am trying to generate all possible combinations from a set of variables, basically n choose r combinations, and have been trying to use the following set of codes which was adapted from other softwares.

The code ends up giving me with the following strings "abc", abd", "ab" and "acd" and then "acd" ^ infinitity, while the correct combinations i am trying to store into the svector are only "abc", "abd" and "acd". Can i get someone's guidance on the correct usage of subroutines, please?

Thanks and regards,

'------------------------------------

!sv = 1
svector(3) sofar_str

subroutine combinationNR(string %sofar, string %rest, scalar !n)
if !n=0 then
sofar_str(!sv) = %sofar
!sv = !sv + 1
else
for !i = 1 to @length(%rest)
call combinationNR(%sofar+@wmid(%rest,!i,1), @wmid(%rest,!i+1), !n-1)
next
endif
endsub

call combinationNR("", "a b c d", 3)

'-------------------------

EViews Matt
EViews Developer
Posts: 584
Joined: Thu Apr 25, 2013 7:48 pm

Re: Endless Subroutine

Postby EViews Matt » Mon Nov 14, 2016 11:40 am

Hello,

There are a pair of issues primarily responsible for the difficulties you're experiencing.

First, inside the for loop, your use of @wmid() assumes that variable !i is an element index, but in the loop's condition !i will iterate through all of %rest's character indices. For example, in the initial invocation of combinationNR() when %rest is "a b c d", you want !i to iterate between 1 and 4, not 1 and 7. In short, you need the upper limit on !i to be the number of elements in %rest, not the number of characters in %rest. This can be accomplished by replacing @length() with @wcount(). As is, the extra calls to @wmid() return the empty string, which is why some of the generated results are missing letters.

Second, also related to the for loop, your use of recursion assumes that variable !i is a local variable and therefore cannot be changed within any recursive call. Unfortunately, !i is a global variable and therefore is modified within recursive calls, which seriously disrupts the flow of the recursion. In order to make !i behave like a local variable the combinationNR() subroutine needs to be made a local subroutine. However, after making that change combinationNR() will lose access to the global !sv and sofar_str, but you can pass them to the subroutine instead.

And FYI, you should expect four resulting strings from your example, abc, abd, acd, and bcd. 4 choose 3 = 4.
Last edited by EViews Matt on Wed Nov 16, 2016 3:29 pm, edited 3 times in total.

jxwong
Posts: 6
Joined: Mon Nov 14, 2016 3:12 am

Re: Endless Subroutine

Postby jxwong » Mon Nov 14, 2016 5:51 pm

Hi Matt,

Thanks much for the guidance! I have tried using both the local and global subroutines as per the code appended below.

When i do not use local, only "abc" and "abd" are generated and when i include local, nothing is generated at all. Could you let me know what else did i miss out in the code please?

'----------------------------------------------

subroutine [local] combinationNR(string %sofar, string %rest, scalar !n)
svector(4) sofar_str
if !n = 0 then
sofar_str(!i) = %sofar
else
for !i = 1 to @wcount(%rest)
call combinationNR(%sofar+@wmid(%rest,!i,1), @wmid(%rest,!i+1), !n-1)
next
endif
endsub

call combinationNR("", "a b c d", 3)

'------------------------------------

jxwong
Posts: 6
Joined: Mon Nov 14, 2016 3:12 am

Re: Endless Subroutine

Postby jxwong » Tue Nov 15, 2016 4:09 am

ok, i found a solution in another thread. can a subroutine be used on an svector (i.e. subroutine(svector %xx))?

'------------------------

subroutine Combinations(string %prefix, string %list_elements, scalar !index, scalar !p)
if !p=0 then
varlist_{!r}(!sv) = %prefix
!sv = !sv + 1
return
endif
if !index=@wcount(%list_elements)+1 then
return
endif
%element=@word(%list_elements,!index)
if @isempty(%prefix)=0 then
%prefix=%prefix + " " + %element
else
%prefix=%element
endif
call Combinations(%prefix, %list_elements, !index+1, !p-1)
%prefix=@wleft(%prefix,@wcount(%prefix)-1)
call Combinations(%prefix, %list_elements, !index+1, !p)
endsub

'-------------------------

EViews Matt
EViews Developer
Posts: 584
Joined: Thu Apr 25, 2013 7:48 pm

Re: Endless Subroutine

Postby EViews Matt » Tue Nov 15, 2016 10:18 am

Hello,

Yes, you can pass an svector to a subroutine. That's actually what I was suggesting you do after making the subroutine local. Here's your original code with the necessary modifications:

Code: Select all

!sv = 1 svector(4) sofar_str subroutine local combinationNR(string %sofar, string %rest, scalar !n, scalar !sv, svector sofar_str) if !n=0 then sofar_str(!sv) = %sofar !sv = !sv + 1 else for !i = 1 to @wcount(%rest) call combinationNR(%sofar+@wmid(%rest,!i,1), @wmid(%rest,!i+1), !n-1, !sv, sofar_str) next endif endsub call combinationNR("", "a b c d", 3, !sv, sofar_str)
There are certainly other ways to recursively generate string combinations, but the above is a pretty minimal change to your original code that accomplishes what I believe you asked for. Note that the !sv variable and sofar_str object still are created outside of the subroutine. This is particularly important for the sofar_str object so that it will exist after the subroutine terminates. Moving sofar_str inside a local subroutine, as one of your subsequent examples did, would create multiple local svectors (one per invocation of combinationNR()) and therefore wouldn't accumulate all the resulting combinations in a single place. Plus, those svectors would be deleted automatically, so you'd lose the results anyway. Passing !sv and sofar_str as above basically permits all invocations of combinationNR() to refer to the global !sv and sofar_str, which otherwise wouldn't be possible within a local subroutine.

jxwong
Posts: 6
Joined: Mon Nov 14, 2016 3:12 am

Re: Endless Subroutine

Postby jxwong » Tue Nov 15, 2016 6:08 pm

Wow, that is great. Thanks much for the kind assistance!


Return to “Programming”

Who is online

Users browsing this forum: No registered users and 2 guests