and I want the subsets with three members, the result would be:

Similar documents
Taking Advantage of Idle Cycles. Make Your Application Work When the User Isn't. The Idea. The Strategy. December, 2003

Formal Methods of Software Design, Eric Hehner, segment 24 page 1 out of 5

Working with the Registry. The Registry class makes it easy. The Registry Structure. January, By Tamar E. Granor

Designing a Database -- Understanding Relational Design

The Stack, Free Store, and Global Namespace

Let's start by taking a look at the object generated by LIST OBJECTS. I used the following code to put a few objects in memory for testing:

Advisor Answers. Create Cross-tabs. July, Visual FoxPro 9/8/7

Instructor: Craig Duckett. Lecture 03: Tuesday, April 3, 2018 SQL Sorting, Aggregates and Joining Tables

Advisor Answers. January, Visual FoxPro 3.0 and 5.0

Intro. Speed V Growth

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology.

MITOCW watch?v=kz7jjltq9r4

Advisor Answers. Clean up a Project. May, Visual FoxPro 9/8/7

Supporting Class / C++ Lecture Notes

Casting in C++ (intermediate level)

A File Open Dialog Box Doug Hennig

This tool lets you specify a new name for each control on a form or class and fixes all code that uses it.

PROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between

Using X-Particles with Team Render

Chapter 9. Variable Scope and Functions

Formal Methods of Software Design, Eric Hehner, segment 1 page 1 out of 5

Parallel scan. Here's an interesting alternative implementation that avoids the second loop.

I'm Andy Glover and this is the Java Technical Series of. the developerworks podcasts. My guest is Brian Jakovich. He is the

Module 10: Imperative Programming, Modularization, and The Future

Hi everyone. I hope everyone had a good Fourth of July. Today we're going to be covering graph search. Now, whenever we bring up graph algorithms, we

CSC 148 Lecture 3. Dynamic Typing, Scoping, and Namespaces. Recursion

Instructor: Craig Duckett. Lecture 07: Tuesday, April 17 th, 2018 Conflicts and Isolation, MySQL Workbench

It can be confusing when you type something like the expressions below and get an error message. a range variable definition a vector of sine values

MITOCW watch?v=sdw8_0rdzuw

MITOCW watch?v=se4p7ivcune

2. INSTALLATION OF SUSE

MITOCW watch?v=hverxup4cfg

MITOCW watch?v=0jljzrnhwoi

Linked Lists. What is a Linked List?

Data Handling Issues, Part I Doug Hennig

How to Improve Your Campaign Conversion Rates

So on the survey, someone mentioned they wanted to work on heaps, and someone else mentioned they wanted to work on balanced binary search trees.

Consolidate data from a field into a list

Inheritance (IS A Relationship)

Instructor: Craig Duckett. Lecture 04: Thursday, April 5, Relationships

Skill 1: Multiplying Polynomials

MITOCW watch?v=4dj1oguwtem

New to the Mac? Then start with this lesson to learn the basics.

PROFESSOR: Well, now that we've given you some power to make independent local state and to model objects,


CSE143 Notes for Monday, 4/25/11

static CS106L Spring 2009 Handout #21 May 12, 2009 Introduction

Problem One: Loops and ASCII Graphics

Slide 1 CS 170 Java Programming 1

MITOCW ocw f99-lec07_300k

Run-Time Data Structures

Transcript: A Day in the Life Desiree: 7 th Grade Learning Coach Profile

CS 440: Programming Languages and Translators, Spring 2019 Mon 2/4


1 Getting used to Python

Programs in memory. The layout of memory is roughly:

Advisor Answers. Match multiple items in a query. December, 2005 VFP 9/8/7

Decisions: Logic Java Programming 2 Lesson 7

4 + 4 = = 1 5 x 2 = 10

Lesson 4: Who Goes There?

6.001 Notes: Section 4.1

Q: I've been playing with the Microsoft Internet Transfer Control (inetctls.inet.1) and it would be great if only it worked.

Fortunately, you only need to know 10% of what's in the main page to get 90% of the benefit. This page will show you that 10%.

CONTENTS: What Is Programming? How a Computer Works Programming Languages Java Basics. COMP-202 Unit 1: Introduction

Slide 1 CS 170 Java Programming 1 The Switch Duration: 00:00:46 Advance mode: Auto

