Convert number to reversed array of digits - c#

So I'm trying to convert a long to a reversed long array. This is what I have:
public static long[] Digitize(long n)
{
string numConvert = n.ToString();
char[] charArray = numConvert.ToCharArray();
long[] charToLong = new long[charArray.Length];
for (int i = 0; i < charArray.Length; i++)
charToLong[i] = Convert.ToInt64(charArray[i]);
return Array.Reverse(charToLong);
}
But every time I compile, I get this error: "Cannot implicitly convert type'void' to 'long[]'"
Just what am I not doing right here?

Array.Reverse(charToLong);
return charToLong;
Array.Reverse returns void, not the reversed array. Click on the link and see the Syntax: public static void .

You need to return the array, rather than the function.
Array.Reverse() doesn't return anything (void), so after calling Array.Reverse(charToLong;), you need to return your array:
return charToLong;

Just call Reverse on the string, then turn each character back to a long and return it.
public static long[] Digitize(long n)
{
var reversed = n.ToString().Reverse().Select(x => long.Parse(x.ToString())).ToArray();
return reversed;
}

Related

C# Array in array

I'm stuck trying to create array of arrays..
This is what i have for now, i would appreciate if someone could point me to right direction.
I have .txt file which has paths to images and each string has desired output separated with "|" like so:
":\\\img.png|1"
I'm trying to create array that has 2 columns and number of imagepaths as rows. Col 0 being a array of flattened rgb values of the image and col 1 being output as int.
I'm getting error from line Data[i][0] = Flat;
"Cannot implicitly convert type 'int[]' to 'int'"
It might be obvious to more experienced coders here but i cant wrap my head around this.
static int[][] CreateDataSet(string DatasetPath)
{
string[] Lines = File.ReadAllLines(DatasetPath);
int[][] Data = new int[Lines.GetUpperBound(0)][];
for (int i = 0; i <= Lines.GetUpperBound(0); i++)
{
Data[i] = new int[2];
string[] StringSplit = Lines[i].Split('|');
Data[i][1] = Convert.ToInt32(StringSplit[1]);
int[] Flat = FlattenArray(ImagetoArray(StringSplit[0]));
Data[i][0] = Flat;
}
return Data;
}
In an array, all elements must have same type (or at least must be assignable to a variable of the element's type).
You have two options.
The bad one: use array of objects.
object[][] data;
Now you can put everything in that array, but it will be slow (boxing of value types) and untyped (hard to use and to maintain).
Instead of a jagged array, use tuples.
(int[] FlattenedImage, int Output)[] data;
That looks a little bit weird, but it's actually very useful. It's strongly typed, it prevents boxing, and it uses nice and modern language features.
The big problem here is you have an int and an int[]. So the [0] index of Data must itself be an array, rather than merely an integer. And since the [0] and [1] subscripts are different types, you're really gonna need a completely different kind of data structure here.
Here's an example using Tuples:
static IEnumerable<(int, int[])> CreateDataSet(string DatasetPath)
{
var result = new List<(int, int[])> = new List<(int, int[])>();
foreach(string line in File.ReadLines(DatasetPath))
{
var lineData = line.Split('|');
yield return (int.Parse(linedata[1]), FlattenArray(ImageToArray(lineData[0])) );
}
}
or with linq:
static IEnumerable<(int, int[])> CreateDataSet(string DatasetPath)
{
return File.ReadLines(DatasetPath).Select(line => {
var data = line.Split('|');
return ( int.Parse(data[1]), FlattenArray(ImageToArray(data[0])) );
});
}
If you would create a class or a struct to containt the data it would look something like this:
class ImageData
{
public int[] FlatImate { get; }
public int Number { get; }
public ImageData(int[] flatImage, int number)
{
FlatImage = flatImage;
Number = number;
}
}
static ImageData[] CreateDataSet(string datasetPath)
{
string[] lines = File.ReadAllLines(datasetPath);
ImageData[] data = new ImageData[Lines.GetUpperBound(0)];
for (int i = 0; i <= lines.GetUpperBound(0); i++)
{
string[] stringSplit = lines[i].Split('|');
int number = Convert.ToInt32(stringSplit[1]);
int[] flat = FlattenArray(ImagetoArray(StringSplit[0]));
data[i] = new ImageData(flat, number);
}
return data;
}

Can a params array be a holding type for a list in C#?

Can a params[] variable hold a list, that has been passed as a parameter through a method in C#?
Wrote a method(AddIntegers) which requires multiple values to be taken as parameters. On the parameter list of a method, there is a params[] variable that is receiving the values thrown, when the method call is made in the Main method. But there is an exception that says "Cannot convert from system.collections.generic.List<> to an integer. Anyone knows why does that happen?
**** this is within the Main Method****
string Demostring = Console.ReadLine();
string[] tokens = Demostring.Split(',');
List<int> nums = new List<int>();
int oneNum;
foreach(string s in tokens)
{
if (Int32.TryParse(s, out oneNum))
nums.Add(oneNum);
}
int result1 = AddIntegers(nums);
**** this is the method to be called****
public static int AddIntegers(params int[] Restnum)
{
int result = 0;
foreach(int temp in Restnum)
{
result += temp;
}
return result;
}
No, a List<int> isn't an int[], so you can't use it as an argument for an int[] parameter. (The fact that it's a parameter array doesn't change that.)
Typically the solution to this is to have two overloads - one accepting a parameter array and one accepting an IEnumerable<T>:
public static int AddIntegers(params int[] numbers) =>
AddIntegers((IEnumerable<int>) numbers);
public static int AddIntegers(IEnumerable<int> numbers)
{
...
}
Note that for this specific example, you can just call the Sum extension method from LINQ to Objects, of course.
There are proposals for parameter arrays to be able to accept IReadOnlyList<T> rather than just T[], but that isn't in C# yet. (I'd love it, personally...)
This is because you are trying to insert a List inside an array parameter.
Instead of this:
int result1 = AddIntegers(nums);
You could do this:
int result1 = AddIntegers(nums.ToArray());
Or alternatively:
public static int AddIntegers(List<int> numbers)
{
return AddIntegers(numbers.ToArray());
}
public static int AddIntegers(params int[] Restnum)
{
int result = 0;
foreach(int temp in Restnum)
{
result += temp;
}
return result;
}
And then call it like you normally would.
private void button4_Click(object sender, EventArgs e)
{
const string demostring = "1,2,3,4,5,6";
var tokens = demostring.Split(',');
var nums = new List<int>();
foreach (var s in tokens)
if (int.TryParse(s, out var oneNum))
nums.Add(oneNum);
var result1 = AddIntegers(nums);
}
public static int AddIntegers(List<int> restnum)
{
var result = 0;
foreach (var temp in restnum)
result += temp;
return result;
}

