I was solving a CodeWars task and faced a problem.
In it you are given the array of numbers, which length is a multiple of 4, you need to visualise it as a (x1^2 + x2^2) * (x3^2 + x4^2) .... * (xn^2 + xn+1^2).
Calculate the result of this and find 2 numbers, which squares in sum, gives the result of initial sequance.
For example, you are given an array of ( 2, 1, 3, 4):
(2^2 + 1^2) * (3^2 + 4^2) = 125;
2 numbers, which squares in sum will give 125, is 2 and 11 because 4 + 121 = 125;
I wrote the code and it works with most of examples, but when i use big arrays such as
(3, 9, 8, 4, 6, 8, 7, 8, 4, 8, 5, 6, 6, 4, 4, 5) in result i receive (0,0);
I can't get the problem, help me pls and if u can use simplified english cause i am from Russia.
Here is my code:
using System;
using System.Numerics;
using System.Collections.Generic;
public class ProdSeq
{
public static BigInteger[] solve(int[] arr)
{
bool simplified = false;
var result = new BigInteger[2];
var index = 0;
BigInteger sequenceSum = 1;
for (int i = 0; i < arr.Length - 1; i+=2)
sequenceSum *= arr[i] * arr[i] + arr[i + 1] * arr[i + 1];
if (sequenceSum >= 1000000)
{
sequenceSum /= 10000;
simplified = true;
}
var list = new List<BigInteger>();
for (BigInteger i = 0; i <= (BigInteger)Math.Sqrt((double)sequenceSum + 1); i++)
list.Add(BigInteger.Multiply(i, i));
for (int i = 0; i < list.Count; i++)
{
var second = sequenceSum - list[i];
index = list.BinarySearch(second);
if (index > -1)
{
if (simplified)
{
result[0] = (BigInteger)(Math.Sqrt((double)list[i]) * 100);
result[1] = (BigInteger)(Math.Sqrt((double)list[index]) * 100);
break;
}
result[0] = (BigInteger)(Math.Sqrt((double)list[i]));
result[1] = (BigInteger)(Math.Sqrt((double)list[index]));
break;
}
}
Console.WriteLine($"A: {result[0]} B: {result[1]}");
return result;
}
}
it seems your error is coming from this line:
for (int i = 0; i <= (int)Math.Sqrt((double)sequenceSum + 1); i++)
list.Add(BigInteger.Multiply(i , i));
you have to use Biginteger.Multiply method
result = 302400 and 29092800 (lot of solutions i think)
Related
I was solving CodeWars task(https://www.codewars.com/kata/5e4bb05b698ef0001e3344bc/train/csharp) and faced a problem. In it you are given the array of numbers, which length is multiply of 4, you need to visualise it as a (x1^2 + x2^2) * (x3^2 + x4^2) .... * (xn^2 + xn+1^2). Calculate the result of this and find 2 numbers, which squares in sum, gives the result of initial sequance. For example, you are given an array of ( 2, 1, 3, 4): (2^2 + 1^2) * (3^2 + 4^2) = 125; 2 numbers, which squares in sum will give 125, is 2 and 11 because 4 + 121 = 125; I wrote the code and it works with most of examples, but when i use big arrays such as (5, 4, 4, 5, 5, 4, 2, 4, 7, 6, 5, 9, 8, 7, 6, 5, 4, 9, 6, 5, 7, 9, 5, 8, 9, 6, 8, 4, 9, 2, 5, 5, 3, 9, 7, 9, 2, 6, 3, 2) in result i receive a timeout. How can i avoid timeouts? If u can use simplified english cause i am from Russia. Here is my code:
using System;
using System.Numerics;
using System.Collections.Generic;
public class ProdSeq
{
public static BigInteger[] solve(int[] arr)
{
bool simplified = false;
var result = new BigInteger[2];
var index = 0;
BigInteger sequenceSum = 1;
for (int i = 0; i < arr.Length - 1; i+=2)
sequenceSum *= arr[i] * arr[i] + arr[i + 1] * arr[i + 1];
if (sequenceSum >= 1000000)
{
sequenceSum /= 10000;
simplified = true;
}
var list = new List<BigInteger>();
for (BigInteger i = 0; i <= (BigInteger)Math.Sqrt((double)sequenceSum + 1); i++)
list.Add(BigInteger.Multiply(i, i));
for (int i = 0; i < list.Count; i++)
{
var second = sequenceSum - list[i];
index = list.BinarySearch(second);
if (index > -1)
{
if (simplified)
{
result[0] = (BigInteger)(Math.Sqrt((double)list[i]) * 100);
result[1] = (BigInteger)(Math.Sqrt((double)list[index]) * 100);
break;
}
result[0] = (BigInteger)(Math.Sqrt((double)list[i]));
result[1] = (BigInteger)(Math.Sqrt((double)list[index]));
break;
}
}
Console.WriteLine($"A: {result[0]} B: {result[1]}");
return result;
}
}
To avoid to waste time to build the list of square number and/or to have an out of memory exception, you just test directly if the big number is the sum of 2 square number like this : (its basic solution)
//method which calulates the sqrt of bigInteger
public static BigInteger Sqrt(BigInteger number)
{
BigInteger n = 0, p = 0;
if (number == BigInteger.Zero)
{
return BigInteger.Zero;
}
var high = number >> 1;
var low = BigInteger.Zero;
while (high > low + 1)
{
n = (high + low) >> 1;
p = n * n;
if (number < p)
{
high = n;
}
else if (number > p)
{
low = n;
}
else
{
break;
}
}
return number == p ? n : low;
}
public static BigInteger[] solve(int[] arr)
{
var result = new BigInteger[2];
BigInteger sequenceSum = BigInteger.One;
for (int i = 0; i < arr.Length - 1; i += 2)
sequenceSum = BigInteger.Multiply(sequenceSum, BigInteger.Add(BigInteger.Multiply(arr[i], arr[i]), BigInteger.Multiply(arr[i + 1], arr[i + 1])));
var range = BigInteger.Add(Sqrt(sequenceSum), BigInteger.One);
var isq = BigInteger.Zero;
var second = BigInteger.Zero;
for (BigInteger first = 1; first <= range; first++)
{
isq = BigInteger.Multiply(first, first);
var diff = BigInteger.Subtract(sequenceSum, isq);
second = Sqrt(diff);
if (BigInteger.Multiply(second, second) == diff)
{
result[0] = first;
result[1] = second;
break;
}
}
Console.WriteLine($"A: {result[0]} B: {result[1]}");
return result;
}
var r = solve(new int[] { 5, 4, 4, 5, 5, 4, 2, 4, 7, 6, 5, 9, 8, 7, 6, 5, 4, 9, 6, 5, 7, 9, 5, 8, 9, 6, 8, 4, 9, 2, 5, 5, 3, 9, 7, 9, 2, 6, 3, 2 });
//one solution is 17123330522880 and 1190972610311564160 after 20 minutes
you could check quickly the solution by setting:
for (BigInteger i = 17123330522870; i <= range; i++)
to increase performance to trap the result:
check if number could be the sum of 2 square number (see differents algorythm on internet)
use parallel for loop to speed the solution (you cut the main for loop by 10 for loops for example)
but for this type of big number, the time to find solution is very long in c# or ypu have to be lucky...
Matlab should speed up really the calculus...
First array is filled randomly, its length is set from the console .I have an array in which I need to write a sub-array of repeating numbers and the number of repeating numbers. For example {3 3 3 3 3 4}, 3 3 3 3 is the repeating numbers, 4 is their number.
The problem is that if there are repeating numbers at the end of the array, the loop doesn't output them and if I enter the debug mode, I can see that not all numbers are written. What could be the problem?
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] == array[i])
{
if((i + 1) != array.Length)
{
duplicateCount++;
addArray = array[i - 1];
duplicate += addArray + " ";
}
else
{
duplicateCount++;
lastElement = array[i - 1];
duplicate += lastElement;
}
}
else
{
if (duplicateCount != 1)
{
addPrevious = array[i - 1];
duplicate += addPrevious + " ";
duplicateArrays.Add(duplicate + duplicateCount);
duplicate = "";
duplicateCount = 1;
}
else
{
duplicateCount = 1;
}
}
}
duplicateArrays.Add(duplicate + duplicateCount);
While the Antidisestablishmentarianism code is the shortest one, it uses '^' which is index from end operator introduced in C# 8.0. I'm not carping about that but it's a difference worth knowing. Compiling the same code in the older version will generate a compile time exception. I'll be giving a long yet beginner friendly code which is pretty self-explanatory if you read it twice.
static void Main(string[] args)
{
int[] RandomArray = new int[] { 1, 2, 2, 3, 4, 4, 3, 1, 5, 2, 9, 8, 9, 8, 8, 5, 3, 4, 1 };
int RandomArrayLength = RandomArray.Length;
List<int[]> SubArrayList = new List<int[]>();
List<int> visited = new List<int>();
for (int i = 0; i < RandomArrayLength; i++)
{
int elem = RandomArray[i];
if (!visited.Contains(elem))
{
visited.Add(elem);
List<int> templist = new List<int>();
for (int j = 0; j < RandomArrayLength; j++)
{
if (elem == RandomArray[j])
{
templist.Add(elem);
}
}
if (templist.Count > 1) //You can remove this condition if you want to include all the elements
{
int elemCount = templist.Count;
List<int> sublist = new List<int>();
sublist.AddRange(templist);
sublist.Add(elemCount);
SubArrayList.Add(sublist.ToArray());
}
}
else
{
continue;
}
}
int SubArrayListCount = SubArrayList.Count;
for (int i = 0; i < SubArrayListCount; i++)
{
int[] SubArr = SubArrList[i];
int SubArrCount = SubArr.Length;
for (int j = 0; j < SubArrCount; j++)
{
Console.Write(SubArr[j].ToString() + " ");
}
Console.WriteLine();
}
}
The prompt is to find the maximal sequence of consecutive equal elements in an array. I don't know what I'm doing wrong but I can't get the right result to show up. :/ Maybe the problem is in the way I iterate with the second loop?
class Class2
{
static void Main(string[] args)
{
int pos=0, bestpos=0, bestlen = 0;
int len = 1;
int[] vargu = { 2, 2, 3, 4, 5, 5, 5, 6, 9, 9, 9, 9 };
for(int i = 0; i < vargu.Length-1; i++)
{
if (vargu[i] == vargu[i++])
{
len++;
if (len > bestlen)
{
bestlen = len;
bestpos = pos;
}
}
else
{
len = 1;
pos = i++;
}
}
for(int k = bestpos; k <= bestlen; k++)
{
Console.Write("{0}", vargu[k]);
}
Console.ReadLine();
}
}
3 problems.
if (vargu[i] == vargu[i++])
dont use ++ with i, it means increment the actual value of i, and you are looping i. Use "i+1" instead.
pos = i++;
same problem here. the array wont get traversed by each index due to this line.
for(int k = bestpos; k <= bestlen; k++)
k < bestlen + bestpos, because bestpos = 8, and bestlen = 4, so loop run condition fails.
int pos = 0, bestpos = 0, bestlen = 0;
int len = 1;
int[] vargu = { 2, 2, 3, 4, 5, 5, 5, 6, 9, 9, 9, 9 };
for (int i = 0; i < vargu.Length - 1; i++)
{
if (vargu[i] == vargu[i+1])
{
len++;
if (len > bestlen)
{
bestlen = len;
bestpos = pos;
}
}
else
{
len = 1;
pos = i+1;
}
}
for (int k = bestpos; k < bestlen + bestpos; k++)
{
Console.Write("{0} ", vargu[k]);
}
Console.ReadLine();
You're using i++ in the loop body when you mean i + 1.
Note that i++ has the side effect of increasing i by 1. Leave the incrementation of i solely in for (int i = 0; i < vargu.Length - 1; i++).
Your problem is 2-fold.
First i++ increments the variable i which shifts the index forward. Something that you don't want. You need to use i+1 if you want to access the consecutive element
Second, when you print in the second loop your array the end-index is wrong. You start at bestpos but you want to end at bestpos + bestlen! Since you measure the length of the sequence and don't save the final index.
This should give you the expected result:
int pos = 0, bestpos = 0, bestlen = 0;
int len = 1;
int[] vargu = { 2, 2, 3, 4, 5, 5, 5, 6, 9, 9, 9, 9 };
for (int i = 0; i < vargu.Length - 1; i++)
{
if (vargu[i] == vargu[i+1])
{
len++;
if (len > bestlen)
{
bestlen = len;
bestpos = pos;
}
}
else
{
len = 1;
pos = i+1;
}
}
for (int k = bestpos; k <= bestpos+bestlen; k++)
{
Console.Write("{0}", vargu[k]);
}
Console.ReadLine();
I would suggest making a structure to hold results :
struct ResultItem
{
public int start;
public int end;
public int value;
}
And then just iterate and compare when signs are changing :
int[] vargu = { 2, 2, 3, 4, 5, 5, 5, 6, 9, 9, 9, 9 };
List<ResultItem> _result = new List<ResultItem>();
ResultItem current = new ResultItem{ value = vargu[0], start = 0, end = 1 };
for (int i = 1; i < vargu.Length; i++)
{
if (vargu [i] != current.value)
{
current.end = i;
_result.Add( current );
current = new ResultItem { value = vargu[i], start = i, end = i };
}
Console.WriteLine(current.value + " " + current.start + " " + current.end);
}
current.end = vargu.Length;
_result.Add(current);
Then you can dump the result as such :
foreach(ResultItem value in _result)
{
Console.WriteLine("integer {0} was placed {1} times in a row", value.value, value.end - value.start);
}
which should result in something like :
integer 2 was placed 2 times in a row
integer 3 was placed 1 times in a row
integer 4 was placed 1 times in a row
integer 5 was placed 3 times in a row
integer 6 was placed 1 times in a row
integer 9 was placed 4 times in a row
Then to find the longest sequence you can use Linq : _result.Max(r => r.end - r.start);
I've been working on the same problem myself. I tried using Mong Zhu's code above and it almost worked so I tweaked two things and it seemed to work.
Change (vargu[i] == vargu[i+1]) to (vargu[i] + 1 == vargu[i+1])
And pos = i + 1; to pos = i; and it seemed to work. My first post. I hope it's okay.
int[] arr = { 1, 2, 3, 5, 4, 3, 3, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 5, 6, 9, 8, 7, 0 };
int pos = 0, bestPos = 0, bestLen = 0;
int len = 1;
for(int i = 0; i < arr.Length -1; i++)
{
if(arr[i] + 1 == arr[i + 1])
{
len++;
if(len > bestLen)
{
bestLen = len;
bestPos = pos;
}
}
else
{
len = 1;
pos = i ;
}
}
for( int k = bestPos; k <= bestLen + bestPos; k++)
{
Console.Write("{0}", arr[k]);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int finalbestsum = 0;
int bestsum = 0;
int bestcount = 0;
int count = 0;
int consval = 0;
int? consval1 = null;
string bestvalue = null;
string bestvalue1 = null;
Console.WriteLine("Enter number of columns for the array");
int col = int.Parse(Console.ReadLine());
Console.WriteLine("Enter number of rows for the array");
int row = int.Parse(Console.ReadLine());
int[,] twodimen = new int[row, col];
for (int index = 0; index < twodimen.GetLength(0); index++ )
{
for (int index1 = 0; index1 < twodimen.GetLength(1); index1++)
{
Console.WriteLine("Enter twodimen {0} {1} value",index, index1);
twodimen[index, index1] = int.Parse(Console.ReadLine());
}
}
for (int index = 0; index < twodimen.GetLength(0); index++ )
{
for (int index1 = 0; index1 < twodimen.GetLength(1)-1; index1++)
{
consval = twodimen[index,index1];
if (consval == twodimen[index, index1 + 1])
{
consval1 = twodimen[index,index1+1];
//Console.Write("{0}" + " ", consval);
bestvalue = bestvalue + Convert.ToString(" " + consval + " ");
count++;
bestsum = bestsum + consval;
}
else if (consval1 != null)
{
//Console.Write(consval1);
count++;
bestvalue = bestvalue + Convert.ToString(" " + consval1 + " ");
bestsum = bestsum + Convert.ToInt16(consval1);
Console.WriteLine();
if (bestcount < count)
{
bestvalue1 = bestvalue;
bestcount = count;
finalbestsum = bestsum;
}
else if (bestcount == count && finalbestsum < bestsum)
{
bestvalue1 = bestvalue;
bestcount = count;
finalbestsum = bestsum;
}
bestvalue = null;
count = 0;
bestsum = 0;
consval1 = null;
}
if (consval == twodimen[index, index1 + 1] && index1 == (twodimen.GetLength(1)-2))
{
bestvalue = bestvalue + Convert.ToString(" " + consval1 + " ");
//Console.Write(consval1);
bestsum = bestsum + Convert.ToInt16(consval1);
count++;
consval1 = null;
if (bestcount < count)
{
bestcount = count;
bestvalue1 = bestvalue;
finalbestsum = bestsum;
}
else if (bestcount == count && finalbestsum < bestsum)
{
bestvalue1 = bestvalue;
bestcount = count;
finalbestsum = bestsum;
}
}
}
bestvalue = null;
count = 0;
bestsum = 0;
Console.WriteLine();
//Console.WriteLine(bestcount);
}
Console.WriteLine(bestvalue1);
Console.ReadLine();
}
}
}
I have written a recursive quicksort algorithm in c# using Visual Studio. What seems weird is ,when the input which is the collection of number that will be sorted,is lower than 9500 in array it gives the result in both best,worse,and avarage case. However, when the input is greater than 9500 it throws a stackoverflow exception. I know there were another question that is nearly same as my question in site but I did the condition also which can recursive.
public int[] quick(int [] myarray,int p,int r)
{
int q;
if (p < r)
{
q = partition(myarray, p, r);
quick(myarray, p, q - 1);
quick(myarray, q + 1, r);
}
return myarray;
}
public int partition(int [] myarray, int left, int right)
{
int i = left - 1;
int tmp = 0;
int pivot = myarray[right];
for (int j = left; j < right; j++)
{
if (myarray[j] < pivot)
{
i = i + 1;
tmp = myarray[i];
myarray[i] = myarray[j];
myarray[j] = tmp;
}
}
tmp = myarray[i + 1];
myarray[i + 1] = myarray[right];
myarray[right] = tmp;
return i + 1;
}
static void Main(string[] args)
{
Stopwatch mwatch = new Stopwatch();
Program quickprogram = new Program();
int[] mydizi = new int[9000];
//int counter = 9000;
//initialization of quick array
for (int i = 0; i < mydizi.Length; i++)
{
mydizi[i] = i + 1;
}
int[] result = new int[9000]; //return array
//time is starting
mwatch.Start();
//algorithm is called
result = quickprogram.quick(mydizi,0,mydizi.Length-1);
//result is returned from quickprogram
for (long j = 0; j < result.Length;j++)
{
Console.Write(result[j] + ",");
}
mwatch.Stop();
//time is up
//Printing the time that show how it takes
Console.Write("Ms:" + mwatch.Elapsed.Milliseconds + " S:" + mwatch.Elapsed.Seconds + " Mn:" + mwatch.Elapsed.Minutes + " Hr:" + mwatch.Elapsed.Hours);
Console.ReadLine();
}
You do a worst-case quicksort. The array is already sorted and you try to sort it again.
Next, your partition() code indeed looks strange:
int i = left - 1; // i = left-1
int pivot = myarray[right];
for (int j = left; j < right; j++) // j = left
{
if (myarray[j] < pivot)
{
i = i + 1; // now i = left-1+1 = left = j
tmp = myarray[i];
myarray[i] = myarray[j];
myarray[j] = tmp;
// congratulations!
// you successfully exchanged a value with itself!
}
In the end result, you call quick() recursively with these arguments (with array size = 9):
quick( 0, 8)
> quick( 0, 7)
>> quick( 0, 6)
>>> quick( 0, 5)
>>>> quick( 0, 4)
>>>>> quick( 0, 3)
>>>>>> quick( 0, 2)
>>>>>>> quick( 0, 1)
>>>>>>>> quick( 0, 0)
>>>>>>>> quick( 2, 1)
>>>>>>> quick( 3, 2)
>>>>>> quick( 4, 3)
>>>>> quick( 5, 4)
>>>> quick( 6, 5)
>>> quick( 7, 6)
>> quick( 8, 7)
> quick( 9, 8)
You see that doing this with 9000 elements will easily reach a recursion level of 9000 nested calls.
I need to sum the first and second, then the third and fourth then the fifth and sixth elements from an array.
For example if I get as input int[] {1, 2, 0, 3, 4, -1} I need to compute it to new int[] {3,3,3}
using System;
class Program
{
static void Main()
{
int[] Arr = new int[] {1, 2, 0, 3, 4, -1};
int sum = 0;
foreach(int index in Arr)
{
//sum = (Arr[index at 0 position] + Arr[item at 0 position + 1]);
//Then do nothing with Arr[index at 1 position]
//Then sum Arr[index at 2 position] + Arr[item at 3 position];
//Then do nothing with Arr[index at 4 position]
//if I test this condition
// if(Arr[index]%2==0) //here I want to test the actual index of the element, not the value behind the index
//{skip the next Arr[index]}
//else{ sum Arr[index]+Arr[index + 1] }
}
}
}
This Sums up each pair and leave the last as is if the length is odd:
int[] Arr = new int[] { 1, 2, 0, 3, 4 };
int ExactResultLength = (int)(((double)Arr.Length / 2) + 0.5);
int[] res = new int[ExactResultLength];
int j = 0;
for (int i = 0; i < Arr.Length; i+= 2)
{
if(i + 1 < Arr.Length)
res[j] = Arr[i] + Arr[i+1];
else
res[j] = Arr[i];
j++;
}
Assuming you don't care about an element left without a pair:
int[] Arr = new int[] {1, 2, 0, 3, 4, -1};
int[] Arr2 = new int[Arr.Length / 2];
for (int i = 0; i < Arr2.Length; i++)
Arr2[i] = Arr[i * 2] + Arr[i * 2 + 1];
But if you do and it should come in the output array, add the following row at the end:
Arr2[Arr2.Length - 1] = Arr[Arr.Length - 1];
and also change Arr2's length to Arr.Lenght / 2 + 1