GRC for N numbers issue with StackOverflowException - c#

I'm trying to find GRC for N numbers. For example N = 4, so the 4 numbers is for example 199 199 -199 -199. And im getting StackOverflowException for those numbers. Why?
first input number of integers for which i should find GRC.
Second input number is array of numbers wroted in one line separeted by " ".
Here is my code:
static int GCD(int a, int b)
{
if (b == 0) return a;
if (a > b) return GCD(b, a - b);
else return GCD(a, b-a);
}
static void Main()
{
var input = Convert.ToInt32(Console.ReadLine());
int gcd;
string readLine = Console.ReadLine();
string[] stringArray = readLine.Split(' ');
int[] intArray = new int[input];
for (int i = 0; i < stringArray.Length; i++)
{
intArray[i] = int.Parse(stringArray[i]);
}
if (input >= 2)
{
gcd= Math.Abs(GCD(intArray[0], intArray[1]));
}
else
{
gcd= intArray[0];
}
for (int i = 2; i < input; i++)
{
gcd= Math.Abs(GCD(gcd, intArray[i]));
}
Console.WriteLine(Math.Abs(gcd));
Console.ReadKey();
}
Any suggestions how to improve the code?

First of all, it's unclear what is GRC. Your code is about GCD - Greatest Common Divisor. Let's improve its implementation.
If you have huge difference, beween a and b, say a = 1_000_000_000 and b = 1 you
are going to have ~ a - b ~ 1_000_000_000 recursive calls in GCD and have Stack Overflow Exception.
Let's use modulo arithmetics instead: if a = b + b + ... + b + remainder, we can find remainder in one go, without subtracting b: remainder = a % b
Code:
static int GCD(int a, int b)
{
a = Math.Abs(a);
b = Math.Abs(b);
if (a == 0)
return b; // b divides both 0 and itself
if (b == 0)
return a; // a divides both 0 and itself
if (a % b == 0) // b divides both a and b, so b is GCD(a, b)
return b;
return GCD(b, a % b);
}
then we can compute GCD for as many numbers as we want
static int GCD(IEnumerable<int> numbers) {
if (numbers is null)
throw new ArgumentNullException(nameof(numbers));
int result = 0;
foreach (var number in numbers)
if (result == 0)
result = number;
else
result = GCD(result, number);
return result != 0
? result
: throw new ArgumentOutOfRangeException(nameof(numbers), "Empty sequence");
}
Usage: (fiddle)
using System.Linq;
...
static void Main() {
int gcd = GCD(Console
.ReadLine()
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Select(item => int.Parse(item)));
Console.Write(gcd);
}

Related

How to perform addition of 2 very large (over 50 digits) binary string values in C#

