I am trying to create a thread which creates generates new RSA keys using my algorithm provided.
The algorithm may not be perfect but is fine by what i am doing - not the problem.
The problem lies with why doesnt the parts below work: from what i have gathered online i am using parameterizedthreadstart correctly?
Thread thread = new Thread(new ParameterizedThreadStart(GenerateKeys)); //issue here!!!!
thread.Start(RSA_KEYS, PublicKeysToDistribute);
it shows the error: no overload for 'GenerateKeys' matches delegate ParameterizedThreadStart.
Any help would be appreciated
static void Main(string[] args)
{
Dictionary<(BigInteger, BigInteger), (BigInteger, BigInteger)> RSA_KEYS = new Dictionary<(BigInteger, BigInteger), (BigInteger, BigInteger)>();
Queue<(BigInteger, BigInteger)> PublicKeysToDistribute = new Queue<(BigInteger, BigInteger)>();
Thread thread = new Thread(new ParameterizedThreadStart(GenerateKeys));
thread.Start(RSA_KEYS, PublicKeysToDistribute);
//recipitent receives public key in form e,n
//splits into Biginteger array : {e,n}
GenerateKeys(RSA_KEYS, PublicKeysToDistribute);
BigInteger[] PublicKey = Array.ConvertAll(PublicKeyRequest(PublicKeysToDistribute).Split(':'), BigInteger.Parse);
string input;
//creates message to encrypt
input = InputToAscii();
//encrypt using PublicKey
BigInteger a = encrypt(PublicKey, input);
BigInteger b = decrypt((RSA_KEYS[(PublicKey[0], PublicKey[1])]).Item1, (RSA_KEYS[(PublicKey[0], PublicKey[1])]).Item2, a);
Console.WriteLine(AsciiToOutput(b));
Console.ReadLine();
}
private static string PublicKeyRequest(Queue<(BigInteger, BigInteger)> PublicKeysToDistribute)
{
string publickey = PublicKeysToDistribute.Peek().Item1 + ":" +PublicKeysToDistribute.Peek().Item2;
PublicKeysToDistribute.Dequeue();
return publickey;
}
//create a key value pair where the publickey is key and private key is value
//publickey = {biginteger,biginteger} where {e,n}
//privatekey = {biginteger,biginteger} where {d,n}
public static void GenerateKeys(Dictionary<(BigInteger, BigInteger), (BigInteger, BigInteger)> RSA_KEYS, Queue<(BigInteger, BigInteger)> PublicKeysToDistribute)
{
int p = 4201; //default use 61 4201
int q = 4007; //default use 53 4007
int n = p * q;
// compute the totient, phi
int ϕn = (p - 1) * (q - 1);
//e for random number which 1 < e < ϕn and is co prime of ϕn
Random rn = new Random();
bool found = false;
BigInteger e = 0;
while (found == false)
{
e = rn.Next(1, ϕn);
if (Coprime(ϕn, e) == true)
{
break;
}
}
// where (d * e) mod ϕn = 1 find d
BigInteger d = 0;
for (int k = 1; k < ϕn; k++)
{
if ((k * e) % ϕn == 1)
{
d = k;
break;
}
}
Console.WriteLine("p="+p+",q="+q+",n="+n+",phi="+ϕn+",e="+e+",d="+d+",n="+n);
Console.WriteLine("Public key: e = " + e + " n = " + n);
Console.WriteLine("Private key: d = " + d + " n = " + n);
RSA_KEYS.Add((e, n), (d, n));
PublicKeysToDistribute.Enqueue((e, n));
Console.WriteLine("added new key to dictionary");
//return new KeyValuePair<(BigInteger, BigInteger), (BigInteger, BigInteger)>((e,n),(d,n));
}
private static BigInteger encrypt(BigInteger[] PublicKey, string input)
{
BigInteger m = BigInteger.Parse(input); //m = message
BigInteger c = eMod(m, PublicKey[0], PublicKey[1]); //cipher text = (message ^ e) mod n
return c;
}
private static BigInteger decrypt(BigInteger d, BigInteger n, BigInteger c)
{
BigInteger f = eMod(c, d, n); //result test = cipher ^ d mod n
return f;
}
private static BigInteger eMod(BigInteger a, BigInteger b, BigInteger c) //where a^b % c;
{
//base case
if (b == 0)
{
return 1;
}
else if (b % 2 == 0)
{
BigInteger d = eMod(a, b / 2, c);
//int result = d * d % c;
return ((d * d) % c);
}
else
{
return ((a % c) * eMod(a, b - 1, c)) % c;
}
}
private static BigInteger GetGCDByModulus(BigInteger value1, BigInteger value2)
{
while (value1 != 0 && value2 != 0)
{
if (value1 > value2)
value1 %= value2;
else
value2 %= value1;
}
return BigInteger.Max(value1, value2);
}
private static bool Coprime(BigInteger value1, BigInteger value2)
{
return GetGCDByModulus(value1, value2) == 1;
}
private static string InputToAscii()
{
Console.Write("Enter values to encrypt:");
char[] input = Console.ReadLine().ToCharArray(); //-1 < input < 999;
//char[] input = "-1".ToCharArray();
string AsciiInput = string.Empty;
for (int i = 0; i < input.Length; i++)
{
AsciiInput += ((int)input[i]).ToString();
}
Console.WriteLine(AsciiInput);
return AsciiInput;
}
private static string AsciiToOutput(BigInteger input)
{
string inputstring = input.ToString();
string output = string.Empty;
for (int i = 0; i < inputstring.Length / 2; i++)
{
output += (char)Convert.ToInt32((inputstring.Substring(i * 2, 2)));
}
return output;
}
}
Related
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;
I have a json web key(https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41) and I want to use it to sign some data with the private key and then later verify it with the public key. I am using c# with .net framework 4.5.1 and I can't seem to instantiate the classes properly using the keys I have. I generated the keys using this tool: https://github.com/mitreid-connect/json-web-key-generator. The following json is available and from this I should be able to sign and verify:
{
"kty": "RSA",
"d": "rZ_cdME7usL5EavJW1q0cjz8dhfdO9P-E4dacHYFf4I-TN7o-Q0ksfWCb4fpQPghUoz6v2b6-m3IZk4CocmdEAoFH2JqI0PbH5HIBqgva-bE8-elNJIKwza0Hbrw13bRU6KgpOrc9hrX-NcRCTkeKHYtDWGUa2NDB_lNQvkyg-V0NVXf5oSa_cZ9_H4kHPXrzcBeQapn2M_CFb3qfYgVgQb5xU5n67eAcSlztWHIaSaLyu_YAR0SxnEAvWiik1rtSYrEOWsVrPHfHBFwVHluP0g--bedH6kI3mZRI6H_UbmTMnRtxBkCA5mVdzOmsyX2e98MUqIlOeDQ4zB21xSDQQ",
"e": "AQAB",
"use": "sig",
"alg": "RS512",
"n": "xwHPJaSvKvLqrqb6oeXDL3A4iNgRo5PEQOQCE5zGa6ZWeoC88IuJZxXFJ93wzJk0J22QZJWofC8vV8GAeB3d9mD25koh0dbtb0yoWK-ttWamMIAN4WPiZu30JWzxY1k8LRzOz5lIT9Ze87gV_lgXbpkzQzKFNhxOmV_BhEu1PCLcOTHhic93WQk_E97nYCOwOifmkEFOCBzHEuTG1XHJ1nGEfBCAsdUXrMg_lU3w86TfVDYS6xLVtfVAq4ihDjBsmtPthrdMG4H5Qls8EM-_cbIRe7UEAQK9MgXDLHaQZbx_lQ46_P852SpCprbvqWaoM8zKyEiDf1q6O89D6YIaDw"
}
Then in C# I have a model with those fields and I made a function to test if I can verify data:
public class RSAKeyPair
{
public string kty { get; set; }
public string e { get; set; }
public string use { get; set; }
public string alg { get; set; }
public string n { get; set; }
public string d { get; set; }
}
And the test code:
public static bool TestSigning(RSAKeyPair keySet)
{
if (keySet.alg != "RS512")
{
throw new ArgumentException("Only RS512 is supported.");
}
var oid = CryptoConfig.MapNameToOID("SHA512");
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
rsaProvider.ImportParameters(
new RSAParameters()
{
Modulus = FromBase64Url(keySet.n),
Exponent = FromBase64Url(keySet.e),
D = FromBase64Url(keySet.d)
}
);
var hasher = SHA512.Create();
var testmsg = System.Text.Encoding.UTF8.GetBytes("TestMsg");
var hash = hasher.ComputeHash(new MemoryStream(testmsg));
var signedData = rsaProvider.SignHash(hash, oid);
var isSigned = rsaProvider.VerifyHash(hash, oid, signedData);
return isSigned;
}
private static byte[] FromBase64Url(string base64Url)
{
string padded = base64Url.Length % 4 == 0
? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
string base64 = padded.Replace("_", "/")
.Replace("-", "+");
var s = Convert.FromBase64String(base64);
return s;
}
However when I run it. I get the System.Security.Cryptography.CryptographicException with the message Object contains only the public half of a key pair. A private key must also be provided. when trying to get the signedData
I have no idea which parameters to set because this seems correct according to what I understand from RSA and reading the docs.
I have also tried to create two instances of the RSACryptoServiceProvider One signer with Exponent = keySet.d and one verifier with Exponent = keySet.e. But when I call RSACryptoServiceProvider.ImportParameters for the signer it throws a Bad data exception.
Any help is appreciated.
The main reason is RSACryptoServiceProvider is not able to generate a private key using modulus, public and private exponent i.e n, e and d only, it requires p,q,dp and dq as well. To generate RsaParameters with private key you will require following code to calculate p,q,dp and dq and finally generate RsaParameters:
private static RSAParameters RecoverRSAParameters(BigInteger n, BigInteger e, BigInteger d)
{
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
BigInteger k = d * e - 1;
if (!k.IsEven)
{
throw new InvalidOperationException("d*e - 1 is odd");
}
BigInteger two = 2;
BigInteger t = BigInteger.One;
BigInteger r = k / two;
while (r.IsEven)
{
t++;
r /= two;
}
byte[] rndBuf = n.ToByteArray();
if (rndBuf[rndBuf.Length - 1] == 0)
{
rndBuf = new byte[rndBuf.Length - 1];
}
BigInteger nMinusOne = n - BigInteger.One;
bool cracked = false;
BigInteger y = BigInteger.Zero;
for (int i = 0; i < 100 && !cracked; i++)
{
BigInteger g;
do
{
rng.GetBytes(rndBuf);
g = GetBigInteger(rndBuf);
}
while (g >= n);
y = BigInteger.ModPow(g, r, n);
if (y.IsOne || y == nMinusOne)
{
i--;
continue;
}
for (BigInteger j = BigInteger.One; j < t; j++)
{
BigInteger x = BigInteger.ModPow(y, two, n);
if (x.IsOne)
{
cracked = true;
break;
}
if (x == nMinusOne)
{
break;
}
y = x;
}
}
if (!cracked)
{
throw new InvalidOperationException("Prime factors not found");
}
BigInteger p = BigInteger.GreatestCommonDivisor(y - BigInteger.One, n);
BigInteger q = n / p;
BigInteger dp = d % (p - BigInteger.One);
BigInteger dq = d % (q - BigInteger.One);
BigInteger inverseQ = ModInverse(q, p);
int modLen = rndBuf.Length;
int halfModLen = (modLen + 1) / 2;
return new RSAParameters
{
Modulus = GetBytes(n, modLen),
Exponent = GetBytes(e, -1),
D = GetBytes(d, modLen),
P = GetBytes(p, halfModLen),
Q = GetBytes(q, halfModLen),
DP = GetBytes(dp, halfModLen),
DQ = GetBytes(dq, halfModLen),
InverseQ = GetBytes(inverseQ, halfModLen),
};
}
}
private static BigInteger GetBigInteger(byte[] bytes)
{
byte[] signPadded = new byte[bytes.Length + 1];
Buffer.BlockCopy(bytes, 0, signPadded, 1, bytes.Length);
Array.Reverse(signPadded);
return new BigInteger(signPadded);
}
private static byte[] GetBytes(BigInteger value, int size)
{
byte[] bytes = value.ToByteArray();
if (size == -1)
{
size = bytes.Length;
}
if (bytes.Length > size + 1)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
if (bytes.Length == size + 1 && bytes[bytes.Length - 1] != 0)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
Array.Resize(ref bytes, size);
Array.Reverse(bytes);
return bytes;
}
private static BigInteger ModInverse(BigInteger e, BigInteger n)
{
BigInteger r = n;
BigInteger newR = e;
BigInteger t = 0;
BigInteger newT = 1;
while (newR != 0)
{
BigInteger quotient = r / newR;
BigInteger temp;
temp = t;
t = newT;
newT = temp - quotient * newT;
temp = r;
r = newR;
newR = temp - quotient * newR;
}
if (t < 0)
{
t = t + n;
}
return t;
}
Now to continue with JWK use it like following:
public static bool TestSigning(RSAKeyPair keySet)
{
if (keySet.alg != "RS512")
{
throw new ArgumentException("Only SHA512 is supported.");
}
var n = GetBigInteger(FromBase64Url(keySet.n));
var d = GetBigInteger(FromBase64Url(keySet.d));
var e = GetBigInteger(FromBase64Url(keySet.e));
var rsaParams= RecoverRSAParameters(n, e, d);
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(512);
rsaProvider.ImportParameters(rsaParams);
var hasher = SHA512.Create();
var testmsg = Encoding.UTF8.GetBytes("TestMsg");
var hash = hasher.ComputeHash(new MemoryStream(testmsg));
var oid = CryptoConfig.MapNameToOID("SHA512");
var signedData = rsaProvider.SignHash(hash, oid);
var isSigned = rsaProvider.VerifyHash(hash, oid, signedData);
return isSigned;
}
Output:
I found this as a Microsoft interview question (see Round 4). I am trying to solve it using C#. My attempt:
private static int NTerm_Tribonacci(int term)
{
int a = 0;
int b = 1;
int c = 1;
int result = 0;
if (term == 1) return a;
if (term == 2) return b;
if (term == 3) return c;
for (int i = 4; i <= term; i++)
{
a = a + b + c; if ((1 + 3 * i) % term == 0) { result = a; break; }
b = a + b + c; if ((2 * i + i - 1) % term == 0) { result = b; break; }
c = a + b + c; if ((3 * i) % term == 0) { result = c; break; }
}
return result;
}
But it is somehow not working var res = NTerm_Tribonacci(5);//should be 4 but getting 44
How can I solve this?
Tribonacci Number
Try this:
private static int NTerm_Tribonacci(int term)
{
int a = 0;
int b = 1;
int c = 1;
int result = 0;
if (term == 0) result = a;
if (term == 1) result = b;
if (term == 2) result = c;
while(term > 2)
{
result = a + b + c;
a = b;
b = c;
c = result;
term--;
}
return result;
}
Note that as per the definition in your link, I have assumed the first term to be T0, not T1.
Demo
I like the "LINQ way" of solving such things:
public IEnumerable<long> InfiniteTribonacciSequence()
{
long a = 0, b = 1, c = 1;
long nextTerm;
yield return a;
yield return b;
yield return c;
while (true)
{
nextTerm = a + b + c;
yield return nextTerm;
a = b;
b = c;
c = nextTerm;
}
}
But this has to be used carefully, because Methods like Min() will go crazy with this. But you can use e.g. InfiniteTribonacciSequence.Take(5).Last() to get the 5th element of the sequence.
I think the recursive way is too suitable for such cases:
example:
using System.IO;
using System;
class Program
{
static void Main()
{
int a=4, b;
b=tribo(a);
Console.WriteLine(b);
}
static public int tribo(int n)
{
if(n==0) return 0;
if(n==1) return 1;
if(n==2) return 1;
return(tribo(n-1)+tribo(n-2)+tribo(n-3));
}
}
this gives the series 0 1 1 2 4 7 13 24 ...
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;
}
}
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;
}
}