What is wrong with my recursion in C? - c

I have written a recursive function for my homework to do the following calculation:
For the imput:
1 2 3 4
It should do this:
((1*3)+2) + ((1*4)+3) = 13, thats less than, ((2*4)+3) + ((1*4)+2) = 17, so it returns 13.
In letters it should do this calculation: ((A*C)+B) + ((A*D)+C) and compare it with the other options, in this case there are 2 options: ((B*D)+C) + ((A*D)+C).
In few words. The numbers indicate the number of "screws" on each end of a segment. The segment is always formed by 2 numbers. Segment A {1 2}, B {2 3}, C {3 4}.
The task is to join all the N segments. I must find the "cheapest" way to do it. Every time I join two segments, (A and B for example), I do this:
"bottom screws"of A (1 - the first number) * "top screws"of B (3 - the third number) + "joining screws" (2 - that is the number between).
I have to join them in order, it always must end in order ABCD. But I can choose where to start from. I can join A to B and then AB to C, or i can join B to C and then A to BC. Basically in one of the cases the "cost" will be the lowest and thats the value to return.
For now I have done this, but I got confused:
The *help is a intercalculation array which i use to store the new values gotten in the recursion.
int *help;
The *mezi is a dynamically alocated array defined as:
int *mezi;
And inside it looks like {0,4,1,2,3,4,-1}.
mezi[0] = here is stored the total prize in the recursion.
mezi[1] = here is stored the number of values in the array, 4 for 4 values (3 segments).
mezi[n+2] = the last number (-1), its just an identifier to find out the number of values.
Here's my code:
int findmin(int *mezi, int *pomocny)
{
int i,j,k;
int prize, prizemin, mini, minih;
for (i=3;i<mezi[1];i++) {
prize = mezi[i-1] * mezi[i+1] + mezi[i];
if (i==3) { mini = i; minih = prize; }
if (prize < minih) { mini = i; minih = prize; }
if (mezi[1] > 3){
k=2;
for (j=2;j<mezi[1];j++) {
if (j != mini) help[k] = mezi[j];
k++;
}
help[1] = (mezi[1]-1);
}
help[0] += prize;
findmin(help,help);
}
prizemin = help[0];
return prizemin;
}
Im kinda of a novice, I started using C not long ago and the recursive functions cofuse me a lot. I would reallz appretiate help. Thanks :)

There are quite a few issues with your program logic.
int findmin(int *mezi, int *pomocny)
{
int i,j,k;
int prize, prizemin, mini, minih;
for (i=3;i<mezi[1];i++)
{
prize = mezi[i-1] * mezi[i+1] + mezi[i];
if (i==3) { mini = i; minih = prize; } //This is a redundant test and
//initialization. i == 3 is true only in the first run of the loop. These
//initialization should be done in the loop itself
if (prize < minih) { mini = i; minih = prize; }
if (mezi[1] > 3){ //This is also redundant as mezi[3] is always greater than 3
// otherwise the loop wont run as you check for this in your test expression
k=2;
for (j=2;j<mezi[1];j++) {
if (j != mini) help[k] = mezi[j];
k++;
}
help[1] = (mezi[1]-1);
}
help[0] += prize;
//The only base case test you have is mezi[1]<3 which you should make sure is
// present in your data set
findmin(help,help);
}
prizemin = help[0];
return prizemin;
}

Related

Is it possible to simplify this algorithm so that it only uses 1 loop and 2 variables?

