New Year Chaos HackerRank Practise Problem - C# solution optimization [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
static void minimumBribes(int[] q)
{
Int32 TotalCount = 0;
bool blnSuccess = true;
Int32[] size = Ordering(q);
for (int intI = 0; intI < q.Length; intI++)
{
Int32 Tempvariable = 0;
Int32 TooChaotic = 0;
Int32 index = Index(size,q[intI]);
do
{
if (q[intI] != size[intI])
{
Tempvariable = size[index];
size[index] = size[index - 1];
size[index - 1] = Tempvariable;
index = index - 1;
TooChaotic = TooChaotic + 1;
if (TooChaotic > 2)
{
break;
}
TotalCount = TotalCount + 1;
}
} while (q[intI] != size[intI]);
if (TooChaotic > 2)
{
Console.WriteLine("Too chaotic");
blnSuccess = false;
break;
}
}
if (blnSuccess)
{
Console.WriteLine(TotalCount);
}
}
static int[] Ordering(int[] z)
{
int[] r = new int[z.Length];
r = z.OrderBy(x => x).ToArray();
return r;
}
static int Index(int[] z,int integer)
{
for (int intI = 0; intI < z.Length; intI++)
{
if(z[intI]== integer)
{
return intI;
}
}
return 0;
}
This code is working fine, but its runtime is too long.
I'm getting "Terminated due to timeout" in HackerRank. However, the solution is working fine on the local computer but it's taking more time.
Problem Link:https://www.hackerrank.com/challenges/new-year-chaos/problem.
Sample Input
2 (the number of test cases)
5 (number of people in the queue)
2 1 5 3 4 (n space-separated integers describing the final state of the queue)
5 (number of people in the queue)
2 5 1 3 4 (n space-separated integers describing the final state of the queue).
It must print an integer representing the minimum number of bribes necessary, or Too chaotic if the line configuration is not possible.
Output
3
Too chaotic
Question:
How do I reduce its runtime? Presently, I am using an array.

I've solved it a few weeks ago, this is my solution to the problem (100%)
static void minimumBribes(int[] q) {
int bribe = 0;
bool chaotic = false;
int n = q.Length;
for(int i = 0; i < n; i++)
{
if(q[i]-(i+1) > 2)
{
chaotic = true;
break;
}
for (int j = Math.Max(0, q[i]-2); j < i; j++)
if (q[j] > q[i])
bribe++;
}
if(chaotic)
Console.WriteLine("Too chaotic");
else
Console.WriteLine(bribe);
}
You don't need any other methods than the one provided by the challenge

Related

