Finding the sum of the values in a 2D Array in C# - c#

Trying to build a method that will find the sum of all the values within the 2D array. I'm very new to programming and can't find a good starting point on trying to figure out how its done. Here is what I have so far (forgive me, I'm usually an english/history guy, logic isn't my forte...)
class Program
{
static void Main(string[] args)
{
int[,] myArray = new int[5,6];
FillArray(myArray);
LargestValue(myArray);
}
//Fills the array with random values 1-15
public static void FillArray(int[,] array)
{
Random rnd = new Random();
int[,] tempArray = new int[,] { };
for (int i = 0; i < tempArray.GetLength(0); i++)
{
for (int j = 0; j < tempArray.GetLength(1); j++)
{
tempArray[i, j] = rnd.Next(1, 16);
}
}
}
//finds the largest value in the array (using an IEnumerator someone
//showed me, but I'm a little fuzzy on how it works...)
public static void LargestValue(int[,] array)
{
FillArray(array);
IEnumerable<int> allValues = array.Cast<int>();
int max = allValues.Max();
Console.WriteLine("Max value: " + max);
}
//finds the sum of all values
public int SumArray(int[,] array)
{
FillArray(array);
}
}
I guess I could try to find the sum of each row or column and add them up with a for loop? Add them up and return an int? If anyone could shed any insight, it would be greatly appreciated, thanks!

Firstly, you don't need to call FillArray in the beginning of each method, you have already populated the array in the main method, you are passing a populated array to these other methods.
A loop similar to what you use to populate the array is the easiest to understand:
//finds the sum of all values
public int SumArray(int[,] array)
{
int total = 0;
// Iterate through the first dimension of the array
for (int i = 0; i < array.GetLength(0); i++)
{
// Iterate through the second dimension
for (int j = 0; j < array.GetLength(1); j++)
{
// Add the value at this location to the total
// (+= is shorthand for saying total = total + <something>)
total += array[i, j];
}
}
return total;
}

To sum an array if you know the length is easy
As a bonus code included to get the highest valeu too.
You could easily expand this to get other kinds of statistical code.
I asume below Xlength and Ylength are integers too, and known by you.
You could also replace them by a number in the code.
int total = 0;
int max=0;
int t=0; // temp valeu
For (int x=0;x<Xlength;x++)
{
for (int y=0;y<Ylength;y++)
{
t = yourArray[x,y];
total =total +t;
if(t>max){max=t;} // an if on a single line
}
}
here is a link with an MSDN sample on how to retrieve unknown array lengths.
and there is a nice site to have around when you start in c#
google ".net perls"

Related

I just can't insert more than 5 elements in a array in C#

I'm trying to make a simple program where I declare the size of an array with one input, but I gives an IndexOutOfRange Exception if the array has more than 5 elements. Somebody can help me understand why, please?
class Program
{
static void Main(string[] args)
{
int[] array = new int[5];
Console.WriteLine("Declare the array size");// 6
int quant = int.Parse(Console.ReadLine());
for (int i = 0; i < quant; i++) {
Console.WriteLine("Fill in the {0}º value ", i+1);
int number = int.Parse(Console.ReadLine());
array[i] = number;
}
for (int i=0; i< quant; i++)
{
Console.WriteLine("\n", array[i]);
}
}
}
You need to create an array specifying the the number of elements after you read the input from the user. what you have done in your code is create an array of int with a size of 5. in case the user write a number larger then 5, you'll get the IndexOutOfRange exception.
class Program
{
static void Main(string[] args)
{
int quant = int.Parse(Console.ReadLine());
int[] array = new int[quant ];
for (int i = 0; i < quant; i++){
Console.WriteLine("Fill in the {0}º value ", i+1);
int number = int.Parse(Console.ReadLine());
array[i] = number;
}
for (int i=0; i< quant; i++){
Console.WriteLine("\n", array[i]);
}
}
}
If you want to use an array without specifing a fixed limit, it's not possible in C# (in JS for instance it is). you can achieve this requirement in C# using a different type called List which represents a strongly typed list of objects that can be accessed by index and does not require specifing a fixed size in initializtion (in contrast to array)
Read more about List - https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-5.0

