Find Maximum sum in a path in a 2D matrix with positive integers - optimization

I would like to know where I can read about algorithms for solving this problem efficiently:
Four directions allowed: up, down, left, right
Cells containing zero can't be visited.
Visiting the same cell twice is illegal.
Moves wraps around the edges:
(first row is connected with last row)
(first col is connected with last col)
Example, 5x5 and 5 steps:
9 1 3 1 9
6 3 2 4 1
0 7 * 7 7
5 4 9 4 9
7 9 1 5 5
Starting point: *
Solution: down,left,down,left,down. That is 9 + 4 + 9 + 7 + 9 = 38
[9] 1 3 1 9
6 3 2 4 1
0 7 * 7 7
5 [4][9] 4 9
[7][9] 1 5 5
This problem is probably not related to:
Finding the maximum sub matrix
Dynamic programming

You specified in comments that you wanted a sub-second way of finding the best value 20-step path out of a 5x5 matrix. I've implemented a basic recursive search tree that does this. Ultimately, the difficulty of this is still O(3^k), but highly saturated cases like yours (21 out of 24 allowed nodes visited) will solve much faster because the problem simplifies to "skip the n*n-z-k-1 lowest value cells" (in this case, n=5, z=1 and k+1 = 21; the winning path skips three 1's).
The problem instance in your question solves in 0.231seconds on a 3 year old i5 laptop and about half a second on ideone.com. I've provided code here http://ideone.com/5kOyxq (note that 'up' and 'down' are reversed because of the way I input the data).
For less saturated problems you may need to add a Bound/Cut method. You can generate a Bound as follows:
First, run over the NxN matrix and collect the K highest value elements (can be done in N² log K) and sort them by max-first. Then, cumulatively calculate the value UB[t] = SUM[i::0->t] SortedElements[i]. So, any t-length path has a UB of UB[t] (max t elements).
At step T, the current Branch's UB is UB[t]. If ValueSoFar[T] + UB[K-T] <= BestPathValue, you can stop that branch.
There may be better ways, but this should be sufficient for reasonably sized matrices and path lengths.

Game or puzzle. Given a matrix, number of steps and a sum, find the path.
Would be nice if there is a real world application for this, but i haven't found it.
Games tend to "burn in" knowledge in young brains, so why not burn in something useful, like addition?

#include<iostream>
#include<climits>
#define R 3
#define C 3
int MAX(int x, int y, int z);
int Max_Cost(int cost[R][C], int m, int n)
{
if (n < 0 || m < 0)
return INT_MIN;
else if (m == 0 && n == 0)
return cost[m][n];
else
return cost[m][n] + MIN( Max_Cost(cost, m-1, n-1),
Max_Cost(cost, m-1, n),
Max_Cost(cost, m, n-1)
);
}
int MAX(int x, int y, int z)
{
return max(max(x, y), z);
}
int main()
{
int cost[R][C] = { {3, 2, 5},
{5, 8, 2},
{9, 7, 1}
};
cout<<Max_Cost(cost, 2, 1);
return 0;
}

Related

Euler Project 401 at Maxima

Statement of the problem:
The divisors of 6 are 1,2,3 and 6. The sum of the squares of these numbers is:
1 + 4 + 9 + 9 + 36 = 50
Allow sigma2(n) to represent the sum of the squares of the n-dividers.
Thus, sigma2(6) = 50.
And addition_sigma2 (n) is the sum of all sigma2, smaller than or equal to n. For example,
addition_sigma2(6) = 113
This is what I have programmed in Maxima:
sigma2(n) :=
divsum(n,2)$
addition_sigma2(n) :=
lreduce("+", makelist(sigma2(k), k, 1, n))$
But, it's very inefficient. Well, I need to calculate addition_sigma2(10^17) and my algorithm is not able to calculate it. Can you think of any improvements?

Prolog: how to optimize this code(Solving 123456789=100 puzzle)

