I'm making a lotto array game where I'm supposed to write 10 different numbers in to the array and see if I get a bingo. I want it to be 2 dimensional and I have got most of the code right (I have tried it in 1D) but just as I change it to be 2D, I get a problem with the array (array[i]) and I don´t know why.
Here is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace kents.lottospel
{
class Program
{
static void Main(string[] args)
{
Random rand = new Random();
int randNum = rand.Next(1, 20);
Console.WriteLine("skriv in nummer");
for(var i= 0; i < 2; i++)
{
for(var j= 0; j < 5; j++)
{
array[i, j] = int.Parse(Console.ReadLine());
if (array[i, j] == randNum) //and this is also
one problem (array[i])
{
Console.WriteLine($"Bing!\nDet rätta talet
var" + " " + randNum);
break;
}
else
{
Console.WriteLine($"tyvärr men du har inte
fått nån bingo denna gången");
}
}
}
Console.WriteLine("skriv in lottoboll nummer" + "
" + i + ":");
Console.WriteLine($"boll nummer" + " " + randNum + " "
+ "gav bingo");
Console.WriteLine("slut på spelet.");
}
}
}
With a two dimensional array, you need two different values to index into it. If you only specify a single value for the index with a 2D jagged array for example, the result will be another array, not a single integer value:
//This will be an int[]
var subArray = array[0]
//This will be an int
var element = array[0][0]
When you are reading input values from the console, you are only specifying one index value for the array so that expression boils down to something like this:
int[] array = new array[5];
array = 42; //compiler error
To populate a 2D array, you will need to change your loop to be a nested one. The outer loop will iterate over the first dimension and the inner loop will iterate over the second dimension:
for(var i = 0; i < 2; i++)
{
for(var j = 0; j < 5; j++)
{
array[i,j] = int.Parse(Console.ReadLine(...));
}
}
The whole point of a 2D array is that it has two dimensions. To access an element, you must specify the index in each dimension. That means that you can't use a single for loop to traverse it either. You generally use two nested for loops, e.g.
for (var i = 0; i <= myArray.GetUpperBound(0); i++)
{
for (var j = 0; j <= myArray.GetUpperBound(1); j++)
{
// Use myArray[i, j] here.
}
}
It's also up to you to make sure that you are consistent with regards to what's a "row" and what's a "column", as they are not explicit in a 2D array.
To be a bit more explicit, here's an example of setting each element in a 2D array and then getting each element:
var myArray = new long[10, 10];
for (var i = 0; i <= myArray.GetUpperBound(0); i++)
{
for (var j = 0; j <= myArray.GetUpperBound(1); j++)
{
myArray[i, j] = DateTime.Now.Ticks;
}
}
for (var i = 0; i <= myArray.GetUpperBound(0); i++)
{
for (var j = 0; j <= myArray.GetUpperBound(1); j++)
{
Console.WriteLine("({0},{1}): {2}", i, j, myArray[i, j]);
}
}
Related
I have a multi-dimensional array in C#, I have assigned the indices of the matrices by capturing input from a user, I am trying to implement a conditional structure that will let me print the rows of my matrix each on a separate line, for example if my array is A and A has a dimension of 3 by 3 then the code prints the first three elements on the first line, the next three elements on the next line and so on and so forth. I am trying to achieve this because it will be easier to understand the structure as a normal matrix and also build an entire matrix class with miscallenous operations.
Code
class Matrix{
static int[,] matrixA;
static void Main(string[] args){
Console.WriteLine("Enter the order of the matrix");
int n = Int32.Parse(Console.ReadLine());
matrixA = new int[n, n];
//assigning the matrix with values from the user
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
matrixA[i, j] = Int32.Parse(Console.ReadLine());
}
}
//the code below tries to implement a line break after each row for the matrix
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if( (n-1-i) == 0)
{
Console.Write("\n");
}
else
{
Console.Write(matrixA[i, j].ToString() + " ");
}
}
}
}
}
How do I modify my code so that if the array has 9 elements and its a square matrix then each row with three elements are printed on a single line.
I would use something like this for the output:
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(matrixA[i, j].ToString() + " ");
}
Console.Write("\n");
}
When the inner loop is done, that means one row has been completely printed. So that's the only time the newline is needed. (n passes of the outer loop ==> n newlines printed).
I am trying to find the smallest number in a dynamic 2d array but i have
hit a block and cannot figure out how this is done. I have done all the set up and populated with values.
using System;
namespace _2D_Array
{
class Program
{
static void Main(string[] args)
{
// Create integers n and r and set up the 2D array
int n = 5;
int[,] a;
int R = 50;
int x;
a = new int[n + 1, n + 1];
// Create number input randomizer
Random r = new Random();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
a[i, j] = r.Next(1, R);
// Print array with random numbers to screen to check set up is correct for i and j
Console.Write(" ");
for (int i = 1; i <= n; ++i)
Console.Write(i.ToString("00" + " "));
Console.WriteLine();
Console.WriteLine();
for (int i = 1; i <= n; ++i)
{
Console.Write(i.ToString("00" + " "));
for (int j = 1; j <= n; ++j)
Console.Write(a[i, j].ToString("00" + " "));
Console.WriteLine();
}
// Get Search Value
Console.Write("What's the value to look for? ");
x = int.Parse(Console.ReadLine());
// look through the array
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
// If the element is found
if (a[i, j] == x)
{
Console.Write("Element found at (" + i + ", " + j + ")\n");
}
}
Console.Write(" Element not found");
```
This is all i have so far. in the end i want to have the smallest
value from a set of random numbers set in my 5x5 array.
First of all, format out your code: hard to read code is hard to debug.
Often, we can query array with a help of Linq:
using System.Linq;
...
int min = a.OfType<int>().Min();
Console.Write($"The smallest element is {min}");
If you want good old nested loops:
// not 0! What if min = 123?
// Another possibility is min = a[0, 0]; - min is the 1st item
int min = int.MaxValue;
// note a.GetLength(0), a.GetLength(0): n is redundant here
// and there's no guarantee that we have a square array
for (int r = 0; r < a.GetLength(0); ++r)
for (int c = 0; c < a.GetLength(1); ++c)
min = Math.Min(min, a[r, c]);
Console.Write($"The smallest element is {min}");
I wrote this simple program:
class Program
{
static void Main(string[] args)
{
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
int[] array = new int[numberOfElements];
for(int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i+1}: ");
array[i] = int.Parse(Console.ReadLine());
}
for(int i = 0; i < array.Length; i++)
{
int count = 0;
for(int j = 0; j < array.Length; j++)
{
if(array[i] == array[j])
{
count++;
}
}
Console.WriteLine($"{array[i]} appears " + count + " times");
}
}
}
}
Is there any option to make the displayed values print only once?
For example, if there are three occurrences - the message displays three times. Is it possible to make it display once when there are more occurrences though?
You could use a GroupBy instead of the for loop
Groups the elements of a sequence.
var results = array
.GroupBy(x => x)
.Select(x => new {Value = x, Count = x.Count()});
foreach(var g in results)
Console.WriteLine($"{g.Value} appears {g.Count} times");
Or another way it to use a HashSet to keep track of what you have displayed. A HashSet is basically a collection that contains no duplicate elements. The Add methods returns true if it can add an element or false otherwise
HashSet<T>.Add(T) Method
returns true if the element is added to the HashSet object; false if the
element is already present.
var hashSet = new HashSet<int>();
for (int i = 0; i < array.Length; i++)
{
int count = 0;
for (int j = 0; j < array.Length; j++)
if (array[i] == array[j])
count++;
// Add to the hashset, if the add method returns true,
// it means the value was uniquely added, ergo you have not displayed yet
if (hashSet.Add(array[i]))
Console.WriteLine($"{array[i]} appears " + count + " times");
}
Full Demo Here
Or another approach is to use a Dictionary. The premise is to iterate over the array, try an add each item to the dictionary with TryAdd if it's already found increment the value
var dictionary = new Dictionary<int,int>();
foreach(var item in array)
if(!dictionary.TryAdd(item,1))
dictionary[item]++;
foreach(var item in dictionary)
Console.WriteLine($"{item.Key} appears {item.Value} times");
Full Demo Here
The first idea I had was the same of the comment from Jon Skeet, since the simplicity it implies.
The idea is to set null for the value we have already counted (matched).
From a developer point of view it is very simple and doesn't deviate too much from the OP's code.
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
int?[] array = new int?[numberOfElements];
for (int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i + 1}: ");
array[i] = int.Parse(Console.ReadLine());
}
for (int i = 0; i < array.Length; i++)
{
int count = 0;
int? current = array[i];
if (array[i] != null)
{
for (int j = 0; j < array.Length; j++)
{
if (current == array[j])
{
count++;
array[j] = null;
}
}
Console.WriteLine($"{current} appears " + count + " times");
}
}
int?[] defines a nullable value type. Therefore each item in the array can have either a null or int value - documentation here.
An approach using Dictionary with O(n) complexity.
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
var dictionary = new Dictionary<int, int>();
for (int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i + 1}: ");
var value = int.Parse(Console.ReadLine());
if (!dictionary.ContainsKey(value)) dictionary.Add(value, 0);
dictionary[value] = dictionary[value] + 1;
}
foreach (var item in dictionary)
{
Console.WriteLine($"{item.Key} appears {item.Value} times");
}
One simple way would be to swap your outer for loop with a foreach using a set to obtain distinct values.
So replace this:
for (int i = 0; i < array.Length; i++)
With this:
foreach (int i in new HashSet<int>(array))
And this:
if (array[i] == array[j])
With this:
if (i == array[j])
Other approach more suited for you would be too take only unique values from array, i.e.:
var unique = array.Distinct().ToArray();
for (int i = 0; i < unique.Length; i++)
{
int count = 0;
for (int j = 0; j < array.Length; j++)
{
if (array[i] == array[j])
{
count++;
}
}
Console.WriteLine($"{unique[i]} appears " + count + " times");
}
In the inner loop, try to check if there were already any occurrences of the current element until you exceed the outer index.
for(int i = 0; i < array.Length-1; i++)
{
int count = 1;
bool appeared = false;
for(int j = 0; j < array.Length; j++)
{
// until we are not at the same index as the outer loop
// check if we haven't already met the current element
if(j < i)
{
if (array[i] == array[j])
{
// set current value appearance to true
// to know if current element should be displayed
appeared = true;
// break the loop because there is no sense of continuing
// current look
break;
}
}
// if we are ahead of outer index
// check if there are occurences of the element
else if(j > i)
{
if (array[i] == array[j])
count++;
}
}
// don't print the current element if it has appeared before
if(!appeared)
Console.WriteLine($"{array[i]} appears {count} times");
}
I believe there should be a more optimal solution, as this one's time complexity is linear... You can think of some optimization. For example, you can store occurred elements in the array and check through the array at each iteration, so you don't need to start the inner loop from the beginning, but instead start it from the outer loop's position + 1 but it's also not the best solution.
P.S check out about string interpolation, because you don't need to concatenate strings when you use it.
You can also use Lookup here:
var sb = new StringBuilder();
foreach (var value in array.ToLookup(item => item))
{
sb.AppendLine($"{value.Key} appears " + value.Count() + " times");
}
Console.WriteLine(sb.ToString());
While printing this jagged array I am getting the no of rows to be 1 less than expected. It should start with 0th index to (h-1)th index creating a total of h rows. What am I doing wrong?
h is the no. of rows.
int h = int.Parse(Console.ReadLine());
int[][] arr = new int[h][];
for(int i = 0; i < h; ++i)
{
arr[i] = new int[i+1];
}
for(int i = 0; i < h; i++)
{
Console.WriteLine();
for(int j = 0; j < i; j++)
{
Console.Write(arr[i][j] + " ");
}
}
That's because your inner for-loop has the condition j < i. If i is 0 in the first pass, the inner for-loop will not be passed.
Try it with
for(int j = 0; j < arr[i].Length; j++)
{
Console.Write(arr[i][j] + " ");
}
The arrays have a growing list of elements, starting with 1 so if you want to scan all the items:
for(int i = 0; i < h; i++)
{
Console.WriteLine();
for(int j = 0; j < (i + 1); j++)
{
Console.Write(arr[i][j] + " ");
}
}
Shouldn't it be:
new int[i];
Instead of:
new int[i+1]
Or is it h - 1? Just change that index of the array.
Or you need j < arr[i].Length
I'm trying to write a code that will fill array with unique numbers.
I could write the code separately for 1, 2 and 3 dimensional arrays but number of for cycles grow to "infinity".
this is the code for 2D array:
static void fillArray(int[,] array)
{
Random rand = new Random();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = rand.Next(1, 100);
for (int k = 0; k < j; k++)
if (array[i, k] == array[i, j])
j--;
}
}
print_info(array);
}
Is it possible to do something like this for n-dimensional arrays?
My approach is to start with a 1-d array of unique numbers, which you can shuffle, and then slot into appropriate places in your real array.
Here is the main function:
private static void Initialize(Array array)
{
var rank = array.Rank;
var dimensionLengths = new List<int>();
var totalSize = 1;
int[] arrayIndices = new int[rank];
for (var dimension = 0; dimension < rank; dimension++)
{
var upperBound = array.GetLength(dimension);
dimensionLengths.Add(upperBound);
totalSize *= upperBound;
}
var singleArray = new int[totalSize];
for (int i = 0; i < totalSize; i++) singleArray[i] = i;
singleArray = Shuffle(singleArray);
for (var i = 0; i < singleArray.Length; i++)
{
var remainingIndex = i;
for (var dimension = array.Rank - 1; dimension >= 0; dimension--)
{
arrayIndices[dimension] = remainingIndex%dimensionLengths[dimension];
remainingIndex /= dimensionLengths[dimension];
}
// Now, set the appropriate cell in your real array:
array.SetValue(singleArray[i], arrayIndices);
}
}
The key in this example is the array.SetValue(value, params int[] indices) function. By building up the correct list of indices, you can use this function to set an arbitrary cell in your array.
Here is the Shuffle function:
private static int[] Shuffle(int[] singleArray)
{
var random = new Random();
for (int i = singleArray.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
int tmp = singleArray[j];
singleArray[j] = singleArray[i - 1];
singleArray[i - 1] = tmp;
}
return singleArray;
}
And finally a demonstration of it in use:
var array1 = new int[2,3,5];
Initialize(array1);
var array2 = new int[2,2,3,4];
Initialize(array2);
My strategy assigns sequential numbers to the original 1-d array to ensure uniqueness, but you can adopt a different strategy for this as you see fit.
You can use Rank property to get the total number of dimentions in your array
To insert use SetValue method
In the first two for loops you are analysing the array properly (i and j go from the start to the end of the corresponding dimension). The problem comes in the most internal part where you introduce a "correction" which actually provokes an endless loop for j.
First iteration:
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
Second iteration
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
. etc., etc.
(I start my analysis in the moment when the internal loop is used for the first time. Also bear in mind that the exact behaviour cannot be predicted as far as random numbers are involved. But the idea is that you are making the j counter back over and over by following an arbitrary rule).
What you want to accomplish exactly? What is this last correction (the one provoking the endless loop) meant to do?
If the only thing you intend to do is checking the previously stored values, you have to rely on a different variable (j2, for example) which will not affect any of the loops above:
int j2 = j;
for (int k = 0; k < j2; k++)
if (array[i, k] == array[i, j2])
j2--;