'Summation of primes' takes too long [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I don't know why this takes forever for big numbers I'm trying to solve Problem 10 in Project Euler (https://projecteuler.net/problem=10). Can someone help me please?
It finds the first prime number and crosses all its factors, Then moves on to the next prime number and so on.
long sum=0;
int howmanyChecked = 1;
int target = 1000000;
int index = -1;
List<int> numbers = new List<int>(target);
List<bool> Isprime = new List<bool>(target);
for(int i=2;i<=target;i++)
{
numbers.Add(i);
Isprime.Add(true);
}
while (1 > 0)
{
index = Isprime.IndexOf(true, index + 1);
int Selected = numbers[index];
howmanyChecked++;
sum += Selected;
//Console.WriteLine($"selected prime number is {Selected}");
//int startfrom =numbers.IndexOf(Selected * Selected);
if (Selected >= target / 2)
{
Console.WriteLine("ss");
for(int i=index+1;i<target-1;i++)
{
if(Isprime[i]==true)
{
Console.WriteLine(numbers[i].ToString());
sum += numbers[i];
}
}
Console.WriteLine($"the sum of all prime nubers below {target} is {sum} tap to continue");
Console.ReadLine();
break;
}
else
{
for (int i = Selected; i * Selected <= target; i++)
{
int k = numbers.IndexOf(i * Selected);
if (k == -1)
break;
if (Isprime[k] == true)
{
Isprime[numbers.IndexOf(i * Selected)] = false;
howmanyChecked++;
//Console.WriteLine($"Checked number is {Selected * i} and we have counted {howmanyChecked} numbers");
}
}
}
if (howmanyChecked == target || index==target)
break;
}
Console.ReadLine();
Apply some straightforward optimizations:
list numbers should not be used because each number can be calculated based on an index
simplified initialization of Isprime.
For 1'000'000 got:
the sum of all prime numbers below 1000000 is 37548466742 tap to continue
long sum = 0;
int howmanyChecked = 1;
int target = 1000000;
int index = -1;
var Isprime = Enumerable.Repeat(true, target).ToArray();
while (1 > 0)
{
index = Array.IndexOf(Isprime, true, index + 1);
int Selected = index + 2;
howmanyChecked++;
sum += Selected;
//Console.WriteLine($"selected prime number is {Selected}");
//int startfrom =numbers.IndexOf(Selected * Selected);
if (Selected >= target / 2)
{
Console.WriteLine("ss");
for (int i = index + 1; i < target - 1; i++)
{
if (Isprime[i] == true)
{
Console.WriteLine(i + 2);
sum += i + 2;
}
}
Console.WriteLine($"the sum of all prime nubers below {target} is {sum} tap to continue");
Console.ReadLine();
break;
}
else
{
for (int i = Selected; i * Selected <= target; i++)
{
int k = i * Selected - 2;
if (k < 0)
break;
if (Isprime[k] == true)
{
Isprime[k] = false;
howmanyChecked++;
//Console.WriteLine($"Checked number is {Selected * i} and we have counted {howmanyChecked} numbers");
}
}
}
if (howmanyChecked == target || index == target)
break;
}
Console.ReadLine();
Do SoE (Sieve of Eratosthenes) up to n=2000000 in case you want to be memory efficient 2000000/16 = 62500 Bytes as you need just one bit per odd number). You can do the sum while filling SoE.
Your description is a SoE but you got too much code for a SoE ... my simple SoE solution for this is just 11 lines of formatted C++ code where half of it is variables declaration:
const DWORD N=2000000; // ~ 36 ms
const DWORD M=N>>1; // store only odd values from 3,5,7,...
char p[M]; // p[i] -> is 1+i+i prime? (factors map)
DWORD i,j,k,ss=0,n=0x10000000-N;
uint<2> s=2;
p[0]=0; for (i=1;i<M;i++) p[i]=1;
for(i=3,j=i>>1;i<N;i+=2,j++)
{
if (p[j]==1) { ss+=i; if (ss>=n) { s+=DWORD(ss); ss=0; }}
for(k=i+j;k<M;k+=i) p[k]=0;
} s+=DWORD(ss);
// s holds the answer 142913828922
where DWORD is unsigned 32bit int and uint<2> is 64bit unsigned int (as I am still on 32bit compiler that is why I do the sum so weirdly). As you can see you got maybe 3 times more code than necessary.
Using IsPrime without memoization is too slow but even with memoization can never beat SoE. see:
Prime numbers by Eratosthenes quicker sequential than concurrently?
btw. I got my Euler projects in single app where I do SoE up to 10^7 which creates a list of all primes up to 10^7 this takes 130 ms on my pretty old PC and that is then used for all the Euler problems related to primes (which speeds them up so the first 40 problems is finished below 1sec) which for this case (different solution code) takes 0.7 ms.
To avoid overflows sum on 64 bit arithmetics.
Also using dynamic lists without pre-allocation is slow. You do not need them anyway.
Try with this:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
int main()
{
int n,i,i1,imax;
long sumprime;
bool *prime5mod6,*prime1mod6;
n=2000000;
imax=(n-n%6)/6+1;
prime5mod6 = (bool *) calloc(imax+1,sizeof(bool));
prime1mod6 = (bool *) calloc(imax+1,sizeof(bool));
sumprime=5;
for(i=1;(6*i-1)*(6*i-1)<=n;i++){
if(prime5mod6[i]==false){
sumprime=sumprime+6*i-1;
for(i1=6*i*i;i1 <= imax+2*i;i1+=(6*i-1)){
if(i1<=imax)
prime5mod6[i1]=true;
prime1mod6[i1-2*i]=true;
}
}
if(prime1mod6[i]==false){
sumprime=sumprime+6*i+1;
for(i1 = 6*i*i;i1<=imax;i1+=(6*i+1)){
prime5mod6[i1]=true;
if(i1<=imax-2*i)
prime1mod6[i1+2*i]=true;
}
}
}
for(i1=i;i1<=imax-1;i1++){
if(prime5mod6[i1]==false)
sumprime=sumprime+6*i1-1;
if(prime1mod6[i1]==false)
sumprime=sumprime+6*i1+1;
}
if(prime5mod6[imax]==false && n%6==5)
sumprime=sumprime+6*imax-1;
if(prime1mod6[imax-1]==false && n%6==0)
sumprime=sumprime-(6*(imax-1)+1);
printf("\nPrime sum: %ld",sumprime);
free(prime5mod6);
free(prime1mod6);
return 0;
}

How do you find the positive sum of an array that also has negative numbers? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
public static int PositiveSum(int[] arr)
{
int sum = 0;
for(int i = 0; i > arr.Length; i++)
{
sum+=arr[i];
}
return sum;
}
Example:
[1,-4,7,12] => 1 + 7 + 12 = 20
Note: if there is nothing to sum, the sum defaults to 0.
One way, with minimum changes to your code, is to add a condition inside the for loop that sums the values allowing only positive numbers to be added.
Something you must change is the condition in the loop, i > arr.Length will break the cycle immediately, even if Length is 0, it needs to be i < arr.Length.
public static int PositiveSum(int[] arr)
{
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0)
sum += arr[i];
}
return sum;
}
I would try filtering the arr to only contain positive numbers, then use sum on that new list:
public static int PositiveSum(int[] arr)
{
var pos = arr.Where(x => x > 0);
int sum = pos.Sum();
return sum;
}

