I have a 2D string array.
I just want to randomize the rows order and shuffle the items within each row.
So for example:
[1,2
3,4]
I want it to be as below, row pairs stay same here (order change is valid):
[4,3
1,2] or
[3,4
2,1] or
[4,3
2,1] or
[1,2
3,4] or
[2,1
3,4] or
[2,1
4,3] or
[3,4
1,2]
and i want to avoid below shuffling because i'll read my array row by row, i want to keep my rows to contain same elements. I want to keep my row pairs. Below, my [1,2] and [3,4] rows does not exist anymore :
[1,3
2,4] or
[3,1
4,2] or
[3,1
2,4] or
[1,4
2,3] ....
So here is my array:
array_to_shuffle = new string[len_2d,2];
Shuffle(array_to_shuffle);
and the function i need help :
public void Shuffle(Random rand, string[,] array)
{
rand = new Random();
int[] randomised_array = new int[len_2d];
for (int i = 0; i < len_2d; i++)
{
randomised_array[i] = i;
}
int[] MyRandomArray = randomised_array.OrderBy(x => rand.Next()).ToArray();
string tmp1 = String.Empty;
string tmp2 = String.Empty;
array[MyRandomArray[0], 0] = tmp1;
array[MyRandomArray[0], 1] = tmp2;
array[MyRandomArray[0], 0] = array[MyRandomArray[1],0];
array[MyRandomArray[0], 1] = array[MyRandomArray[1],1];
array[MyRandomArray[1], 0] = tmp2;
array[MyRandomArray[1], 1] = tmp1;
}
Thank you everyone...
Try this code (necessary comments are in code):
static void Main(string[] args)
{
int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 10 }, { 11, 12 } };
matrix = Shuffle(matrix);
}
static T[,] Shuffle<T>(T[,] matrix)
{
int howManyRows = matrix.GetLength(0);
int howManyColumns = matrix.GetLength(1);
T[,] randomizedMatrix = new T[howManyRows, howManyColumns];
//we will use those arrays to randomize indexes
int[] shuffledRowIndexes = Enumerable.Range(0, howManyRows).ToArray();
int[] shuffledColumnIndexes = Enumerable.Range(0, howManyColumns).ToArray();
Random rnd = new Random();
shuffledRowIndexes = shuffledRowIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int i = 0; i < howManyRows; i++)
{
// at every loop we get new randomized column idexes, so every row will be shuffled independently
shuffledColumnIndexes = shuffledColumnIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int j = 0; j < howManyColumns; j++)
randomizedMatrix[i, j] = matrix[shuffledRowIndexes.ElementAt(i), shuffledColumnIndexes.ElementAt(j)];
}
return randomizedMatrix;
}
Helpful articles:
Best way to randomize an array with .NET
What are the differences between a multidimensional array and an array of arrays in C#?
Related
I'd like help* in creating a method or (linq) expression that can row-wise concatenate lists (of varying lengths) of jagged arrays as the one below:
List<double[][]> orgArrayList = new List<double[][]>();
double[][] one = {
new [] {5d, 6},
new [] {7d, 9}};
double [][] two = {
new [] {5d, 6},
new [] {7d, 9}};
double [][] three= {
new [] {5d, 6},
new [] {7d, 9}};
orgArrayList.AddRange(new[] {one, two, three});
So that the resulting array will be equal to this one:
double[][] expected = {
new [] {5d, 6, 5, 6, 5, 6},
new [] {7d, 9, 7, 9, 7, 9}};
The number of jagged arrays in my input list(s) will be >=1. All arrays within a single list will be jagged with 2 dimensions, but none of the 2 dimensions will have a fixed/known length (size).
*'help' being a euphemism for someone telling me how to do it
You could start with something like this, which appends the elements of each row of add[] to the rows of src[], producing a new 2-dimensional array:
public static double[][] AppendToRows(double[][] src, double[][] add)
{
// Allocate new array to hold elements from src[] and add[]
double[][] res = new double[src.Length][];
// Append elements to each row of res[]
for (int i = 0; i < src.Length; i++)
{
// Allocate row res[i] large enough to hold elements from src[i] and add[i]
res[i] = new double[src[i].Length + add[i].Length];
// Copy/append elements from src[i] to res[i]
int ri = 0;
for (int j = 0; j < src[i].Length; j++)
res[i][ri++] = src[i][j];
// Copy/append elements from add[i] to res[i]
if (i >= add.Length)
continue;
for (int j = 0; j < add[i].Length; j++)
res[i][ri++] = add[i][j];
}
return res;
}
To append multiple arrays together, just call this method multiple times, once for each additional array that needs to be concatenated onto the resulting array.
A more comprehensive solution would be to take a List<double[][]> of input arrays, and to loop through each array in the list as you build each row of the result. But I have left that as an exercise for the reader.
You can create an extension, that will concatenate arrays the way you need, so it will looks like Linq:
public static class Extension
{
public static T[][] ConcatArrays<T>(this T[][] array, T[][] concatWith)
{
var max = Math.Max(array.Length, concatWith.Length);
var result = new T[max][];
for (var index = 0; index < max; index++)
{
var list = new List<T>();
if (index < array.Length)
{
list.AddRange(array[index]);
}
if (index < concatWith.Length)
{
list.AddRange(concatWith[index]);
}
result[index] = list.ToArray();
}
return result;
}
}
So the usage of this is:
var expected = one.ConcatArrays(two).ConcatArrays(three);
Hope it makes sense
As a final solution for my use case I simply combined David's and Valdimir's answer into a single method that can handle lists of varying lengths (>=1).
// ========================================
// My interpretation of David's suggestion
// using Valdimir's solution as a basis
// ========================================
public static double[][] RowWiseConcatListedJaggedArrays(List<double[][]> listOfJaggedArray)
{
var resArray = listOfJaggedArray[0];
for (int rInd = 1; rInd < listOfJaggedArray.Count; rInd++)
{
resArray = resArray.ConcatArrays(listOfJaggedArray[rInd]);
}
return resArray;
}
And putting everything together...
using System;
using System.Collections.Generic;
namespace RowWiseConcat
{
public static class Extension
{
// ====================
// Vladimir's solution
// ====================
public static T[][] ConcatArrays<T>(this T[][] array, T[][] concatWith)
{
var max = Math.Max(array.Length, concatWith.Length);
var result = new T[max][];
for (var index = 0; index < max; index++)
{
var list = new List<T>();
if (index < array.Length)
{
list.AddRange(array[index]);
}
if (index < concatWith.Length)
{
list.AddRange(concatWith[index]);
}
result[index] = list.ToArray();
}
return result;
}
}
class Program
{
// ========================================
// My interpretation of David's suggestion
// using Valdimir's solution as a basis
// ========================================
public static double[][] RowWiseConcatListedJaggedArrays(List<double[][]> listOfJaggedArray)
{
var resArray = listOfJaggedArray[0];
for (int rInd = 1; rInd < listOfJaggedArray.Count; rInd++)
{
resArray = resArray.ConcatArrays(listOfJaggedArray[rInd]);
}
return resArray;
}
static void Main(string[] args)
{
// ... do something that results in orgArrayList, e.g.
double[][] one =
{
new[] {5d, 6},
new[] {7d, 9}
};
double[][] two =
{
new[] {5d, 6},
new[] {7d, 9}
};
double[][] three =
{
new[] {5d, 6},
new[] {7d, 9}
};
List<double[][]> orgArrayList = new List<double[][]>()
{ one, two, three};
// Concat list items
var resArray = RowWiseConcatListedJaggedArrays(orgArrayList);
// ... continue with resArray
}
}
}
Let's say I want to insert values into an array while at the same time sorting it.
This was my solution:
int[] arr = new int[5];
int k;
arr[0] = int.Parse(Console.ReadLine());
for (int i = 1; i < arr.Length; i++)
{
int num = int.Parse(Console.ReadLine());
for (k = i; k > 0 && num < arr[k - 1];--k) arr[k] = arr[k - 1];
arr[k] = num;
}
I know I didn't handle exceptions, I'm just talking about the code itself.
Is there a better way of doing this?
You can use a SortedSet<>, that gets automatically sorted as you add items.
var numbers = new SortedSet<int>()
{
4,
9,
6,
3
};
foreach (var number in numbers)
{
Console.WriteLine(number);
}
If it doesn't have to be array you could do this:
static void Main(string[] args)
{
List<int> list = new List<int>
{
1,
2,
7,
10
};
int k = int.Parse(Console.ReadLine());
list.Add(k);
list.Sort();
}
Edit: if you want to sort when inserting you could do this:
int k = int.Parse(Console.ReadLine());
int i = list.Where(x => x > k).Min();
int index = list.IndexOf(i);
list.Insert(index, k);
You can use a List and convert it into an array. When you maintain your list ordered at all time you can use the list's BinarySearch method to get the insert index:
const int length = 5;
List<int> result = new List<int>(length);
for (int i = 0; i < length; i++) {
int num = int.Parse(Console.ReadLine());
int insertIndex = result.BinarySearch(num);
if (insertIndex < 0) {
insertIndex = ~insertIndex;
}
result.Insert(insertIndex, num);
}
int[] arr = result.ToArray();
The binary search is much faster than the linear search you are currently performing. You won't see that with your current 5 values. You would defenitely see it with larger lists (hundrets or thousands of values).
Can't figure out why the line winningNumbers[i] += count; comes up as outside the bounds of the array.
static int[] CheckWinningNumbers(int[][]lottoNumbers, int[]drawNumbers)
{
int[] winningNumbers = new int[8];
for (int i = 0; i < lottoNumbers.Length; i++)
{
int k = 0;
int count = 0;
for (int j = 0; j < lottoNumbers[i].Length; j++)
{
if (lottoNumbers[i][j] == drawNumbers[k])
{
count +=1;
}
k += 1;
winningNumbers[i] += count;
}
}
return winningNumbers;
Just replace
int[] winningNumbers = new int[8];
With
int[] winningNumbers = new int[lottoNumbers.Length];
As long as you are iterating lottoNumbers.Length the variable i will not exceed its boundaries.
Edit
I ran it with the following data and it works
int[][] lottoNumbers = { new[] { 1, 2 },
new[]{ 3, 4 },
new[]{ 5, 6 },
new[]{ 7, 8 } };
int[] drawNumbers = {1, 4, 5, 8};
I don't know what data you are testing it on but you are using jagged arrays intead of multidimensional. this will not guarantee that all your sub arrays have the same length which might be problematic. If all the arrays have the same length and performance is not critical here I'd suggest you use Multidimensional Arrays
How to delete a specific row and column from 2D array in C#?
int[,] array= {{1,2,3},{4,5,6},{7,8,9}};
lets say I want to delete row i and column i (skipping them) ... for nXn array not just 3x3 and store the remaining array in a new array...
so the output would be:
{5,6},{8,9}
There's no built-in way to do that, you can do it yourself:
static void Main()
{
int[,] array = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
var trim = TrimArray(0, 2, array);
}
public static int[,] TrimArray(int rowToRemove, int columnToRemove, int[,] originalArray)
{
int[,] result = new int[originalArray.GetLength(0) - 1, originalArray.GetLength(1) - 1];
for (int i = 0, j = 0; i < originalArray.GetLength(0); i++)
{
if (i == rowToRemove)
continue;
for (int k = 0, u = 0; k < originalArray.GetLength(1); k++)
{
if (k == columnToRemove)
continue;
result[j, u] = originalArray[i, k];
u++;
}
j++;
}
return result;
}
No, arrays don't let you do that. You could make your own data structure for that, but it's not going to be exactly simple (unlike if you only wanted to be able to remove rows, for example).
For simple operations, it would be quite enough to build a class on top of an underlying array, and handle the re-indexing to map the virtual 2D array to the physical array underneath. But it's going to get a bit tricky as you combine removals and additions, and deform the array overall.
Very simple logic. Just play with the loop:
int[,] array = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int[,] arrayskip = new int[array.GetLength(0) - 1, array.GetLength(1) - 1];
for (int i = 1; i < array.GetLength(0); i++)
{
for (int j = 1; j < array.GetLength(1); j++)
{
arrayskip[i - 1, j - 1] = array[i, j];
}
}
I created this method, have a look
public static double[,] fillNewArr(double[,] originalArr, int row, int col)
{
double[,] tempArray = new double[originalArr.GetLength(0) - 1, originalArr.GetLength(1) - 1];
int newRow = 0;
int newCol = 0;
for (int i = 0; i < originalArr.GetLength(0); i++)
{
for (int j = 0; j < originalArr.GetLength(1); j++)
{
if(i != row && j != col)
{
tempArray[newRow, newCol] = originalArr[i, j];
newRow++;
newCol++;
}
}
}
return tempArray;
}
having some out of range, It's obvious why but I'm trying to get there...
I have this Array i wrote a function MostFreq that takes an array of integers and return 2 values : the more frequent number in the array and its frequency check this code i worte what do you think ? is there a better way to do it?
static void Main()
{
int [] M={4,5,6,4,4,3,5,3};
int x;
int f=MyMath.MostFreq(M,out x );
console.WriteLine("the most Frequent Item = {0} with frequency = {1}",x,f);
}
=====
in the class Mymath
public static int MostFreq(int[] _M, out int x)
{
//First I need to sort the array in ascending order
int Max_Freq, No_Freq, i, k;
Array.Sort(_M);
k = _M[0];
Max_Freq = 0; i = 0; x = 0;
while (i < _M.Length)
{
//No_Freq= the frequency of the current number
No_Freq = 0;
//X here is the number which is appear in the array Frequently
while (k == _M[i])
{
No_Freq++;
i++;
if (i == _M.Length)
break;
}
if (No_Freq > Max_Freq)
{
//so it will be printed the same
Max_Freq = No_Freq;
x = k;
}
if (i < _M.Length) k = _M[i];
}
return (Max_Freq);
}
LINQ it up. I know this is in VB but you should be able to convert it to C#:
Dim i = From Numbers In ints _
Group Numbers By Numbers Into Group _
Aggregate feq In Group Into Count() _
Select New With {.Number = Numbers, .Count = Count}
EDIT: Now in C# too:
var i = from numbers in M
group numbers by numbers into grouped
select new { Number = grouped.Key, Freq = grouped.Count()};
Assuming you can't use LINQ, I'd probably approach the algorithm like this:
Create Key/Value dictionary
Iterate your array, add a key the dictionary for each unique elem, increment the value each time that element is repeated.
Walk the dictionary keys, and return the elem with the highest value.
This isn't a great solution but it is simple, ContainsKey is an O(1) lookup, so you'll be at most iterating your array twice.
From a software engineering standpoint, I would expect a function called MostFreq to return the element with the highest frequency - not the frequency itself. I would switch your out and return values.
You could eliminate the sort you do at the start by iterating the entire array once, keeping a count of how many times you come across each value in a temporary array, and then iterating the temporary array for the highest number. You could keep both the highest frequency count and the most frequent item throughout, too.
Different sorts have different efficiencies on different types of data, of course, but this would be a worst case of just two iterations.
Edit: Apologies for the repeat... 'Tweren't there when I started :)
Done in 1 pass....
public class PopularNumber
{
private Int32[] numbers = {5, 4, 3, 32, 6, 6, 3, 3, 2, 2, 31, 1, 32, 4, 3, 4, 5, 6};
public PopularNumber()
{
Dictionary<Int32,Int32> bucket = new Dictionary<Int32,Int32>();
Int32 maxInt = Int32.MinValue;
Int32 maxCount = 0;
Int32 count;
foreach (var i in numbers)
{
if (bucket.TryGetValue(i, out count))
{
count++;
bucket[i] = count;
}
else
{
count = 1;
bucket.Add(i,count);
}
if (count >= maxCount)
{
maxInt = i;
maxCount = count;
}
}
Console.WriteLine("{0},{1}",maxCount, maxInt);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MostFrequentElement
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[] { 4, 1, 1, 4, 2, 3, 4, 4, 1, 2, 4, 9, 3, 1, 1, 7, 7, 7, 7, 7 };
Array.Sort(array, (a, b) => a.CompareTo(b));
int counter = 1;
int temp=0 ;
List<int> LOCE = new List<int>();
foreach (int i in array)
{
counter = 1;
foreach (int j in array)
{
if (array[j] == array[i])
{
counter++;
}
else {
counter=1;
}
if (counter == temp)
{
LOCE.Add(array[i]);
}
if (counter > temp)
{
LOCE.Clear();
LOCE.Add(array[i]);
temp = counter;
}
}
}
foreach (var element in LOCE)
{
Console.Write(element + ",");
}
Console.WriteLine();
Console.WriteLine("(" + temp + " times)");
Console.Read();
}
}
}
Here's an example how you could do it without LINQ and no dictionaries and lists, just two simple nested loops:
public class MostFrequentNumber
{
public static void Main()
{
int[] numbers = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
int counter = 0;
int longestOccurance = 0;
int mostFrequentNumber = 0;
for (int i = 0; i < numbers.Length; i++)
{
counter = 0;
for (int j = 0; j < numbers.Length; j++)
{
if (numbers[j] == numbers[i])
{
counter++;
}
}
if (counter > longestOccurance)
{
longestOccurance = counter;
mostFrequentNumber = numbers[i];
}
}
Console.WriteLine(mostFrequentNumber);
//Console.WriteLine($"occured {longestOccurance} times");
}
}
You get the value of the most frequently occurring number, and (commented) you could get also the numbers of the occurrences.
I know I have an "using Linq;", that's just to convert the initial input string to an int array and to spare a couple of lines and a parsing loop. Algorithm is fine even without it, if you fill the array the "long" way...
Lets suppose the array is as follows :
int arr[] = {10, 20, 10, 20, 30, 20, 20,40,40,50,15,15,15};
int max = 0;
int result = 0;
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i]))
map.put(arr[i], map.get(arr[i]) + 1);
else
map.put(arr[i], 1);
int key = map.keySet().iterator().next();
if (map.get(key) > max) {
max = map.get(key) ;
result = key;
}
}
System.out.println(result);
Explanation:
In the above code I have taken HashMap to store the elements in keys and the repetition of the elements as values. We have initialized variable max = 0 ( max is the maximum count of repeated element) While iterating over elements We are also getting the max count of keys.
The result variable returns the keys with the mostly repeated.
int[] arr = { 4, 5, 6, 4, 4, 3, 5, 3 };
var gr = arr.GroupBy(x => x).OrderBy(x => x.Count()).Last();
Console.WriteLine($"The most Frequent Item = {gr.Key} with frequency = {gr.Count()}"); // The most Frequent Item = 4 with frequency = 3
int[] numbers = new int[] {1, 2, 3, 2, 1, 4, 2};
Dictionary<int, int> numberCounts = new Dictionary<int, int>();
foreach (int number in numbers)
{
if (numberCounts.ContainsKey(number))
{
numberCounts[number]++;
}
else
{
numberCounts[number] = 1;
}
}
int maxCount = numberCounts.Values.Max();
int mostFrequentNumber = numberCounts.Where(x => x.Value == maxCount).OrderByDescending(x => x.Key).First().Key;
Console.WriteLine("Most frequent number: " + mostFrequentNumber);
int count = 1;
int currentIndex = 0;
for (int i = 1; i < A.Length; i++)
{
if (A[i] == A[currentIndex])
count++;
else
count--;
if (count == 0)
{
currentIndex = i;
count = 1;
}
}
int mostFreq = A[currentIndex];