In a method I am calculating the longest row of elements. The 1-dimensional array is filled up with random values (0 or 1). The method looks up the longest row (being 0 or 1, whatever is the longest).
For example:
In 1110100 the longest row would be 3 (3 * 1)
In 0110000 the longest row would be 4 (4 * 0)
For 1110100 the position in the array would be 0 to 2.
For 0110000 the position in the array would be 3 to 6.
I have been trying with foreach loops, for loops, etc. but I cannot seem to get the proper indexes of both and cannot seem to display both positions properly.
The longest row of similar elements gets calculated as the following based on my previous question:
public int BerekenDeelrij (int [] table)
{
int count = 0;
int value = 0;
int largest = 0;
for (int i=0; i < tabel.Length; i++)
{
if (value == tabel[i])
counter + +;
else
{
largest = Math.Max largest (largest, counter);
final value = value
count = 1;
}
}
return Math.Max(largest, counter);
}
If you replace the foreach() with a regular for(;;) you immediately have your indices available at the moment you need them.
I'm not posting complete code, since this is tagged homework, but a completely different approach to solving this problem, would be to find all the occurrences of consecutive items, and aggregate them into a new array:
[0, 1, 1, 0, 0, 0, 0] => ["0", "11", "0000"]
Then you could just order that by item.Length, descending, select top 1 item, i.e. "0000"
After that, join the aggregated array
["0", "11", "0000"] => "0110000"
And from there, return joinedResult.IndexOf( longestItem ) and that index + longestItem.Length
Related
This is my first question on this site. I am practicing on a problem on Hackerrank that asks to find numbers "Between two Sets". Given two arrays of integers, I must find the number(s) that fit the following two criteria:
1) The elements in the first array must all be factors of the number(s)
2) The number(s) must factor into all elements of the second array
I know that I need to find all common multiples of every element in the first array, but those multiples need to be less than or equal to the minimum value of the second array. I first sort the first array then find all the multiples of ONLY the largest number in the first array (again, up to a max of the second array's minimum) and store those multiples in a list. Then, I move on to the second largest element in the first array and test it against the array of existing multiples. All elements in the list of existing multiples that isn't also a multiple of the second largest element of the first array is removed. I then test the third largest value of the first array, all the way to the minimum value. The list of existing multiples should be getting trimmed as I iterate through the first array in descending order. I've written a solution which passes only 5 out of the 9 test cases on the site, see code below. My task was to edit the getTotalX function and I created the getCommonMultiples function myself as a helper. I did not create nor edit the main function. I am not sure why I am not passing the other 4 test cases as I can't see what any of the test cases are.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {
/*
* Complete the getTotalX function below.
*/
static int getTotalX(int[] a, int[] b) {
//get minimum value of second array
int b_min = b.Min();
//create List to hold multiples
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = new List<int>();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x == 0 && !solutions.Contains(x))
{
solutions.Add(x);
}
else
{
break;
}
}
}
return solutions.Count;
}
static List<int> getCommonMultiples(int[] array, int max)
{
//make sure array is sorted
Array.Sort(array);
int x = array.Length - 1; //x will be the last # in array -- the max
int y = 1;
//find all multiples of largest number first and store in a list
int z = array[x] * y;
List<int> commonMultiples = new List<int>();
while(z <= max)
{
commonMultiples.Add(z);
y++;
z = array[x] * y;
}
//all multiples of largest number are now added to the list
//go through the smaller numbers in query array
//only keep elements in list if they are also multiples of smaller
//numbers
int xx = array.Length - 2;
for(int a = array[xx]; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % a != 0)
{
commonMultiples.Remove(b);
}
else
{
continue;
}
}
}
return commonMultiples;
}
static void Main(string[] args) {
TextWriter tw = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
string[] nm = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nm[0]);
int m = Convert.ToInt32(nm[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] b = Array.ConvertAll(Console.ReadLine().Split(' '), bTemp => Convert.ToInt32(bTemp))
;
int total = getTotalX(a, b);
tw.WriteLine(total);
tw.Flush();
tw.Close();
}
}
Again, I can't see the test cases so I do not know what exactly the issue is. I went through the code line by line and can't find any OutOfBoundExceptions or things of that sort so it has to be a logic issue. Thanks for the help!
A typical sample involves 3 lines of input. The first line has 2 integers which gives the length of the first array and the second array, respectively. The second line will give the integers in the first array. The third line will give the integers in the second array. The output needs to be the total number of integers "in between" the two arrays. It will looks like this:
Sample Input
2 3
2 4
16 32 96
Sample Output
3
Explanation: 2 and 4 divide evenly into 4, 8, 12 and 16.
4, 8 and 16 divide evenly into 16, 32, 96.
4, 8 and 16 are the only three numbers for which each element of the first array is a factor and each is a factor of all elements of the second array.
I see two issues with the code you posted.
Firstly, as #Hans Kesting pointed out, a = array[xx] is not being updated each time in the for loop. Since the variable a is only used in one spot, I recommend just replacing that use with array[xx] and be done with it as follows:
for(int xx = array.Length - 2; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % array[xx] != 0)
{
commonMultiples.Remove(b);
For your understanding of for loops: to properly increment a each time you'd write the for loop like this:
for(int xx = array.Length - 2, a = array[xx]; xx >= 0; xx--, a = array[xx])
The first part of the for loop (up until ;) is the initialization stage which is only called before the entering the loop the first time. The second part is the while condition that is checked before each time through loop (including the first) and if at any time it evaluates to false, the loop is broken (stopped). The third part is the increment stage that is called only after each successful loop.
Because of that in order to keep a up to date in the for loop head, it must appear twice.
Secondly, your solutions in getTotalX is additive, meaning that each multiple that works for each value in array b is added as a solution even if it doesn't fit the other values in b. To get it to work the way that you want, we have to use a Remove loop, rather than an Add loop.
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = multiples.ToList();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x != 0)
{
solutions.Remove(x);
break;
}
}
}
You could also use LINQ to perform an additive solution where it takes into account All members of b:
//create List to hold number of ints which are in solution
List<int> solutions = multiples.Where((x) => b.All((y) => y % x == 0)).ToList();
I'm trying to do a simple sorting of my own (I know Array.Sort() exists), receiving a user input array and then calling the method sortMyArray() to sort the numbers from smallest to largest. Which does what intended, except for when I try to find the smallest number of an array that contains 0.
As you will see: I'm initialising the variable smallest to the value int.MaxValue at each iteration, but if the array contains a 0, it stays set to to the int.MaxValue.
static int findSmallest(int[] original, int[] sorted, int smallest)
{
for (int i = 0; i < sorted.Length; i++)
{
if (original[i] < smallest & !sorted.Contains(original[i]))
{
smallest = original[i];
}
}
return smallest;
}
static int[] sortMyArray(int[] original)
{
int[] sorted = new int[original.Length];
for (int i = 0; i < sorted.Length; i++)
{
int smallest = int.MaxValue;
smallest = findSmallest(original, sorted, smallest);
sorted[i] = smallest;
}
return sorted;
}
sortMyArray(inputArray);
My question is, how can I make sure 0 is properly handled?
The code behaves as intended for positive and negative integer values, but what is causing the 0 to not work?
Edit: For example, if the inputArray contains {5, -1, 7, 0, 33}, then the method will return it sorted as such: {-1, 5, 7, 33, 2147483647}.
With !sorted.Contains(original[i]) you skip over any value that is already in the array. sorted is initialized to all 0's so it will never set smallest = 0. In your last iteration in sortMyArray, smallest will be equal to int.Max. Note, this will also happen when you have the same element twice. Since you want to implement your own sorting method (and not use Array.Sort), you should look into various sorting algorithms (i.e. Merge Sort, Quick Sort, etc.) as yours won't work as intended.
I want to make a program where users have to enter a list of 100 numbers.
The outcome has to be a 2 dimensional matrix with with 34 rows and 3 columns (where the last row has only 1 number of course).
Now I want to: first sort the array by ascending order. Then I want to sort each row separately by descending order.
I'll demonstrate with a two dimensional array containing 10 elements
If these are the numbers the user enters: 2, 4, 6, 9, 5, 2, 3, 4, 9, 7
I want the array to look like this:
3 2 2
5 4 4
9 7 6
9
I think it's easier to start with a 1D array which you can later copy to a 2D array if you really have to.
Array.Sort(input); //input is an int[100]
//Now, sort each row in descending order
var comparer = Comparer<int>.Create((a, b) => b.CompareTo(a));
for (int row = 0; row < 99; r+=3) {
Array.Sort(input, row, 3, comparer);
}
It's straightforward if you do the sorting and restructuring as separate steps:
Collect the results in a flat (i.e. one-dimensional) array.
Sort the flat array (e.g. with Array.Sort(...)).
Build up your new data structure by looping through the flat array. You don't need to do any further sorting here. Each time just take [arr[n+2], arr[n+1], arr[n]] as the row in the new 2D array and jump forward to n = n + 3.
I also favour creating the output structure by looping over the sorted input structure. The following will achieve what you want. It will take any size array of integers and the required number of columns for the two-dimensional output array and return the result as you defined it.
public static int?[,] SortInput(int[] input, int requiredColumnCount)
{
// Guard conditions.
if (input == null)
throw new ArgumentNullException(nameof(input));
if (input.Length < 1)
throw new ArgumentOutOfRangeException(nameof(input));
if (requiredColumnCount < 1)
throw new ArgumentOutOfRangeException(nameof(requiredColumnCount));
var inputLength = input.Length;
// Sort the input array in ascending order.
Array.Sort(input);
// Dimension the output array.
var requiredRowCount = (int)Math.Ceiling((decimal)inputLength / requiredColumnCount);
var output = new int?[requiredRowCount, requiredColumnCount];
// Setup variables to check for special handling of last output row.
var lastRowIndex = output.GetUpperBound(0);
var columnCountForLastRow = inputLength % requiredColumnCount;
// Populate the output array.
for (var inputIndex = 0; inputIndex < inputLength; inputIndex += requiredColumnCount)
{
var rowIndex = inputIndex / requiredColumnCount;
// Special handling may be required if there are insufficient
// input values to fully populate the last output row.
if ((rowIndex == lastRowIndex) && (columnCountForLastRow != 0))
requiredColumnCount = columnCountForLastRow;
for (var columnIndex = 0; columnIndex < requiredColumnCount; columnIndex++)
{
output[rowIndex, columnIndex] = input[inputIndex + requiredColumnCount - columnIndex - 1];
}
}
return output;
}
I need to find items count in the C# array which type is integer.
What I mean is;
int[] intArray=new int[10]
int[0]=34
int[1]=65
int[2]=98
Items count for intArray is 3.
I found the code for strArray below but It doesn't work for int arrays.
string[] strArray = new string[50];
...
int result = strArray.Count(s => s != null);
Well, first you have to decide what an invalid value would be. Is it 0? If so, you could do this:
int result = intArray.Count(i => i != 0);
Note that this only works because, by default, elements of an int array are initialized to zero. You'd have to fill the array with a different, invalid value beforehand if 0 ends up being valid in your situation.
Another way would be to use a nullable type:
int?[] intArray = new int?[10];
intArray[0] = 34;
intArray[1] = 65;
intArray[2] = 98;
int result = intArray.Count(i => i.HasValue);
While itsme86 provided you a good answer to your actual question, I suspect you may be better off reconsidering how you write this entirely.
If this is your goal, I would recommend thinking about this differently. Instead of allocating a fixed size array, and only assigning specific values to it, you might want to consider using a List<int>:
List<int> intList = new List<int>();
intList.Add(34);
intList.Add(65);
intList.Add(98);
The number of items will always be intList.Count, and you can add as many items as you wish this way, without worry about the "allocated size", since the list will automatically grow as needed. It also won't provide you bad results if you add 0 to the list as an actual value, where counting non-zero elements will not count a zero if it's a valid value.
Note that you can also access the items by index, just like you do with an array:
int secondValue = intList[1]; // Access like you do with arrays
int[] intArray=new int[3] // Edit: Changed this to 3 to make my answer work. :)
int[0]=34
int[1]=65
int[2]=98
int count = intArray.Length; // <-- Is this what you're after?
Edit:
Ahem. As was so humbly pointed out to me, Length will return the total number of elements in the array, which in your example would have been 10. If you are looking for the number of non-zero elements in the array, you should do as suggested in some of the other answers.
When you initialize an integer array without specifying any values, C# assigns a value of zero to every element. So if zero isn't a valid value for your array, you could always test for that.
Alternatively, you could initialize the elements of your array to some value that is invalid in your context (ie if negative numbers aren't valid, initialize to -1), and then loop through the array counting the valid elements.
If the array is guaranteed to only be accessed in sequence, you can beat the full iterative IEnumerable Count (for larger arrays) with a little divide and conquer, e.g.
static int DivideCount(int[] arr, int idx, int bottom, int top)
{
if (idx <= 0)
return 0;
else if (idx >= arr.Length - 1)
return arr.Length;
else if (arr[idx] == 0 && arr[idx - 1] != 0)
return idx;
else if (arr[idx] == 0 && arr[idx - 1] == 0)
return DivideCount(arr, bottom + ((idx - bottom) / 2), bottom, idx);
else if (arr[idx] != 0 && arr[idx - 1] != 0)
return DivideCount(arr, top - ((top - idx) / 2), idx, top);
else
return -1; // hello compiler
}
int[] intArray = new int[10];
intArray[0] = 35;
intArray[1] = 65;
intArray[2] = 98;
var count = DivideCount(intArray, intArray.Length / 2, 0, intArray.Length);
None of the previous solutions are optimal if someone other than you initialized the array (i.e. you don't have the option of initializing the array values to invalid values -- null, -1, etc.).
Suppose you have an array:
var arr = new[] {0, 10, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0};
If you simply count the number of zero entries:
int result = arr.Count(i => i != 0);
Count() returns 3, when in reality 5 entries have been initialized. An example would be an array of raw bytes that were read out of an audio file into a buffer, and you want to know the index of the last element that was read.
An alternative that isn't perfect but could do what you're looking for is to look for the last non-zero entry, as described here: Linq - Get the Index of the Last Non-Zero Number of Array
I want to generate a shuffled merged list that will keep the internal order of the lists.
For example:
list A: 11 22 33
list B: 6 7 8
valid result: 11 22 6 33 7 8
invalid result: 22 11 7 6 33 8
Just randomly select a list (e.g. generate a random number between 0 and 1, if < 0.5 list A, otherwise list B) and then take the element from that list and add it to you new list. Repeat until you have no elements left in each list.
Generate A.Length random integers in the interval [0, B.Length). Sort the random numbers, then iterate i from 0..A.Length adding A[i] to into position r[i]+i in B. The +i is because you're shifting the original values in B to the right as you insert values from A.
This will be as random as your RNG.
None of the answers provided in this page work if you need the outputs to be uniformly distributed.
To illustrate my examples, assume we are merging two lists A=[1,2,3], B=[a,b,c]
In the approach mentioned in most answers (i.e. merging two lists a la mergesort, but choosing a list head randomly each time), the output [1 a 2 b 3 c] is far less likely than [1 2 3 a b c]. Intuitively, this happens because when you run out of elements in a list, then the elements on the other list are appended at the end. Because of that, the probability for the first case is 0.5*0.5*0.5 = 0.5^3 = 0.125, but in the second case, there are more random random events, since a random head has to be picked 5 times instead of just 3, leaving us with a probability of 0.5^5 = 0.03125. An empirical evaluation also easily validates these results.
The answer suggested by #marcog is almost correct. However, there is an issue where the distribution of r is not uniform after sorting it. This happens because original lists [0,1,2], [2,1,0], [2,1,0] all get sorted into [0,1,2], making this sorted r more likely than, for example, [0,0,0] for which there is only one possibility.
There is a clever way of generating the list r in such a way that it is uniformly distributed, as seen in this Math StackExchange question: https://math.stackexchange.com/questions/3218854/randomly-generate-a-sorted-set-with-uniform-distribution
To summarize the answer to that question, you must sample |B| elements (uniformly at random, and without repetition) from the set {0,1,..|A|+|B|-1}, sort the result and then subtract its index to each element in this new list. The result is the list r that can be used in replacement at #marcog's answer.
Original Answer:
static IEnumerable<T> MergeShuffle<T>(IEnumerable<T> lista, IEnumerable<T> listb)
{
var first = lista.GetEnumerator();
var second = listb.GetEnumerator();
var rand = new Random();
bool exhaustedA = false;
bool exhaustedB = false;
while (!(exhaustedA && exhaustedB))
{
bool found = false;
if (!exhaustedB && (exhaustedA || rand.Next(0, 2) == 0))
{
exhaustedB = !(found = second.MoveNext());
if (found)
yield return second.Current;
}
if (!found && !exhaustedA)
{
exhaustedA = !(found = first.MoveNext());
if (found)
yield return first.Current;
}
}
}
Second answer based on marcog's answer
static IEnumerable<T> MergeShuffle<T>(IEnumerable<T> lista, IEnumerable<T> listb)
{
int total = lista.Count() + listb.Count();
var random = new Random();
var indexes = Enumerable.Range(0, total-1)
.OrderBy(_=>random.NextDouble())
.Take(lista.Count())
.OrderBy(x=>x)
.ToList();
var first = lista.GetEnumerator();
var second = listb.GetEnumerator();
for (int i = 0; i < total; i++)
if (indexes.Contains(i))
{
first.MoveNext();
yield return first.Current;
}
else
{
second.MoveNext();
yield return second.Current;
}
}
Rather than generating a list of indices, this can be done by adjusting the probabilities based on the number of elements left in each list. On each iteration, A will have A_size elements remaining, and B will have B_size elements remaining. Choose a random number R from 1..(A_size + B_size). If R <= A_size, then use an element from A as the next element in the output. Otherwise use an element from B.
int A[] = {11, 22, 33}, A_pos = 0, A_remaining = 3;
int B[] = {6, 7, 8}, B_pos = 0, B_remaining = 3;
while (A_remaining || B_remaining) {
int r = rand() % (A_remaining + B_remaining);
if (r < A_remaining) {
printf("%d ", A[A_pos++]);
A_remaining--;
} else {
printf("%d ", B[B_pos++]);
B_remaining--;
}
}
printf("\n");
As a list gets smaller, the probability an element gets chosen from it will decrease.
This can be scaled to multiple lists. For example, given lists A, B, and C with sizes A_size, B_size, and C_size, choose R in 1..(A_size+B_size+C_size). If R <= A_size, use an element from A. Otherwise, if R <= A_size+B_size use an element from B. Otherwise C.
Here is a solution that ensures a uniformly distributed output, and is easy to reason why. The idea is first to generate a list of tokens, where each token represent an element of a specific list, but not a specific element. For example for two lists having 3 elements each, we generate this list of tokens: 0, 0, 0, 1, 1, 1. Then we shuffle the tokens. Finally we yield an element for each token, selecting the next element from the corresponding original list.
public static IEnumerable<T> MergeShufflePreservingOrder<T>(
params IEnumerable<T>[] sources)
{
var random = new Random();
var queues = sources
.Select(source => new Queue<T>(source))
.ToArray();
var tokens = queues
.SelectMany((queue, i) => Enumerable.Repeat(i, queue.Count))
.ToArray();
Shuffle(tokens);
return tokens.Select(token => queues[token].Dequeue());
void Shuffle(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
int j = random.Next(i, array.Length);
if (i == j) continue;
if (array[i] == array[j]) continue;
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
Usage example:
var list1 = "ABCDEFGHIJKL".ToCharArray();
var list2 = "abcd".ToCharArray();
var list3 = "#".ToCharArray();
var merged = MergeShufflePreservingOrder(list1, list2, list3);
Console.WriteLine(String.Join("", merged));
Output:
ABCDaEFGHIb#cJKLd
This might be easier, assuming you have a list of three values in order that match 3 values in another table.
You can also sequence with the identity using identity (1,2)
Create TABLE #tmp1 (ID int identity(1,1),firstvalue char(2),secondvalue char(2))
Create TABLE #tmp2 (ID int identity(1,1),firstvalue char(2),secondvalue char(2))
Insert into #tmp1(firstvalue,secondvalue) Select firstvalue,null secondvalue from firsttable
Insert into #tmp2(firstvalue,secondvalue) Select null firstvalue,secondvalue from secondtable
Select a.firstvalue,b.secondvalue from #tmp1 a join #tmp2 b on a.id=b.id
DROP TABLE #tmp1
DROP TABLE #tmp2