So there was a puzzle:
This equation is incomplete: 1 2 3 4 5 6 7 8 9 = 100. One way to make
it accurate is by adding seven plus and minus signs, like so: 1 + 2 +
3 – 4 + 5 + 6 + 78 + 9 = 100.
How can you do it using only 3 plus or minus signs?
I'm quite new to Prolog, solved the puzzle, but i wonder how to optimize it
makeInt(S,F,FinInt):-
getInt(S,F,0,FinInt).
getInt(Start, Finish, Acc, FinInt):-
0 =< Finish - Start,
NewAcc is Acc*10 + Start,
NewStart is Start +1,
getInt(NewStart, Finish, NewAcc, FinInt).
getInt(Start, Finish, A, A):-
0 > Finish - Start.
itCounts(X,Y,Z,Q):-
member(XLastDigit,[1,2,3,4,5,6]),
FromY is XLastDigit+1,
numlist(FromY, 7, ListYLastDigit),
member(YLastDigit, ListYLastDigit),
FromZ is YLastDigit+1,
numlist(FromZ, 8, ListZLastDigit),
member(ZLastDigit,ListZLastDigit),
FromQ is ZLastDigit+1,
member(YSign,[-1,1]),
member(ZSign,[-1,1]),
member(QSign,[-1,1]),
0 is XLastDigit + YSign*YLastDigit + ZSign*ZLastDigit + QSign*9,
makeInt(1, XLastDigit, FirstNumber),
makeInt(FromY, YLastDigit, SecondNumber),
makeInt(FromZ, ZLastDigit, ThirdNumber),
makeInt(FromQ, 9, FourthNumber),
X is FirstNumber,
Y is YSign*SecondNumber,
Z is ZSign*ThirdNumber,
Q is QSign*FourthNumber,
100 =:= X + Y + Z + Q.
Not sure this stands for an optimization. The code is just shorter:
sum_123456789_eq_100_with_3_sum_or_sub(L) :-
append([G1,G2,G3,G4], [0'1,0'2,0'3,0'4,0'5,0'6,0'7,0'8,0'9]),
maplist([X]>>(length(X,N), N>0), [G1,G2,G3,G4]),
maplist([G,F]>>(member(Op, [0'+,0'-]),F=[Op|G]), [G2,G3,G4], [F2,F3,F4]),
append([G1,F2,F3,F4], L),
read_term_from_codes(L, T, []),
100 is T.
It took me a while, but I got what your code is doing. It's something like this:
itCounts(X,Y,Z,Q) :- % generate X, Y, Z, and Q s.t. X+Y+Z+Q=100, etc.
generate X as a list of digits
do the same for Y, Z, and Q
pick the signs for Y, Z, and Q
convert all those lists of digits into numbers
verify that, with the signs, they add to 100.
The inefficiency here is that the testing is all done at the last minute. You can improve the efficiency if you can throw out some possible solutions as soon as you pick one of your numbers, that is, testing earlier.
itCounts(X,Y,Z,Q) :- % generate X, Y, Z, and Q s.t. X+Y+Z+Q=100, etc.
generate X as a list of digits, and convert it to a number
if it's so big or small the rest can't possibly bring the sum back to 100, fail
generate Y as a list of digits, convert to number, and pick it sign
if it's so big or so small the rest can't possibly bring the sum to 100, fail
do the same for Z
do the same for Q
Your function is running pretty fast already, even if I search all possible solutions. It only picks 6 X's; 42 Y's; 224 Z's; and 15 Q's. I don't think optimizing will be worth your while.
But if you really wanted to: I tested this by putting a testing function immediately after selecting an X. It reduced the 6 X's to 3 (all before finding the solution); 42 Y's to 30; 224 Z's to 184; and 15 Q's to 11. I believe we could reduce it further by testing immediately after a Y is picked, to see whether X YSign Y is already so large or small there can be no solution.
In PROLOG programs that are more computationally intensive, putting parts of the 'test' earlier in 'generate and test' algorithms can help a lot.

VB.NET doesn't round numbers correctly?

I'm testing the speed of some functions so I made a test to run the functions over and over again and I stored the results in an array. I needed them to be sorted by the size of the array I randomly generated. I generate 100 elements. Merge sort to the rescue! I used this link to get me started.
The section of code I'm focusing on:
private void mergesort(int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
which translated to VB.NET is
private sub mergesort(low as integer, high as integer)
' check if low is smaller then high, if not then the array is sorted
if (low < high)
' Get the index of the element which is in the middle
dim middle as integer = low + (high - low) / 2
' Sort the left side of the array
mergesort(low, middle)
' Sort the right side of the array
mergesort(middle + 1, high)
' Combine them both
merge(low, middle, high)
end if
end sub
Of more importance the LOC that only matters to this question is
dim middle as integer = low + (high - low) / 2
In case you wanna see how merge sort is gonna run this baby
high low high low
100 0 10 0
50 0 6 4
25 0 5 4
12 0 12 7
6 0 10 7
3 0 8 7
2 0 :stackoverflow error:
The error comes from the fact 7 + (8 - 7) / 2 = 8. You'll see 7 and 8 get passed in to mergesort(low, middle) and then we infinite loop. Now earlier in the sort you see a comparison like this again. At 5 and 4. 4 + (5 - 4) / 2 = 4. So essentially for 5 and 4 it becomes 4 + (1) / 2 = 4.5 = 4. For 8 and 7 though it's 7 + (1) / 2 = 7.5 = 8. Remember the numbers are typecasted to an int.
Maybe I'm just using a bad implementation of it or my typecasting is wrong, but my question is: Shouldn't this be a red flag signaling something isn't right with the rounding that's occuring?
Without understanding the whole algorithm, note that VB.NET / is different than C# /. The latter has integer division by default, if you want to truncate decimal places also in VB.NET you have to use \.
Read: \ Operator
So i think that this is what you want:
Dim middle as Int32 = low + (high - low) \ 2
You are correct in your diagnosis: there's something inconsistent with the rounding that's occurring, but this is entirely expected if you know where to look.
From the VB.NET documentation on the / operator:
Divides two numbers and returns a floating-point result.
This documentation explicitly states that , if x and y are integral types, x / y returns a Double. So, 5 / 2 in VB.NET would be expected to be 2.5.
From the C# documentation on the / operator:
All numeric types have predefined division operators.
And further down the page:
When you divide two integers, the result is always an integer.
In the case of C#, if x and y are integers, x / y returns an integer (rounded down). 5 / 2 in C# is expected to return 2.

What does a percentage sign (%) do mathematically in Objective C?

I am super confused what the percentage sign does in Objective C. Can someone explain to me in language that an average idiot like myself can understand?! Thanks.
% is the modulo operator, so for example 10 % 3 would result in 1.
If you have some numbers a and b, a % b gives you just the remainder of a divided by b.
So in the example 10 % 3, 10 divided by 3 is 3 with remainder 1, so the answer is 1.
If there is no remainder to a divided by b, the answer is zero, so for example, 4 % 2 = 0.
Here's a relevant SO question about modular arithmetic.
Same as what it does in C, it's "modulo" (also known as integer remainder).
% is the modulo operator. It returns the remainder of <number> / <number>. For example:
5 % 2
means 5 / 2, which equals 2 with a remainder of 1, so, 1 is the value that is returned. Here's some more examples:
3 % 3 == 0 //remainder of 3/3 is 0
6 % 3 == 0 //remainder of 6/3 is 0
5 % 3 == 2 //remainder of 5/3 is 2
15 % 4 == 3 //remainder of 15/4 is 3
99 % 30 == 9 //remainder of 99/30 is 9
The definition of modulo is:
mod·u·lo
(in number theory) with respect to or using a modulus of a specified number. Two numbers are congruent modulo a given number if they give the same remainder when divided by that number.
In Mathematics, The Percentage Sign %, Called Modulo (Or Sometimes The Remainder Operator) Is A Operator Which Will Find The Remainder Of Two Numbers x And y. Mathematically Speaking, If x/y = {(z, r) : y * z + r = x}, Where All x, y, and z Are All Integers, Then
x % y = {r: ∃z: x/y = (z, r)}. So, For Example, 10 % 3 = 1.
Some Theorems And Properties About Modulo
If x < y, Then x % y = x
x % 1 = 0
x % x = 0
If n < x, Then (x + n) % x = n
x Is Even If And Only If x % 2 = 0
x Is Odd If And Only If x % 2 = 1
And Much More!
Now, One Might Ask: How Do We Find x % y? Well, Here's A Fairly Simple Way:
Do Long Division. I Could Explain How To Do It, But Instead, Here's A Link To A Page Which Explains Long Division: https://www.mathsisfun.com/numbers/long-division-index.html
Stop At Fractions. Once We Reach The Part Where We Would Normally Write The Answer As A Fraction, We Should Stop. So, For Example, 101/2 Would Be 50.5, But, As We Said, We Would Stop At The Fractions, So Our Answer Ends Up Being 50.
Output What's Left As The Answer. Here's An Example: 103/3. First, Do Long Division. 103 - 90 = 13. 13 - 12 = 1. Now, As We Said, We Stop At The Fractions. So Instead Of Continuing The Process And Getting The Answer 34.3333333..., We Get 34. And Finally, We Output The Remainder, In This Case, 1.
NOTE: Some Mathematicians Write x mod y Instead Of x % y, But Most Programming Languages Only Understand %.

Divide int into 2 other int

I need to divide one int into 2 other int's. the first int is not constant so one problem would be, what to do with odd numbers because I only want whole numbers. For example, if int = 5, then int(2) will = 2 and int(3) will = 3. Any help will greatly be appreciated.
Supposing you want to express x = a + b, where a and b are as close to x/2 as possible:
a = ceiling(x / 2.0);
b = floor(x / 2.0);
That's pseudo code, you have to find out the actual functions for floor and ceiling from your library. Make sure the division is performed as floating point numbers.
As pure integers:
a = x / 2 + (x % 2 == 0 ? 0 : 1);
b = x / 2
(This may be a bit fishy for negative numbers, because it'll depend on the behaviour of division and modulo for negative numbers.)
You can try ceil and floor functions from math to produce results like 2 and 3 for odd inputs;
int(2)=ceil(int/2); //will produce 3 for input 5
int(3)=floor(int/2); //will produce 2 for input 5
Well my answer is not in Objective-C but i guess you could translate this easily.
My idea is:
part1 = source_number div 2
part2 = source_number div 2 + (source_number mod 2)
This way the second number will be bigger if the starting number is an odd number.