Is it possible to get the same results as this code using only a and b?
I'm trying to calculate c from a and b to avoid using a third variable, but I can't find a solution.
#include <stdio.h>
#include <stdlib.h>
const int LENGTH = 20;
int main()
{
char arr[LENGTH];
for (int a = 0, b = 1, c = 0; c < LENGTH; c++) {
if (a < b) {
arr[c] = '*';
a++;
} else {
arr[c] = ' ';
a = 0;
b++;
}
}
printf(arr);
return EXIT_SUCCESS;
}
Code result : * ** *** **** *****
In the event that checking if a number is triangular by linking or writing some sort of sqrt() function is not a solution that you find acceptable:
Each group of **... in the final string has a ' ' at the end, so the shortest segment in the string is "* ", which is 2 chars long.
The c in your loop is the index of the char array that this iteration should write to, the a is the index inside the current group of '*'s, and b is length of the current group of '*'s less one (since we want to count the spaces). Directly before the if clause in your for loop, it can be said that c is the sum from 2 to b plus a.
In other words, if a=0, and b=1, then c=0, because the sum from 2 to 0 is 0, plus 0 is 0.
If a=3, and b=4, then c= (2+3+4) + 3 = 12.
This means that you could write your code like this:
#include <stdio.h>
const int LENGTH = 20;
int sumFromTwo(int in){ //Recursive function to calculate sigma(2:in)
if(in < 2)
return 0;
else
return in + sumFromTwo(in - 1);
}
int main()
{
char arr[LENGTH + 1]; //Extra byte for null-terminator
for (int a = 0, b = 1; sumFromTwo(b) + a < LENGTH ; ) {
if (a < b) {
arr[sumFromTwo(b) + a] = '*';
a++;
} else {
arr[sumFromTwo(b) + a] = ' ';
a = 0;
b++;
}
}
arr[LENGTH] = '\0'; //Always null-terminate your strings
printf(arr);
return EXIT_SUCCESS;
}
But using recursion to avoid using a variable that is almost certainly going to be optimized into a register anyway is not going to save your computer any resources, least of all RAM, so it is definitely cleaner to do it the way you did in your question (but please null-terminate your string before passing it to your choice of printf or puts).

How do I re-arrange a char array according to another sequence (which is a float array sorted in ascending order)?

