I have done the coding and my few test cases got passed but the test case 2 and few more did not pass. When I ran the same code in local, I got the desired result but on HackerRank, it shows Runtime error.
Here is the question - https://www.hackerrank.com/challenges/dynamic-array/problem
Here is my solution:-
public static List dynamicArray(int n, List> queries) {
List<List<int>> seqList = new List<List<int>>();
for (int j = 0; j < n ; j++)
{
seqList.Insert(j, new List<int>(n-1)) ;
}
List<int> seqList2 = new List<int>();
int lastAnswer = 0;
int index;
for (int i = 0; i < queries.Count ; i++)
{
index = ((queries[i][1] ^ lastAnswer) % n);
if (queries[i][0] == 1)
{
seqList[index].Add(Convert.ToInt32(queries[i][2]));
}
else
{
int value = queries[i][2] % seqList[index].Count ;
lastAnswer = seqList[index][value];
Console.WriteLine(lastAnswer);
seqList2.Add(lastAnswer);
}
}
A runtime error on Hackerrank can be because of uninitialized variables or because of trying to access an element in an array which is not there (ArgumentOutOfRangeException)
I'm guessing in your case because of the latter.
Related
I was doing a coding test (for practice) that went something like this:
Input is a string with |'s and *'s.
E.g. **|*|*|**|***
Implement the function:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
Count the number of * characters that are between an opening and closing pair of | characters.
Where the 2 locations are arrays with the start and end locations (indices) to consider withing the string line.
For example if line = *|*|* and startLocations = [1] and endLocations = [3] it means
I need to check the substring *|*.
And since there is only 1 pipe, the result is zero.
The location values seemed to be 1-based and not 0-based for some reason.
If the range was 1 and 5, for example, the result would be 1 because there is only 1 * between pipes.
The code I came up with that did manage to solve about half the test cases is as follows:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
{
var results = new List<int>();
if (String.IsNullOrWhiteSpace(line) || startLocations.Count == 0)
{
return results;
}
for (var i = 0; i < startLocations.Count; i++)
{
var startIndex = startLocations[i] - 1;
var endIndex = endLocations[i] - 1;
var start = false;
var total = 0;
var tempTotal = 0;
for (var j = startIndex; j < endIndex; j++)
{
if (!start && line[j] == '|')
{
start = true;
tempTotal = 0;
}
else if (start && line[j] == '*')
{
tempTotal++;
}
else if (line[j] == '|')
{
total += tempTotal;
tempTotal = 0;
}
}
if (line[endIndex] == '|')
{
total += tempTotal;
}
results.Add(total);
}
return results;
}
All the test cases either passed or failed because it ran out of time.
The error said it exceeded a time of 3 seconds.
Now I couldn't see the actual data being passed into the tests, so I'm not able to test it more.
But I suspect the solution was some kind of temporary list or dictionary so as to only iterate over the string 1 time instead of many times as in my code.
I want to learn what kind of solution to use in cases like this, but not really sure if this is a common type of question where the solution has some kind of name or common concept.
I would appreciate any obvious pointers to solving this type of question or even links to similar programming challenges where I can practice more.
In this case I think the best option would be to use stack theory.
It is a variation of the parenthesis balancing problem. You can find more about it here
Article parenthesis balancing problem
I managed to redo the test and I found the answer and problem type.
This is a "plates between candles" type of problem.
I was trying to solve it myself but almost ran out of time and eventually just copy/pasted an answer I found.
This was a practice run, not an actual test or application.
This was the solution that worked... I'll be studying it to better understand it...
List<int> numberOfItems(string s, List<int> startIndices, List<int> endIndices)
{
int q = startIndices.Count;
int l = s.Length;
for (var i = 0; i < startIndices.Count; i++)
{
startIndices[i]--;
endIndices[i]--;
}
var ans = new List<int>();
var prev = new int[l];
var next = new int[l];
var preSum = new int[l];
int p = -1, nxt = -1;
// calculating prev candle up to this index.
for (int i = 0; i < l; i++)
{
if (s[i] == '|')
{
p = i;
}
prev[i] = p;
}
//Calculating next candle from this index.
for (int i = l - 1; i >= 0; i--)
{
if (s[i] == '|')
{
nxt = i;
}
next[i] = nxt;
}
int c = 0;
// calculating the number of stars between these indices.
for (int i = 0; i < l; i++)
{
if (s[i] == '*')
{
c++;
}
preSum[i] = c;
}
// calculating ans.
for (int k = 0; k < q; k++)
{
int i = startIndices[k];
int j = endIndices[k];
int right = prev[j];// position of left candle.
int left = next[i];// position of right candle.
//cout<<right<<left;
if (left == -1 || right == -1 || left > right)
{
ans.Add(0);
}
else
{
ans.Add(preSum[right] - preSum[left]);
}
}
return ans;
}
I am a complete beginner in programming. Trying to make sorting a choice. Everything seems to be ok. Only there is one caveat. Only numbers up to 24 index are filled in the new array. I can’t understand what the problem is.
int[] Fillin(int[] mass)
{
Random r = new Random();
for(int i = 0; i < mass.Length; i++)
{
mass[i] = r.Next(1, 101);
}
return mass;
}
int SearchSmall(int[] mass)
{
int smallest = mass[0];
int small_index = 0;
for(int i = 1; i < mass.Length; i++)
{
if (mass[i] < smallest)
{
smallest = mass[i];
small_index = i;
}
}
return small_index;
}
int[] Remove(int[] massiv,int remind)
{
List<int> tmp = new List<int>(massiv);
tmp.RemoveAt(remind);
massiv = tmp.ToArray();
return massiv;
}
public int[] SortMass(int[] mass)
{
mass = Fillin(mass);
Print(mass);
Console.WriteLine("________________________________");
int[] newmass = new int[mass.Length];
int small;
for(int i = 0; i < mass.Length; i++)
{
small = SearchSmall(mass);
newmass[i] = mass[small];
mass = Remove(mass, small);
}
return newmass;
}
I think your main issue is that when you remove an element in the Remove function, the main loop in for (int i = 0; i < mass.Length; i++) will not check all elements o the initial array. A simple (and ugly) way to fix that would be not to remove the elements but to assign a very high value
public static int[] Remove(int[] massiv, int remind)
{
massiv[remind] = 999999;
return massiv;
}
Or as Legacy suggested simply modify the mass.length for newmass.lengh in the main loop.
As some others have mentioned this is not the best way to order an array, but it is an interesting exercise.
I've been trying to learn more about C#, and so I was doing a little practicing with Lists:
static void Main()
{
List<List<int>> a = new List<List<int>>();
List<int> temp = new List<int>();
temp.Add(1);
a.Add(temp);
for (int i = 0; i < 9; i++)
{
temp.Clear();
temp.Add(1);
for (int q = 0; q < a[i].Count-1; q++)
{
temp.Add(a[i][q] + a[i][q+1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var i in a[8])
Console.Write(i + " ");
Console.WriteLine();
}
I converted this to C++, and it works perfectly. However, in C#, a[i].Count is always 1. Even though after the first loop the size must be 2.
My only guess is that there's some major difference between C++'s Vector and C#'s List that I've apparently missed. Any ideas?
Here's the C++ code which works:
int main()
{
std::vector<std::vector<int>> a;
std::vector<int> b;
b.push_back(1);
a.push_back(b);
for (int i = 0; i < 9; i++)
{
b.clear();
b.push_back(1);
for (int q = 0; q < a[i].size()-1; q++)
{
b.push_back(a[i][q] + a[i][q+1]);
}
b.push_back(1);
a.push_back(b);
}
for (auto i : a[8])
{
std::cout << i << ' ';
}
}
Output for C++ Code:
1 8 28 56 70 56 28 8 1
Output For C# Code:
1 1
Any help is appreciated, thanks!
Look at your C# code a.Add(temp);. This temp variable is a reference type, so it will always add the same memory object.
To fix that, you can use LINQ to solve it:
a.Add(temp.ToList());. ToList() will generate a new object with different memory.
I have modified your code slightly, the main difference to not is, C# there are mainly 2
kind of types, one is a reference type and one is a value type.
List is a reference type.
In your code, you always clearing and adding numbers to the temp list.
that always points to the same object, so when you clear in the nth row, it's also clearing all the rows before it.
List<List<int>> a = new List<List<int>>();
a.Add(new List<int> { 1 });
for (int i = 0; i < 9; i++)
{
List<int> temp = new List<int>();
temp.Add(1);
for (int q = 0; q < a[i].Count - 1; q++)
{
temp.Add(a[i][q] + a[i][q + 1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var row in a)
{
foreach (var col in row)
{
Console.Write(col + " ");
}
Console.WriteLine();
}
Console.ReadKey();
I'm trying to fill one dimensional array with random BUT unique numbers (No single number should be same). As I guess I have a logical error in second for loop, but can't get it right.
P.S I'm not looking for a more "complex" solution - all I know at is this time is while,for,if.
P.P.S I know that it's a really beginner's problem and feel sorry for this kind of question.
int[] x = new int[10];
for (int i = 0; i < x.Length; i++)
{
x[i] = r.Next(9);
for (int j = 0; j <i; j++)
{
if (x[i] == x[j]) break;
}
}
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i);
}
Here is a solution with your code.
int[] x = new int[10];
for (int i = 0; i < x.Length;)
{
bool stop = false;
x[i] = r.Next(9);
for (int j = 0; j <i; j++)
{
if (x[i] == x[j]) {
stop = true;
break;
}
}
if (!stop)
i++;
}
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
A simple trace of the posted code reveals some of the issues. To be specific, on the line…
if (x[i] == x[j]) break;
if the random number is “already” in the array, then simply breaking out of the j loop is going to SKIP the current i value into the x array. This means that whenever a duplicate is found, x[i] is going to be 0 (zero) the default value, then skipped.
The outer i loop is obviously looping through the x int array, this is pretty clear and looks ok. However, the second inner loop can’t really be a for loop… and here’s why… basically you need to find a random int, then loop through the existing ints to see if it already exists. Given this, in theory you could grab the same random number “many” times over before getting a unique one. Therefore, in this scenario… you really have NO idea how many times you will loop around before you find this unique number.
With that said, it may help to “break” your problem down. I am guessing a “method” that returns a “unique” int compared to the existing ints in the x array, may come in handy. Create an endless while loop, inside this loop, we would grab a random number, then loop through the “existing” ints. If the random number is not a duplicate, then we can simply return this value. This is all this method does and it may look something like below.
private static int GetNextInt(Random r, int[] x, int numberOfRandsFound) {
int currentRand;
bool itemAlreadyExist = false;
while (true) {
currentRand = r.Next(RandomNumberSize);
itemAlreadyExist = false;
for (int i = 0; i < numberOfRandsFound; i++) {
if (x[i] == currentRand) {
itemAlreadyExist = true;
break;
}
}
if (!itemAlreadyExist) {
return currentRand;
}
}
}
NOTE: Here would be a good time to describe a possible endless loop in this code…
Currently, the random numbers and the size of the array are the same, however, if the array size is “larger” than the random number spread, then the code above will NEVER exit. Example, if the current x array is set to size 11 and the random numbers is left at 10, then you will never be able to set the x[10] item since ALL possible random numbers are already used. I hope that makes sense.
Once we have the method above… the rest should be fairly straight forward.
static int DataSize;
static int RandomNumberSize;
static void Main(string[] args) {
Random random = new Random();
DataSize = 10;
RandomNumberSize = 10;
int numberOfRandsFound = 0;
int[] ArrayOfInts = new int[DataSize];
int currentRand;
for (int i = 0; i < ArrayOfInts.Length; i++) {
currentRand = GetNextInt(random, ArrayOfInts, numberOfRandsFound);
ArrayOfInts[i] = currentRand;
numberOfRandsFound++;
}
for (int i = 0; i < ArrayOfInts.Length; i++) {
Console.WriteLine(ArrayOfInts[i]);
}
Console.ReadKey();
}
Lastly as other have mentioned, this is much easier with a List<int>…
static int DataSize;
static int RandomNumberSize;
static void Main(string[] args) {
Random random = new Random();
DataSize = 10;
RandomNumberSize = 10;
List<int> listOfInts = new List<int>();
bool stillWorking = true;
int currentRand;
while (stillWorking) {
currentRand = random.Next(RandomNumberSize);
if (!listOfInts.Contains(currentRand)) {
listOfInts.Add(currentRand);
if (listOfInts.Count == DataSize)
stillWorking = false;
}
}
for (int i = 0; i < listOfInts.Count; i++) {
Console.WriteLine(i + " - " + listOfInts[i]);
}
Console.ReadKey();
}
Hope this helps ;-)
The typical solution is to generate the entire potential set in sequence (in this case an array with values from 0 to 9). Then shuffle the sequence.
private static Random rng = new Random();
public static void Shuffle(int[] items)
{
int n = list.Length;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
int temp = items[k];
items[k] = items[n];
items[n] = temp;
}
}
static void Main(string[] args)
{
int[] x = new int[10];
for(int i = 0; i<x.Length; i++)
{
x[i] = i;
}
Shuffle(x);
for(int i = 0; i < x.Length; i++)
{
Console.WritLine(x[i]);
}
}
//alternate version of Main()
static void Main(string[] args)
{
var x = Enumerable.Range(0,10).ToArray();
Shuffle(x);
Console.WriteLine(String.Join("\n", x));
}
You can simply do this:
private void AddUniqueNumber()
{
Random r = new Random();
List<int> uniqueList = new List<int>();
int num = 0, count = 10;
for (int i = 0; i < count; i++)
{
num = r.Next(count);
if (!uniqueList.Contains(num))
uniqueList.Add(num);
}
}
Or:
int[] x = new int[10];
Random r1 = new Random();
int num = 0;
for (int i = 0; i < x.Length; i++)
{
num = r1.Next(10);
x[num] = num;
}
I am learning C# these days and still a beginner.
While practicing creating methods, I made this method that yields the sum of the members of a numeric array (my codes are massive and I am not good at math).
VS returns an ArgumentOutOfRangeException Error, but I don't know how to fix this.
Please save me!
public static int SumAll(int[] a)
{
List<int> sum = new List<int>();
int sumAll;
if (a.Length == 0)
{
sumAll = 0;
}
else
{
sum[0] = a[0];
for (int i = 1; i < (a.Length - 1); i++)
{
sum[i] = sum[i - 1] + a[i];
}
sumAll = sum[a.Length - 1];
}
return sumAll;
}
Use the += addition assignment operator:
public static int SumAll(int[] a)
{
int sumAll = 0;
for (int i = 0; i < (a.Length - 1); i++)
{
sumAll += a[i];
}
return sumAll;
}
The ArgumentOutOfRangeException is typically to do with an item out of the range of an array, collection or list.. Because you use a List<int> sum you are not adding items to it. sum.Add(a[i]); and that's why you get the exception; the sum variable doesn't have any items.
The reason you're getting that exception is because you are trying to assign a value to an index in the List that doesn't exist yet when you do this:
sum[0] = a[0];
Instead, you should just use the .Add method to add items to the List. Once they're added, you can access them by index. The reason for this is that the list is not pre-populated to any set size (whereas an array is), so to begin with there is nothing at [0].
sum.Add(a[0]);
You will also get this exception here:
sumAll = sum[a.Length - 1];
This is because the sum List will only contain a.Length - 2 items (your loop stops when i == a.Length - 1). This is a bug in your code! You should be using i < a.Length as the condition:
for (int i = 1; i < a.Length; i++)
This way you are looping through ALL the items in your a array.
Your method would then look something like this (notice I also added a check for a == null):
public static int SumAll(int[] a)
{
if (a == null) return 0;
List<int> sum = new List<int>();
int sumAll;
if (a.Length == 0)
{
sumAll = 0;
}
else
{
sum.Add(a[0]);
for (int i = 1; i < a.Length; i++)
{
sum.Add(sum[i - 1] + a[i]);
}
sumAll = sum[a.Length - 1];
}
return sumAll;
}
Now, this code could be simplified if you wanted, by removing the list, starting with sumAll = 0, and then just adding each item from a to it in your loop:
public static int SumAll(int[] a)
{
if (a == null) return 0;
int sumAll = 0;
for (int i = 0; i < a.Length; i++)
{
sumAll += a[i];
}
return sumAll;
}
Or you can really shorten it by using the System.Linq extension method, Sum:
public static int SumAll(int[] a)
{
return a == null ? 0 : a.Sum();
}