Selection Sort Implementation

I'm not really sure what's wrong with the implementation I have. How would I fix this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SelectionSort
{
class Program
{
static void algorithm(int[] to_sort)
{
int bufor;
for (int i = 0; i < to_sort.Length; i++)
{
for (int j = i + 1; j < to_sort.Length; j++)
{
if (to_sort[i] >= to_sort[j])
{
bufor = to_sort[i];
to_sort[i] = to_sort[j];
to_sort[j] = bufor;
}
}
}
}
static void Main(string[] args)
{
int[] to_sort = new int[100];
Console.WriteLine("");
for (int i = 1; i < 100; i++)
{
Console.Write(to_sort[i] + " ");
}
Console.WriteLine("");
algorithm(to_sort);
Console.WriteLine("\n");
Console.WriteLine("Sorted list:");
for (int i = 0; i < 100; i++)
{
Console.Write(to_sort[i] + " ");
}
Console.Read();
}
}
}
This produces the following output:
Original list: 00000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
Sorted list: 000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
It looks like my array (int[] to_sort) was empty, am I right? How can I get this:
Original list: 123456789....100
Sorted list: 123456789...100
Perhaps you originate from the C++ world where initializing an array does not mean the array is "cleaned" (the data that happened to be located at the allocated memory remains untouched), but in C# if you initialize an array like:
int[] to_sort = new int[100];
It means you construct an array where every element is set to default(T) with T the type. For an int that is 0 (for objects it is null, etc.). So you just constructed an array filled with zeros.
You can however for instance fill it with random numbers like:
Random rand = new Random();
for(int i = 0; i < to_sort.Length; i++) {
to_sort[i] = rand.Next(0,1000);
}
EDIT
Based on your comment, you want to fill it with the positions, you can do this like:
for(int i = 0; i < to_sort.Length; i++) {
to_sort[i] = i+1;
}
I think the easiest and shortest way you can initialize an array of sequential numbers is like this:
int[] to_sort = Enumerable.Range(1, 100).ToArray();
What you have will just allocate the array and fill it with the default value for int, which is 0:
int[] to_sort = new int[100];

Array Contains Performance