Chapter 1 Getting Started

Smart formatting for better compatibility between OpenOffice.org and Microsoft Office

Client Side JavaScript and AJAX

Create Models or Use a Library? Create your own library How to Get Started? [ 140 ]

Hello, and welcome to another episode of. Getting the Most Out of IBM U2. This is Kenny Brunel, and

More Complicated Recursion CMPSC 122

Design and Analysis of Algorithms Prof. Madhavan Mukund Chennai Mathematical Institute. Module 02 Lecture - 45 Memoization

To figure this out we need a more precise understanding of how ML works

Advisor Answers. Creating New Sort Orders. June, Visual FoxPro 6.0, 5.0 and 3.0

MITOCW ocw f99-lec12_300k

MITOCW watch?v=w_-sx4vr53m

Range Minimum Queries Part Two

There are many other applications like constructing the expression tree from the postorder expression. I leave you with an idea as how to do it.

Stored procedures - what is it?

(Refer Slide Time: 00:51)

Master Syndication Gateway V2. User's Manual. Copyright Bontrager Connection LLC

Troubleshooting Maple Worksheets: Common Problems

CS 230 Programming Languages

CS02b Project 2 String compression with Huffman trees

Welcome to another episode of Getting the Most. Out of IBM U2. I'm Kenny Brunel, and I'm your host for

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

Every language has its own scoping rules. For example, what is the scope of variable j in this Java program?

Advisor Discovery. Use BindEvent() to keep things in synch. BindEvent() Refresher. June, By Tamar E. Granor, technical editor

COSC 2P95 Lab 5 Object Orientation

How To Set User Account Password In Windows 7 From Guest

CS193D Handout 10 Winter 2005/2006 January 23, 2006 Pimp Your Classes

Sub Programs. To Solve a Problem, First Make It Simpler

CSE200 Lecture 6: RECURSION

Lab 7 Macros, Modules, Data Access Pages and Internet Summary Macros: How to Create and Run Modules vs. Macros 1. Jumping to Internet

CircuitPython 101: Working with Lists, Iterators and Generators

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting

Part 1 Your First Function

CSE 333 Autumn 2013 Midterm

MITOCW ocw apr k

About this exam review

Transcription:

June, 2003 Advisor Answers Generating combinations VFP 8/7/6 Q: How can I find all the groups of ten numbers out of a set of 45? More generally, how can I find all the subsets of a particular size in a set of numbers? For example, if I have these six numbers: 5, 6, 7, 8, 9, 10 and I want the subsets with three members, the result would be: 5, 6, 7 5, 6, 8 5, 6, 9 5, 6, 10 5, 7, 8 5, 7, 9 5, 7, 10... Wayne Stephenson (via Advisor Forums) A: Generating all the combinations of a list is a classic problem in mathematics. It's also a great example of a problem where recursion produces a much simpler solution than other approaches. Let's start by talking about the general solution, then we'll dig into recursion, and finally, I'll show a recursive solution to this problem. First, it's important to note that we're talking here about combinations, not permutations. Combinations are all the subsets without regard to order; permutations are the subsets where the order of elements varies. So, in the example above, the list of combinations includes (5, 6, 7), but not (6, 5, 7) or (7, 6, 5) or any of the other orderings of those three numbers. The list of permutations would include all of them. How do you find all the combinations of a set? The list above gives you a clue. In pseudo-code, it looks something like: FOR ni = 1 TO nlistsize-nsubsetsize + 1 * Make the item at position ni the first item FOR nj = ni+1 TO nlistsize-nsubsetsize+2 * Make the item at position nj the second item FOR nk = nj+1 TO nlistsize-nsubsetsize+3

* Make the item at position nk the third item... If you know the subset size ahead of time, you can write code with nested loops like this. However, if you want to solve the general problem, where you can have a list of any size and subsets of any size, you have to take another approach. Enter recursion. Recursion is the act of a program calling itself. The most familiar example of recursion is probably the definition of the factorial function, the product of all the numbers from 1 to n, normally expressed with an exclamation point: 0! = 1 n! = n * (n-1)! for n>=1 You can write code to compute factorials in VFP like this: FUNCTION Factorial( nnumber AS Number ) LOCAL nresult IF nnumber = 0 nresult = 1 ELSE nresult = nnumber * Factorial(nNumber-1) RETURN nresult This example points out an important rule for recursive functions there must be a termination point defined. For factorial, it's passing 0. How can we solve the combination problem recursively? The idea is to call a function once for each number in the subset; the function chooses one item. The termination point is having the specified number of items. When writing recursive code, you need to be extra careful about the scope of variables. Be sure to declare any variables used only within the current call as local, so another call doesn't step on their values. Sometimes, you have items you want modified by successive calls. For the combination problem, we track the number of subsets found so far. Make sure to declare those variables private prior to calling the recursive routine. It's not unusual to have two functions involved in a recursive situation. The first sets things up, including declaring any private variables, and