I have been thinking of adding binary numbers where binary numbers are in a form of string and we add those two binary numbers to get a resultant binary number (in string).
So far I have been using this:
long first = Convert.ToInt64(a, 2);
long second = Convert.ToInt64(b, 2);
long addresult = first + second;
string result = Convert.ToString(addresult, 2);
return result;
Courtesy of Stackoverflow: Binary addition of 2 values represented as strings
But, now I want to add numbers which are far greater than the scope of a long data type.
For Example, a Binary value whose decimel result is a BigInteger, i.e., incredibly huge integers as shown below:
111101101000010111101000101010001010010010010110011010100001000010110110110000110001101 which equals to149014059082024308625334669
1111001101011000001011000111100011101011110100101010010001110101011101010100101000001101000010000110001110100010011101011111111110110101100101110001010101011110001010000010111110011011 which equals to23307765732196437339985049250988196614799400063289798555
At least I think it does.
Courtesy of Stackoverflow:
C# Convert large binary string to decimal system
BigInteger to Hex/Decimal/Octal/Binary strings?
I have used logic provided in above links which are more or less perfect.
But, is there a more compact way to add the given two binary strings?
Kindly let me know as this question is rattling in my mind for some time now.
You can exploit the same scheme you used before but with BigInteger:
using System.Linq;
using System.Numerics;
...
BigInteger first = a.Aggregate(BigInteger.Zero, (s, item) => s * 2 + item - '0');
BigInteger second = b.Aggregate(BigInteger.Zero, (s, item) => s * 2 + item - '0');
StringBuilder sb = new StringBuilder();
for (BigInteger addresult = first + second; addresult > 0; addresult /= 2)
sb.Append(addresult % 2);
if (sb.Length <= 0)
sb.Append('0');
string result = string.Concat(sb.ToString().Reverse());
This question was a nostalgic one - thanks. Note that my code is explanatory and inefficient with little to no validation, but it works for your example. You definitely do not want to use anything like this in a real world solution, this is just to illustrate binary addition in principle.
BinaryString#1
111101101000010111101000101010001010010010010110011010100001000010110110110000110001101
decimal:149014059082024308625334669
BinaryString#2
1111001101011000001011000111100011101011110100101010010001110101011101010100101000001101000010000110001110100010011101011111111110110101100101110001010101011110001010000010111110011011
decimal:23307765732196437339985049250988196614799400063289798555
Calculated Sum
1111001101011000001011000111100011101011110100101010010001110101011101010100101000001101000010001101111011100101011010100101010000000111111000100100101001100110100000111001000100101000
decimal:23307765732196437339985049251137210673881424371915133224
Check
23307765732196437339985049251137210673881424371915133224
decimal:23307765732196437339985049251137210673881424371915133224
Here's the code
using System;
using System.Linq;
using System.Numerics;
namespace ConsoleApp3
{
class Program
{
// return 0 for '0' and 1 for '1' (C# chars promotion to ints)
static int CharAsInt(char c) { return c - '0'; }
// and vice-versa
static char IntAsChar(int bit) { return (char)('0' + bit); }
static string BinaryStringAdd(string x, string y)
{
// get rid of spaces
x = x.Trim();
y = y.Trim();
// check if valid binaries
if (x.Any(c => c != '0' && c != '1') || y.Any(c => c != '0' && c != '1'))
throw new ArgumentException("binary representation may contain only '0' and '1'");
// align on right-most bit
if (x.Length < y.Length)
x = x.PadLeft(y.Length, '0');
else
y = y.PadLeft(x.Length, '0');
// NNB: the result may require one more bit than the longer of the two input strings (carry at the end), let's not forget this
var result = new char[x.Length];
// add from least significant to most significant (right to left)
var i = result.Length;
var carry = '0';
while (--i >= 0)
{
// to add x[i], y[i] and carry
// - if 2 or 3 bits are set then we carry '1' again (otherwise '0')
// - if the number of set bits is odd the sum bit is '1' otherwise '0'
var countSetBits = CharAsInt(x[i]) + CharAsInt(y[i]) + CharAsInt(carry);
carry = countSetBits > 1 ? '1' : '0';
result[i] = countSetBits == 1 || countSetBits == 3 ? '1' : '0';
}
// now to make this byte[] a string
var ret = new string(result);
// remember that final carry?
return carry == '1' ? carry + ret : ret;
}
static BigInteger BigIntegerFromBinaryString(string s)
{
var biRet = new BigInteger(0);
foreach (var t in s)
{
biRet = biRet << 1;
if (t == '1')
biRet += 1;
}
return biRet;
}
static void Main(string[] args)
{
var s1 = "111101101000010111101000101010001010010010010110011010100001000010110110110000110001101";
var s2 = "1111001101011000001011000111100011101011110100101010010001110101011101010100101000001101000010000110001110100010011101011111111110110101100101110001010101011110001010000010111110011011";
var sum = BinaryStringAdd(s1, s2);
var bi1 = BigIntegerFromBinaryString(s1);
var bi2 = BigIntegerFromBinaryString(s2);
var bi3 = bi1 + bi2;
Console.WriteLine($"BinaryString#1\n {s1}\n decimal:{bi1}");
Console.WriteLine($"BinaryString#2\n {s2}\n decimal:{bi2}");
Console.WriteLine($"Calculated Sum\n {sum}\n decimal:{BigIntegerFromBinaryString(sum)}");
Console.WriteLine($"Check\n {bi3}\n decimal:{bi3}");
Console.ReadKey();
}
}
}
I'll add an alternative solution alongside AlanK's just as an example of how you might go about this without converting the numbers to some form of integer before adding them.
static string BinaryStringAdd(string b1, string b2)
{
char[] c = new char[Math.Max(b1.Length, b2.Length) + 1];
int carry = 0;
for (int i = 1; i <= c.Length; i++)
{
int d1 = i <= b1.Length ? b1[^i] : 48;
int d2 = i <= b2.Length ? b2[^i] : 48;
int sum = carry + (d1-48) + (d2-48);
if (sum == 3)
{
sum = 1;
carry = 1;
}
else if (sum == 2)
{
sum = 0;
carry = 1;
}
else
{
carry = 0;
}
c[^i] = (char) (sum+48);
}
return c[0] == '0' ? String.Join("", c)[1..] : String.Join("", c);
}
Note that this solution is ~10% slower than Alan's solution (at least for this test case), and assumes the strings arrive to the method formatted correctly.

