Related
I have this question:
Given a grid of positive numbers, start from 0,0 and end at n,n.
Move only to right and down.
Find path with sum of numbers is maximum.
Input Example:
5 1 2
6 7 8
1 4 9
output Example:
35
I solved it with many scenarios for example i wrote an easy equation to get the max path length then take some decisions to get the correct result.
But this example is easy to got that it should solved using dynamic programming as it's recursion and some overlaps with small space:
fn(0,0)
fn(0,1) f(1,0)
f(0,2) f(1,1) f(2,0) f(1,1)
I solved it easy using Memoization technique:
public int GetMaxPathTopDown(int r, int c, int[,] arr, int[,] mem)
{
if (r >= arr.GetLength(0) || c >= arr.GetLength(1))
{
return 0;
}
// Base Case
if (r == arr.GetLength(0) - 1 && c == arr.GetLength(1) - 1)
{
return arr[r, c];
}
if (mem[r, c] != -1)
{
return mem[r, c];
}
int firstPath = GetMaxPathTopDown(r, c + 1, arr, mem);
int secondPath = GetMaxPathTopDown(r + 1, c, arr, mem);
return mem[r, c] = arr[r, c] + Math.Max(firstPath, secondPath);
}
but I want to find standard solution to solve it using Tabulation way. I tried many solutions but i thought it's not a correct way of tabulation so any help?
#Marzouk, you can try this:
dp[i, j] will be the maximum sum you can get from (0, 0) to (i, j). Now, dp[i, j] will depend on dp[i - 1, j] and dp[i, j - 1]. So, the recurrence will be:
dp[i, j] = max(dp[i - 1, j], dp[i, j - 1]) + mt[i, j]
You need to handle corner cases here (i = 0 or j = 0).
using System;
class MainClass {
public static void Main (string[] args) {
int[,] mt = new[,] { {5, 1, 2}, {6, 7, 8}, {1, 4, 9} };
int[,] dp = new[,] { {0, 0, 0}, {0, 0, 0}, {0, 0, 0} };
int R = mt.GetLength(0);
int C = mt.GetLength(1);
for (int i = 0; i < R; i++)
for (int j = 0; j < C; j++) {
dp[i, j] = mt[i, j];
if (i > 0 && j > 0) {
dp[i, j] += Math.Max(dp[i - 1, j], dp[i, j - 1]);
} else if (i > 0) {
dp[i, j] += dp[i - 1, j];
} else if (j > 0) {
dp[i, j] += dp[i, j - 1];
}
}
Console.WriteLine(dp[R-1, C-1]);
}
}
The basic steps to build bottom-up dynamic programming solutions are as follows:
1- Determine the required set of parameters that uniquely describe the problem (the state).
2- If there are N parameters required to represent the states, prepare an N dimensional DP table, with one entry per state.
This is equivalent to the memo table in top-down DP. However, there are differences. In bottom-up DP, we only need to initialize some cells of the DP table with known initial values (the base cases). Recall that in topdown DP, we initialize the memo table completely with dummy values (usually -1) to indicate that we have not yet computed the values.
3- Now, with the base-case cells/states in the DP table already filled, determine the cells/states that can be filled next (the transitions).
Repeat this process until the DP table is complete.
For the bottom-up DP, this part is usually accomplished through iterations, using loops.
lets build a table for 3*3 array with values:
5 1 2
3 1 2
0 1 1
we notice that we need two parameters : Move_right, Move_down
initially, the first row and column should have the cumulative sum of the array elements to start maximization
then follow the steps in the attached picture which explain the code below
dp[0,0] = arr[0,0];
for (int i = 1; i < n; i++){
dp[0,i] = arr[0,i] + dp[0,i - 1];
}
for (int i = 1; i < n; i++){
dp[i,0] = arr[i,0] + dp[i-1,0];
}
for (int i = 1; i < n; i++){
for (int j = 1; j < n; j++){
dp[i,j] = arr[i,j] + Math.max(dp[i - 1,j], dp[i,j - 1]);
}
}
Console.WriteLine(dp[n - 1,n - 1]);
the required answer should be 12, and you find it in the most right-down cell
building table
I'm working on a math game in the Unity game engine using C#, specifically a reusable component to teach the grid method for multiplication. For example, when given the numbers 34 and 13, it should generate a 3X3 grid (a header column and row for the multiplier and multiplicand place values and 2X2 for the number of places in the multiplier and multiplicand). Something that looks like this:
My issue is that I don't know the best way to extract the place values of the numbers (eg 34 -> 30 and 4). I was thinking of just converting it to a string, adding 0s to the higher place values based on its index, and converting it back to an int, but this seems like a bad solution. Is there a better way of doing this?
Note: I'll pretty much only be dealing with positive whole numbers, but the number of place values might vary.
Thanks to all who answered! Thought it might be helpful to post my Unity-specific solution that I constructed with all the replies:
List<int> GetPlaceValues(int num) {
List<int> placeValues = new List<int>();
while (num > 0) {
placeValues.Add(num % 10);
num /= 10;
}
for(int i = 0;i<placeValues.Count;i++) {
placeValues[i] *= (int)Mathf.Pow(10, i);
}
placeValues.Reverse();
return placeValues;
}
Take advantage of the way our number system works. Here's a basic example:
string test = "12034";
for (int i = 0; i < test.Length; ++i) {
int digit = test[test.Length - i - 1] - '0';
digit *= (int)Math.Pow(10, i);
Console.WriteLine("digit = " + digit);
}
Basically, it reads from the rightmost digit (assuming the input is an integer), and uses the convenient place value of the way our system works to calculate the meaning of the digit.
test.Length - i - 1 treats the rightmost as 0, and indexes positive to the left of there.
- '0' converts from the encoding value for '0' to an actual digit.
Play with the code
Perhaps you want something like this (ideone):
int n = 76302;
int mul = 1;
int cnt = 0;
int res[10];
while(n) {
res[cnt++] = (n % 10) * mul;
mul*=10;
cout << res[cnt-1] << " ";
n = n / 10;
}
output
2 0 300 6000 70000
My answer is incredibly crude, and could likely be improved by someone with better maths skills:
void Main()
{
GetMulGrid(34, 13).Dump();
}
int[,] GetMulGrid(int x, int y)
{
int[] GetPlaceValues(int num)
{
var numDigits = (int)Math.Floor(Math.Log10(num) + 1);
var digits = num.ToString().ToCharArray().Select(ch => Convert.ToInt32(ch.ToString())).ToArray();
var multiplied =
digits
.Select((d, i) =>
{
if (i != (numDigits - 1) && d == 0) d = 1;
return d * (int)Math.Pow(10, (numDigits - i) - 1);
})
.ToArray();
return multiplied;
}
var xComponents = GetPlaceValues(x);
var yComponents = GetPlaceValues(y);
var arr = new int[xComponents.Length + 1, yComponents.Length + 1];
for(var row = 0; row < yComponents.Length; row++)
{
for(var col = 0; col < xComponents.Length; col++)
{
arr[row + 1,col + 1] = xComponents[col] * yComponents[row];
if (row == 0)
{
arr[0, col + 1] = xComponents[col];
}
if (col == 0)
{
arr[row + 1, 0] = yComponents[row];
}
}
}
return arr;
}
For your example of 34 x 13 it produces:
And for 304 x 132 it produces:
It spits this out as an array, so how you consume and display the results will be up to you.
For two-digit numbers you can use modulo
int n = 34;
int x = n % 10; // 4
int y = n - x; // 30
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm struggling in the making of algorithm that "shuffles" a set of numbers in such way that they are sorted in ascending order starting from 0 ,the next number must not exceed the previous one + 1, they must also have a length of 15 and every single number from the set of numbers must be included. For example if we have the numbers :
0, 1
the desired output is :
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 (yes those are 14 zeros)
0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
..
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1
same goes if the numbers were
0, 1, 2
0,0,0,0,0,0,0,0,0,0,0,0,0,1,2 (every number must be included)
I tried the following and I failed miserably :
Version 1
private static List<List<int>> GetNumbers(int lastNumber)
{
if (lastNumber == 0)
{
return new List<List<int>> { new List<int> { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
}
int[] setOfNumbers = new int[lastNumber + 1];
List<List<int>> possibleRoutes = new List<List<int>>().ToList();
for (int i = 0; i <= lastNumber; i++)
{
setOfNumbers[i] = i;
}
var temp = new List<int>();
int[] possibleRoute = new int[15];
for (int j = 0; j < size - lastNumber; j++)
{
possibleRoute[j] = 0;
}
for (int j = lastNumber; j < possibleRoute.Length; j++)
{
for (int k = j; k > 0; k--)
{
possibleRoute[k] = lastNumber - 1;
}
for (int i = size - 1; i >= j; i--)
{
possibleRoute[i] = lastNumber;
}
possibleRoutes.Add(possibleRoute.ToList());
generalCounter++;
}
return possibleRoutes;
}
Version 2
private static List<List<int>> GetNumbers(int lastNumber)
{
if (lastNumber == 0)
{
return new List<List<int>> {new List<int> {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
}
int[] setOfNumbers = new int[lastNumber + 1];
List<List<int>> possibleRoutes = new List<List<int>>().ToList();
for (int i = 0; i <= lastNumber; i++)
{
setOfNumbers[i] = i;
}
var temp = new List<int>();
int[] possibleRoute = new int[15];
for (int j = 0; j < size - lastNumber; j++)
{
possibleRoute[j] = 0;
}
for (int i = 1 ; i <= lastNumber ; i++)
{
int newNumber = lastNumber - i;
for (int k1 = i + 1; k1 <= size; k1++)
{
for (int j = possibleRoute.Length - 1; j > k1 - i - 1; j--)
{
possibleRoute[j] = lastNumber;
}
for (int k = i; k <= k1 - 1; k++)
{
possibleRoute[k] = newNumber;
}
possibleRoutes.Add(possibleRoute.ToList());
generalCounter++;
}
}
return possibleRoutes;
}
I misunderstood the problem. Starting this answer over.
Let's state the problem another way.
We have a number of items, fifteen.
We have a number of digits, say 0, 1, 2.
We wish to know what are the combinations of x zeros, y ones and z twos such that x + y + z = 15 and x, y and z are all at least one.
So, reduce it to an easier problem. Suppose there is one zero. Now can you solve the easier problem? The problem is now smaller: the problem is now "generate all the sequences of length 14 that have at least one 1 and one 2". Do you see how to solve the easier problem?
If not, break it down into a still easier problem. Suppose there is one 1. Can you solve the problem now? The problem now is to find all the sequences that have thirteen 2s in them, and there's only one of those.
Now suppose there are two 1s. Can you solve the problem there?
Do you see how to use the solution to the easier problems to solve the harder problems?
A simple strategy which works with a wide variety of problems like this is to list the possibilities in lexicographical order. In pseudocode, you would do something like this:
Set V to the first possible sequence, in lexicographical order.
Repeat the following:
Output V
If possible, set V to the next sequence in lexicographical order.
If that was not possible, exit the loop.
For many cases, you can solve the second sub-problem ("set V to the next sequence") by searching backwards in V for the right-most "incrementable" value; that is, the right-most value which could be incremented resulting an a possible prefix of a sequence. Once that value has been incremented (by the minimum amount), you find the minimum sequence which starts with that prefix. (Which is a simple generalization of the first sub-problem: "find the minimum sequence".)
In this case, both of these sub-problems are simple.
A value is incrementable if it is not the largest number in the set and it is the same as the preceding value. It can only be incremented to the next larger value in the set.
To find the smallest sequence starting with a prefix ending with k, start by finding all the values in the set which are greater than k, and putting them in order at the end of the sequence. Then fill in the rest of the values after the prefix (if any) with k.
For the application of this approach to a different enumeration problem, see https://stackoverflow.com/a/30898130/1566221. It is also the essence of the standard implementation of next_permutation.
I have the following code in the main() method:
const int Length = 20;
const int NumberOfExperiments = 100;
static void Main(string[] args)
{
Random gen = new Random();
double[][] arr = new double[NumberOfExperiments][];
for (int j = 0; j < NumberOfExperiments; ++j)
{
arr[j] = new double[Length + 4];
for (int i = 0; i < Length; ++i)
{
arr[j][i] = gen.NextDouble();
}
arr[j][Length] = bubbleSort(arr[j]);
arr[j][Length + 1] = insertSort(arr[j]);
arr[j][Length + 2] = arr[j][Length] - arr[j][Length + 1];
arr[j][Length + 3] = arr[j][Length + 2] * arr[j][Length + 2];
foreach(double memb in arr[j]){
Console.WriteLine("{0}", memb);
}
Console.ReadKey();
}
WriteExcel(arr, "sorting");
Console.ReadKey();
}
After the first ReadKey() i have the following output:
0
0
0
0
0.046667384
0.178001223
0.197902503
0.206131403
0.24464349
0.306212793
0.307806501
0.354127458
0.385836004
0.389128544
0.431109518
0.489858235
0.530548627
0.558604611
0.647516463
0.762527595
0.874646365
152
-151.1253536
22838.87251
I don't know why the first several elements of array are filled with 0. The first iteration always begins with i=0(or j=0), so it's Ok.
Functions bubbleSort() and insertSort() work correctly and return the number of swaps.
I have used C# for several years, but I really can't understand why this code doesn't work.
When you create the "row", you do this:
arr[j] = new double[Length + 4];
But then loop like this:
for (int i = 0; i < Length; ++i)
So the last 4 elements are left with the default value (0). When you sort, these elements go to the beginning.
It looks like bubbleSort() gets an array and sorts it, at the time of the call the last 4 elements are empty (set to 0), so they go to the beginning in the result. Check if bubbleSort() uses Array.Length somewhere and make sure it subtracts 4 there.
Given an array of integers...
var numbers = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
I need to determine a the maximum sequence of numbers that alternate up then down or down then up.
Not sure the best way to approach this, the process psuedo wise strikes me as simple but materializing code for it is evading me.
The key is the fact we are looking for max sequence, so while the above numbers could be interpreted in many ways, like a sequence of seven up-down-up and seven down-up-down the important fact is starting with the first number there is a down-up-down sequence that is 14 long.
Also I should not that we count the first item, 121 is a sequence of length 3, one could argue the sequence doesn't begin until the second digit but lets not split hairs.
This seems to work, it assumes that the length of numbers is greater than 4 (that case should be trivial anyways):
var numbers = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
int count = 2, max = 0;
for (int i = 1; i < numbers.Length - 1; i++)
{
if ((numbers[i - 1] < numbers[i] && numbers[i + 1] < numbers[i]) ||
(numbers[i - 1] > numbers[i] && numbers[i + 1] > numbers[i]))
{
count++;
max = Math.Max(count, max);
}
else if ((numbers[i - 1] < numbers[i]) || (numbers[i - 1] > numbers[i])
|| ((numbers[i] < numbers[i + 1]) || (numbers[i] > numbers[i + 1])))
{
max = Math.Max(max, 2);
count = 2;
}
}
Console.WriteLine(max); // 14
Here's how I thought of it
First, you need to know whether you're starting high or starting low. eg: 1-2-1 or 2-1-2. You might not even have an alternating pair.
Then, you consider each number afterwards to see if it belongs in the sequence, taking into consideration the current direction.
Everytime the sequence breaks, you need to start again by checking the direction.
I am not sure if it is possible that out of the numbers you have already seen, picking a different starting number can POSSIBLY generate a longer sequence. Maybe there is a theorem that shows it is not possible; maybe it is obvious and I am over-thinking. But I don't think it is possible since the reason why a sequence is broken is because you have two high's or two low's and there is no way around this.
I assumed the following cases
{} - no elements, returns 0
{1} - single element, returns 0
{1, 1, 1} - no alternating sequence, returns 0
No restriction on the input beyond what C# expects. It could probably be condensed. Not sure if there is a way to capture the direction-change logic without explicitly keeping track of the direction.
static int max_alternate(int[] numbers)
{
int maxCount = 0;
int count = 0;
int dir = 0; // whether we're going up or down
for (int j = 1; j < numbers.Length; j++)
{
// don't know direction yet
if (dir == 0)
{
if (numbers[j] > numbers[j-1])
{
count += 2; // include first number
dir = 1; // start low, up to high
}
else if (numbers[j] < numbers[j-1])
{
count += 2;
dir = -1; // start high, down to low
}
}
else
{
if (dir == -1 && numbers[j] > numbers[j-1])
{
count += 1;
dir = 1; // up to high
}
else if (dir == 1 && numbers[j] < numbers[j-1])
{
count += 1;
dir = -1; // down to low
}
else
{
// sequence broken
if (count > maxCount)
{
maxCount = count;
}
count = 0;
dir = 0;
}
}
}
// final check after loop is done
if (count > maxCount)
{
maxCount = count;
}
return maxCount;
}
And some test cases with results based on my understanding of the question and some assumptions.
static void Main(string[] args)
{
int[] nums = { 1}; // base case == 0
int[] nums2 = { 2, 1 }; // even case == 2
int[] nums3 = { 1, 2, 1 }; // odd case == 3
int[] nums4 = { 2, 1, 2 }; // flipped starting == 3
int[] nums5 = { 2, 1, 2, 2, 1, 2, 1 }; // broken seqeuence == 4
int[] nums6 = { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1 }; // long sequence == 14
Console.WriteLine(max_alternate(nums));
Console.WriteLine(max_alternate(nums2));
Console.WriteLine(max_alternate(nums3));
Console.WriteLine(max_alternate(nums4));
Console.WriteLine(max_alternate(nums5));
Console.WriteLine(max_alternate(nums6));
Console.ReadLine();
}
I'm not from a pc with a compiler right now, so I just give a try:
int max = 0;
int aux =0;
for(int i = 2 ; i < length; ++i)
{
if (!((numbers[i - 2] > numbers[i - 1] && numbers[i - 1] < numbers[i]) ||
numbers[i - 2] < numbers[i - 1] && numbers[i - 1] > numbers[i]))
{
aux = i - 2;
}
max = Math.Max(i - aux,max);
}
if (max > 0 && aux >0)
++max;
Note: should works for sequence of at least 3 elements.
There are probably a lot of ways to approach this, but here is one option:
var numbers = new int[] { 7,1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1 };
int maxCount = 0;
for (int j = 0; j+1 < numbers.Length; j++)
{
int count = 0;
if (numbers[j] < numbers[j+1])
{
count += 2;
for (int i = j+2; i+1 < numbers.Length; i += 2)
{
if (numbers[i] < numbers[i + 1] )
{
count += 2;
}
else
{
break;
}
}
}
if (maxCount < count)
{
maxCount = count;
}
}
Console.WriteLine(maxCount);
Console.ReadLine();
This solution assumes that you want a sequence of the same two alternating numbers. If that's not a requirement you could alter the second if.
Now that it's written out, it looks more complex than I had imagined in my head... Maybe someone else can come up with a better solution.
Assumes at least 2 elements.
int max = 1;
bool expectGreaterThanNext = (numbers[0] > numbers[1]);
int count = 1;
for (var i = 0; i < numbers.Length - 1; i++)
{
if (numbers[i] == numbers[i + 1] || expectGreaterThanNext && numbers[i] < numbers[i + 1])
{
count = 1;
expectGreaterThanNext = (i != numbers.Length - 1) && !(numbers[i] > numbers[i+1]);
continue;
}
count++;
expectGreaterThanNext = !expectGreaterThanNext;
max = Math.Max(count, max);
}
This works for any integers, it tracks low-hi-low and hi-low-hi just like you asked.
int numbers[] = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
int count = 0;
int updownup = 0;
int downupdown = 0;
for(int x = 0;x<=numbers.Length;x++)
{
if(x<numbers.Length - 2)
{
if(numbers[x]<numbers[x+1])
{
if(numbers[x+1]>numbers[x+2])
{
downupdown++;
}
}
}
}
count = 0;
for(x=0;x<=numbers.Length;x++)
{
if(x<numbers.Length - 2)
{
if(numbers[x]>numbers[x+1]
{
if(numbers[x+1]<numbers[x+2])
{
updownup++;
}
}
}
}