generating random numbers in asp.net

i want to generate vouchers of alpha numeric code of 10 digits and the error is
"cannot implicitly convert 'void' to system.collections.generric.list"
voucher_no= generatedVouchers.Add(voucher);//it is giving me error in this line
static Random random = new Random();
public ActionResult RandomVouchers()
{
int vouchersToGenerate = 1;
int lengthOfVoucher = 10;
List<string> voucher_no = new List<string>();
List<string> generatedVouchers = new List<string>();
char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890".ToCharArray();
while (generatedVouchers.Count < vouchersToGenerate)
{
string voucher = GenerateVoucher(keys, lengthOfVoucher);
if (!generatedVouchers.Contains(voucher))
{
voucher_no= generatedVouchers.Add(voucher);//it is giving me error in this line
}
}
return View(voucher_no);
}
private static string GenerateVoucher(char[] keys, int lengthOfVoucher)
{
return Enumerable
.Range(1, lengthOfVoucher) // for(i.. )
.Select(k => keys[random.Next(0, keys.Length - 1)]) // generate a new random char
.Aggregate("", (e, c) => e + c); // join into a string
}
List<T>.Add does not return a value, its of return type void so you cant assign the result of this method call to anything.
Also there is no reason to have both voucher_no and generatedVouchers. Remove one of those, in the refactored code below I removed voucher_no.
As far as your lists are concerned do not use a List<T>, instead use a HashSet<T> so that way the check for duplicates in your list inside the loop is much more efficient as the number of codes you want to generate increases.
public ActionResult RandomVouchers()
{
int vouchersToGenerate = 1;
int lengthOfVoucher = 10;
void generatedVouchers = new HashSet<string>();
char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890".ToCharArray();
while (generatedVouchers.Count < vouchersToGenerate)
{
string voucher = GenerateVoucher(keys, lengthOfVoucher);
if (!generatedVouchers.Contains(voucher))
{
generatedVouchers.Add(voucher);
}
}
return View(generatedVouchers);
}
Also see this as a reference for how to generate a random code: How can I generate random alphanumeric strings in C#?
You are trying to equalize a void function (.Add), to a list of string. Add function returns nothing but you are assuming that it does. That's why you are getting the error. You should do it like this
voucher_no.Add(voucher);
generatedVouchers.Add(voucher);