I have a program which works with arrays and at some point I have to check if a lsit of values are inside an array, the function that does this takes about 70% of the program CPU time, so I was wondering if there's a way to do this more efficiently.
These are my functions:
private static int[] GenerateRow(int length, Random RNG)
{
int[] row = InitalizeRow(length);
int index = 0;
while (!AreAllNumbersGenerated(row))
{
int value = RNG.Next(0, length);
if (!RowContains(row, value))
{
row[index] = value;
index++;
}
}
return row;
}
private static bool AreAllNumbersGenerated(int[] row)
{
for (int i = 0; i < row.Length; i++)
if(!RowContains(row, i))
return false;
return true;
}
private static bool RowContains(int[] row, int value)
{
for (int i = 0; i < row.Length; i++)
if (row[i] == value)
return true;
return false;
}
All the work is by AreAllNumbersGenerated(), then by RowContains() and finally by this line:
if (row[i] == value)
That this functions take most of the time is normal, since they do heavy work, but I wanted to know if there's a better way to do this.
EDIT:
private static int[] InitalizeRow(int length)
{
int[] row = new int[length];
for (int i = 0; i < length; i++)
row[i] = -1;
return row;
}
You're wasting a lot of work by doing a linear scan for every number throughout the array. What you should instead do is walk the array once and start observing the last number you've seen. If you see any gaps, return false. If you reach the end of the array, return true. This is O(N) instead of O(N^2) like you have it now.
Like so:
public static bool AreAllNumbersGenerated(int[] row)
{
var last = 0;
return row.Aggregate(true, (l, r) => l && r == last++);
}
You can make some additional optimizations that won't affect your big-O complexity, e.g. using a proper loop and early-exiting.
EDIT: I'm assuming here that you're expecting the items to occur sequentially. If this isn't the case, you can easily convert the array to a structure with ~O(1) lookups in O(N), then do the check in O(N) as well. For large input, this is still better than your O(N^2) approach above
Like so:
public static bool AreAllNumbersGenerated2(int[] row)
{
var available = row.ToDictionary(x => x);
return Enumerable.Range(0, row.Length).All(i => available.ContainsKey(i));
}
EDIT: From what I'm seeing in the comments it looks like the goal of this code is to populate an array with a contiguous sequence of numbers in a random order. I didn't realize that was the goal, and if that is the case, shuffling is certainly better than reattempting to generate over and over. But what is even better than generating the array then shuffling (again, for sufficiently large input) is to simply generate the array by assigning each number to a randomly sampled index without substitution. Not as easy to LINQ out, but you can figure it out.
As others in the comments have pointed out, the most efficient way to do this is to generate an array with the values you want and shuffle it:
public static void Shuffle<T>(T[] arr, Random r)
{
for (int i = arr.Length - 1; i > 0; --i)
{
int j = r.Next(i + 1);
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
public static int[] Generate(int length, Random r)
{
var arr = new int[length];
for(int i = 0; i < length; ++i)
{
arr[i] = i;
}
Shuffle(arr, r);
return arr;
}
then
var arr = Generate(10, new Random());
foreach (int i in arr) { Console.WriteLine(i); }
I found a method, thanks to #sous2817 comment, that works perfectly for me.
public static int[] GetRandomNumbers(int count, Random RNG)
{
HashSet<int> randomNumbers = new HashSet<int>();
for (int i = 0; i < count; i++)
while (!randomNumbers.Add(RNG.Next(count))) ;
return randomNumbers.ToArray();
}
This works ~10 times faster then what I was doing and works nicely with the rest of my program.I needed the code to be "linear" so other solutions mess my program. Anyway, thanks to everyone that helped :)
Instead of shuffle, you can generate the possible values in a list and take values at random positions. That way you can start using the items even before the whole row is generated:
IEnumerable<int> RandomRange(int count) {
var random = new Random();
var list = new int[count];
for (int i = 0; i < count; i++) list[i] = i;
while (count > 0) {
var i = random.Next(count);
yield return list[i] ;
list[i] = list[--count];
}
}
sample use:
foreach(var item in RandomRange(10))
// ...

I have a function that makes an array and shuffles it but I don't know how to call it in the way I want to

This is a function that makes an array and fills it from LoLim till HiLim and then shuffles the order:
static Random random = new Random(); //these two statics are to make a random number, i need the first static to be outside the function so it won't keep making the same random number
static int RandomNum(int LoLim, int HiLim, int index)
{
var nums = Enumerable.Range(LoLim,HiLim).ToArray(); //these next lines make an array from LoLim to HiLim and then shuffle it
for (int i = 0; i < nums.Length; i++)
{
int randomIndex = random.Next(nums.Length);
int temp = nums[randomIndex];
nums[randomIndex] = nums[i];
nums[i] = temp;
}
return nums[index];
Then I have this function that makes a 2 dimensional array and then prints it. It uses RandomNum but not in the way I want to, but I don't know how to make it work.
static Array Matrix(int Rows, int Columns) //this is a function to initiate and print the array
{
int[,] LotteryArray = new int[Rows, Columns];
for (int i = 0; i < LotteryArray.GetLength(0); i++) //this is a series of loops to initiate and print the array
{
for (int j = 0; j < LotteryArray.GetLength(1); j++)
{
LotteryArray[i, j] = RandomNum(1,46,j); //the numbers are supposed to be between 1 and 45, so i tell it to do it until 46 because the upper limit is exclusive
Console.Write("{0,3},", LotteryArray[i, j]); //the {0,3} the 3 is three spaces after the first variable
}
Console.WriteLine();
}
return LotteryArray;
Basically I want it to call to RandomNum every "row" so it could shuffle the array, then I want it to pull out nums[index] and print it out. The reason I want this is so I can have non repeating random numbers in every row. For example: I don't want a row to be "21, 4, 21, 5, 40, 30".
There are various problems with your code, even if it worked. The "logical" problems are:
You are using a biased shuffling algorithm. You should use Fisher-Yates to do correct shuffling (see http://blog.codinghorror.com/the-danger-of-naivete/)
If you really want to do a "good" shuffling, you shouldn't use the Random number generator, and instead use the RNGCryptoServiceProvider (see http://www.cigital.com/papers/download/developer_gambling.php, but note that this is a much lesser problem than the other other one... we can survive with "a little less random" shuffles, if are the generated shuffles are all equiprobable)
You are using wrongly the arguments of Enumerable.Range()
Your coding problem is different: you have to save the shuffled row somewhere, and then take the first column values.
Here I'm using a class to encapsulate a row with shuffling
public class ShuffledRow
{
public static readonly Random Random = new Random();
public readonly int[] Row;
/// <summary>
/// Generates and shuffles some numbers
/// from min to max-1
/// </summary>
/// <param name="min"></param>
/// <param name="max">Max is excluded</param>
public ShuffledRow(int min, int max)
{
int count = max - min;
Row = Enumerable.Range(min, count).ToArray();
Shuffle(Row);
}
private static void Shuffle<T>(T[] array)
{
// Fisher-Yates correct shuffling
for (int i = array.Length - 1; i > 0; i--)
{
int j = Random.Next(i + 1);
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
Another problem: don't ever use multidimensional arrays in C# unless you know what you are doing. Sadly they are a bastard-and-forgotten child of .NET. Use jagged arrays (arrays of arrays).
public static int[][] Matrix(int rows, int columns)
{
int[][] lottery = new int[rows][];
for (int i = 0; i < lottery.Length; i++)
{
ShuffledRow sr = new ShuffledRow(1, 46);
lottery[i] = sr.Row;
Array.Resize(ref lottery[i], columns);
Console.WriteLine(
string.Join(",", lottery[i].Select(
x => string.Format("{0,3}", x))));
}
return lottery;
}
public static int[][] Matrix(int rows, int columns)
{
int[][] lottery = new int[rows][];
for (int i = 0; i < lottery.Length; i++)
{
ShuffledRow sr = new ShuffledRow(1, 46);
lottery[i] = new int[columns];
for (int j = 0; j < columns; j++)
{
lottery[i][j] = sr.Row[j];
Console.Write("{0,3},", lottery[i][j]);
}
Console.WriteLine();
}
return lottery;
}
I have prepared two versions of the Matrix function, one that is more similar to the one you are using, one that is more LINQ and "advanced".
to generate random numbers really do not use random function, use this:
private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
// Main method.
public static int[] generateTrueRandomOK()
{
const int totalRolls = 2500;
int[] results = new int[50]; //Number of random ints that you need
// Roll the dice 25000 times and display
// the results to the console.
for (int x = 0; x < totalRolls; x++)
{
byte roll = RollDice((byte)results.Length);
results[roll - 1]++;
}
return results;
}
// This method simulates a roll of the dice. The input parameter is the
// number of sides of the dice.
public static byte RollDice(byte numberSides)
{
if (numberSides <= 0)
throw new ArgumentOutOfRangeException("numberSides");
// Create a byte array to hold the random value.
byte[] randomNumber = new byte[1];
do
{
// Fill the array with a random value.
rngCsp.GetBytes(randomNumber);
}
while (!IsFairRoll(randomNumber[0], numberSides));
// Return the random number mod the number
// of sides. The possible values are zero-
// based, so we add one.
return (byte)((randomNumber[0] % numberSides) + 1);
}
private static bool IsFairRoll(byte roll, byte numSides)
{
// There are MaxValue / numSides full sets of numbers that can come up
// in a single byte. For instance, if we have a 6 sided die, there are
// 42 full sets of 1-6 that come up. The 43rd set is incomplete.
int fullSetsOfValues = Byte.MaxValue / numSides;
// If the roll is within this range of fair values, then we let it continue.
// In the 6 sided die case, a roll between 0 and 251 is allowed. (We use
// < rather than <= since the = portion allows through an extra 0 value).
// 252 through 255 would provide an extra 0, 1, 2, 3 so they are not fair
// to use.
return roll < numSides * fullSetsOfValues;
}
You could use jagged arrays:
Random random = new Random();
int[] RandomNum(int LoLim, int HiLim)
{
var nums = Enumerable.Range(LoLim,HiLim).ToArray();
for (int i = 0; i < nums.Length; i++)
{
int randomIndex = random.Next(nums.Length);
int temp = nums[randomIndex];
nums[randomIndex] = nums[i];
nums[i] = temp;
}
return nums;
}
int[][] Matrix(int Rows, int Columns)
{
int[][] LotteryArray = new int[Rows][];
for (int i = 0; i < LotteryArray.Length; i++)
{
LotteryArray[i] = RandomNum(1,46);
for (int j = 0; j < LotteryArray[i].Length; j++)
{
Console.Write("{0,3},", LotteryArray[i][j]);
}
Console.WriteLine();
}
return LotteryArray;
}

Finding the maximum value on a random array

Well im trying to find a maxValue in a array and its harder then i feel it should. Normally this code here works. If i declare an array and manually put in numbers for the array it find the max value fine. But when i put in a method to make an array with random numbers it breaks and returns the last value set as the maximum one.
static int MaxArray(int[] Array)
{
int maxVal = Array[0];
for(int i = 0; i < Array.Length; i++)
{
if(Array[i] > maxVal)
{
maxVal = Array[i];
}
}
return maxVal;
}
static void Main(string[] args)
{
Random r = new Random();
int[] myArray = new int[5];
for(int i = 0; i < myArray.Length; i++)
{
int rNumb = r.Next(0, 100);
for (int v = 0; v < myArray.Length; v++)
{
myArray[v] = rNumb;
}
Console.WriteLine(myArray[i]);
}
Console.WriteLine("Press entere to find the max value");
Console.ReadKey();
Console.Write(MaxArray(myArray));
Console.Read();
}
The inner for-loop in your Main method is useless. It fills the whole array with the current random number (so at the end the whole array will contain the last random number repeated).
The correct code is the following:
for(int i = 0; i < myArray.Length; i++)
{
int rNumb = r.Next(0, 100);
myArray[i] = rNumb;
Console.WriteLine(myArray[i]);
}
You were overwriting the values with your second for loop,
for (int v = 0; v < myArray.Length; v++)
{
myArray[v] = rNumb;
}
will write the current random number at each index of your array. The last random number will overwrite previous ones, so it will be declared as max since it's the only available number in your array.
Try this instead :
static void Main(string[] args)
{
Random r = new Random();
int[] myArray = new int[5];
for (int i = 0; i < myArray.Length; i++)
{
myArray[i] = r.Next(0, 100);
Console.WriteLine(myArray[i]);
}
Console.WriteLine("Press entere to find the max value");
Console.Write(MaxArray(myArray));
Console.Read();
}
But honestly that MaxArray method is useless, don't reinvent the wheel, use Max from LINQ instead :
Console.Write(myArray.Max());
This is easily achieved using Linq.
using System.Linq;
private static Random _random = new Random();
public static int[] GenerateRandomArray(int arrayLength)
{
return Enumerable.Range(0, arrayLength).Select(i => _random.Next(0, 100)).ToArray();
}
public static int FindMaxValue(int[] array)
{
return array.Max();
}
It's because your array initialization is completely useless. This is what you're looking for:
for(int i = 0; i < myArray.Length; i++)
{
myArray[i] = r.Next(0, 100);
Console.WriteLine(myArray[i]);
}
At the end of it, the array will look like this (with your code):
{n, n, n, n, n}
where n is the last random number.
You don't need this loop. You should change this
for (int v = 0; v < myArray.Length; v++)
{
myArray[v] = rNumb;
}
with
myArray[i] = rNumb;
By writing this loop you are overwriting all the values in the array with the last value.
The reason you get the last value set as the maximum every time is because you set every element in the array to the last random number generated on the last iteration of the outer for loop.
Your Console.WriteLine(myArray[i]); is giving you a false impression of what the values of the array you pass into MaxValue() actually are!

Categories