Trying to remove the last "and" at the end of my output list

For my C# programming homework, we had to write a program that allows the user to input an integer and use a loop to print out the factors of that integer.
I got the program to output the integers.
The problem is, for example, when I enter in the integer "24", I want the output to be
1 and 2 and 3 and 4 and 6 and 8 and 12 and 24
but the output that comes out is
1 and 2 and 3 and 4 and 6 and 8 and 12 and 24 and
I don't want the extra "and" at the end of my Factors List
Here is what my code looks like:
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
int a, b;
Console.WriteLine("Please enter your integer: ");
a = int.Parse(Console.ReadLine());
for (b = 1; b <= a; b++)
{
if (a % b == 0)
{
Console.Write(b + " ");
}
}
Console.ReadLine();
}
}
}
EDIT: The output has to be formatted as
1 and 2 and 3 and 4 and 6 and 8 and 12 and 24
or else I won't get credit for the assignment
You can enumerate factors, and then Join them with " and "
private static IEnumerable<int> Factors(int value) {
// Simplest, not that efficient
for (int i = 1; i <= value; ++i)
if (value % i == 0)
yield return i;
}
...
Console.Write(string.Join(" and ", Factors(24)));
Or you can add " and " before, not after printing factors (i)
int value = 24;
bool firstTime = true;
// Simplest, not that efficient
for (int i = 1; i <= value; ++i) {
if (value % i == 0) {
// print "and" before printing i
if (!firstTime)
Console.Write(" and ");
firstTime = false;
Console.Write(i);
}
}
How about adding the numbers to a List and printing after the loop:
int a, b;
a = int.Parse(Console.ReadLine());
var result = new List<int>();
for (b = 1; b <= a; b++)
{
if (a % b == 0)
{
result.Add(b);
}
}
Console.Write(string.Join(" and ", result));
static void Main(string[] args)
{
//get input from user
Console.WriteLine("Please enter your integer: ");
int a = int.Parse(Console.ReadLine());
//enumerate factors
var factors = Enumerable.Range(1, a)
.Where(i => a % i == 0).ToArray();
//join for nicely printed output
Console.Write(string.Join(" and ", factors));
Console.ReadLine();
}
I would recommend you to create a string and output that string becouse it allows you to do more things with it, then do something like this:
int a, b;
string x="";
Console.WriteLine("Please enter your integer: ");
a = int.Parse(Console.ReadLine());
for (b = 1; b <= a; b++)
{
if (a % b == 0)
{
x=x + b.toString() +" and";
}
}
if you know that always will be an "and" at the end you can simply do this
string x = x.Substring(0, x.Length - 3);
and then
Console.Write(x);
Console.ReadLine();

Cannot implicitly convert type `string' to `System.Collections.Generic.List<int>'