C# % throws DivideByZeroException [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
public static List<int> getDenoms(long n)
{
List<int> result = new List<int>();
for (int i = 1; i < n; i++)
{
if (n % i == 0)
{
result.Add(i);
}
}
return result;
}
public static int getHighestPrime(List<int> seq)
{
int currentHigh = 1;
foreach (int number in seq)
{
List<int> temp = getDenoms(number);
if (temp.Count == 1)
{
if (number > currentHigh)
{
currentHigh = number;
}
}
}
return currentHigh;
}
I have the current code going in C#. So, I have the two methods. In the getDenoms method, I assumed that the statement n%i would not throw any errors since i is greater than or equal to 1, but it does indeed throw that error.
I used the two methods in the following manner:
Console.WriteLine(getHighestPrime(getDenoms(600851475143)));
Any insight on why the code is throwing that error?
The reason is that 600851475143 is too big for an int!
Your looping variable i is an int, but you compare it to a long. 600851475143 is greater than int.MaxValue, so i eventually overflows and restarts at int.MinValue. Then it increases until it's 0 again and voilá:
DivideByZeroException
To solve this change the type of your loop variable to long, too:
for (long i = 1; i < n; i++)
'i' is a int as 'n' is long, so in the for cicle 'i' overflows and after a while reaches the '0' value.
Fix:
for (long i = 1; i < n; i++)
I have not tested this myself, but when I look at your code I see that your loop is using an int variable while your input is a long. The number that you are testing your function with, namely 600851475143, is larger than what an 32-bit int can represent. Try changing your variable i to long.
The reason for the failure is that your value 600851475143 is larger than int.MaxValue to solve this problem go ahead and use long instead of int
Note that long.MaxValue is: 9223372036854775807
See code below
public static List<long> getDenoms(long n)
{
List<long> result = new List<long>();
for (long i = 1; i < n; i++)
{
if (n % i == 0)
{
result.Add(i);
}
}
return result;
}
public static long getHighestPrime(List<long> seq)
{
int currentHigh = 1;
foreach (long number in seq)
{
List<long> temp = getDenoms(number);
if (temp.Count == 1)
{
if (number > currentHigh)
{
currentHigh = number;
}
}
}
return currentHigh;
}