C#, returning an array in a function

I have a method that generates an array. I want to return this array so I can use it another method. Here is my code so far:
public static Array[] generateFirstArray(int seedValue)
{
int[] firstArray = new int[20];
Random randomNumber = new Random(seedValue);
for (int i = 0; i < firstArray.Length; i++)
{
firstArray[i] = randomNumber.Next(0, 4);
}
return firstArray;
}
But when I run it, I get the following error:
Error 1 Cannot implicitly convert type 'int[]' to 'System.Array[]'
I tried to add [] after firstArray but still not working.
Your return type is currently an array of Array objects. Change your return type to an array of ints (int[]):
public static int[] generateFirstArray(int seedValue)
The signature of your methods says you're trying to return an Array of Array (Array[]).
You want to return an int[] instead so just change your signature to
public static int[] generateFirstArray(int seedValue)
the return type of your method must be int[] and not Array[]
Here is one more way of implementing it
int Min = 0;
int Max = 4;
Random randNum = new Random(seedValue);
int[] firstArray = Enumerable
.Repeat(0, 20)
.Select(i => randNum.Next(Min, Max))
.ToArray();
return firstArray;

Is there an easy way to return a string repeated X number of times?

I'm trying to insert a certain number of indentations before a string based on an items depth and I'm wondering if there is a way to return a string repeated X times. Example:
string indent = "---";
Console.WriteLine(indent.Repeat(0)); //would print nothing.
Console.WriteLine(indent.Repeat(1)); //would print "---".
Console.WriteLine(indent.Repeat(2)); //would print "------".
Console.WriteLine(indent.Repeat(3)); //would print "---------".
If you only intend to repeat the same character you can use the string constructor that accepts a char and the number of times to repeat it new String(char c, int count).
For example, to repeat a dash five times:
string result = new String('-', 5);
Output: -----
If you're using .NET 4.0, you could use string.Concat together with Enumerable.Repeat.
int N = 5; // or whatever
Console.WriteLine(string.Concat(Enumerable.Repeat(indent, N)));
Otherwise I'd go with something like Adam's answer.
The reason I generally wouldn't advise using Andrey's answer is simply that the ToArray() call introduces superfluous overhead that is avoided with the StringBuilder approach suggested by Adam. That said, at least it works without requiring .NET 4.0; and it's quick and easy (and isn't going to kill you if efficiency isn't too much of a concern).
most performant solution for string
string result = new StringBuilder().Insert(0, "---", 5).ToString();
public static class StringExtensions
{
public static string Repeat(this string input, int count)
{
if (string.IsNullOrEmpty(input) || count <= 1)
return input;
var builder = new StringBuilder(input.Length * count);
for(var i = 0; i < count; i++) builder.Append(input);
return builder.ToString();
}
}
For many scenarios, this is probably the neatest solution:
public static class StringExtensions
{
public static string Repeat(this string s, int n)
=> new StringBuilder(s.Length * n).Insert(0, s, n).ToString();
}
Usage is then:
text = "Hello World! ".Repeat(5);
This builds on other answers (particularly #c0rd's). As well as simplicity, it has the following features, which not all the other techniques discussed share:
Repetition of a string of any length, not just a character (as requested by the OP).
Efficient use of StringBuilder through storage preallocation.
Strings and chars [version 1]
string.Join("", Enumerable.Repeat("text" , 2 ));
//result: texttext
Strings and chars [version 2]:
String.Concat(Enumerable.Repeat("text", 2));
//result: texttext
Strings and chars [version 3]
new StringBuilder().Insert(0, "text", 2).ToString();
//result: texttext
Chars only:
new string('5', 3);
//result: 555
Extension way:
(works FASTER - better for WEB)
public static class RepeatExtensions
{
public static string Repeat(this string str, int times)
{
var a = new StringBuilder();
//Append is faster than Insert
( () => a.Append(str) ).RepeatAction(times) ;
return a.ToString();
}
public static void RepeatAction(this Action action, int count)
{
for (int i = 0; i < count; i++)
{
action();
}
}
}
usage:
var a = "Hello".Repeat(3);
//result: HelloHelloHello
Use String.PadLeft, if your desired string contains only a single char.
public static string Indent(int count, char pad)
{
return String.Empty.PadLeft(count, pad);
}
Credit due here
You can repeat your string (in case it's not a single char) and concat the result, like this:
String.Concat(Enumerable.Repeat("---", 5))
I would go for Dan Tao's answer, but if you're not using .NET 4.0 you can do something like that:
public static string Repeat(this string str, int count)
{
return Enumerable.Repeat(str, count)
.Aggregate(
new StringBuilder(str.Length * count),
(sb, s) => sb.Append(s))
.ToString();
}
string indent = "---";
string n = string.Concat(Enumerable.Repeat(indent, 1).ToArray());
string n = string.Concat(Enumerable.Repeat(indent, 2).ToArray());
string n = string.Concat(Enumerable.Repeat(indent, 3).ToArray());
Adding the Extension Method I am using all over my projects:
public static string Repeat(this string text, int count)
{
if (!String.IsNullOrEmpty(text))
{
return String.Concat(Enumerable.Repeat(text, count));
}
return "";
}
Hope someone can take use of it...
I like the answer given. Along the same lines though is what I've used in the past:
"".PadLeft(3*Indent,'-')
This will fulfill creating an indent but technically the question was to repeat a string. If the string indent is something like >-< then this as well as the accepted answer would not work. In this case, c0rd's solution using StringBuilder looks good, though the overhead of StringBuilder may in fact not make it the most performant. One option is to build an array of strings, fill it with indent strings, then concat that. To whit:
int Indent = 2;
string[] sarray = new string[6]; //assuming max of 6 levels of indent, 0 based
for (int iter = 0; iter < 6; iter++)
{
//using c0rd's stringbuilder concept, insert ABC as the indent characters to demonstrate any string can be used
sarray[iter] = new StringBuilder().Insert(0, "ABC", iter).ToString();
}
Console.WriteLine(sarray[Indent] +"blah"); //now pretend to output some indented line
We all love a clever solution but sometimes simple is best.
Surprised nobody went old-school.
I am not making any claims about this code, but just for fun:
public static string Repeat(this string #this, int count)
{
var dest = new char[#this.Length * count];
for (int i = 0; i < dest.Length; i += 1)
{
dest[i] = #this[i % #this.Length];
}
return new string(dest);
}
Print a line with repetition.
Console.Write(new string('=', 30) + "\n");
==============================
For general use, solutions involving the StringBuilder class are best for repeating multi-character strings. It's optimized to handle the combination of large numbers of strings in a way that simple concatenation can't and that would be difficult or impossible to do more efficiently by hand. The StringBuilder solutions shown here use O(N) iterations to complete, a flat rate proportional to the number of times it is repeated.
However, for very large number of repeats, or where high levels of efficiency must be squeezed out of it, a better approach is to do something similar to StringBuilder's basic functionality but to produce additional copies from the destination, rather than from the original string, as below.
public static string Repeat_CharArray_LogN(this string str, int times)
{
int limit = (int)Math.Log(times, 2);
char[] buffer = new char[str.Length * times];
int width = str.Length;
Array.Copy(str.ToCharArray(), buffer, width);
for (int index = 0; index < limit; index++)
{
Array.Copy(buffer, 0, buffer, width, width);
width *= 2;
}
Array.Copy(buffer, 0, buffer, width, str.Length * times - width);
return new string(buffer);
}
This doubles the length of the source/destination string with each iteration, which saves the overhead of resetting counters each time it would go through the original string, instead smoothly reading through and copying the now much longer string, something that modern processors can do much more efficiently.
It uses a base-2 logarithm to find how many times it needs to double the length of the string and then proceeds to do so that many times. Since the remainder to be copied is now less than the total length it is copying from, it can then simply copy a subset of what it has already generated.
I have used the Array.Copy() method over the use of StringBuilder, as a copying of the content of the StringBuilder into itself would have the overhead of producing a new string with that content with each iteration. Array.Copy() avoids this, while still operating with an extremely high rate of efficiency.
This solution takes O(1 + log N) iterations to complete, a rate that increases logarithmically with the number of repeats (doubling the number of repeats equals one additional iteration), a substantial savings over the other methods, which increase proportionally.
Another approach is to consider string as IEnumerable<char> and have a generic extension method which will multiply the items in a collection by the specified factor.
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int times)
{
source = source.ToArray();
return Enumerable.Range(0, times).SelectMany(_ => source);
}
So in your case:
string indent = "---";
var f = string.Concat(indent.Repeat(0)); //.NET 4 required
//or
var g = new string(indent.Repeat(5).ToArray());
Not sure how this would perform, but it's an easy piece of code. (I have probably made it appear more complicated than it is.)
int indentCount = 3;
string indent = "---";
string stringToBeIndented = "Blah";
// Need dummy char NOT in stringToBeIndented - vertical tab, anyone?
char dummy = '\v';
stringToBeIndented.PadLeft(stringToBeIndented.Length + indentCount, dummy).Replace(dummy.ToString(), indent);
Alternatively, if you know the maximum number of levels you can expect, you could just declare an array and index into it. You would probably want to make this array static or a constant.
string[] indents = new string[4] { "", indent, indent.Replace("-", "--"), indent.Replace("-", "---"), indent.Replace("-", "----") };
output = indents[indentCount] + stringToBeIndented;
I don't have enough rep to comment on Adam's answer, but the best way to do it imo is like this:
public static string RepeatString(string content, int numTimes) {
if(!string.IsNullOrEmpty(content) && numTimes > 0) {
StringBuilder builder = new StringBuilder(content.Length * numTimes);
for(int i = 0; i < numTimes; i++) builder.Append(content);
return builder.ToString();
}
return string.Empty;
}
You must check to see if numTimes is greater then zero, otherwise you will get an exception.
Using the new string.Create function, we can pre-allocate the right size and copy a single string in a loop using Span<char>.
I suspect this is likely to be the fastest method, as there is no extra allocation at all: the string is precisely allocated.
public static string Repeat(this string source, int times)
{
return string.Create(source.Length * times, source, RepeatFromString);
}
private static void RepeatFromString(Span<char> result, string source)
{
ReadOnlySpan<char> sourceSpan = source.AsSpan();
for (var i = 0; i < result.Length; i += sourceSpan.Length)
sourceSpan.CopyTo(result.Slice(i, sourceSpan.Length));
}
dotnetfiddle
I didn't see this solution. I find it simpler for where I currently am in software development:
public static void PrintFigure(int shapeSize)
{
string figure = "\\/";
for (int loopTwo = 1; loopTwo <= shapeSize - 1; loopTwo++)
{
Console.Write($"{figure}");
}
}
You can create an ExtensionMethod to do that!
public static class StringExtension
{
public static string Repeat(this string str, int count)
{
string ret = "";
for (var x = 0; x < count; x++)
{
ret += str;
}
return ret;
}
}
Or using #Dan Tao solution:
public static class StringExtension
{
public static string Repeat(this string str, int count)
{
if (count == 0)
return "";
return string.Concat(Enumerable.Repeat(indent, N))
}
}

Categories

Resources