makes the initial call to the actual recursive routine. That's the case for solving this problem. The first function creates a cursor to hold the results, initializes a private counter variable and then calls the recursive function. Rather than worrying about the actual items that need to go into subsets, these functions assume that they're stored in an array or cursor where each item can be accessed by its position. So, each subset in the resulting cursor is the list of positions where the appropriate items can be found. Here's the code: LPARAMETER ncount, nsetsize * Parameter checking omitted PRIVATE nreccount * Create a cursor to hold results cfieldlist = "" FOR nitem = 1 TO nsetsize cfieldlist = cfieldlist + "Item" + ; TRANSFORM(nItem) + " N(4)," cfieldlist = LEFT(cFieldList, LEN(cFieldList)-1) CREATE CURSOR Results (&cfieldlist) nreccount = 0 GetNextValue(nCount, nsetsize, 1, 1) RETURN nreccount PROCEDURE GetNextValue LPARAMETERS ncount, nsetsize, nstartpos, nresultpos * Parameter checking omitted LOCAL npos, noldreccount FOR npos = nstartpos TO ncount-nsetsize+nresultpos noldreccount = nreccount * Drill down first IF nresultpos<nsetsize GetNextValue(nCount,nSetSize,nPos+1,nResultPos+1) * Save results IF nresultpos=nsetsize nreccount = nreccount + 1 APPEND BLANK IN Results GO noldreccount + 1 SCAN REST REPLACE ("Item"+TRANSFORM(nResultPos)) ; WITH npos IN Results ENDSCAN RETURN

The trickiest part of this particular problem turns out to be putting the values into the result. Having determined the value for a particular position, it may apply to a whole series of records in the result. But at the time we figure it out, we don't know how many. So we wait to save the value until we've drilled all the way down and come back. By that point, all the appropriate records have been added. The noldreccount variable keeps track of the record pointer position when we enter the routine each time. (Note that it's local so that each call to the function has its own variable.) When we return from the recursive call, we need to put the value for this position into the appropriate field of every record added after that. Let's look at a simple example. Suppose we have four items and want all combinations with two items. The first time GetNextValue is called, it receives the following parameters: 4, 2, 1, 1 indicating that there are four items total, we want subsets with two items, this item should start with position 1 and we're working on the first element in the resulting subsets. The loop starts by setting npos to 1; in other words, the first item in the subsets we're working on now is item 1. Since nreccount is 0, noldreccount is set to 0. The recursive call passes these parameters: 4, 2, 2, 2 So, on the second call to GetNextValue, npos starts at 2; that is, the second item in the subset we're now working on is item 2. Again, noldreccount is set to 0. Because nresultpos (2) is the same as nsetsize (2), there's no recursive call and we add a record to the cursor. The REPLACE command sets field Item2 to 2 in the newly added record (leaving field Item1 blank for now). We return to the top of the loop and npos becomes 3. Again, there's no recursive call and we add another record, this time setting Item2 to 3. We go through the loop one more time, adding another record, setting Item2 to 4. At this point, we return to the original call to GetNextValue. nresultpos (1) isn't equal to nsetsize (2), so we don't add a record. We move the record pointer to one beyond noldreccount, in this case, record 1, and we loop through all records from there to the end of the cursor (there are three at this point), setting field Item1 to 1.

The loop continues, with npos=2, but this should be enough to demonstrate the technique. Recursion in VFP is limited by the program stack, 128 in recent versions. For this program, that means it can't handle subsets of more than 127 items. The program above is included as GetSetsToCursor.PRG on this month's Professional Resource CD. Incidentally, there's a connection between the factorial function and combinations. The number of combinations can be expressed as: ncount!/(nsetsize! * (ncount-nsetsize)!) Tamar