how can i find lcs length between two large strings - c#

I've written the following code in C# for obtaining the length of longest common subsequence of two texts given by use, but it doesn't work with large strings. Could you please help me. I'm really confused.
public Form1()
{
InitializeComponent();
}
public int lcs(char[] s1, char[] s2, int s1size, int s2size)
{
if (s1size == 0 || s2size == 0)
{
return 0;
}
else
{
if (s1[s1size - 1] == s2[s2size - 1])
{
return (lcs(s1, s2, s1size - 1, s2size - 1) + 1);
}
else
{
int x = lcs(s1, s2, s1size, s2size - 1);
int y = lcs(s1, s2, s1size - 1, s2size);
if (x > y)
{
return x;
}
else
return y;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
string st1 = textBox2.Text.Trim(' ');
string st2 = textBox3.Text.Trim(' ');
char[] a = st1.ToCharArray();
char[] b = st2.ToCharArray();
int s1 = a.Length;
int s2 = b.Length;
textBox1.Text = lcs(a, b, s1, s2).ToString();
}

Here you are using the Recursion method. So it leads the program to occur performance problems as you mentioned.
Instead of recursion, use the dynamic programming approach.
Here is the C# Code.
public static void LCS(char[] str1, char[] str2)
{
int[,] l = new int[str1.Length, str2.Length];
int lcs = -1;
string substr = string.Empty;
int end = -1;
for (int i = 0; i < str1.Length; i++)
{
for (int j = 0; j < str2.Length; j++)
{
if (str1[i] == str2[j])
{
if (i == 0 || j == 0)
{
l[i, j] = 1;
}
else
l[i, j] = l[i - 1, j - 1] + 1;
if (l[i, j] > lcs)
{
lcs = l[i, j];
end = i;
}
}
else
l[i, j] = 0;
}
}
for (int i = end - lcs + 1; i <= end; i++)
{
substr += str1[i];
}
Console.WriteLine("Longest Common SubString Length = {0}, Longest Common Substring = {1}", lcs, substr);
}

Here is a solution how to find the longest common substring in C#:
public static string GetLongestCommonSubstring(params string[] strings)
{
var commonSubstrings = new HashSet<string>(strings[0].GetSubstrings());
foreach (string str in strings.Skip(1))
{
commonSubstrings.IntersectWith(str.GetSubstrings());
if (commonSubstrings.Count == 0)
return string.Empty;
}
return commonSubstrings.OrderByDescending(s => s.Length).DefaultIfEmpty(string.Empty).First();
}
private static IEnumerable<string> GetSubstrings(this string str)
{
for (int c = 0; c < str.Length - 1; c++)
{
for (int cc = 1; c + cc <= str.Length; cc++)
{
yield return str.Substring(c, cc);
}
}
}
I found it here: http://www.snippetsource.net/Snippet/75/longest-common-substring

Just for fun, here is one example using Queue<T>:
string LongestCommonSubstring(params string[] strings)
{
return LongestCommonSubstring(strings[0], new Queue<string>(strings.Skip(1)));
}
string LongestCommonSubstring(string x, Queue<string> strings)
{
if (!strings.TryDequeue(out var y))
{
return x;
}
var output = string.Empty;
for (int i = 0; i < x.Length; i++)
{
for (int j = x.Length - i; j > -1; j--)
{
string common = x.Substring(i, j);
if (y.IndexOf(common) > -1 && common.Length > output.Length) output = common;
}
}
return LongestCommonSubstring(output, strings);
}
It's still using recursion though, but it's a nice example of Queue<T>.

I refactored the C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ to create a rolling hash approach in C# - this will find the substring in O(N * log(N)^2) time and O(N) space
using System;
using System.Collections.Generic;
public class RollingHash
{
private class RollingHashPowers
{
// _mod = prime modulus of polynomial hashing
// any prime number over a billion should suffice
internal const int _mod = (int)1e9 + 123;
// _hashBase = base (point of hashing)
// this should be a prime number larger than the number of characters used
// in my use case I am only interested in ASCII (256) characters
// for strings in languages using non-latin characters, this should be much larger
internal const long _hashBase = 257;
// _pow1 = powers of base modulo mod
internal readonly List<int> _pow1 = new List<int> { 1 };
// _pow2 = powers of base modulo 2^64
internal readonly List<long> _pow2 = new List<long> { 1L };
internal void EnsureLength(int length)
{
if (_pow1.Capacity < length)
{
_pow1.Capacity = _pow2.Capacity = length;
}
for (int currentIndx = _pow1.Count - 1; currentIndx < length; ++currentIndx)
{
_pow1.Add((int)(_pow1[currentIndx] * _hashBase % _mod));
_pow2.Add(_pow2[currentIndx] * _hashBase);
}
}
}
private class RollingHashedString
{
readonly RollingHashPowers _pows;
readonly int[] _pref1; // Hash on prefix modulo mod
readonly long[] _pref2; // Hash on prefix modulo 2^64
// Constructor from string:
internal RollingHashedString(RollingHashPowers pows, string s, bool caseInsensitive = false)
{
_pows = pows;
_pref1 = new int[s.Length + 1];
_pref2 = new long[s.Length + 1];
const long capAVal = 'A';
const long capZVal = 'Z';
const long aADif = 'a' - 'A';
unsafe
{
fixed (char* c = s)
{
// Fill arrays with polynomial hashes on prefix
for (int i = 0; i < s.Length; ++i)
{
long v = c[i];
if (caseInsensitive && capAVal <= v && v <= capZVal)
{
v += aADif;
}
_pref1[i + 1] = (int)((_pref1[i] + v * _pows._pow1[i]) % RollingHashPowers._mod);
_pref2[i + 1] = _pref2[i] + v * _pows._pow2[i];
}
}
}
}
// Rollingnomial hash of subsequence [pos, pos+len)
// If mxPow != 0, value automatically multiply on base in needed power.
// Finally base ^ mxPow
internal Tuple<int, long> Apply(int pos, int len, int mxPow = 0)
{
int hash1 = _pref1[pos + len] - _pref1[pos];
long hash2 = _pref2[pos + len] - _pref2[pos];
if (hash1 < 0)
{
hash1 += RollingHashPowers._mod;
}
if (mxPow != 0)
{
hash1 = (int)((long)hash1 * _pows._pow1[mxPow - (pos + len - 1)] % RollingHashPowers._mod);
hash2 *= _pows._pow2[mxPow - (pos + len - 1)];
}
return Tuple.Create(hash1, hash2);
}
}
private readonly RollingHashPowers _rhp;
public RollingHash(int longestLength = 0)
{
_rhp = new RollingHashPowers();
if (longestLength > 0)
{
_rhp.EnsureLength(longestLength);
}
}
public string FindCommonSubstring(string a, string b, bool caseInsensitive = false)
{
// Calculate max neede power of base:
int mxPow = Math.Max(a.Length, b.Length);
_rhp.EnsureLength(mxPow);
// Create hashing objects from strings:
RollingHashedString hash_a = new RollingHashedString(_rhp, a, caseInsensitive);
RollingHashedString hash_b = new RollingHashedString(_rhp, b, caseInsensitive);
// Binary search by length of same subsequence:
int pos = -1;
int low = 0;
int minLen = Math.Min(a.Length, b.Length);
int high = minLen + 1;
var tupleCompare = Comparer<Tuple<int, long>>.Default;
while (high - low > 1)
{
int mid = (low + high) / 2;
List<Tuple<int, long>> hashes = new List<Tuple<int, long>>(a.Length - mid + 1);
for (int i = 0; i + mid <= a.Length; ++i)
{
hashes.Add(hash_a.Apply(i, mid, mxPow));
}
hashes.Sort(tupleCompare);
int p = -1;
for (int i = 0; i + mid <= b.Length; ++i)
{
if (hashes.BinarySearch(hash_b.Apply(i, mid, mxPow), tupleCompare) >= 0)
{
p = i;
break;
}
}
if (p >= 0)
{
low = mid;
pos = p;
}
else
{
high = mid;
}
}
// Output answer:
return pos >= 0
? b.Substring(pos, low)
: string.Empty;
}
}

Related

C# SPOJ time optimalization

I'm trying to get the job done MOHIBPIZ - PIZZA (https://www.spoj.com/problems/MOHIBPIZ/).
I'm already sitting on it the second day, I've tried everything I can and found on the internet. The last chance before giving up is to ask you guys
For recudces time I'm using InputOutput class created by davidsekar (https://github.com/davidsekar/C-sharp-Programming-IO/blob/master/ConsoleInOut/InputOutput.cs)
but still I have time "time limit exceeded". :(
I tried with two loops, but the method with the function seems more optimal to me. Thanks in advance for all the hints, suggestions and answers.
This is code (link on ideone: https://ideone.com/):
using System;
using System.IO;
public class Test
{
public static void Main()
{
InputOutput reader = new InputOutput();
StreamWriter _output = new StreamWriter(Console.OpenStandardOutput());
int T = reader.ReadInt();
for (int i = 0; i < T; i++)
{
_output.WriteLine(Recursion(reader.ReadInt()));
}
_output.Flush();
}
private static int Recursion(int x)
{
if(x <= 1)
{
return 2;
}
else
{
return Recursion(x - 1) + x;
}
}
#region Input Output Helper
public class InputOutput : System.IDisposable
{
private System.IO.Stream _readStream, _writeStream;
private int _readIdx, _bytesRead, _writeIdx, _inBuffSize, _outBuffSize;
private readonly byte[] _inBuff, _outBuff;
private readonly bool _bThrowErrorOnEof;
public void SetBuffSize(int n)
{
_inBuffSize = _outBuffSize = n;
}
public InputOutput(bool throwEndOfInputsError = false)
{
_readStream = System.Console.OpenStandardInput();
_writeStream = System.Console.OpenStandardOutput();
_readIdx = _bytesRead = _writeIdx = 0;
_inBuffSize = _outBuffSize = 1 << 22;
_inBuff = new byte[_inBuffSize];
_outBuff = new byte[_outBuffSize];
_bThrowErrorOnEof = throwEndOfInputsError;
}
public void SetFilePath(string strPath)
{
strPath = System.IO.Path.GetFullPath(strPath);
_readStream = System.IO.File.Open(strPath, System.IO.FileMode.Open);
}
public T ReadNumber<T>()
{
byte rb;
while ((rb = GetByte()) < '-')
;
var neg = false;
if (rb == '-')
{
neg = true;
rb = GetByte();
}
dynamic m = (T)Convert.ChangeType(rb - '0', typeof(T));
while (true)
{
rb = GetByte();
if (rb < '0')
break;
m = m * 10 + (rb - '0');
}
return neg ? -m : m;
}
public int ReadInt()
{
byte readByte;
while ((readByte = GetByte()) < '-')
;
var neg = false;
if (readByte == '-')
{
neg = true;
readByte = GetByte();
}
var m = readByte - '0';
while (true)
{
readByte = GetByte();
if (readByte < '0')
break;
m = m * 10 + (readByte - '0');
}
return neg ? -m : m;
}
public string ReadString()
{
return ReadString(' ');
}
public string ReadString(string delimiter)
{
return ReadString(delimiter[0]);
}
public string ReadString(char delimiter)
{
byte readByte;
while ((readByte = GetByte()) <= delimiter)
;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
do
{
sb.Append((char)readByte);
} while ((readByte = GetByte()) > delimiter);
return sb.ToString();
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
private byte GetByte()
{
if (_readIdx >= _bytesRead)
{
_readIdx = 0;
_bytesRead = _readStream.Read(_inBuff, 0, _inBuffSize);
if (_bytesRead >= 1)
return _inBuff[_readIdx++];
if (_bThrowErrorOnEof)
throw new System.Exception("End Of Input");
_inBuff[_bytesRead++] = 0;
}
return _inBuff[_readIdx++];
}
public void WriteToBuffer(string s)
{
foreach (var b in System.Text.Encoding.ASCII.GetBytes(s))
{
if (_writeIdx == _outBuffSize)
Flush();
_outBuff[_writeIdx++] = b;
}
}
public void WriteLineToBuffer(string s)
{
WriteToBuffer(s);
if (_writeIdx == _outBuffSize)
Flush();
_outBuff[_writeIdx++] = 10;
}
public void WriteToBuffer(int c)
{
byte[] temp = new byte[10];
int tempidx = 0;
if (c < 0)
{
if (_writeIdx == _outBuffSize)
Flush();
_outBuff[_writeIdx++] = (byte)'-';
c = -c;
}
do
{
temp[tempidx++] = (byte)((c % 10) + '0');
c /= 10;
} while (c > 0);
for (int i = tempidx - 1; i >= 0; i--)
{
if (_writeIdx == _outBuffSize)
Flush();
_outBuff[_writeIdx++] = temp[i];
}
}
public void WriteLineToBuffer(int c)
{
WriteToBuffer(c);
if (_writeIdx == _outBuffSize)
Flush();
_outBuff[_writeIdx++] = 10;
}
private void Flush()
{
_writeStream.Write(_outBuff, 0, _writeIdx);
_writeStream.Flush();
_writeIdx = 0;
}
public void Dispose()
{
Flush();
_writeStream.Close();
_readStream.Close();
}
}
#endregion Input Output Helper
}
As far as I can see, you have a well known Circle Division problem; see also A000124 sequence:
number of pieces after n cuts are (n * n + n + 2) / 2
That's why we can put O(1) time and space complexity
Code:
private static int Solution(int n) => (int)(((long)n * n + n + 2) / 2);
Here I've put (long) n in case n * n exceeds int.MaxValue, when (n * n + n + 2) / 2 doesn't.
Edit: I've implemented int Solution(int n) method which is based on current code int Recursion(int x) signature; but if there're tests for large n we are going to have integer overflow.
In this case
private static long Solution(long n) =>
1 + (n % 2 == 0 ? n / 2 * (n + 1) : (n + 1) / 2 * n);
In case of arbitrary n we have to use BigInteger:
using System.Numerics;
...
private static BigInteger Solution(BigInteger n) =>
1 + (n * n + n) / 2;

How to transform this recursive function to iterative

I would like to replace this function by a iterative version.
I found some versions that accept unique inputs.
private static void FindCombinations(char[] A, string output, ref int counter, int i, int n, int k)
{
//Console.WriteLine($"i:{i} n:{n} k:{k} r:{output}");
if (k == 0)
{
Console.WriteLine(output);
counter++;
return;
}
for (int j = i; j < n; j++)
{
FindCombinations(A, output + " " + A[j].ToString(), ref counter, j + 1, n, k - 1);
while (j < n - 1 && A[j] == A[j + 1])
j++;
}
}
private static void Main(string[] args)
{
string output = "";
char[] keys = new char[] { 'A', 'A', 'B', 'C', 'D' };
int count = 0;
FindCombinations(keys, output, ref count, 0, keys.Length, 3);
Console.WriteLine(count.ToString());
Console.ReadKey();
}
The next time, you have to provide first your code attempts as this community is not programming for you, it is trying to help you program. Also, some more context would be much appreciated.
Anyway, I think this method below should work for you. Check if it works for many different cases, specially for boundary conditions. Surely this code can be optimized (I just tried to mimic what your recursive methods does), but as you are just asking for non-recursive code, it should suffice:
private static void FindCombinations2(char[] A, string output, ref int counter, int i, int n, int k)
{
i = Math.Max(i, 0);
n = Math.Min(A.Length, n);
char[] A_used = new char[n - i];
Array.Copy(A, i, A_used, 0, n - i);
int[] indexVect = new int[k];
for (int j = 0; j < indexVect.Length; j++)
indexVect[j] = j;
int L = A_used.Length;
string currentBase = output;
int movingIndex = 0;
while (true)
{
int indexA = indexVect[movingIndex];
if (indexA >= L)
{
indexVect[movingIndex] = movingIndex;
movingIndex--;
if (movingIndex < 0)
break;
currentBase = currentBase.Substring(0, currentBase.Length - 2);
continue;
}
char nextA = A_used[indexA];
currentBase += " " + nextA;
int t;
for ( t= indexVect[movingIndex]+1; t< L; t++)
{
if(A_used[t]!=nextA)
{
indexVect[movingIndex] = t;
break;
}
}
if (t >= L)
indexVect[movingIndex] = L;
movingIndex++;
if (movingIndex >= k)
{
Console.WriteLine(currentBase);
counter++;
movingIndex--;
currentBase = currentBase.Substring(0, currentBase.Length - 2);
}
else
indexVect[movingIndex] = Math.Max(indexVect[movingIndex], indexA+1);
}
}

Am I using the wrong 'stackalloc' to cope with the string.Split() function to be used in Unity?

I use Unity. but this engine cannot use Span ..
so, I made string parsing function
My function purpose is converting string to Single struct value(int, float, bool, UnityEngine.Vector4 etc..)
and i thought about how to not generate GC as much as possible
string data is read xml file
Examples of string data specifications are: "-1234.23,234,-.232.344", "554", "-.55"
During the test, I found something interesting
public unsafe Vector4 GetVectorToStackAlloc()
{
Vector4 vec = Vector4.Zero;
char* data = stackalloc char[8];
int dot = -1;
int index = 0;
int colume = 0;
for (int i = 0; i < Str.Length; ++i)
{
if (Str[i] == Token)
{
Parse();
dot = -1;
index = 0;
colume++;
}
else
{
if (Str[i] == '.') dot = index;
data[index++] = Str[i];
}
}
Parse();
void Parse()
{
if (index == 0) return;
bool isMinus = data[0] == '-';
int length = isMinus ? 1 : 0;
int mul = dot != -1 ? (dot - index) + 1 : 0;
for (int x = index - 1; x >= length; --x)
{
if (data[x] == '.') continue;
int k = data[x] - '0';
float m = MathF.Pow(10, mul++);
vec[colume] += k * m;
}
if (isMinus) vec[colume] *= -1;
}
return vec;
}
public Vector4 GetDefaultVector()
{
Vector4 vec = Vector4.Zero;
string[] split = Str.Split(Token);
for (int i = 0; i < split.Length; ++i)
{
if (string.IsNullOrWhiteSpace(split[i])) continue;
vec[i] = float.Parse(split[i]);
}
return vec;
}
public Vector4 GetSpanVector()
{
Vector4 vec = Vector4.Zero;
Span<char> span = stackalloc char[8];
int index = 0;
int colume = 0;
for (int i = 0; i < Str.Length; ++i)
{
if (Str[i] == ',')
{
if (index == 0) { vec[colume++] = 0; }
else vec[colume++] = float.Parse(span);
index = 0;
span.Clear();
}
else span[index++] = Str[i];
}
vec[colume] = float.Parse(span);
return vec;
}
Testing Vector4
During the testing process, I discovered that there was overhead in float.Parse() function and tested with a single float
public unsafe float GetStackAllocFloat()
{
float value = 0;
char* data = stackalloc char[8];
int dot = -1;
int index = 0;
for (int i = 0; i < Str.Length; ++i)
{
if (Str[i] == '.') dot = index;
data[index++] = Str[i];
}
if (index == 0) return value;
bool isMinus = data[0] == '-';
int length = isMinus ? 1 : 0;
int mul = dot != -1 ? (dot - index) + 1 : 0;
for (int x = index - 1; x >= length; --x)
{
if (data[x] == '.') continue;
int k = data[x] - '0';
float m = MathF.Pow(10, mul++);
value += k * m;
}
if (isMinus) value *= -1;
return value;
}
public unsafe float GetDefaultFloat()
{
return float.Parse(Str);
}
Testing Float
I think it is better to use stackalloc if the test method is normal.
Had I made mistake?
OK, I tested it again to fit the Unity engine as much as possible
I think it's not bad!
public readonly string[] Strs = new string[200] { // data is fill .. }
public const char Token = ',';
[Benchmark]
public unsafe Vector4 GetVectorToStackAlloc()
{
Vector4 result = Vector4.Zero;
int r = Strs.Length - 1;
while (r != -1)
{
Vector4 vec = Vector4.Zero;
char* data = stackalloc char[12];
int dot = -1;
int index = 0;
int colume = 0;
string Str = Strs[r--];
for (int i = 0; i < Str.Length; ++i)
{
if (Str[i] == Token)
{
vec[colume++] = Parse(index, data, dot);
dot = -1;
index = 0;
}
else
{
if (Str[i] == '.') dot = index;
data[index++] = Str[i];
}
}
vec[colume] = Parse(index, data, dot);
result.x += vec.x;
}
return result;
float Parse(int _index, char* _data, int _dot)
{
if (_index == 0) return 0;
float val = 0;
bool isMinus = _data[0] == '-';
int length = isMinus ? 1 : 0;
int mul = _dot != -1 ? (_dot - _index) + 1 : 0;
for (int x = _index - 1; x >= length; --x)
{
if (_data[x] == '.') continue;
int k = _data[x] - '0';
float m = MathF.Pow(10, mul++);
val = k * m;
}
return isMinus ? val * -1 : val;
}
}
[Benchmark]
public Vector4 GetDefaultVector()
{
Vector4 result = Vector4.Zero;
int r = Strs.Length - 1;
while (r != -1)
{
Vector4 vec = Vector4.Zero;
string Str = Strs[r--];
string[] split = Str.Split(Token);
for (int i = 0; i < split.Length; ++i)
{
if (string.IsNullOrWhiteSpace(split[i])) continue;
vec[i] = float.Parse(split[i]);
}
result.x += vec.x;
}
return result;
}

How to add or subtract very large numbers without bigint in C#?

So let me start by saying that I'm a newbie with little to moderate knowledge about C#.
Coming to the topic: I need to make a program that is able to add/subtract very large integers. Initially, used BigInt only to find out it's not allowed. There should be a logical workaround for this? I have an idea which is using "elementary school method" where you add each digit starting from right to left.
I made a string which I split into char array and added each digit from right to left(GetUpperBound-i). But it doesn't seem to work.
My Code:
string s, s2;
char[] c_arr, c_arr2;
int i, erg;
s = "1234";
s2 = "5678";
c_arr = s.ToCharArray();
c_arr2 = s2.ToCharArray();
for (i = 0; i <= c_arr.GetUpperBound(0); i++)
{
erg = c_arr[c_arr.GetUpperBound(0)-i]+c_arr2[c_arr2.GetUpperBound(0)-i];
Console.Write(erg);
}
Console.ReadKey();
There are a few things wrong with your code for the 'elementary school method'. You don't account for carry, you're adding up ascii values rather than actual values between 0-9, and you're outputting the results in the wrong order.
The code below, whilst not very elegant, does produce the correct results:
var s1 = "12345";
var s2 = "5678";
var carry = false;
var result = String.Empty;
if(s1.Length != s2.Length)
{
var diff = Math.Abs(s1.Length - s2.Length);
if(s1.Length < s2.Length)
{
s1 = String.Join("", Enumerable.Repeat("0", diff)) + s1;
}
else
{
s2 = String.Join("", Enumerable.Repeat("0", diff)) + s2;
}
}
for(int i = s1.Length-1;i >= 0; i--)
{
var augend = Convert.ToInt32(s1.Substring(i,1));
var addend = Convert.ToInt32(s2.Substring(i,1));
var sum = augend + addend;
sum += (carry ? 1 : 0);
carry = false;
if(sum > 9)
{
carry = true;
sum -= 10;
}
result = sum.ToString() + result;
}
if(carry)
{
result = "1" + result;
}
Console.WriteLine(result);
The following program can be used to add two large numbers, I have used string builder to store the result. You can add numbers containing digits upto '2,147,483,647'.
Using System;
using System.Text;
using System.Linq;
public class Test
{
public static void Main()
{
string term1="15245142151235123512352362362352351236";
string term2="1522135123612646436143613461344";
StringBuilder sum=new StringBuilder();
int n1=term1.Length;
int n2=term2.Length;
int carry=0;
int n=(n1>n2)?n1:n2;
if(n1>n2)
term2=term2.PadLeft(n1,'0');
else
term1=term1.PadLeft(n2,'0');
for(int i=n-1;i>=0;i--)
{
int value=(carry+term1[i]-48+term2[i]-48)%10;
sum.Append(value);
carry=(carry+term1[i]-48+term2[i]-48)/10;
}
char[] c=sum.ToString().ToCharArray();
Array.Reverse(c);
Console.WriteLine(c);
}
}
string Add(string s1, string s2)
{
bool carry = false;
string result = string.Empty;
if(s1[0] != '-' && s2[0] != '-')
{
if (s1.Length < s2.Length)
s1 = s1.PadLeft(s2.Length, '0');
if(s2.Length < s1.Length)
s2 = s2.PadLeft(s1.Length, '0');
for(int i = s1.Length-1; i >= 0; i--)
{
var augend = Convert.ToInt64(s1.Substring(i,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
var sum = augend + addend;
sum += (carry ? 1 : 0);
carry = false;
if(sum > 9)
{
carry = true;
sum -= 10;
}
result = sum.ToString() + result;
}
if(carry)
{
result = "1" + result;
}
}
else if(s1[0] == '-' || s2[0] == '-')
{
long sum = 0;
if(s2[0] == '-')
{
//Removing negative sign
char[] MyChar = {'-'};
string NewString = s2.TrimStart(MyChar);
s2 = NewString;
if(s2.Length < s1.Length)
s2 = s2.PadLeft(s1.Length, '0');
for (int i = s1.Length - 1; i >= 0; i--)
{
var augend = Convert.ToInt64(s1.Substring(i,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
if(augend >= addend)
{
sum = augend - addend;
}
else
{
int temp = i - 1;
long numberNext = Convert.ToInt64(s1.Substring(temp,1));
//if number before is 0
while(numberNext == 0)
{
temp--;
numberNext = Convert.ToInt64(s1.Substring(temp,1));
}
//taking one from the neighbor number
int a = int.Parse(s1[temp].ToString());
a--;
StringBuilder tempString = new StringBuilder(s1);
string aString = a.ToString();
tempString[temp] = Convert.ToChar(aString);
s1 = tempString.ToString();
while(temp < i)
{
temp++;
StringBuilder copyS1 = new StringBuilder(s1);
string nine = "9";
tempString[temp] = Convert.ToChar(nine);
s1 = tempString.ToString();
}
augend += 10;
sum = augend - addend;
}
result = sum.ToString() + result;
}
//Removing the zero infront of the answer
char[] zeroChar = {'0'};
string tempResult = result.TrimStart(zeroChar);
result = tempResult;
}
}
return result;
}
string Multiply(string s1, string s2)
{
string result = string.Empty;
//For multipication
bool Negative = false;
if(s1[0] == '-' && s2[0] == '-')
Negative = false;
else if(s1[0] == '-' || s2[0] == '-')
Negative = true;
char[] minusChar = {'-'};
string NewString;
NewString = s2.TrimStart(minusChar);
s2 = NewString;
NewString = s1.TrimStart(minusChar);
s1 = NewString;
List<string> resultList = new List<string>();
for(int i = s2.Length - 1; i >= 0; i--)
{
string multiplycation = string.Empty;
for (int j = s1.Length - 1; j >= 0; j--)
{
var augend = Convert.ToInt64(s1.Substring(j,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
long multiply = augend * addend;
// print(multiply);
multiplycation = multiply.ToString() + multiplycation;
}
//Adding zero at the end of the multiplication
for (int k = s2.Length - 1 - i; k > 0; k--)
{
multiplycation += "0";
}
resultList.Add(multiplycation);
}
for (int i = 1; i < resultList.Count; i++)
{
resultList[0] = Add(resultList[0],resultList[i]);
}
//Finally assigning if negative negative sign in front of the number
if(Negative)
result = resultList[0].Insert(0,"-");
else
result = resultList[0];
return result;
}
string Divide(string dividend, string divisor)
{
string result = string.Empty;
int remainder = 0;
int intNumberstoGet = divisor.Length;
int currentInt = 0;
int dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
int intDivisor = int.Parse(divisor);
while(currentInt < dividend.Length)
{
if(dividing == 0)
{
currentInt++;
result += "0";
}
else
{
while(dividing < intDivisor)
{
intNumberstoGet++;
dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
}
if (dividing > 0)
{
remainder = dividing % intDivisor;
result += ((dividing - remainder) / intDivisor).ToString();
intNumberstoGet = 1;
if(currentInt < dividend.Length - 2)
currentInt += 2;
else
currentInt++;
if(currentInt != dividend.Length)
{
dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
remainder *= 10;
dividing += remainder;
}
}
}
}
return result;
}
Here you go. Another example. It's 10 to 30 times faster than the accepted answer.
static string AddNumStr(string v1, string v2)
{
var v1Len = v1.Length;
var v2Len = v2.Length;
var count = Math.Max(v1Len, v2Len);
var answ = new char[count + 1];
while (count >= 0) answ[count--] = (char)((v1Len > 0 ? v1[--v1Len] & 0xF:0) + (v2Len>0 ? v2[--v2Len]&0xF : 0));
for (var i = answ.Length - 1; i >= 0; i--)
{
if (answ[i] > 9)
{
answ[i - 1]++;
answ[i] -= (char)10;
}
answ[i] = (char)(answ[i] | 48);
}
return new string(answ).TrimStart('0');
}
Below SO question has some interesting approaches. Though the answer is in Java, but you will surely get to know what needs to be done.
How to handle very large numbers in Java without using java.math.BigInteger
public static int[] addTwoNumbers(string s1, string s2)
{
char[] num1 = s1.ToCharArray();
char[] num2 = s2.ToCharArray();
int sum = 0;
int carry = 0;
int size = (s1.Length > s2.Length) ? s1.Length + 1 : s2.Length + 1;
int[] result = new int[size];
int index = size - 1;
int num1index = num1.Length - 1;
int num2index = num2.Length - 1;
while (true)
{
if (num1index >= 0 && num2index >= 0)
{
sum = (num1[num1index]-'0') + (num2[num2index]-'0') + carry;
}
else if(num1index< 0 && num2index >= 0)
{
sum = (num2[num2index]-'0') + carry;
}
else if (num1index >= 0 && num2index < 0)
{
sum = (num1[num1index]-'0') + carry;
}
else { break; }
carry = sum /10;
result[index] = sum % 10;
index--;
num1index--;
num2index--;
}
if(carry>0)
{
result[index] = carry;
}
return result;
}

Returning Nth Fibonacci number the sequence?

I have a question on my homework for class and I need to know how to return nth number of Fibonacci sequence using iteration (no recursion allowed).
I need some tips on how to do this so I can better understand what I am doing wrong. I output to the console in my program.cs, hence it being absent in the code below.
// Q1)
//
// Return the Nth Fibonacci number in the sequence
//
// Input: uint n (which number to get)
// Output: The nth fibonacci number
//
public static UInt64 GetNthFibonacciNumber(uint n)
{
// Return the nth fibonacci number based on n.
if (n == 0 || n == 1)
{
return 1;
}
// The basic Fibonacci sequence is
// 1, 1, 2, 3, 5, 8, 13, 21, 34...
// f(0) = 1
// f(1) = 1
// f(n) = f(n-1) + f(n-2)
///////////////
//my code is below this comment
uint a = 0;
uint b = 1;
for (uint i = 0; i < n; i++)
{
n = b + a;
a = b;
b = n;
}
return n;
:)
static ulong Fib(int n)
{
double sqrt5 = Math.Sqrt(5);
double p1 = (1 + sqrt5) / 2;
double p2 = -1 * (p1 - 1);
double n1 = Math.Pow(p1, n + 1);
double n2 = Math.Pow(p2, n + 1);
return (ulong)((n1 - n2) / sqrt5);
}
Just for a little fun you could do it with an infinite Fibonacci list and some IEnumerable extensions
public IEnumerable<int> Fibonacci(){
var current = 1;
var b = 0;
while(true){
var next = current + b;
yield return next;
b = current;
current = next;
}
}
public T Nth<T>(this IEnumerable<T> seq, int n){
return seq.Skip.(n-1).First();
}
Getting the nth number would then be
Fibonacci().Nth(n);
public static int GetNthFibonacci(int n)
{
var previous = -1;
var current = 1;
int index = 1;
int element = 0;
while (index++ <= n)
{
element = previous + current;
previous = current;
current = element;
}
return element;
}
I think this should do the trick:
uint a = 0;
uint b = 1;
uint c = 1;
for (uint i = 0; i < n; i++)
{
c = b + a;
a = b;
b = c;
}
return c;
public IEnumerable<BigInteger> FibonacciBig(int maxn)
{
BigInteger Fn=1;
BigInteger Fn_1=1;
BigInteger Fn_2=1;
yield return Fn;
yield return Fn;
for (int i = 3; i < maxn; i++)
{
Fn = Fn_1 + Fn_2;
yield return Fn;
Fn_2 = Fn_1;
Fn_1 = Fn;
}
}
you can get the n-th Number by
FibonacciBig(100000).Skip(n).First();
This is the solution for your homework, you should start from 3 because you already have numbers for f1 and f2 (first two numbers). Please note that there is no point in getting 0th Fibonacci number.
public static UInt64 GetNthFibonacciNumber(uint n)
{
// Return the nth fibonacci number based on n.
if (n == 1 || n == 2)
{
return 1;
}
uint a = 1;
uint b = 1;
uint c;
for (uint i = 3; i <= n; i++)
{
c = b + a;
a = b;
b = c;
}
return c;
}
public static UInt64 GetNthFibonacciNumber(uint n)
{
if (n == 0 || n == 1)
{
return 1;
}
UInt64 a = 1, b = 1;
uint i = 2;
while (i <= n)
{
if (a > b) b += a;
else a += b;
++i;
}
return (a > b) ? a : b;
}
public static List<int> PrintFibonacci(int number)
{
List<int> result = new List<int>();
if (number == 0)
{
result.Add(0);
return result;
}
else if (number == 1)
{
result.Add(0);
return result;
}
else if (number == 2)
{
result.AddRange(new List<int>() { 0, 1 });
return result;
}
else
{
//if we got thus far,we should have f1,f2 and f3 as fibonacci numbers
int f1 = 0,
f2 = 1;
result.AddRange(new List<int>() { f1, f2 });
for (int i = 2; i < number; i++)
{
result.Add(result[i - 1] + result[i - 2]);
}
}
return result;
}
Only 2 variables are needed (declaring one in a for loop counts too).
public int NthFib(int n)
{
int curFib = 0;
int nextFib = 1;
while (--n > 0)
{
nextFib += curFib;
curFib = nextFib - curFib;
}
return curFib;
}
If you want to see the sequence to n change it to:
public IEnumerable<int> NthFib(int n)
{
int curFib = 0;
int nextFib = 1;
while (n-- > 0)
{
yield return curFib;
nextFib += curFib;
curFib = nextFib - curFib;
}
}

Categories