Generate random 16-digit string - c#

What's a better way to create a random 16-digit string? I've used this code, can you suggest a more efficient or elegant way to do it?
static string Random16DigitString() {
var rand = new Random();
return $"{rand.Next(100000000).ToString().PadLeft(8, '0')}{rand.Next(100000000).ToString().PadLeft(8, '0')}";
}
PS: My reason for making this is to create a string of the form 0.0000000000000000 so I would use it in the following way:
var myString = "0." + Random16DigitString();

Your solution depends on string manipulation that will slow it down.
Try:
private static Random r = new Random();
static string Random16DigitString() {
var v = new char[16];
for (var j = 0; j < 16; j++) v[j] = (char)(r.NextDouble()*10 + 48);
return new string(v);
}
This will be faster since it doesn't depend on string operations like concatenation or interpolation. It just pokes random characters into a char array and then converts that array to a string. Executing your solution 100 million times takes about 47 seconds on my machine and my code takes about 27 seconds to produce the same results.
r.Next(10) + 48 would work in the above code but it's actually a little slower. r.Next(48,57) is even slower.
Your code could be simpler, also. $"{rand.Next(100000000):D8}{rand.Next(100000000):D8}" would do the same thing. It's about the same time to execute.

Here's the code I ended up using:
static readonly Random rnd = new Random();
static string Q() {
// https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number/768001#768001
// It was decided to use a lock instead of [ThreadStatic] because this api object is designed to be used by many threads simultaneously.
lock (rnd) {
// Get a string representing a positive number greater than 0 and less than 1 with exactly 16 decimal places.
// Original implementation
//return $"0.{rnd.Next(100000000).ToString().PadLeft(8, '0')}{rnd.Next(100000000).ToString().PadLeft(8, '0')}";
// This works but is slow
//return rnd.NextDouble().ToString("F16");
// Found a better faster way: https://stackoverflow.com/questions/48455624/generate-random-16-digit-string/48457354#48457354
var chars = new char[18];
chars[0] = '0';
chars[1] = '.';
for (var i = 2; i < 18; i++)
chars[i] = (char)(rnd.NextDouble() * 10 + 48);
return new string(chars);
}
}
Here are the tests I used (with thanks to Jim Berg for his answer)
using System;
using System.Diagnostics;
using System.Text;
namespace NetCoreApp1 {
class Program {
static void Main(string[] args) {
var sync = new object();
var rnd = new Random();
Time("method1", () => {
var value = $"{rnd.Next(100000000).ToString().PadLeft(8, '0')}{rnd.Next(100000000).ToString().PadLeft(8, '0')}";
});
Time("method2", () => {
var value = $"{rnd.Next(100000000):D8}{rnd.Next(100000000):D8}";
});
Time("next double", () => {
var value = rnd.NextDouble().ToString("F16"); // turns out surprisingly slow, even slower than the first two
});
Time("method3", () => {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // fastest
var value = new string(v);
});
Time("method3 with lock", () => {
lock (sync) {
var v = new char[16];
for (var j = 0; j < 16; j++)
v[j] = (char)(rnd.NextDouble() * 10 + 48); // a tiny bit slower with the lock
var value = new string(v);
}
});
Time("method4", () => {
var sb = new StringBuilder(16);
for (var j = 0; j < 16; j++)
sb.Append((char)(rnd.NextDouble() * 10 + 48)); // slower than method 3
var value = sb.ToString();
});
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
static void Time(string testName, Action action) {
var sw = Stopwatch.StartNew();
for (var i = 0; i < 10000000; i++)
action();
sw.Stop();
Console.WriteLine($"{testName}: {sw.ElapsedMilliseconds}ms");
}
}
}

Related

Random number in Do While Loop

I have been trying to create a random string out of alphanumeric characters and to use Do-While Loop to check if the random string meet the requirement. Otherwise, it should continue the Do Loop. However, I found the code I have always generates the same string over and over again. To demonstrate, I set int message_length = 2 and ask While Loop to check if the generated string is "ab" like while (check != "ab").
I have tried to put Random seed = new Random() in the Do Loop, out of the Do Loop, and out of the Main() as you can see the code I commented out. None of them is working. I used Visual Studio 2017, Windows 10 Home. Anyone could help? Many thanks!
(Further comments: Although I got the code working fine now, I still don't understand why the original line check = all_message.ToString(); can interrupt the random number generator in this case. IMHO, the while condition while (check != "ab") is still True so the loop will keep going. But why Random Number Generator stop generating new seed? Anyone could share knowledge about this?
using System;
using System.Text;
using System.Collections.Generic;
public class Program
{
//static Random seed = new Random();
public static void Main(string[] arggs)
{
Random seed = new Random();
const string src = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Console.WriteLine(src.Length);
int string_length = 2;
List<string> all_message = new List<string>();
string check = "";
do
{
//Random seed = new Random();
int i = 0;
StringBuilder message = new StringBuilder();
for (int j = 0; j < string_length; j++)
{
char c = src[seed.Next(0, src.Length)];
message.Append(c);
}
all_message.Add(message.ToString());
check = all_message.ToString();
Console.WriteLine(i + " = " + all_message[i]);
i++;
}
while (check != "ab");
}
}
You are resetting your counter 'i' on every iteration of the loop, so you will always write the first element of the generated list to the console. Initialize i outside the loop.
With the help from others, I figured out the issue. The critical change is check = string.Join("", all_message.ToArray());. With few other minor changes, the solutions is here:
using System;
using System.Text;
using System.Collections.Generic;
public class Program
{
//static Random seed = new Random();
public static void Main(string[] arggs)
{
Random seed = new Random();
const string src = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Console.WriteLine(src.Length);
int string_length = 2;
string check = "";
int i = 0;
do
{
//Random seed = new Random();
List<string> all_message = new List<string>();
StringBuilder message = new StringBuilder();
for (int j = 0; j < string_length; j++)
{
char c = src[seed.Next(0, src.Length)];
message.Append(c);
}
all_message.Add(message.ToString());
check = string.Join("", all_message.ToArray());
//Console.WriteLine(check);
Console.WriteLine(i + " = " + check);
i++;
}
while (check != "ab");
}
}
Hint: Read the comments.
Random seed = new Random();
const string src = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Console.WriteLine(src.Length);
int string_length = 2;
List<string> all_message = new List<string>();
string check = "";
do
{
//Random seed = new Random(); -- you do not need it any more hier.
int i = 0; // if you whant counting with i, put it above the do while.
StringBuilder message = new StringBuilder();
for (int j = 0; j < string_length; j++)
{
char c = src[seed.Next(0, src.Length)];
message.Append(c);
}
all_message.Add(message.ToString());
check = all_message.ToString(); // this is the list from string you do not need it realy and list to string = System.Collections.Generics.List....
//instead check should be equal to all_message[i] case i counting properly
Console.WriteLine(i + " = " + all_message[i]); // and hier simply print the check, you allready have the value.
i++;
}
while (check != "ab");
I ran the following:
Random seed = new Random();
const string src = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Console.WriteLine(src.Length);
int string_length = 2;
List<string> all_message = new List<string>();
string check = "";
int i = 0;
do
{
//Random seed = new Random();
StringBuilder message = new StringBuilder();
for (int j = 0; j < string_length; j++)
{
char c = src[seed.Next(0, src.Length)];
message.Append(c);
}
all_message.Add(message.ToString());
check = all_message.ToString();
Console.WriteLine(i + " = " + all_message[i]);
i++;
}
while (i < 3);
My output was:
62
0 = PQ
1 = xw
2 = he
Note that the index i is initialised outside the loop and so it not reset every time through.
The question then becomes, what are your requirements and when to terminate the loop and what should check be?

Ways to Improve generic Dictionary performance

I have a Dictinary<int, int> which populated with ~5Mio records.
While the performance is reasonably good considering the volume of data I'm looking to improve it. I don't care about data population my main concern is data retrieval.
First thing I'd done - I changed value type from decimal to int which got me twice better performance.
Then I tried trading 'genericness' for speed by passing non-generic IntComparer into Dictionary's ctor as follows:
public class IntegerComparer : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
return x == y;
}
public int GetHashCode(int obj)
{
return obj;
}
}
but to no avail, performance got degraded by 20%. SortedDictionary slowed things down by 10 times (didn't have much hope on it though). Wonder what can be done for improving the performance if any?
here's a synthetic test just for measuring performance:
var d = new Dictionary<int, int>();
for (var i = 0; i < 5000000; i++)
{
d.Add(i, i + 5);
}
var r = new Random();
var s = new Stopwatch();
s.Start();
for (var i = 0; i < 100000; i++)
{
var r0 = Enumerable.Range(1, 255).Select(t => r.Next(5000000));
var values = r0.Select(t => d[t]).ToList();
}
s.Stop();
MessageBox.Show(s.ElapsedMilliseconds.ToString());
As the comments point out your test is seriously flawed...
If the highest index you will see is 5,000,0000 then an array will be the most performant option. I've tried to quickly rewrite your test to try an eliminate some of the error. There will probably be mistakes, writing accurate benchmarks is hard.
static void Main(string[] args)
{
var loopLength = 100000000;
var d = new Dictionary<int, int>();
for (var i = 0; i < 5000000; i++)
{
d.Add(i, i + 5);
}
var ignore = d[7];
var a = new int[5000000];
for (var i = 0; i < 5000000; i++)
{
a[i] = i + 5;
}
ignore = a[7];
var s = new Stopwatch();
var x = 1;
s.Start();
for (var i = 0; i < loopLength; i++)
{
x = (x * 1664525 + 1013904223) & (4194303);
var y = d[x];
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
s.Reset();
x = 1;
s.Start();
for (var i = 0; i < loopLength; i++)
{
x = (x * 1664525 + 1013904223) & (4194303);
var y = a[x];
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
Console.ReadKey(true);
}
x coefficients borrowed from Wikipedia's Linear congruential generator article
My results:
24390
2076
That makes the array over 12x faster

Array to new string

I'm making a webshop for school and had a quick question.
I'm trying to write a code that generates a random coupon code and it actually works (did some extreme programming in Console Application), but it's simply not efficient.
static void Main(string[] args)
{
Random r = new Random();
string ALphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 4;
char[] code1 = new char[size]
char[] code2 = new char[size]
char[] code3 = new char[size]
for (int i = 0; i < size; i++)
{
code1[i] = Alphabet[r.Next(Alphabet.Length)];
code2[i] = Alphabet[r.Next(Alphabet.Length)];
code3[i] = Alphabet[r.Next(Alphabet.Length)];
}
string code4 = new string(code1);
string code5 = new string(code2);
string code6 = new string(code3);
Console.WriteLine(code4 + " - " + code5 + " - " + code6);
Console.ReadLine();
}
This works.. somehow. But I would like to see it more efficient, because when I want to generate 100 coupons... this isn't really the way to do that.
I did see something on joining strings, use string.Insert to get that " - " in between and loop it multiple times, but I couldn't get a clear tutorial on how to do that with... well this kind of code.
Anyone got a efficient and (preferable) easy solution?
=======
UPDATE!
this does end up in a database eventually
You could be using a StringBuilder for this:
StringBuilder sb = new StringBuilder();
Random r = new Random();
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 16;
for (var i = 0; i < size; i++)
{
sb.Append(Alphabet[r.Next(Alphabet.Length)]);
}
Console.WriteLine(sb.ToString());
If you want less code you can make use of a GUID and format it.
Guid.NewGuid().ToString("N").Substring(0, 16);
Update, just saw you needed some formatting between each part of the coupon, so I changed it a litle bit:
StringBuilder sb = new StringBuilder();
Random r = new Random();
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int pieces = 3, pieceSize = 4;
for (var i = 0; i < pieces; i++)
{
if(i != 0)
sb.Append(" - ");
for (var j = 0; j < pieceSize; j++)
{
sb.Append(Alphabet[r.Next(Alphabet.Length)]);
}
}
Console.WriteLine(sb.ToString());
Code is not quite good, but for school app will play I guess )
static string GenerateCoupon(Random r)
{
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 4;
char[] code1 = new char[size];
char[] code2 = new char[size];
char[] code3 = new char[size];
for (int i = 0; i < size; i++)
{
code1[i] = Alphabet[r.Next(Alphabet.Length)];
code2[i] = Alphabet[r.Next(Alphabet.Length)];
code3[i] = Alphabet[r.Next(Alphabet.Length)];
}
string code4 = new string(code1);
string code5 = new string(code2);
string code6 = new string(code3);
return string.Format("{0}-{1}-{2}", code4, code5, code6);
}
static void Main(string[] args)
{
Random rnd = new Random();
for (int i = 0; i < 100;i++ )
Console.WriteLine(GenerateCoupon(rnd));
Console.ReadLine();
}

Sorting many TValue arrays with one TKey array

I have an outer array of N inner arrays of size M. I want to sort each inner array according to another array K exactly in the same way as a built-in Array.Sort<TKey, TValue> Method (TKey[], TValue[], IComparer<TKey>) .NET method does.
The method modifies the Key array after sorting, so I can use it to sort only single inner array. To sort many arrays, I copy the Key array to another KeyBuffer array for each inner array, reusing the KeyBuffer on each sorting step and avoiding allocation and GC. Is that the most efficient way if the typical N is 10K-100K and M < 1000? Given the low size of M the copying and sorting should be done in CPU cache, - which is the fastest that I can get?
My concern is that by doing so, I am sorting the buffer and discarding the results (N-1) times, which is a kind of waste. Also I am doing actual sorting N times, but after the first sorting I already know a map of old indexes to new indexes and I could somehow reuse that mapping for other (N-1) steps.
How would you avoid unnecessary sorting and apply known mapping from the first step to other steps?
Here is the code how I do it now. The question is if it is possible to do it more efficiently.
using System;
using System.Collections.Generic;
namespace MultiSorting {
class Program {
static void Main(string[] args) {
var N = 10;
var M = 5;
var outer = new List<string[]>(N);
for (var i = 0; i < N; i++) {
string[] inner = { "a" + i, "d" + i, "c" + i, "b" + i, "e" + i };
outer.Add(inner);
}
int[] keys = { 1, 4, 3, 2, 5 };
var keysBuffer = new int[M];
for (int i = 0; i < N; i++) {
Array.Copy(keys, keysBuffer, M);
// doing sort N times, but we know the map
// old_index -> new_index from the first sorting
// plus we sort keysBuffer N times but use the result only one time
Array.Sort(keysBuffer, outer[i]);
}
keys = keysBuffer;
foreach (var key in keys) {
Console.Write(key + " "); // 1, 2, 3, 4, 5
}
Console.WriteLine("");
for (var i = 0; i < N; i++) {
foreach (var item in outer[i]) {
Console.Write(item + " "); // a{i}, b{i}, c{i}, d{i}, e{i}
}
Console.WriteLine("");
}
Console.ReadLine();
}
}
Just played with this and implemented mapping reuse directly in a for loop. I didn't expect that a simple loop instead of native built-in methods could speed up things, probably because I had underestimated algorithmic costs of sorting vs costs of array looping and I used to relax when a profiler said the job was mostly done inside .NET methods...
Naive is the code from the question, ReuseMap is what is described in words in the question, Linq is from the answer by #L.B. ...InPlace modifies input, ...Copy doesn't.
Results with N = 2000, M = 500, 10 runs, in milliseconds:
NaiveInPlace: 1005
ReuseMapInPlace: 129 (Log2(500) = 9.0, speed-up = 7.8x)
NaiveCopy: 1181
ReuseMapCopy: 304
LinqCopy: 3284
The entire test is below:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace MultiSorting {
class Program {
static void Main() {
const int n = 2;
const int m = 10;
var keys = GenerateKeys(m);
foreach (var key in keys) {
Console.Write(key + " ");
}
Console.WriteLine("");
var keysBuffer = new int[keys.Length];
Array.Copy(keys, keysBuffer, keys.Length);
Array.Sort(keysBuffer);
foreach (var key in keysBuffer) {
Console.Write(key + " ");
}
Console.WriteLine("");
// warm up, check that output is the same
List<string[]> outer = MultiSortNaiveInPlace(keys, GenerateOuter(n, m));
PrintResults(outer);
outer = MultiSortNaiveCopy(keys, GenerateOuter(n, m));
PrintResults(outer);
outer = MultiSortReuseMapInPlace(keys, GenerateOuter(n, m));
PrintResults(outer);
outer = MultiSortReuseMapCopy(keys, GenerateOuter(n, m));
PrintResults(outer);
outer = MultiSortLinqCopy(keys, GenerateOuter(n, m));
PrintResults(outer);
// tests
keys = GenerateKeys(500);
NaiveInPlace(2000, 500, keys);
ReuseMapInPlace(2000, 500, keys);
NaiveCopy(2000, 500, keys);
ReuseMapCopy(2000, 500, keys);
LinqCopy(2000, 500, keys);
Console.ReadLine();
}
private static void NaiveInPlace(int n, int m, int[] keys) {
const int rounds = 10;
var source = new List<List<string[]>>(rounds);
for (int i = 0; i < rounds; i++) {
source.Add(GenerateOuter(n, m));
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < rounds; i++) {
source[i] = MultiSortNaiveInPlace(keys, source[i]);
}
sw.Stop();
Console.WriteLine("NaiveInPlace: " + sw.ElapsedMilliseconds);
}
private static void ReuseMapInPlace(int n, int m, int[] keys) {
const int rounds = 10;
var source = new List<List<string[]>>(rounds);
for (int i = 0; i < rounds; i++) {
source.Add(GenerateOuter(n, m));
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < rounds; i++) {
source[i] = MultiSortReuseMapInPlace(keys, source[i]);
}
sw.Stop();
Console.WriteLine("ReuseMapInPlace: " + sw.ElapsedMilliseconds);
}
private static void NaiveCopy(int n, int m, int[] keys) {
const int rounds = 10;
var source = new List<List<string[]>>(rounds);
for (int i = 0; i < rounds; i++) {
source.Add(GenerateOuter(n, m));
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < rounds; i++) {
source[i] = MultiSortNaiveCopy(keys, source[i]);
}
sw.Stop();
Console.WriteLine("NaiveCopy: " + sw.ElapsedMilliseconds);
}
private static void ReuseMapCopy(int n, int m, int[] keys) {
const int rounds = 10;
var source = new List<List<string[]>>(rounds);
for (int i = 0; i < rounds; i++) {
source.Add(GenerateOuter(n, m));
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < rounds; i++) {
source[i] = MultiSortReuseMapCopy(keys, source[i]);
}
sw.Stop();
Console.WriteLine("ReuseMapCopy: " + sw.ElapsedMilliseconds);
}
private static void LinqCopy(int n, int m, int[] keys) {
const int rounds = 10;
var source = new List<List<string[]>>(rounds);
for (int i = 0; i < rounds; i++) {
source.Add(GenerateOuter(n, m));
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < rounds; i++) {
source[i] = MultiSortLinqCopy(keys, source[i]);
}
sw.Stop();
Console.WriteLine("LinqCopy: " + sw.ElapsedMilliseconds);
}
private static void PrintResults(List<string[]> outer) {
for (var i = 0; i < outer.Count; i++) {
foreach (var item in outer[i]) {
Console.Write(item + " "); // a{i}, b{i}, c{i}, d{i}, e{i}
}
Console.WriteLine("");
}
}
private static int[] GenerateKeys(int m) {
var keys = new int[m];
for (int i = 0; i < m; i++) { keys[i] = i; }
var rnd = new Random();
keys = keys.OrderBy(x => rnd.Next()).ToArray();
return keys;
}
private static List<string[]> GenerateOuter(int n, int m) {
var outer = new List<string[]>(n);
for (var o = 0; o < n; o++) {
var inner = new string[m];
for (int i = 0; i < m; i++) { inner[i] = "R" + o + "C" + i; }
outer.Add(inner);
}
return outer;
}
private static List<string[]> MultiSortNaiveInPlace(int[] keys, List<string[]> outer) {
var keysBuffer = new int[keys.Length];
foreach (var inner in outer) {
Array.Copy(keys, keysBuffer, keys.Length);
// doing sort N times, but we know the map
// old_index -> new_index from the first sorting
// plus we sort keysBuffer N times but use the result only one time
Array.Sort(keysBuffer, inner);
}
return outer;
}
private static List<string[]> MultiSortNaiveCopy(int[] keys, List<string[]> outer) {
var result = new List<string[]>(outer.Count);
var keysBuffer = new int[keys.Length];
for (var n = 0; n < outer.Count(); n++) {
var inner = outer[n];
var newInner = new string[keys.Length];
Array.Copy(keys, keysBuffer, keys.Length);
Array.Copy(inner, newInner, keys.Length);
// doing sort N times, but we know the map
// old_index -> new_index from the first sorting
// plus we sort keysBuffer N times but use the result only one time
Array.Sort(keysBuffer, newInner);
result.Add(newInner);
}
return result;
}
private static List<string[]> MultiSortReuseMapInPlace(int[] keys, List<string[]> outer) {
var itemsBuffer = new string[keys.Length];
var keysBuffer = new int[keys.Length];
Array.Copy(keys, keysBuffer, keysBuffer.Length);
var map = new int[keysBuffer.Length];
for (int m = 0; m < keysBuffer.Length; m++) {
map[m] = m;
}
Array.Sort(keysBuffer, map);
for (var n = 0; n < outer.Count(); n++) {
var inner = outer[n];
for (int m = 0; m < map.Length; m++) {
itemsBuffer[m] = inner[map[m]];
}
Array.Copy(itemsBuffer, outer[n], inner.Length);
}
return outer;
}
private static List<string[]> MultiSortReuseMapCopy(int[] keys, List<string[]> outer) {
var keysBuffer = new int[keys.Length];
Array.Copy(keys, keysBuffer, keysBuffer.Length);
var map = new int[keysBuffer.Length];
for (int m = 0; m < keysBuffer.Length; m++) {
map[m] = m;
}
Array.Sort(keysBuffer, map);
var result = new List<string[]>(outer.Count);
for (var n = 0; n < outer.Count(); n++) {
var inner = outer[n];
var newInner = new string[keys.Length];
for (int m = 0; m < map.Length; m++) {
newInner[m] = inner[map[m]];
}
result.Add(newInner);
}
return result;
}
private static List<string[]> MultiSortLinqCopy(int[] keys, List<string[]> outer) {
var result = outer.Select(arr => arr.Select((item, inx) => new { item, key = keys[inx] })
.OrderBy(x => x.key)
.Select(x => x.item)
.ToArray()) // allocating
.ToList(); // allocating
return result;
}
}
}

How to change stack size of a console application? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to change stack size for a .NET program?
I want to change the stack size for the following console application:
using System;
using System.IO;
class Test {
static int n;
static bool[] us;
static int[,] matr;
static void dfs(int a) {
us[a] = true;
for (int b = 0; b < n; b++) {
if (!us[b]) {
dfs(b);
}
}
}
static void Main() {
StreamReader input = new StreamReader("input.txt");
StreamWriter output = new StreamWriter("output.txt");
string[] snum = input.ReadLine().Split(' ');
n = int.Parse(snum[0]); // number of vertices
int m = int.Parse(snum[1]); // number of edges
us = new bool[n];
matr = new int[n, n];
for (int i = 0; i < m; i++) {
snum = input.ReadLine().Split(' ');
int a = int.Parse(snum[0]) - 1, b = int.Parse(snum[1]) - 1;
matr[a, b] = matr[b, a] = 1;
}
for (int i = 0; i < n; i++) {
if (!us[i]) {
dfs(i);
}
}
input.Close();
output.Close();
}
}
When n is aprox. 100,000, the depth of dfs is aprox. 100,000 and the application throws a StackOverflowException.
I know that the default stack size is 1 MB, but I do not know how to change it.
int stackSize = 1024*1024*64;
Thread th = new Thread( ()=>
{
//YourCode
},
stackSize);
th.Start();
th.Join();
The easiest way to specify a larger stack size is to create a new thread -- there's a constructor overload that allows you to specify the size. Move the logic to a new method, then, in the Main method, create a new thread with a larger stack size to run the new method. Example:
static void Main() {
const int stackSize = 0x400000;
var thread = new Thread(NewMethod, stackSize);
thread.Start();
thread.Join();
}
static void NewMethod() {
StreamReader input = new StreamReader("input.txt");
StreamWriter output = new StreamWriter("output.txt");
string[] snum = input.ReadLine().Split(' ');
n = int.Parse(snum[0]);
int m = int.Parse(snum[1]);
us = new bool[n];
matr = new int[n, n];
for (int i = 0; i < m; i++) {
snum = input.ReadLine().Split(' ');
int a = int.Parse(snum[0]) - 1, b = int.Parse(snum[1]) - 1;
matr[a, b] = matr[b, a] = 1;
}
for (int i = 0; i < n; i++) {
if (!us[i]) {
dfs(i);
}
}
input.Close();
output.Close();
}
You can also use EDITBIN, if you're not able to change the source code. See this answer for details: https://stackoverflow.com/a/2556970/385844

Categories

Resources