least sum of vertical line in 2d array - c#

I have a 2D array I have the
number of rows = H
number of columns = W
the 2d array itself = arr
they are all integers
I am tasked to return the lowest sum of the vertical line starts with each point at first row
input
1 2 3
4 5 6
7 8 9
output 12
I thought about a way to solve this by using recursion but i don't get right results.
the function takes the array, the position i want to calculate minimum sum at (should be on the first-row coz it's a line) number of columns and rows and res is to return the sum res is initialized in the main function by arr at row x and column y
I am sure about the idea but the way I am summing is probably wrong
static int Summ(int [,]arr,int x,int y,int W,int H,int res)
{
if (x == H - 1)
res += arr[x, y];
else
if (y == 0)
res += Math.Min(Summ(arr, x + 1, y, W, H, res), Summ(arr, x + 1, y + 1, W, H, res));
else if (y== W-1)
res += Math.Min(Summ(arr, x + 1, y, W, H, res), Summ(arr, x + 1, y - 1, W, H, res));
else
res+= res += Math.Min(Math.Min(Summ(arr, x + 1, y, W, H, res), Summ(arr, x + 1, y + 1, W, H, res)),Summ(arr,x+1,y-1,W,H,res));
return res;
}

An iterative solution may be simpler:
static int MinSum(int [,]arr)
{
int min = Int32.MaxValue;
for (int j = 0; j < arr.GetLength(1); ++j)
{
int sum = 0;
for (int i = 0; i < arr.GetLength(0); ++i)
{
sum += arr[i, j];
}
min = Math.min(min, sum);
}
return min;
}
EDIT:
Given the clarification in the comment below, this solution is not correct.
Instead, you could iterate over the rows and sum the minimal value in each row:
static int MinSum(int [,]arr)
{
int sum = 0;
for (int i = 0; j < arr.GetLength(0); ++i)
{
int minCol = arr[i, 0];
for (int j = 1; j < arr.GetLength(1); +_j)
{
minCoal = Math.min(minCol, arr[i, j]);
}
min += minCol;
}
return sum;
}

Related

Is it possible to move around in an array for new location?

I am messing around and making a text based game, I am using an array as my layout for a map and I have a random starting point, and from that point I want to be able to move up down left and right but I am not sure how to proceed
int[,] dungeon = new int[5, 5] { {1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15},
{16,17,18,19,20},
{21,22,23,24,25}};
shuffleArray(dungeon);
int startingPoint;
// i think this has to be in the actual game loop for a new random spot?
for(int i = 0; i<1; i++)
{
for(int j = 0; j < 1; j++)
{
startingPoint = dungeon[i,j];
Console.WriteLine(startingPoint);
}
}
void shuffleArray(int[,] arr)
{
int n = arr.GetLength(0);
int m = arr.GetLength(1);
Random rand = new Random();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
swap(arr, i + rand.Next(n - i), j + rand.Next(m - j), i, j);
}
}
}
void swap(int[,] arr, int changed, int changedB, int a, int b)
{
int temp = arr[a, b];
arr[a, b] = arr[changed, changedB];
arr[changed, changedB] = temp;
}
Given a starting point (I'm calling it "position"), you can find the value in the shuffled array with this method:
// position is NOT zero-based! In a 5x5 matrix 1 is the first position
// and 25 is the last position
int getValueAtPosition(int position)
{
//assuming non-jagged board!
var w = dungeon.GetLength(0);
int row = position % w == 0 ? (position / w) : (position / w) + 1;
int col = position % w == 0 ? w : position - ((row - 1) * w);
int location = dungeon[row - 1, col - 1];
return location;
}
Now, if you move left you subtract one from the current position and pass it into this method. Likewise, add 1 to move right.
To move up or down subtract or add 5.
Be sure to check bounds so you don't move out of the matrix when adding or subtracting.

How to find 3x3 square matrix with maximum sum in bigger rectangular matrix in C#?

I have matrix with size N x M and I want to find smaller matrix inside which has maximum sum and is of size 3 x 3. I can manually sum all the elements but wthis is imposible in bigger matrices, can you point me a better approach.
Look for Kadane 2D algorithm.
I think it is one of the best solution for this problem
If I understand the problem ¯\_(ツ)_/¯
Given
public static int FindStuff(int[,] array)
{
var largest = 0;
for (var i = 0; i < array.GetLength(0) - 2; i++)
for (var j = 0; j < array.GetLength(1) - 2; j++)
{
var sum = 0;
for (var x = i; x < i+3; x++)
for (var y = j; y < j+3; y++)
sum += array[x, y];
if (sum > largest)
largest = sum;
}
return largest;
}
Usage
var array = new[,]
{
{1, 1, 1, 1},
{1, 2, 3, 4},
{1, 1, 1, 1},
{5, 1, 1, 1},
};
Console.WriteLine(FindStuff(array));
Result
16
In pure C# you must calculate all inner matricies, you can speed up algorithms with paraller task, you can also use CUDA, and a naive solution with checking inner matrices should looks like this:
public void TestMethod(int[][] matrix)
{
int largestSum = 0;
int columnLargestIdx = 0;
int rowLargestIdx = 0;
for (int column = 0; column < matrix.Length; column++)
for (int row = 0; row < matrix[column].Length; row++)
{
if (IsBuild3x3Possible(matrix, column, row))
{
int sum = CalculateSum(matrix, column, row);
if (sum > largestSum)
{
largestSum = sum;
columnLargestIdx = column;
rowLargestIdx = row;
}
}
}
}
public bool IsBuild3x3Possible(int[][] matrix, int column, int row)
{
var columns = (matrix.Length - column) >= 3;
var rows = (matrix[column].Length - row) >= 3;
return columns && rows;
}
public int CalculateSum(int[][] matrix, int column, int row)
{
int sum = 0;
for (int i = column; i < column + 3; i++)
for (int j = row; j < row + 3; j++)
sum += matrix[i][j];
return sum;
}

Fill 1D array from matrix

I have a matrix, my mission is to fill 1D array from my matrix.
Example:
1 2 3
1 2 3
1 2 3
I need to sum the columns and fill the sum of every column in a 1D array
Here is my code (that doesn't work), (int[,] mat) is the matrix that the function gets.
public static int sumcolumn(int[,] mat)
{
int sum = 0;
int[] sumcol = new int[mat.GetLength(0)];
for (int y = 0; y < mat.GetLength(0); y++)
{
for (int i = 0; i < mat.GetLength(0); i++)
{
for (int j = 0; j < mat.GetLength(1); j++)
{
sum = sum + mat[j, i];
}
sumcol[i] = sum;
return sum;
sum = 0;
}
return sum;
}
return sumcol;
}
How should I do this mission?
Thanks in advance.
You need only 2 for loops. For each column run through all rows and sum up the content. Write the sum at the proper col index. Then after each column reset the sum. You also need to return the array with the sums. So I changed the return value:
Also it helps if you call the index variables with meaningful names.
public static int[] sumcolumn(int[,] mat)
{
int[] sumcol = new int[mat.GetLength(1)];
for (int col = 0; col < mat.GetLength(1); col++)
{
for (int row = 0; row < mat.GetLength(0); row++)
{
// since sumcol is initially filled with zeros you can just
// sum up the values from mat onto the zeros in each cell
sumcol[col] += mat[row, col];
}
}
return sumcol;
}
In the main you can test it like this:
void Main()
{
int[,] array = {
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 },};
// this is just for test display
Console.WriteLine(String.Join(" ", sumcolumn(array)));
// normally you would call it like this and catch the return value in a new array
int[] result = sumcolumn(array);
}
So you need to evaluate a 2D matrix to get the column wise sum to a 1D array. So first thing you have to do is change the return type of the method to int[] instead for int.
Let me quote Few things that you have to notice before moving to a fix:
If you execute a return during iteration of the loop rest of iterations will not be executed.
A function can return only one value in a single call.
Let i and j be two positive unequal integers then a[i,j] and a[j,i] will points to two different elements in the matrix a.
As a whole you have to modify the method signature like the following:
public static int[] sumcolumn(int[,] mat)
{
int sum = 0;
int[] sumcol = new int[mat.GetLength(1)];
for (int i= 0; i< mat.GetLength(1); i++)
{
sum = 0; // reset sum for next colomn
for (int j= 0; j< mat.GetLength(0); j++)
{
sum += mat[i, j];
}
// iteration of column completed
sumcol[i] = sum;
}
return sumcol;
}
Linq approach
int[,] array = new int[3, 3] { { 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 } };
int[] result = Enumerable.Range(0, array.GetUpperBound(1) + 1)
.Select(y => Enumerable.Range(0, array.GetUpperBound(0) + 1)
.Select(x => array[x, y]).Sum()).ToArray(); // [3,6,9]
public static int[] sumColumn(int[,] mat)
{
//int sum = 0;
int colCount = mat.GetLength(0);
int[] sumCol = new int[colCount];
for (int y = 0; y < colCount; y++)
{
int rowCount = mat.GetLength(1);
sumCol[y] = 0;
for (int x = 0; x < rowCount; x++)
{
sumCol[y] += mat[y, x];
}
//sum += sumCol[y];
}
//return sum;
return sumCol;
}

Smallest and biggest value in slice of 3D array

I have a 3d-array double[,,] numbers = new double[x,y,z]; and now if one imagines the 3d-array to look like a cube with numbers I need to find the smallest and biggest value of every slice along all three directions.
It is of course easy to do by simply looping over it, but does C# have any functions to find the smallest and biggest value in a slice?
To explain it a bit further, maybe this "unreal" code will help:
int i;
double[] xmin = new double[x];
double[] xmax = new double[x];
double[] ymin = new double[y];
double[] ymax = new double[y];
double[] zmin = new double[z];
double[] zmax = new double[z];
for(i = 0; i < x; i++)
{
MinOf(numbers[i, y, z]) = xmin[i];
MaxOf(numbers[i, y, z]) = xmax[i];
}
for(i = 0; i < y; i++)
{
MinOf(numbers[x, i, z]) = ymin[i];
MaxOf(numbers[x, i, z]) = ymax[i];
}
for(i = 0; i < z; i++)
{
MinOf(numbers[x, y, i]) = zmin[i];
MaxOf(numbers[x, y, i]) = zmax[i];
}
Hopefully someone can help me with that.
Cheers, Phil13131
You can make methods for enumerating the slices. This is for one dimension, you would need another two, but I think you can manage that:
public static IEnumerable<T> SliceX<T>(T[,,] data, int x) {
for (int y = 0; y < data.GetLength(1); y++) {
for (int z = 0; z < data.GetLength(2); z++) {
yield return data[x, y, z];
}
}
}
Then you can just use the Min and Max methods, but that will of course loop through the data twice:
double min = SliceX(numbers, x).Min();
double max = SliceX(numbers, x).Max();
You can make an extension method that gets both min and max in one iteration:
public static class IEnumerableExtensions {
public static void GetMinMax<T>(this IEnumerable<T> data, out T min, out T max) where T : IComparable<T> {
bool first = true;
min = max = default(T);
foreach (T value in data) {
if (first) {
min = max = value;
first = false;
} else {
if (value.CompareTo(min) < 0) min = value;
if (value.CompareTo(max) > 0) max = value;
}
}
}
}
Usage:
double min, max;
SliceX(numbers, 0).GetMinMax(out min, out max);
Are you looking for something like this?
double[, ,] numbers = new double[2, 2, 2];
numbers[0, 0, 0] = 0;
numbers[0, 0, 1] = 1;
numbers[0, 1, 0] = 2;
numbers[0, 1, 1] = 3;
numbers[1, 0, 0] = 4;
numbers[1, 0, 1] = 5;
numbers[1, 1, 0] = 6;
numbers[1, 1, 1] = 7;
double[] xmax = new double[numbers.GetLength(0)];
double[] ymax = new double[numbers.GetLength(1)];
double[] zmax = new double[numbers.GetLength(2)];
for (int x = 0; x < xmax.Length; x++) xmax[x] = int.MinValue;
for (int y = 0; y < ymax.Length; y++) ymax[y] = int.MinValue;
for (int z = 0; z < zmax.Length; z++) zmax[z] = int.MinValue;
for (int x = 0; x < xmax.Length; x++)
for (int y = 0; y < ymax.Length; y++)
for (int z = 0; z < zmax.Length; z++)
{
xmax[x] = Math.Max(xmax[x], numbers[x, y, z]);
ymax[y] = Math.Max(ymax[y], numbers[x, y, z]);
zmax[z] = Math.Max(zmax[z], numbers[x, y, z]);
}
// xmax == { 3, 7 }
// ymax == { 5, 7 }
// zmax == { 6, 7 }

Generate coordinates for cube

Hi i just write function in C# that generate coordinate for cube but the problem i want just
generate the coordinate of cube sides not in the depth !!!
static class Util
{
public static List<string> GenerateCubeCoord(double bc,int nt,double stp)
{
List<string> list = new List<string>();
double CoorBase = bc;
int n = nt;
double step = stp;
int id = 1;
for (int x = 0; x < n; x++)
{
for (int y = 0; y < n; y++)
{
for (int z = 0; z < n; z++)
{
list.Add(string.Format("GRID {0} {1}.0 {2}.0 {3}.0 \n",
id, step * x + CoorBase, step * y + CoorBase, step * z + CoorBase));
id++;
}
}
}
return list;
}
}
I wat to generate all this coordinate not the corner coordinates of cube , in the image one
side of may cube
Without changing your code too much (assuming you meant all corner points, it's a little unclear):
for (int x = 0; x <= n; x += n)
for (int y = 0; y <= n; y += n)
for (int z = 0; z <= n; z += n)
Console.WriteLine("{0} {1} {2}", x, y, z);
A little cleaner using LINQ:
int n = 6;
var coords = from x in new[] { 0, n }
from y in new[] { 0, n }
from z in new[] { 0, n }
select new { x, y, z };
foreach(var coord in coords)
Console.WriteLine("{0} {1} {2}", coord.x, coord.y, coord.z);
Edit after updated question:
If you just want the coordinates of the sides, the allowed values for one coordinate (x,y or z) are either 0 or n-1:
var coords = from x in new[] { 0, n-1 }
from y in Enumerable.Range(0, n)
from z in Enumerable.Range(0, n)
select new { x, y, z };
Rinse and repeat for the other two and you have the set of coordinates for all 6 sides.
Edit:
With above solution there are overlaps between the different sides (the edge points), so you'd have to use the union of all 3 collections. A better solution is to query for all coordinates in one go:
var coords = from x in Enumerable.Range(0, n)
from y in Enumerable.Range(0, n)
from z in Enumerable.Range(0, n)
where ( x == 0 || x==n-1 || y == 0 || y== n-1 || z == 0 || z== n-1)
select new { x, y, z };

Categories

Resources