List of Non-Negative Integers - concatenate into largest possible nr - e.g. [1,2,5] = 521 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm following this blog asking
Five programming problems every Software Engineer should be able to solve in less than 1 hour
I am absolutely stumped by question 4 (5 is a different story too)
Write a function that given a list of non negative integers, arranges them such that they form the largest possible number. For example, given [50, 2, 1, 9], the largest formed number is 95021.
Now the author posted a answer, and I saw an python attempt too:
import math
numbers = [50,2,1,9,10,100,52]
def arrange(lst):
for i in xrange(0, len(lst)):
for j in xrange(0, len(lst)):
if i != j:
comparison = compare(lst[i], lst[j])
if lst[i] == comparison[0]:
temp = lst[j]
lst[j] = lst[i]
lst[i] = temp
return lst
def compare(num1, num2):
pow10_1 = math.floor(math.log10(num1))
pow10_2 = math.floor(math.log10(num2))
temp1 = num1
temp2 = num2
if pow10_1 > pow10_2:
temp2 = (temp2 / math.pow(10, pow10_2)) * math.pow(10, pow10_1)
elif pow10_2 > pow10_1:
temp1 = (temp1 / math.pow(10, pow10_1)) * math.pow(10, pow10_2)
print "Starting", num1, num2
print "Comparing", temp1, temp2
if temp1 > temp2:
return [num1, num2]
elif temp2 > temp1:
return [num2, num1]
else:
if num1 < num2:
return [num1, num2]
else:
return [num2, num1]
print arrange(numbers)
but I'm not going to learn these languages soon. Is anyone willing to share how they would sort the numbers in C# to form the largest number please?
I've also tried straight conversion to C# in VaryCode but when the IComparer gets involved, then it causes erroneous conversions.
The python attempt uses a bubble sort it seems.
Is bubble sort a starting point? What else would be used?
The solution presented uses the approach to sort the numbers in the array in a special way. For example the value 5 comes before 50 because "505" ("50"+"5") comes before "550" ("5"+"50"). The thinking behind this isn't explained, and I'm not convinced that it actually works...
When looking that the problem, I came to this solution:
You can do it recursively. Make a method that loops through the numbers in the array and concatenates each number with the largest value that can be formed by the remaining numbers, to see which one of those is largest:
public static int GetLargest(int[] numbers) {
if (numbers.Length == 1) {
return numbers[0];
} else {
int largest = 0;
for (int i = 0; i < numbers.Length; i++) {
int[] other = numbers.Take(i).Concat(numbers.Skip(i + 1)).ToArray();
int n = Int32.Parse(numbers[i].ToString() + GetLargest(other).ToString());
if (i == 0 || n > largest) {
largest = n;
}
}
return largest;
}
}
If you want to do it by bubble sort, try this:
public static void Main()
{
bool swapped = true;
while (swapped)
{
swapped = false;
for (int i = 0; i < VALUES.Length - 1; i++)
{
if (Compare(VALUES[i], VALUES[i + 1]) > 0)
{
int temp = VALUES[i];
VALUES[i] = VALUES[i + 1];
VALUES[i + 1] = temp;
swapped = true;
}
}
}
String result = "";
foreach (int integer in VALUES)
{
result += integer.ToString();
}
Console.WriteLine(result);
}
public static int Compare(int lhs, int rhs)
{
String v1 = lhs.ToString();
String v2 = rhs.ToString();
return (v1 + v2).CompareTo(v2 + v1) * -1;
}
The Compare method compares the order of two numbers that would create the largest number. When it returns value larger than 0, that means you need to swap.
This is the sorting part:
while (swapped)
{
swapped = false;
for (int i = 0; i < VALUES.Length - 1; i++)
{
if (Compare(VALUES[i], VALUES[i + 1]) > 0)
{
int temp = VALUES[i];
VALUES[i] = VALUES[i + 1];
VALUES[i + 1] = temp;
swapped = true;
}
}
}
It checks to consecutive values in the array and swaps if necessary. After one iteration without swapping, the sort is finished.
Finally, you concatenate the values in the array and print it out.

How to compute the average for every n number in a list [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Having a List of numbers, I want to take every n(e.g. 5 , 10 , etc.) element, compute their average and put the average in a new list. As an example lets assume we have the following list:
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8
Now we compute the average every 2 elements and we will get the following list as output:
1.5 , 3.5 , 5.5 , 7.5
How can I do that?
You could use a for-loop and Enumerable.Average:
var averages = new List<double>();
for (int i = 0; i < ints.Length; i += 2)
{
int thisInt = ints[i];
int nextInt = i == ints.Length - 1 ? thisInt : ints[i + 1];
averages.Add(new[] { thisInt, nextInt }.Average());
}
Here's a dynamic approach that works with any length:
int take = 2;
for (int i = 0; i < ints.Length; i += take)
{
if(i + take >= ints.Length)
take = ints.Length - i;
int[] subArray = new int[take];
Array.Copy(ints, i, subArray, 0, take);
averages.Add(subArray.Average());
}
This problem is just testing your use of iteration and the modulus operator. Modulus gives you the remainder of division, you can use it to check whether or not the current number should be included in the average as you iterate the array. Here is a sample method;
public float nthsAverage(int n, int[] numbers)
{
// quick check to avoid a divide by 0 error
if (numbers.Length == 0)
return 0;
int sum = 0;
int count = 0;
for (int i = 0; i < numbers.Length; i++)
{
// might want i+1 here instead to compensate for array being 0 indexed, ie 9th number is at the 8th index
if (i % n == 0)
{
sum = sum + numbers[i];
count++;
}
}
return (float)sum / count;
}
public List<double> Average(List<double> number, int nElement)
{
var currentElement = 0;
var currentSum = 0.0;
var newList = new List<double>();
foreach (var item in number)
{
currentSum += item;
currentElement++;
if(currentElement == nElement)
{
newList.Add(currentSum / nElement);
currentElement = 0;
currentSum = 0.0;
}
}
// Maybe the array element count is not the same to the asked, so average the last sum. You can remove this condition if you want
if(currentElement > 0)
{
newList.Add(currentSum / currentElement);
}
return newList;
}

Categories

Resources