For an assignment, I've been tasked with creating a Polyclinic Patient Attendance viewer. I have been given the following data: Percentage attendance for 4 different cases for a given year. For the project, we have to complete 5 functions. I've got 4 down but I still can't get my head around 1. According to the question, I have to display "The lowest to the highest percentage of case and name of the case for the year". I understand bubble sorting and I am able to arrange the percentages in ascending order. What I struggle to do however is display the names of the cases according to that ascending order I can get.
I tried to create a 2D char array which includes the names of the 4 cases and also a float array with the percentages. Then included in the "swapping" portion of the sorting algorithm, I tried to do swapping with the char array as well.
float year2010Cases[4] = { 11.2,8.9,15.6,15.9 };
char caseName[4][28] = { "Respiratory Tract Infection", "Diabetes
Mellitus","Hyperlipidemia","Hypertensive Disease" };
char swap[1][28];
#include <stdio.h>
void main(void)
{
int c, d;
float temp;
char swap[1][28];
for (c = 0; c < 3; c++)
{
for (d = 0; d < 3 - c; d++)
{
if (year2010Cases[d] > year2010Cases[d + 1])
{
temp = year2010Cases[d];
year2010Cases[d] = year2010Cases[d + 1];
year2010Cases[d + 1] = temp;
swap[1][28] = caseName[d][28];
caseName[d][28] = caseName[d + 1][28];
caseName[d + 1][28] = swap[1][28];
}
}
}
printf("Sorted list in ascending order:\n");
for (c = 0; c < 4; c++)
printf("%.1f\n", year2010Cases[c]);
printf("Sorted list in ascending order:\n");
for (c = 0; c < 4; c++)
printf("%s \n", caseName[c][28]);
}
I expected the case names to be displayed in the same order as the percentages as they are swapping at the same time as the percentages swapped. However, for my actual results, it does not display anything at all below the second "Sorted list in ascending order:\n"
To swap strings you need strcpy() (prototype in <string.h>)
//swap[1][28] = caseName[d][28];
//caseName[d][28] = caseName[d + 1][28];
//caseName[d + 1][28] = swap[1][28];
strcpy(swap[0], caseName[d]);
strcpy(caseName[d], caseName[d + 1]);
strcpy(caseName[d + 1], swap[0]);
Also note that swap[1] as well as casename[j][28] do not exist.
Let me add a suggestion (a bit too long for a comment): sort the indexes instead.
int indexes[] = { 0, 1, 2, 3 };
// sort indexes <== YOUR TASK
// indexes now is { 1, 0, 2, 3 }
for (i = 0; i < 4; i++) {
printf("%f for %s\n", year2010Cases[indexes[i]], caseName[indexes[i]]);
}
When you have data like two different values that "belongs together", you don't put them in two different arrays. Instead you make a struct that can hold both values. After that you make an array of the struct. Like:
// Define a type to hold both percentage and name
typedef struct
{
float percentage;
char caseName[28];
} CaseType;
// In some function make the array
CaseType year2010Cases[4] = {
{11.2, "Respiratory Tract Infection"},
{8.9, "Diabetes Mellitus"},
{15.6, "Hyperlipidemia"},
{15.9, "Hypertensive Disease"}};
One benefit of this is that the two values that belongs together always stays together. Another benefit is that we can use standard qsort for sorting data. Like:
typedef struct
{
float percentage;
char caseName[28];
} CaseType;
// Compare function used by qsort
int compar(const void * a, const void * b)
{
CaseType* pa = (CaseType*)a;
CaseType* pb = (CaseType*)b;
if (pa->percentage > pb->percentage) return 1;
if (pa->percentage < pb->percentage) return -1;
return 0;
}
int main(void)
{
CaseType year2010Cases[4] = {
{11.2, "Respiratory Tract Infection"},
{8.9, "Diabetes Mellitus"},
{15.6, "Hyperlipidemia"},
{15.9, "Hypertensive Disease"}};
printf("Original list:\n");
for (int c = 0; c < 4; c++)
printf("%.1f - %s\n", year2010Cases[c].percentage, year2010Cases[c].caseName);
// Sort the array with a single call of qsort
qsort(year2010Cases, 4, sizeof *year2010Cases, compar);
printf("-------------------------------------\n");
printf("Sorted list:\n");
for (int c = 0; c < 4; c++)
printf("%.1f - %s\n", year2010Cases[c].percentage, year2010Cases[c].caseName);
return 0;
}
Output:
Original list:
11.2 - Respiratory Tract Infection
8.9 - Diabetes Mellitus
15.6 - Hyperlipidemia
15.9 - Hypertensive Disease
-------------------------------------
Sorted list:
8.9 - Diabetes Mellitus
11.2 - Respiratory Tract Infection
15.6 - Hyperlipidemia
15.9 - Hypertensive Disease

How to get largest number of consecutive integers in a substantially large array (spread across multiple machines)

I was asked this question in an interview. The first part was fairly simple in which I had to write a code to get maximum number of consecutive integers in an array. Following is the code that I wrote:
int count = 0, max = 0;
for(int i = 1; i < array.length; i++) {
if((array[i - 1] + 1) == array[i])) //curr is consecutive to prev
count++;
else
count = 0; //reset the counter as sequence is broken
//Keep track of maximum
if(count > max)
max = count;
}
System.out.println(max); //print the length of largest consecutive integers
The second part was follow up question on it:
How would you modify this logic to work for arrays that are stored in multiple machines?
You can implement it using the Reduce Parallel Pattern
Example in Python (sorry for bad namings):
def longest_seq(seq):
Result = namedtuple("Result", ["left", "left_n", "max_n", "right", "right_n", "is_const"])
def _longest_seq(seq):
if 1 == len(seq):
x = seq[0]
return Result(left=x, left_n=1, max_n=1, is_const=True, right=x, right_n=1)
l_res = _longest_seq(seq[0: int(len(seq) / 2)])
r_res = _longest_seq(seq[int(len(seq) / 2): len(seq)])
left_n = l_res.left_n + r_res.left_n if l_res.is_const and l_res.right == r_res.left else l_res.left_n
right_n = r_res.right_n + l_res.right_n if r_res.is_const and r_res.left == l_res.right else r_res.right_n
max_n = max(l_res.max_n, r_res.max_n, l_res.right_n + r_res.left_n if l_res.right == r_res.left else 0)
is_const = l_res.is_const and r_res.is_const and l_res.right == r_res.left
return Result(left=l_res.left,
left_n=left_n,
max_n=max_n,
right=r_res.right,
right_n=right_n,
is_const=is_const)
return _longest_seq(seq).max_n
Suppose we are distributing the whole array left to right to each machine sequentially. For example, for only two machine(machine1 and machine2), we will distribute array 0.... i to machine1 and i + 1....n to machine2. From each machine, we can return several additional information along with local maximum.
class result {
public int machineId;
public int maxSoFar; // the max value as your code
public int leftElement; // the leftmost element
public int leftLength; // number of times the leftElement appears consecutively in left
public int rightElement; // the rightmost element
public int rightLength; // number of times the rightElement appears consecutively in right
};
During merging two machine's result, for any two machine whose machineId are consecutive(e.g. 3 and 4), we can maximize like this -
return Math.max(((machine1.rightElement == machine2.leftElement) ? machine1.rightLength + machine2.leftLength : 0),
Math.max(machine1.maxSoFar, machine2.maxSoFar));

