In attempt to understand recursion better, I tried to print some output within my code so that I could study the steps.
#include <tuple>
#include <string>
#include <iostream>
#include <map>
#include "print.h"
std::tuple<int, int, int> find_max_crossing_subarray(int A[], int low, int mid, int high)
{
int max_left, max_right;
int left_sum = std::numeric_limits<int>::min();
int sum = 0;
for(int i = mid; i >= low; i--) {
sum += A[i];
if(sum > left_sum) {
left_sum = sum;
max_left = i;
}
}
int right_sum = std::numeric_limits<int>::min();
sum = 0;
for(int j = mid + 1; j <= high; j++) {
sum += A[j];
if(sum > right_sum) {
right_sum = sum;
max_right = j;
}
}
return std::make_tuple(max_left, max_right, left_sum + right_sum);
}
std::tuple<int, int, int> find_max_subarray(int A[], int low, int high)
{
if(high == low) {
return std::make_tuple(low, high, A[low]);
}
else {
int mid = (high + low) / 2;
std::tuple<int, int, int> left(find_max_subarray(A, low, mid));
std::cout << "left: ";
print(left);
int left_low, left_high, left_sum;
std::tie(left_low, left_high, left_sum) = left;
std::tuple<int, int, int> right(find_max_subarray(A, mid + 1, high));
std::cout << "right: ";
print(right);
int right_low, right_high, right_sum;
std::tie(right_low, right_high, right_sum) = right;
std::tuple<int, int, int> cross(find_max_crossing_subarray(A, low, mid, high));
std::cout << "cross: ";
print(cross);
int cross_low, cross_high, cross_sum;
std::tie(cross_low, cross_high, cross_sum) = cross;
if(left_sum >= right_sum && left_sum >= cross_sum) {
return left;
}
else if(right_sum >= left_sum && right_sum >= cross_sum) {
return right;
}
else {
return cross;
}
}
}
int main()
{
int arr_3[3] = {-3, 2, 3};
int arr_4[4] = {5, -23, 1, 44};
int arr_6[6] = {5, -23, 1, 44, -2, 5};
int arr[16] = {-23, 3, 9 ,7, -12, 87, -25, 2, 3, 5, 32, -8, 6, -82, 3, 9};
print(arr_4, 4);
std::tuple<int, int, int> maple(find_max_subarray(arr_4, 0, 3));
print(maple);
return 0;
}
OUTPUT::
5 -23 1 44
left: 0 0 5
right: 1 1 -23
cross: 0 1 -18
left: 0 0 5
left: 2 2 1
right: 3 3 44
cross: 2 3 45
right: 2 3 45
cross: 0 3 27
2 3 45
I understand the first three lines of the output (that is, where the left, right, cross begin). But I do not understand where the fourth line and beyond come from. I tried tracing back the functions and I keep thinking I should get left: 1 1 -23 in my fourth line of output after cross: 0 1 -18.
EDIT:
I should point out that after left: 2 2 1, although it's hard to visualize, I understand somewhat. The recursion has reached the end and the code is just cascading backwards.
SECOND EDIT:
I guess what is happening in the fourth line is that the very first find_max_subarray is completing and it is returning the first if statement in the function code. Now it is moving to the second find_max_subarray.
THIRD EDIT:
I guess my confusion is that the code doesn't cascade backwards but instead just returns to the very first call after it reaches the end of the recursion.
FOURTH EDIT:
When I go out to six elements though it seems like it doesn't simply return to the first call.
5 -23 1 44 -2 5
left: 0 0 5
right: 1 1 -23
cross: 0 1 -18
left: 0 0 5
right: 2 2 1
cross: 0 2 -17
left: 0 0 5
left: 3 3 44
right: 4 4 -2
cross: 3 4 42
left: 3 3 44
right: 5 5 5
cross: 3 5 47
right: 3 5 47
cross: 2 5 48
2 5 48
I mean I guess it's because the sub array has three elements as opposed to two. So there are two pairs as opposed to one. It makes sense when you take it for granted but can't see it visually.
LAST EDIT:
So when I go out to 8, it goes in pairs. First two elements and then return the original call. The next two pairs and return the call. I'm not exactly sure why though in the odd case it won't return the call until both the first and second and first and third pairs have completed.
5 -23 1 44 -2 5 6 -3
left: 0 0 5
right: 1 1 -23
cross: 0 1 -18
left: 0 0 5
left: 2 2 1
right: 3 3 44
cross: 2 3 45
right: 2 3 45
cross: 0 3 27
left: 2 3 45
left: 4 4 -2
right: 5 5 5
cross: 4 5 3
left: 5 5 5
left: 6 6 6
right: 7 7 -3
cross: 6 7 3
right: 6 6 6
cross: 5 6 11
right: 5 6 11
cross: 2 6 54
2 6 54
PROBLEM SOLVED:
The problem I was having in understanding the recursion is that for each recursive step I was using the original high value. I actually wrote it down on paper in blocks using the correct high and everything came together.
As stated above in my problem solved section following the last edit, I realized that in my analysis I was using the wrong value for high. I was not seeing this because although I was using blocks I was going in blocks of sequences and not blocks of blocks.
I went block by block with the updated high for each sub-block. I posted the illustration below. And this agrees with the output I was getting. The return statement accompanies each block.
Four element case:
(0,3)
(0,1)
(0,0) -> left
(1,1) -> right
-> cross
return left
(2,3)
(2,2) -> left
(3,3) -> right
-> cross
return right
return cross
Five element case:
(0,4)
(0,2)
(0,1)
(0,0) -> left
(1,1) -> right
-> cross
return left
(2,2) -> right
-> cross
return left
(3,4)
(3,3) -> left
(4,4) -> right
-> cross
return right
return cross
Related
Hello Friends, I was trying to make Triplet form of a sparse matrix using pointers and DMA but the output in first row is returning garbage values can anyone help me in resolving this issue.
int main(){
int k=0,z=0,arr[6][6]={
{15,0,0,22,0,-15},
{0,11,3,0,0,0},
{0,0,0,-6,0,0},
{0,0,0,0,0,0},
{91,0,0,0,0,0},
{0,0,28,0,0,0}
};
int **trip=new int *[3];
for(int i=0;i<6;i++){
for(int j=0;j<6;j++){
if (arr[i][j]==0){
z++;
}
else{
trip[k]=new int(1);
trip[k][0]=i;
trip[k][1]=j;
trip[k][2]=arr[i][j];
k++;
}
}
}
}
Output-
-65511600 22028 -65511568
0 3 22
0 5 -15
1 1 11
1 2 3
2 3 -6
4 0 91
5 2 28
Expected Output
0 0 15
0 3 22
0 5 -15
1 1 11
1 2 3
2 3 -6
4 0 91
5 2 28
A number is called a stepping number if all adjacent digits in the number have an absolute difference of 1.
Examples of stepping numbers :- 0,1,2,3,4,5,6,7,8,9,10,12,21,23,...
I have to generate stepping numbers upto a given number N. The numbers generated should be in order.
I used the simple method of moving over all the numbers upto N and checking if it is stepping number or not. My teacher told me it is brute force and will take more time. Now, I have to optimize my approach.
Any suggestions.
Stepping numbers can be generated using Breadth First Search like approach.
Example to find all the stepping numbers from 0 to N
-> 0 is a stepping Number and it is in the range
so display it.
-> 1 is a Stepping Number, find neighbors of 1 i.e.,
10 and 12 and push them into the queue
How to get 10 and 12?
Here U is 1 and last Digit is also 1
V = 10 + 0 = 10 ( Adding lastDigit - 1 )
V = 10 + 2 = 12 ( Adding lastDigit + 1 )
Then do the same for 10 and 12 this will result into
101, 123, 121 but these Numbers are out of range.
Now any number transformed from 10 and 12 will result
into a number greater than 21 so no need to explore
their neighbors.
-> 2 is a Stepping Number, find neighbors of 2 i.e.
21, 23.
-> generate stepping numbers till N.
The other stepping numbers will be 3, 4, 5, 6, 7, 8, 9.
C++ code to do generate stepping numbers in a given range:
#include<bits/stdc++.h>
using namespace std;
// Prints all stepping numbers reachable from num
// and in range [n, m]
void bfs(int n, int m)
{
// Queue will contain all the stepping Numbers
queue<int> q;
for (int i = 0 ; i <= 9 ; i++)
q.push(i);
while (!q.empty())
{
// Get the front element and pop from the queue
int stepNum = q.front();
q.pop();
// If the Stepping Number is in the range
// [n, m] then display
if (stepNum <= m && stepNum >= n)
cout << stepNum << " ";
// If Stepping Number is 0 or greater than m,
// need to explore the neighbors
if (stepNum == 0 || stepNum > m)
continue;
// Get the last digit of the currently visited
// Stepping Number
int lastDigit = stepNum % 10;
// There can be 2 cases either digit to be
// appended is lastDigit + 1 or lastDigit - 1
int stepNumA = stepNum * 10 + (lastDigit- 1);
int stepNumB = stepNum * 10 + (lastDigit + 1);
// If lastDigit is 0 then only possible digit
// after 0 can be 1 for a Stepping Number
if (lastDigit == 0)
q.push(stepNumB);
//If lastDigit is 9 then only possible
//digit after 9 can be 8 for a Stepping
//Number
else if (lastDigit == 9)
q.push(stepNumA);
else
{
q.push(stepNumA);
q.push(stepNumB);
}
}
}
//Driver program to test above function
int main()
{
int n = 0, m = 99;
// Display Stepping Numbers in the
// range [n,m]
bfs(n,m);
return 0;
}
Visit this link.
The mentioned link has both BFS and DFS approach.
It will provide you with explaination and code in different languages for the above problem.
We also can use simple rules to move to the next stepping number and generate them in order to avoid storing "parents".
C.f. OEIS sequence
#include <iostream>
int next_stepping(int n) {
int left = n / 10;
if (left == 0)
return (n + 1); // 6=>7
int last = n % 10;
int leftlast = left % 10;
if (leftlast - last == 1 & last < 8)
return (n + 2); // 32=>34
int nxt = next_stepping(left);
int nxtlast = nxt % 10;
if (nxtlast == 0)
return (nxt * 10 + 1); // to get 101
return (nxt * 10 + nxtlast - 1); //to get 121
}
int main()
{
int t = 0;
for (int i = 1; i < 126; i++, t = next_stepping(t)) {
std::cout << t << "\t";
if (i % 10 == 0)
std::cout << "\n";
}
}
0 1 2 3 4 5 6 7 8 9
10 12 21 23 32 34 43 45 54 56
65 67 76 78 87 89 98 101 121 123
210 212 232 234 321 323 343 345 432 434
454 456 543 545 565 567 654 656 676 678
765 767 787 789 876 878 898 987 989 1010
1012 1210 1212 1232 1234 2101 2121 2123 2321 2323
2343 2345 3210 3212 3232 3234 3432 3434 3454 3456
4321 4323 4343 4345 4543 4545 4565 4567 5432 5434
5454 5456 5654 5656 5676 5678 6543 6545 6565 6567
6765 6767 6787 6789 7654 7656 7676 7678 7876 7878
7898 8765 8767 8787 8789 8987 8989 9876 9878 9898
10101 10121 10123 12101 12121
def steppingNumbers(self, n, m):
def _solve(v):
if v>m: return 0
ans = 1 if n<=v<=m else 0
last = v%10
if last > 0: ans += _solve(v*10 + last-1)
if last < 9: ans += _solve(v*10 + last+1)
return ans
ans = 0 if n>0 else 1
for i in range(1, 10):
ans += _solve(i)
return ans
I wrote an implementation of the following tutorial: LINK
Basically, since C/C++ does not have BIG Integer we are storing the factorial decimal values in an array. This is equivalent to writing a multiplication that performs the multiplication kids are taught at schools.
Problem: It works fine for values up to 17! after that (18!, 19!,... ) it does not output correct values.
#include <iostream>
using namespace std;
int main(){
int fact[1000]={1};
int n; scanf("%d", &n); //n are the number of factorials we will calculate
while(n--){
int number; scanf("%d", &number); //scan the number
if(number == 0) printf("%d", 1);
int flag = number;
int index = 0, length = 0;
//following lines we find the length of the entered number
while(flag!=0){
fact[index] = flag%10;
flag /= 10;
index++; length++;
}
//following lines are the multiplication code
while(number>1){
index = 0;
int temp = 0;
number--;
for(index = 0; index<length; index++){
int x = (fact[index] * number) + temp;
fact[index] = x%10;
temp = x/10;
}
//here we append the carry over left from multiplication
while(temp){
fact[index] = temp%10;
temp /= 10;
length++;
}
}
//print the array from most to least significant digit
for(int i = length-1; i>=0; i--){
printf("%d", fact[i]);
}
printf("\n");
}
return 0;
}
For a start, you need to be very careful with:
long long int x = (fact[index] * number) + temp;
Since fact[], number and temp are all int types, the calculation will be done as an int and only widened to a long long when placing the value into x.
You would be better off with:
long long x = fact[index];
x *= number;
x += temp;
That way, it becomes a long long early enough that the calculations will be done with that type.
However, that doesn't actually fix your problem, so let's modify your code a little to see where the problem lies:
#include <iostream>
using namespace std;
int main(){
int fact[1000]={1};
int n = 18, numberx = 0;
while(n-- > 0){
int number = ++numberx;
if(number == 0) { printf("%d", 1); continue; }
int flag = number;
int index = 0, length = 0;
//following lines we find the length of the entered number
while(flag!=0){
fact[index] = flag%10;
flag /= 10;
index++; length++;
}
//following lines are the multiplication code
while(number>1){
index = 0;
int temp = 0;
number--;
for(index = 0; index<length; index++){
long long int x = fact[index];
x *= number;
x += temp;
fact[index] = x%10;
temp = x/10;
}
//here we append the carry over left from multiplication
while(temp){
fact[index] = temp%10;
temp /= 10;
length++;
}
}
//print the array from most to least significant digit
printf("%d! = ", number);
for(int i = length-1; i>=0; i--){
printf("%d ", fact[i]);
}
printf("\n");
}
return 0;
}
Running this gives you:
1! = 1
2! = 2
3! = 6
4! = 2 4
5! = 1 2 0
6! = 7 2 0
7! = 5 0 4 0
8! = 4 0 3 2 0
9! = 3 6 2 8 8 0
10! = 3 6 2 8 8 0 0
11! = 3 9 9 1 6 8 0 0
12! = 4 7 9 0 0 1 6 0 0
13! = 6 2 2 7 0 2 0 8 0 0
14! = 8 7 1 7 8 2 9 1 2 0 0
15! = 1 3 0 7 6 7 4 3 6 8 0 0 0
16! = 2 0 9 2 2 7 8 9 8 8 8 0 0 0
17! = 3 5 5 6 8 7 4 2 8 0 9 6 0 0 0
18! = 1 9 9 1 0 4 7 1 7 3 8 5 7 2 8 0 0 0
which is, as you state okay up until 18!, where if fails. And, in fact, you can see the ratio between 17! and 18! is about 500 rather than 18 so that's where we should look.
Let's first strip out the extraneous stuff by starting at 17!. That can be done simply by changing a couple of starting values:
int n = 2, numberx = 16;
and that gives:
17! = 3 5 5 6 8 7 4 2 8 0 9 6 0 0 0
18! = 1 9 9 1 0 4 7 1 7 3 8 5 7 2 8 0 0 0
Then we can add debug code to see what's happening, outputting temporary results along the way. The main loop can become:
while(number>1){
index = 0;
int temp = 0;
number--;
if (numberx > 17) printf("\n");
for(index = 0; index<length; index++){
if (numberx > 17) printf("index %d fact[] %d number %d temp %d", index, fact[index], number, temp);
long long int x = fact[index];
x *= number;
x += temp;
fact[index] = x%10;
temp = x/10;
if (numberx > 17) printf(" -> fact[] %d temp %d\n", fact[index], temp);
}
//here we append the carry over left from multiplication
while(temp){
fact[index] = temp%10;
temp /= 10;
length++;
}
if (numberx > 17) {
printf("temp: ");
for(int i = length-1; i>=0; i--){
printf("%d ", fact[i]);
}
printf("\n");
}
}
This shows you *exactly where things start to go wrong (// bits are added by me):
17! = 3 5 5 6 8 7 4 2 8 0 9 6 0 0 0
index 0 fact[] 8 number 17 temp 0 -> fact[] 6 temp 13
index 1 fact[] 1 number 17 temp 13 -> fact[] 0 temp 3
temp: 3 0 6 // okay: 18 * 17 = 306
index 0 fact[] 6 number 16 temp 0 -> fact[] 6 temp 9
index 1 fact[] 0 number 16 temp 9 -> fact[] 9 temp 0
index 2 fact[] 3 number 16 temp 0 -> fact[] 8 temp 4
temp: 4 8 9 6 // okay 306 * 16 = 4896
index 0 fact[] 6 number 15 temp 0 -> fact[] 0 temp 9
index 1 fact[] 9 number 15 temp 9 -> fact[] 4 temp 14
index 2 fact[] 8 number 15 temp 14 -> fact[] 4 temp 13
index 3 fact[] 4 number 15 temp 13 -> fact[] 3 temp 7
temp: 7 3 4 4 0 // okay 4896 * 15 = 73440
index 0 fact[] 0 number 14 temp 0 -> fact[] 0 temp 0
index 1 fact[] 4 number 14 temp 0 -> fact[] 6 temp 5
index 2 fact[] 4 number 14 temp 5 -> fact[] 1 temp 6
index 3 fact[] 3 number 14 temp 6 -> fact[] 8 temp 4
index 4 fact[] 7 number 14 temp 4 -> fact[] 2 temp 10
temp: 8 1 2 8 1 6 0 // no good: 73440 * 14 = 10128160 !!!
1 0 2 8 1 6 0 // is what it should be
With a bit of thought, it appears to be the point where the final "carry" from the multiplication is greater than nine, meaning it's almost certainly in the code for handling that:
while(temp){
fact[index] = temp%10;
temp /= 10;
length++;
}
Thinking about that (and comparing it to other code that changes index and length together), it becomes obvious - even though you increase the length of the array, you're not increasing the index. That means, for a final carry of ten or more, the subsequent carry will not populate the correct index, it will simply overwrite the same index each time.
This can be seen here:
temp: 8 1 2 8 1 6 0 // no good: 73440 * 14 = 10128160 !!!
1 0 2 8 1 6 0 // is what it should be
where it will have placed the zero (10 % 10) at that second location (increasing the length) but then placed the one (10 / 10) at the same index, leaving the 8 at whatever value it had before.
So, if we increment index as well, what do we see (going back to the less verbose code)?
1! = 1
2! = 2
3! = 6
4! = 2 4
5! = 1 2 0
6! = 7 2 0
7! = 5 0 4 0
8! = 4 0 3 2 0
9! = 3 6 2 8 8 0
10! = 3 6 2 8 8 0 0
11! = 3 9 9 1 6 8 0 0
12! = 4 7 9 0 0 1 6 0 0
13! = 6 2 2 7 0 2 0 8 0 0
14! = 8 7 1 7 8 2 9 1 2 0 0
15! = 1 3 0 7 6 7 4 3 6 8 0 0 0
16! = 2 0 9 2 2 7 8 9 8 8 8 0 0 0
17! = 3 5 5 6 8 7 4 2 8 0 9 6 0 0 0
18! = 6 4 0 2 3 7 3 7 0 5 7 2 8 0 0 0
19! = 1 2 1 6 4 5 1 0 0 4 0 8 8 3 2 0 0 0
20! = 2 4 3 2 9 0 2 0 0 8 1 7 6 6 4 0 0 0 0
That solves your specific problem and hopefully provides some education on debugging as well :-)
I want to loop an array then during each loop I want to loop backwards over the previous 5 elements.
So given this array
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
and this nested loop
for(int i=0;i<arr.size;i++)
{
for(int h=i-5; h<i; h++)
{
//things happen
}
}
So, if i=0, second loop would loop last few elements 4,6,2,6,5.
How could you handle this?
I'm assuming that:
You only want to go over previous values (i.e. no wrap around) You
You don't actually want arr to be a multi-dimensional array as suggested
by your choice of tags
You want to include the current i in your five values
This is just a small modification to your code that will do (what I think) you are asking:
#include <math>
int main()
{
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
for(int i=0;i<arr.size;i++)
{
for(int h = max(i-4, 0); h < i+1; h++)
{
//things happen
}
}
}
note the h = max(i-4, 0) and h < i+1This will reduce the number of iterations of the inner loop so that it starts from index 0 and loops up through the five values up to and including i. (four values and i). h will always be within bounds.
The case where i==arr.size won't be a problem in the inner loop as the outer loop will terminate before that happens (i is always within bounds).
Edit: I saw this comment:
I want the first element to consider the last final 5 elements of the array though.
in which case, your loops should look like:
for(int i=0;i<arr.size;i++)
{
for(int h=0; h<5; h++)
{
int index = (i + arr.size - h) % arr.size;
//things happen
//access array with arr[index];
}
}
This should do what you want:
When i=0, h=0 index=(0+24-0)%24 which is 0. For h=1 we go one less, index=(0+24-1)%24 = 23 and so on for the next values of h.
The code gets the last 5 values, wrapping round, inclusive of the current value. (so will get 20,21,22,23,0 when i=0, 21,22,23,0,1 when i=1)
If you want the five before, non-inclusive, then inner loop should be:
for(int h=1; h<=5; h++)
here is the current output of the loop as it stands:
i 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 ... 22 22 22 22 22 23 23 23 23 23
h 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 ... 0 1 2 3 4 0 1 2 3 4
index 0 23 22 21 20 1 0 23 22 21 2 1 0 23 22 3 2 1 0 23 ... 22 21 20 19 18 23 22 21 20 19
I assume you want it to loop around (don't know why). if so, use modulo:
int index = (h + arr.size) % arr.size;
Using the modulo operator.
for (int i = 0; i < arr.size; i++)
{
for (int h = 5; h > 0; h--)
{
const int array_length = sizeof(arr) / sizeof(arr[0]);
int index = (i - h + array_length) % array_length; // Use 'sizeof(arr) / sizeof(arr[0])' to get the size of the array
//things happen
}
}
Is using if statement not an option?
const int array_size = 24;
int arr[array_size] = { 1,3,4,5,...,2 }
for(int i=0;i<array_size;i++)
{
for(int h=i-5; h<i; h++)
{
int arr_index = (h >= 0) ? h : (array_size + h);
//do your things with arr[arr_index]
}
}
you may also start the nested loop with something like:
for(int h=i-min(i,5);h<i;++h)
{
}
which let you process first 5 cells as well. also, if you are dealing with some kind of signal or image processing consider extending arr to have 29 elements with preceding 5 zeros or whatever value would be suitable, and start the first for-loop with 5th element.
Just make an if statement in nested loop. Something like this
for( int h = i-5; h < i; h++ )
{
// do stuff
if( i == 0 )
break;
}
Hi I have a question on an existing algo problem.
Existing problem description: Generate 10-digit number using a phone keypad
1 2 3
4 5 6
7 8 9
0
Though this question has a tag of C++, consider this pseudo-code to express the algorithm (which conveniently happens to be written in ruby.)
# Where the knight can jump to
$m = {
0 => [4,6], 1 => [6,8], 2 => [7,9], 3 => [4,8], 4 => [0,3,9],
5 => [], 6 => [0,1,7], 7 => [2,6], 8 => [1,3], 9 => [2,4]
}
$cache = Hash.new
# return count
def nseq( k, n, e=0 )
e += 1 if k.even?
return 0 if 3 < e
return 1 if n == 1
key = "#{k}:#{n}:#{e}" # for the memoization
return $cache[key] if $cache.has_key? key
# Sum nseq(j,n-1,e) for j in $m[k]
return $cache[key] = $m[k].inject(0) { |sum,j| sum + nseq( j, n-1, e ) }
end
0.upto(9) do |k|
2.upto(8) do |n|
count = nseq(k,n)
puts "k=#{k},n=#{n}: #{count}"
break if count.zero?
end
end
This outputs
k=0,n=2: 2
k=0,n=3: 6
k=0,n=4: 8
k=0,n=5: 16
k=0,n=6: 0
k=1,n=2: 2
k=1,n=3: 5
k=1,n=4: 10
k=1,n=5: 24
k=1,n=6: 32
k=1,n=7: 64
k=1,n=8: 0
k=2,n=2: 2
k=2,n=3: 4
k=2,n=4: 10
k=2,n=5: 16
k=2,n=6: 32
k=2,n=7: 0
k=3,n=2: 2
k=3,n=3: 5
k=3,n=4: 10
k=3,n=5: 24
k=3,n=6: 32
k=3,n=7: 64
k=3,n=8: 0
k=4,n=2: 3
k=4,n=3: 6
k=4,n=4: 14
k=4,n=5: 16
k=4,n=6: 32
k=4,n=7: 0
k=5,n=2: 0
k=6,n=2: 3
k=6,n=3: 6
k=6,n=4: 14
k=6,n=5: 16
k=6,n=6: 32
k=6,n=7: 0
k=7,n=2: 2
k=7,n=3: 5
k=7,n=4: 10
k=7,n=5: 24
k=7,n=6: 32
k=7,n=7: 64
k=7,n=8: 0
k=8,n=2: 2
k=8,n=3: 4
k=8,n=4: 10
k=8,n=5: 16
k=8,n=6: 32
k=8,n=7: 0
k=9,n=2: 2
k=9,n=3: 5
k=9,n=4: 10
k=9,n=5: 24
k=9,n=6: 32
k=9,n=7: 64
k=9,n=8: 0
The result is the number of all n-length sequences starting on key k, which have no more than 3 even digits in them. For example, the last entry is k=9,n=8: 0. This means that all sequences of length 8 starting on key 9 include more than 3 even digits.
EDIT: Here it is translated into C++. It produces identical output as above.
#include<iostream>
#include<map>
using namespace std;
const int MAX_EVENS = 3; // Assume < 8
// Where the knight can jump to
const int jumpto[][3] = { {4,6}, // 0
{6,8}, {7,9}, {4,8}, // 1 2 3
{0,3,9}, {}, {0,1,7}, // 4 5 6
{2,6}, {1,3}, {2,4} }; // 7 8 9
const int jumpto_size[] = { 2, // 0
2, 2, 2, // 1 2 3
3, 0, 3, // 4 5 6
2, 2, 2 }; // 7 8 9
typedef map<unsigned,int> cachetype;
cachetype cache;
int nseq( int k, int n, int e=0 )
{
e += k&1^1; // increment e if k is even.
if( MAX_EVENS < e ) return 0;
if( n <= 1 ) return 1;
unsigned key = (n << 4 | k) << 3 | e; // n is left with 32-7=25 bits
cachetype::const_iterator it = cache.find(key);
if( it != cache.end() ) return it->second;
int sum = 0;
for( int i=0 ; i<jumpto_size[k] ; ++i ) sum += nseq( jumpto[k][i], n-1, e );
return cache[key] = sum;
}
int main()
{
for( int k=0 ; k<=9 ; ++k )
for( int n=2 ; n<=8 ; ++n )
{
int count = nseq(k,n);
cout << "k="<<k<<",n="<<n<<": "<<count<<endl;
if( count == 0 ) break;
}
return 0;
}