This should compare three numbers that are on each list and give a point to C if the number in A is greater than the number in B or a point to D if the number in B is greater than the number in A and will do nothing if They are equal. Here is an example:
Input | output
A= 1 3 2 | C D
B= 3 2 2 | 1 1
Here's the code:
static List<int> compareTriplets(List<int> a, List<int> b)
{
int c = 0;
int d = 0;
for (int i = 0; i < 3; i++)
{
if (a[i] > b[i])
{
c++;
}
else if (b[i] > a[i])
{
d++;
}
}
return c + " " + d;
}
This code returns me this:
error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.List<int>'
To me, this piece of code looks like you want to return 2 numbers:
return c + " " + d;
However, this way it will become a string, which dies not match the method signature.
To return a list of numbers (e.g. 2 numbers), you can use
return new List<int>{c, d};
You're trying to convert a string to List. The function compareTriplets must return a string.
An advice: you need to check bounds of list when iterate using index.
static string compareTriplets(List<int> a, List<int> b)
{
int c = 0;
int d = 0;
for (int i = 0; i < 3; i++)
{
if (a[i] > b[i])
c++;
else if (b[i] > a[i])
d++;
}
return c + " " + d;
}
Using C# 6.0+, you can return like this:
return $"{c} {d}";
Your return type is string: a + " " + b, so you need to change method signature:
static string compareTriplets(List<int> a, List<int> b) {
// etc....
You should return type List<int> but you are returning c +" "+ d. I don't understand the rest of the question.
You should return a list. Here's an example:
static List<int> compareTriplets(List<int> a, List<int> b)
{
int c = 0;
int d = 0;
for (int i=0;i<3;i++)
if (a[i]>b[i])
c++;
else if (b[i]>a[i])
d++;
return new List<int>{ c, d };
}
You're specifying that your function will return a list of integers: static List<int>. You need to change this to string.
static String compareTriplets(List<int> a, List<int> b) {
int c = 0;
int d = 0;
for (int i=0;i<3;i++){
if (a[i]>b[i]){
c++;
}
else if (b[i]>a[i])
{
d++;
}
}
return c.ToString() + " " + d.ToString();
}
EDIT: Explicit ToString() cast isn't required.
If you truly want to return a List<int>, do the following:
static List<int> compareTriplets(List<int> a, List<int> b) {
int c = 0;
int d = 0;
for (int i=0;i<3;i++){
if (a[i]>b[i]){
c++;
}
else if (b[i]>a[i])
{
d++;
}
}
return new List<int>(){ c, d };
}

How to Display Numbers in the Form(0 1 1 2 3 5 8 13)

How to Display Numbers in the Form(0 1 1 2 3 5 8 13)
Such that the number first 1 number is displayed then second is the number with addition of previous
=>
0 then 1 then 1+0 = 1then 1+1= 2 then 1+2=3 and so on?
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
Console.Write(i) ;
}
Console.ReadKey();
}
}
}
Suggest some code please
Decompose your solution into Fibonacci sequence generator:
using System.Numerics;
using System.Linq;
public static IEnumerable<BigInteger> Fibonacci() {
BigInteger a = 0;
BigInteger b = 1;
yield return a;
yield return b;
while (true) {
BigInteger result = a + b;
a = b;
b = result;
yield return result;
}
}
And sequence representation:
Console.Write(String.Join(" ", Fibonacci().Take(20)));
This will do it. I wouldn't recommend handing this in to your teacher, though:
double Phi = (1.0 + Math.Sqrt(5.0)) / 2.0;
double D = 1.0 / Math.Sqrt(5.0);
Func<int, ulong> fib = i => (ulong) ((Math.Pow(Phi, i) - Math.Pow(1.0 - Phi, i))*D);
Console.WriteLine(string.Join(" ", Enumerable.Range(0, 21).Select(i => fib(i))));
(In seriousness, I just posted this to demonstrate that there is an analytic solution to fibonnaci, as well as the normal iterative one. This only works up to n == 71, though.)

Reverse binary representation of int (only significant bits)

I'm trying to write a program for reversing numbers in binary. For instance, the binary representation of 13 is 1101, and reversing it gives 1011, which corresponds to number 11 right?
Here's my code:
static void Main(string[] args)
{
Console.WriteLine("Enter a Number");
int numb = int.Parse(Console.ReadLine());
int reverse = 0;
while (numb > 0)
{
int rem = numb % 10;
reverse = (reverse * 10) + rem;
numb = numb / 10;
}
Console.WriteLine("Reverse number={0}", reverse);
Console.ReadLine();
}
By this code I only get the numbers to reverse (13 -> 31)...
The input should contain a single line with an integer N, 1≤N≤1000000000 and I want my output in one line with one integer, the number I want to get by reversing the binary representation of N.
Something like that
// 13 = 1101b
int value = 13;
// 11 = 1011b
int result = Convert.ToInt32(new String(
Convert.ToString(value, 2)
.Reverse()
.ToArray()), 2);
Explanation:
Convert.ToString(value, 2) returns value in binary representation ("1101")
Reverse().ToArray() - reverse the string ('1','0','1','1') as sequence of characters and converts to array char[].
new String(...) constructs string "1011" from array of char
finally, Convert.ToInt32(..., 2) convert binary representation back to int
You can use Convert.ToString and Convert.ToInt32 methods, where 2 means binary:
int numb = int.Parse(Console.ReadLine());
var reversedString = Convert.ToString(numb, 2).ReverseString();
var result = Convert.ToInt32(reversedString, 2);
...
public static string ReverseString(this string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
A fun excercise would be doing this without using the string conversion.
I have very little experience with bit twiddling so there is probably a faster and better way of doing this, but this seems to work:
public static IEnumerable<bool> ToBinary(this int n)
{
for (int i = 0; i < 32; i++)
{
yield return (n & (1 << i)) != 0;
}
}
public static int ToInt(this IEnumerable<bool> b)
{
var n = 0;
var counter = 0;
foreach (var i in b.Trim().Take(32))
{
n = n | (i ? 1 : 0) << counter;
counter++
}
return n;
}
private static IEnumerable<bool> Trim(this IEnumerable<bool> list)
{
bool trim = true;
foreach (var i in list)
{
if (i)
{
trim = false;
}
if (!trim)
{
yield return i;
}
}
}
And now you'd call it like this:
var reversed = n.ToBinary().Reverse().ToInt();

Categories

Resources