Implement Array Random Shuffle

Prelude
I am writing a grid-based random-map generator.
Currently, I want to populate a 2D array with a variety of tiles.
Problem
In the parenthesis is a more concrete example.
Here is what you are given:
2D array and its dimensions. (i.e. 3x4 grid)
Integer Random(Range) (i.e. Range: 0-11, Output: integer from 0-11)
You do NOT have a function that randomly sorts an array, unless you implement it yourself.
Number of each type of tile (i.e. Desert: 2, Lake: 4, Forrest: 6)
How do I populate this array with the given tiles?
Example
3x4 map; 6 Forrest; 4 Lake; 2 Desert...
F F L
L D F
D F F
L F L
Attempt
I do have my own implementation, however its Big-O is... infinity, I think. :)
Of course, the chances that it will never finish are slim; however, this is part of a video game and I don't want to keep the player waiting.
Postscript
I don't really care what language that it is implemented in; pseudo-code will be satisfactory.
make sure the inputs are correct (e.g. total count of tiles equals
the count of slots in the grid)
put all give tiles into a queue Q, whose length is n(in your
example, n=12)
intialize a result array R[p], p is intialized as 0
get k=random(1->n), deque Q[k] into R[p], p++
repeat step 4 until p goes to n
Things can be much more easier if you use a language that has built-in sort functions:
verify input
put given tiles into an one demension array A[n]
sort A[n] randomly
Code in C#:
int m = 3;
int n = 4; //m*n grid
int forrests = 6;
int lakes = 4;
int deserts = 2;
if (m * n != forrests + lakes + deserts)
{
//invalid input!
}
char[] tiles = new char[m * n];
for (int i = 0; i < m * n; i++)
{
if (i < forrests)
{
tiles[i] = 'F';
}
else if (i < forrests + lakes)
{
tiles[i] = 'L';
}
else
{
tiles[i] = 'D';
}
}
//preparation completed, now tiles[] looks like
//F,F,F,F,F,F,L,L,L,L,D,D
char[] output = tiles.OrderBy(t => Guid.NewGuid()).ToArray();
//output is randomly sorted from tiles
//if you really need a two-demension array
char[][] map = new char[n][];
for (int i = 0; i < n; i++)
{
map[i] = output.Skip(m * i).Take(m).ToArray();
}
This could one of the way to do it.
#include<iostream>
#include <cstdlib>
#include <map>
using namespace std;
//Map which keeps the value for each key (2,4,6)
map<int,char> alphabet;
void initMap()
{
alphabet[2] = 'D';
alphabet[4] = 'L';
alphabet[6] = 'F';
}
int main()
{
char a[3][4];
// counter variables to keep track of d,f and l
int temp,d=0,f=0,l=0;
initMap();
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
//This determines if the generated random number is already entered in the grid. If no than breaks out. If yes than again a new random number is generated and process is iterated untill the new number is found to enter
while(1)
{
temp = rand()%4;
if(temp==0)
{
temp = 2;
}
else
{
temp = temp*2;
}
if(temp ==2 && d<2)
{
d++;
break;
}
else if(temp ==4 && l<4)
{
l++;
break;
}
else if(temp ==6 && f<6)
{
f++;
break;
}
else
{
continue;
}
}
//char value for the number temp is assigned from the alphabet map
a[i][j] = alphabet.at(temp);
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
output:
D F L D
L L L F
F F F F
You can map the alphabet according the number when entering the value or accessing the value from array.

Permutations for digits represented by Phone Number

I have an interview in 2 days and I am having a very hard time finding a solutions for this question:
What I want to do is .. for any phone number .. the program should print out all the possible strings it represents. For eg.) A 2 in the number can be replaced by 'a' or 'b' or 'c', 3 by 'd' 'e' 'f' etc. In this way how many possible permutations can be formed from a given phone number.
I don't want anyone to write code for it ... a good algorithm or psuedocode would be great.
Thank you
This is the popular correspondence table:
d = { '2': "ABC",
'3': "DEF",
'4': "GHI",
'5': "JKL",
'6': "MNO",
'7': "PQRS",
'8': "TUV",
'9': "WXYZ",
}
Given this, or any other d, (executable) pseudocode to transform a string of digits into all possible strings of letters:
def digstolets(digs):
if len(digs) == 0:
yield ''
return
first, rest = digs[0], digs[1:]
if first not in d:
for x in digstolets(rest): yield first + x
return
else:
for x in d[first]:
for y in digstolets(rest): yield x + y
tweakable depending on what you want to do for characters in the input string that aren't between 2 and 9 included (this version just echoes them out!-).
For example,
print list(digstolets('1234'))
in this version emits
['1ADG', '1ADH', '1ADI', '1AEG', '1AEH', '1AEI', '1AFG', '1AFH', '1AFI',
'1BDG', '1BDH', '1BDI', '1BEG', '1BEH', '1BEI', '1BFG', '1BFH', '1BFI',
'1CDG', '1CDH', '1CDI', '1CEG', '1CEH', '1CEI', '1CFG', '1CFH', '1CFI']
Edit: the OP asks for more explanation, here's an attempt. Function digstolets (digits to letters) takes a string of digits digs and yields a sequence of strings of characters which can be letters or "non-digits". 0 and 1 count as non-digits here because they don't expand into letters, just like spaces and punctuations don't -- only digits 2 to 9 included expand to letters (three possibilities each in most cases, four in two cases, since 7 can expand to any of PQRS and 9 can expand to any of WXYZ).
First, the base case: if nothing is left (string digs is empty), the only possible result is the empty string, and that's all, this recursive call is done, finished, kaput.
If digs is non-empty it can be split into a "head", the first character, and a "tail", all the rest (0 or more characters after the first one).
The "head" either stays as it is in the output, if a non-digit; or expands to any of three or four possibilities, if a digit. In either case, the one, three, or four possible expansions of the head must be concatenated with every possible expansion of the tail -- whence, the recursive call, to get all possible expansions of the tail (so we loop over all said possible expansion of the tail, and yield each of the one, three, or four possible expansions of the head concatenated with each possible expansion of the tail). And then, once again, th-th-that's all, folks.
I don't know how to put this in terms that are any more elementary -- if the OP is still lost after THIS, I can only recommend a serious, total review of everything concerning recursion. Removing the recursion in favor of an explicitly maintained stack cannot simplify this conceptual exposition -- depending on the language involved (it would be nice to hear about what languages the OP is totally comfortable with!), recursion elimination can be an important optimization, but it's never a conceptual simplification...!-)
If asked this in an interview, I'd start by breaking the problem down. What are the problems you have to solve?
First, you need to map a number to a set of letters. Some numbers will map to different numbers of letters. So start by figuring out how to store that data. Basically you want a map of a number to a collection of letters.
Once you're there, make it easier, how would you generate all the "words" for a 1-digit number? Basically how to iterate through the collection that's mapped to a given number. And how many possibilities are there?
OK, now the next step is, you've got two numbers and want to generate all the words. How would you do this if you were just gonna do it manually? You'd start with the first letter for the first number, and the first letter for the second number. Then go to the next letter for the second number, keeping the first letter for the first, etc. Think about it as numbers (basically indices into the collections for two numbers which each map to 3 letters):
00,01,02,10,11,12,20,21,22
So how would you generate that sequence of numbers in code?
Once you can do that, translating it to code should be trivial.
Good luck!
Another version in Java.
First it selects character arrays based on each digit of the phone number. Then using recursion it generates all possible permutations.
public class PhonePermutations {
public static void main(String[] args) {
char[][] letters =
{{'0'},{'1'},{'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'}};
String n = "1234";
char[][] sel = new char[n.length()][];
for (int i = 0; i < n.length(); i++) {
int digit = Integer.parseInt("" +n.charAt(i));
sel[i] = letters[digit];
}
permutations(sel, 0, "");
}
public static void permutations(char[][] symbols, int n, String s) {
if (n == symbols.length) {
System.out.println(s);
return;
}
for (int i = 0; i < symbols[n].length; i ++) {
permutations(symbols, n+1, s + symbols[n][i]);
}
}
}
This is a counting problem, so it usually helps to find a solution for a smaller problem, then think about how it expands to your general case.
If you had a 1 digit phone number, how many possibilities would there be? What if you had 2 digits? How did you move from one to the other, and could you come up with a way to solve it for n digits?
Here's what I came up with:
import java.util.*;
public class PhoneMmemonics {
/**
* Mapping between a digit and the characters it represents
*/
private static Map<Character,List<Character>> numberToCharacters = new HashMap<Character,List<Character>>();
static {
numberToCharacters.put('0',new ArrayList<Character>(Arrays.asList('0')));
numberToCharacters.put('1',new ArrayList<Character>(Arrays.asList('1')));
numberToCharacters.put('2',new ArrayList<Character>(Arrays.asList('A','B','C')));
numberToCharacters.put('3',new ArrayList<Character>(Arrays.asList('D','E','F')));
numberToCharacters.put('4',new ArrayList<Character>(Arrays.asList('G','H','I')));
numberToCharacters.put('5',new ArrayList<Character>(Arrays.asList('J','K','L')));
numberToCharacters.put('6',new ArrayList<Character>(Arrays.asList('M','N','O')));
numberToCharacters.put('7',new ArrayList<Character>(Arrays.asList('P','Q','R')));
numberToCharacters.put('8',new ArrayList<Character>(Arrays.asList('T','U','V')));
numberToCharacters.put('9',new ArrayList<Character>(Arrays.asList('W','X','Y','Z')));
}
/**
* Generates a list of all the mmemonics that can exists for the number
* #param phoneNumber
* #return
*/
public static List<String> getMmemonics(int phoneNumber) {
// prepare results
StringBuilder stringBuffer = new StringBuilder();
List<String> results = new ArrayList<String>();
// generate all the mmenonics
generateMmemonics(Integer.toString(phoneNumber), stringBuffer, results);
// return results
return results;
}
/**
* Recursive helper method to generate all mmemonics
*
* #param partialPhoneNumber Numbers in the phone number that haven't converted to characters yet
* #param partialMmemonic The partial word that we have come up with so far
* #param results total list of all results of complete mmemonics
*/
private static void generateMmemonics(String partialPhoneNumber, StringBuilder partialMmemonic, List<String> results) {
// are we there yet?
if (partialPhoneNumber.length() == 0) {
//Printing the pnemmonics
//System.out.println(partialMmemonic.toString());
// base case: so add the mmemonic is complete
results.add(partialMmemonic.toString());
return;
}
// prepare variables for recursion
int currentPartialLength = partialMmemonic.length();
char firstNumber = partialPhoneNumber.charAt(0);
String remainingNumbers = partialPhoneNumber.substring(1);
// for each character that the single number represents
for(Character singleCharacter : numberToCharacters.get(firstNumber)) {
// append single character to our partial mmemonic so far
// and recurse down with the remaining characters
partialMmemonic.setLength(currentPartialLength);
generateMmemonics(remainingNumbers, partialMmemonic.append(singleCharacter), results);
}
}
}
Use recursion and a good data structure to hold the possible characters. Since we are talking numbers, an array of array would work.
char[][] toChar = {{'0'}, {'1'}, {'2', 'A', 'B', 'C'}, ..., {'9', 'W', 'X'. 'Y'} };
Notice that the ith array in this array of arrays holds the characters corresponding to the ith button on the telephone. I.e., tochar[2][0] is '2', tochar[2][1] is 'A', etc.
The recursive function will take index as a parameter. It will have a for loop that iterates through the replacement chars, replacing the char at that index with one from the array. If the length equals the length of the input string, then it outputs the string.
In Java or C#, you would want to use a string buffer to hold the changing string.
function recur(index)
if (index == input.length) output stringbuffer
else
for (i = 0; i < tochar[input[index]].length; i++)
stringbuffer[index] = tochar[input[index]][i]
recur(index + 1)
A question that comes to my mind is the question of what should 0 and 1 become in such a system? Otherwise, what you have is something where you could basically just recursively go through the letters for each value in the 2-9 range for the simple brute force way to churn out all the values.
Assuming normal phone number length within North America and ignoring special area codes initially there is also the question of how many digits represent 4 values instead of 3 as 7 and 9 tend to get those often unused letters Q and Z, because the count could range from 3^10 = 59,049 to 4^10 = 1,048,576. The latter is 1024 squared, I just noticed.
The OP seems to be asking for an implementation as he is struggling to understand the pseudocode above. Perhaps this Tcl script will help:
array set d {
2 {a b c}
3 {d e f}
4 {g h i}
5 {j k l}
6 {m n o}
7 {p q r s}
8 {t u v}
9 {w x y z}
}
proc digstolets {digits} {
global d
set l [list]
if {[string length $digits] == 0} {
return $l
}
set first [string index $digits 0]
catch {set first $d($first)}
if {[string length $digits] == 1} {
return $first
}
set res [digstolets [string range $digits 1 end]]
foreach x $first {
foreach y $res {
lappend l $x$y
}
}
return $l
}
puts [digstolets "1234"]
#include <sstream>
#include <map>
#include <vector>
map< int, string> keyMap;
void MakeCombinations( string first, string joinThis , vector<string>& eachResult )
{
if( !first.size() )
return;
int length = joinThis.length();
vector<string> result;
while( length )
{
string each;
char firstCharacter = first.at(0);
each = firstCharacter;
each += joinThis[length -1];
length--;
result.push_back(each);
}
first = first.substr(1);
vector<string>::iterator begin = result.begin();
vector<string>::iterator end = result.end();
while( begin != end)
{
eachResult.push_back( *begin);
begin++;
}
return MakeCombinations( first, joinThis, eachResult);
}
void ProduceCombinations( int inNumber, vector<string>& result)
{
vector<string> inputUnits;
vector<string> finalres;
int number = inNumber;
while( number )
{
int lastdigit ;
lastdigit = number % 10;
number = number/10;
inputUnits.push_back( keyMap[lastdigit]);
}
if( inputUnits.size() == 2)
{
MakeCombinations(inputUnits[0], inputUnits[1], result);
}
else if ( inputUnits.size() > 2 )
{
MakeCombinations( inputUnits[0] , inputUnits[1], result);
vector<string>::iterator begin = inputUnits.begin();
vector<string>::iterator end = inputUnits.end();
begin += 2;
while( begin != end )
{
vector<string> intermediate = result;
vector<string>::iterator ibegin = intermediate.begin();
vector<string>::iterator iend = intermediate.end();
while( ibegin != iend)
{
MakeCombinations( *ibegin , *begin, result);
//resultbegin =
ibegin++;
}
begin++;
}
}
else
{
}
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
keyMap[1] = "";
keyMap[2] = "abc";
keyMap[3] = "def";
keyMap[4] = "ghi";
keyMap[5] = "jkl";
keyMap[6] = "mno";
keyMap[7] = "pqrs";
keyMap[8] = "tuv";
keyMap[9] = "wxyz";
keyMap[0] = "";
string inputStr;
getline(cin, inputStr);
int number = 0;
int length = inputStr.length();
int tens = 1;
while( length )
{
number += tens*(inputStr[length -1] - '0');
length--;
tens *= 10;
}
vector<string> r;
ProduceCombinations(number, r);
cout << "[" ;
vector<string>::iterator begin = r.begin();
vector<string>::iterator end = r.end();
while ( begin != end)
{
cout << *begin << "," ;
begin++;
}
cout << "]" ;
return 0;
}
C program:
char *str[] = {"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz"};
const char number[]="2061234569";
char printstr[15];
int len;
printph(int index)
{
int i;
int n;
if (index == len)
{
printf("\n");
printstr[len] = '\0';
printf("%s\n", printstr);
return;
}
n =number[index] - '0';
for(i = 0; i < strlen(str[n]); i++)
{
printstr[index] = str[n][i];
printph(index +1);
}
}
Call
printph(0);

Resources