How to write a toString method without using other class libraries [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to write my own toString method since I am not allowed to use any class libraries.
So I took a look into the source code of the toString method, but it uses a lot of other libraries. I want to convert an Integer into a String, but I am not sure how i can address the numbers one by one.
If I could do that, I could continue by casting the Integers into a Char and in the end add up all the Chars for a String.
Can someone help?

Here's a similar approach to the other answers.
The important points:
We calculate the last digit of a number by finding its remainder when it's divided by 10 (i.e. lastDigit = number % 10;)
To throw away the last digit of a number, simply divide it by 10.
When finding digits that way, they will of course be returned in reverse order (least significant digit first) so you have to reverse the digits to get the correct answer. One way to do this is to store from the end to the beginning of a char array.
Negative numbers have to be handled specially. The easiest way is to note that the number is negative so that a - sign can be added when appropriate; then, negate the number to make it positive. However, note that you can't negate int.MinValue, so that has to be handled specially.
You can convert from a numeric digit to its char equivalent by adding it to the char '0' and casting the result back to char.
Here's an approach that uses those points:
public static string MyToString(int number)
{
if (number == int.MinValue)
return "-2147483648"; // Special case.
char[] digits = new char[64]; // Support at most 64 digits.
int last = digits.Length;
bool isNegative = number < 0;
if (isNegative)
number = -number;
do
{
digits[--last] = (char) ('0' + number % 10);
number /= 10;
}
while (number != 0);
if (isNegative)
digits[--last] = '-';
return new string(digits, last, digits.Length-last);
}
I think the main part you were asking about is how to get the digits of a number one-by-one, which is answered by the do/while loop above.
[EDIT] Addressed the points raised in the comments below.

I don't understand why you're not allowed to use any libraries. But if you need to do the conversion entirely by hand, you could do it something like this
private static string IntToString(int i)
{
string[] digits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
string sign = (i < 0 ? "-" : "");
var absI = (i < 0 ? -i : i);
string result = "";
while (absI != 0)
{
int digit = absI % 10;
result = digits[digit] + result;
absI = (absI - digit) / 10;
}
return sign + result;
}
The code above doesn't work properly for zero. If you need that, it's very simple to add.

For example you can split your number into individual characters:
// Note that this is just for example and for positive numbers only.
IEnumerable<char> ToChar(int num)
{
while (num > 0)
{
// adding '0' to number will return char for that number
char ch = (char)(num % 10 + '0');
num /= 10;
yield return ch;
}
}
then create new string based on that:
string ToString(int num)
{
// ToChar will return char collection in reverse order,
// so you will need to reverse collection before using.
// Well in your situation you will be probably needed to
// to write Reverse method by yourself, so this is just for
// working example
var chArray = ToChar(num).Reverse().ToArray();
string str = new string(chArray);
return str;
}
and usage:
int i = 554;
string str = ToString(i);
References: DotNetFiddle Example (with simplified ToChar() method)

Related

Maximum product of 13 adjacent numbers

List<int> arr = new List<int>();
long max = 0;
long mul = 1;
string abc = #"73167176531330624919225119674426574742355349194934
85861560789112949495459501737958331952853208805511
96983520312774506326239578318016984801869478851843
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450";
foreach (char a in abc)
{
if(arr.Count == 13)
{
arr.RemoveAt(0);
}
int value = (int)Char.GetNumericValue(a);
arr.Add(value);
if(arr.Count == 13)
{
foreach(int b in arr)
{
mul = mul * b;
if (mul > max)
{
max = mul;
}
}
mul = 1;
}
}
Console.WriteLine(max);
I am getting 5377010688 which is a wrong answer and when I am trying same logic with given example in project Euler it is working fine, please help me.
Don't say the answer just correct me where I am doing wrong or where the code is not running as it should.
The string constant, as it is written down like above, contains blanks and \r\n's, e.g. between the last '4' of the first line and the first '8' on the second line. Char.GetNumericValue() returns -1 for a blank.
Propably the character sequence with the highest product spans across adjacent lines in your string, therefore there are blanks in between, which count as -1, which disables your code in finding them.
Write your constant like this:
string abc = #"73167176531330624919225119674426574742355349194934" +
"85861560789112949495459501737958331952853208805511" +
"96983520312774506326239578318016984801869478851843" + etc.
The result is then 23514624000, I hope that's correct.
Don't say the answer just correct me where I am doing wrong or where
the code is not running as it should
You have included all characters into calculation but you should not do that. The input string also contains for example carriage return '\n' at the end of each line.
Your actual string look like this:
string abc = #"73167176531330624919225119674426574742355349194934\r\n
85861560789112949495459501737958331952853208805511\r\n
...
How to solve this? You should ignore these characters, one possible solution is to check each char if it is a digit:
if(!char.IsDigit(a))
{
continue;
}

How to take digits from two different numbers and form a new one

I have the following problem here:My input is several lines of 2 digit numbers and I need to make a new number using the second digit of the first number and the first of the next one.
Example:
int linesOfNumbers = Convert.ToInt32(Console.ReadLine());
for(int i = 0,i<linesOfNumbers,i++)
{
int numbers = Conver.ToInt32(Console.ReadLine());
//that's for reading the input
}
I know how to separate the numbers into digits.My question is how to merge them.
For example if your input is 12 and 21 the output should be 22.
I like oRole's answer, but I think they're missing a couple things with the example input that you provided in your comment. I'll also point out some of the errors in the code that you have.
First off, if you're only given the input 12,23,34,45, then you don't need to call Console.ReadLine within your for loop. You've already gotten the input, you don't need to get any more (from what you've described).
Secondly, unless you're doing mathematical operations, there is no need to store numerical data as ints, keep it as a string, especially in this case. (What I mean is that you don't store Zip Codes in a database as a number, you store it as a string.)
Now, onto the code. You had the right way to get your data:
var listOfNumbers = Console.ReadLine();
At that point, listOfNumbers is equal to "12,23,34,45". If you iterate on that variable as a string, you'll be taking each individual character, including the commas. To get each of the numbers to operate on, you'll need to use string.Split.
var numbers = listOfNumbers.Split(',');
This turns that list into four different two character numbers (in string form). Now, you can iterate over them, but you don't need to worry about converting them to numbers as you're operating on the characters in each string. Also, you'll need a results collection to put everything into.
var results = new List<string>();
// Instead of the regular "i < numbers.Length", we want to skip the last.
for (var i = 0; i < numbers.Length - 1; i++)
{
var first = numbers[i];
var second = numbers[i + 1]; // This is why we skip the last.
results.Add(first[1] + second[0]);
}
Now your results is a collection of the numbers "22", "33", and "44". To get those back into a single string, you can use the helper method string.Join.
Console.WriteLine(string.Join(",", results));
You could use the string-method .Substring(..) to achieve what you want.
If you want to keep int-conversion in combination with user input, you could do:
int numA = 23;
int numB = 34;
int resultAB = Convert.ToInt16(numA.ToString().Substring(1, 1) + numB.ToString().Substring(0, 1));
Another option would be to take the users input as string values and to convert them afterwards like that:
string numC = "12";
string numD = "21";
int resultCD = Convert.ToInt16(numC.Substring(1, 1) + numD.Substring(0, 1));
I hope this code snippet will help you combining your numbers. The modulo operator (%) means: 53 / 10 = 5 Rest 3
This example shows the computation of the numbers 34 and 12
int firstNumber = 34 - (34 % 10) // firstNumber = 30
int secondNumber = 12 % 10; // secondNumber = 2
int combined = firstNumber + secondNumber; // combined = 32
EDIT (added reading and ouput code):
boolean reading = true;
List<int> numbers = new ArrayList();
while(reading)
{
try
{
int number = Convert.ToInt32(Console.ReadLine());
if (number > 9 && number < 100) numbers.Add(number);
else reading = false; // leave reading process if no 2-digit-number
}
catch (Exception ex)
{
// leave reading process by typing a character instead of a number;
reading = false;
}
}
if (numbers.Count() > 1)
{
List<int> combined = new ArrayList();
for (int i = 1; i <= numbers.Count(); i++)
{
combined.Add((numbers[i-1] % 10) + (numbers[i] - (numbers[i] % 10)));
}
//Logging output:
foreach (int combination in combined) Console.WriteLine(combination);
}
As you mention, if you already have both numbers, and they are always valid two digit integers, following code should work for you.
var num1 = 12;
var num2 = 22;
var result = (num2 / 10)*10 + (num1 % 10);
num2/10 returns the first digit of second number, and num1 % 10 returns the second digit of the first number.
The % and / signs are your savior.
If you want the 'ones' digit of a number (lets call it X), simply do X%10 - the remainder will be whatever number is in the 'ones' digit. (23%10=3)
If, instead, the number is two digits and you want the 'tens' digit, divide it by ten. (19/10=1).
To merge them, multiply the number you want to be in the 'tens' digit by ten, and add the other number to it (2*10+2=22)
There are other solutions like substring, etc and many one have already given it above. I am giving the solution VIA LINQ, note that this isn't efficient and it's recommended only for learning purpose here
int numA = 12;
int numB = 21 ;
string secondPartofNumA = numA.ToString().Select(q => new string(q,1)).ToArray()[1]; // first digit
string firstPartofNumB = numB.ToString().Select(q => new string(q,1)).ToArray()[0]; // second digit
string resultAsString = secondPartofNumA + firstPartofNumB;
int resultAsInt = Convert.ToInt32(resultAsString);
Console.WriteLine(resultAsString);
Console.WriteLine(resultAsInt);

How to get count of numbers in int and how to split a number without making a string

I have a number like 601511616
If all number's length is multiple of 3, how can a split the number into an array without making a string
Also, how can I count numbers in the int without making a string?
Edit: Is there a way to simply split the number, knowing it's always in a multiple of 3... good output should look like this: {616,511,601}
You can use i % 10 in order to get the last digit of integer.
Then, you can use division by 10 for removing the last digit.
1234567 % 10 = 7
1234567 / 10 = 123456
Here is the code sample:
int value = 601511616;
List<int> digits = new List<int>();
while (value > 0)
{
digits.Add(value % 10);
value /= 10;
}
// digits is [6,1,6,1,1,5,1,0,6] now
digits.Reverse(); // Values has been inserted from least significant to the most
// digits is [6,0,1,5,1,1,6,1,6] now
Console.WriteLine("Count of digits: {0}", digits.Count); // Outputs "9"
for (int i = 0; i < digits.Count; i++) // Outputs "601,511,616"
{
Console.Write("{0}", digits[i]);
if (i > 0 && i % 3 == 0) Console.Write(","); // Insert comma after every 3 digits
}
IDEOne working demonstration of List and division approach.
Actually, if you don't need to split it up but only need to output in 3-digit groups, then there is a very convenient and proper way to do this with formatting.
It will work as well :)
int value = 601511616;
Console.WriteLine("{0:N0}", value); // 601,511,616
Console.WriteLine("{0:N2}", value); // 601,511,616.00
IDEOne working demonstration of formatting approach.
I can't understand your question regarding how to split a number into an array without making a string - sorry. But I can understand the question about getting the count of numbers in an int.
Here's your answer to that question.
Math.Floor(Math.Log10(601511616) + 1) = 9
Edit:
Here's the answer to your first question..
var n = 601511616;
var nArray = new int[3];
for (int i = 0, numMod = n; i < 3; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Please keep in mind there's no safety in this operation.
Edit#3
Still not perfect, but a better example.
var n = 601511616;
var nLength = (int)Math.Floor(Math.Log10(n) + 1)/ 3;
var nArray = new int[nLength];
for (int i = 0, numMod = n; i < nLength; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Edit#3:
IDEOne example http://ideone.com/SSz3Ni
the output is exactly as the edit approved by the poster suggested.
{ 616, 511, 601 }
Using Log10 to calculate the number of digits is easy, but it involves floating-point operations which is very slow and sometimes incorrect due to rounding errors. You can use this way without calculating the value size first. It doesn't care if the number of digits is a multiple of 3 or not.
int value = 601511616;
List<int> list = new List<int>();
while (value > 0) // main part to split the number
{
int t = value % 1000;
value /= 1000;
list.Add(t);
}
// Convert back to an array only if it's necessary, otherwise use List<T> directly
int[] splitted = list.ToArray();
This will store the splitted numbers in reverse order, i.e. 601511616 will become {616, 511, 601}. If you want the numbers in original order, simply iterate the array backwards. Alternatively use Array.Reverse or a Stack
Since you already know they are in multiples of 3, you can just use the extracting each digit method but use 1000 instead of 10. Here is the example
a = 601511616
b = []
while(a):
b.append(a%1000)
a = a//1000
print(b)
#[616, 511, 601]

Finding number of digits of a number in C#

I'm trying to write a piece of code in C# to find the number digits of a integer number, the code works perfectly for all numbers (negative and positive) but I have problem with 10, 100,1000 and so on, it shows one less digits than the numbers' actual number of digits. like 1 for 10 and 2 for 100..
long i = 0;
double n;
Console.Write("N? ");
n = Convert.ToInt64(Console.ReadLine());
do
{
n = n / 10;
i++;
}
while(Math.Abs(n) > 1);
Console.WriteLine(i);
Your while condition is Math.Abs(n) > 1, but in the case of 10, you are only greater than 1 the first time. You could change this check to be >=1 and that should fix your problem.
do
{
n = n / 10;
i++;
}
while(Math.Abs(n) >= 1);
Use char.IsDigit:
string input = Console.ReadLine();
int numOfDigits = input.Count(char.IsDigit);
What's wrong with:
Math.Abs(n).ToString(NumberFormatInfo.InvariantInfo).Length;
Indeed, converting a number to a string is computationally expensive compared to some arithmetic, but it is hard to deal with negative nubers, overflow,...
You need to use Math.Abs to make sure the sign is not counted, and it is a safe option to use NumberFormatInfo.InvariantInfo so that for instance certain cultures that use spaces and accents, do not alter the behavior.
public static int NumDigits(int value, double #base)
{
if(#base == 1 || #base <= 0 || value == 0)
{
throw new Exception();
}
double rawlog = Math.Log(Math.Abs(value), #base);
return rawlog - (rawlog % 1);
}
This NumDigits function is designed to find the number of digits for a value in any base. It also includes error handling for invalid input. The # with the base variable is to make it a verbatim variable (because base is a keyword).
Console.ReadLine().Replace(",", String.Empty).Length;
this will count all the char in a string
int amount = 0;
string input = Console.ReadLine();
char[] chars = input.ToArray();
foreach (char c in chars)
{
amount++;
}
Console.WriteLine(amount.ToString());
Console.ReadKey();

Constantly Incrementing String

So, what I'm trying to do this something like this: (example)
a,b,c,d.. etc. aa,ab,ac.. etc. ba,bb,bc, etc.
So, this can essentially be explained as generally increasing and just printing all possible variations, starting at a. So far, I've been able to do it with one letter, starting out like this:
for (int i = 97; i <= 122; i++)
{
item = (char)i
}
But, I'm unable to eventually add the second letter, third letter, and so forth. Is anyone able to provide input? Thanks.
Since there hasn't been a solution so far that would literally "increment a string", here is one that does:
static string Increment(string s) {
if (s.All(c => c == 'z')) {
return new string('a', s.Length + 1);
}
var res = s.ToCharArray();
var pos = res.Length - 1;
do {
if (res[pos] != 'z') {
res[pos]++;
break;
}
res[pos--] = 'a';
} while (true);
return new string(res);
}
The idea is simple: pretend that letters are your digits, and do an increment the way they teach in an elementary school. Start from the rightmost "digit", and increment it. If you hit a nine (which is 'z' in our system), move on to the prior digit; otherwise, you are done incrementing.
The obvious special case is when the "number" is composed entirely of nines. This is when your "counter" needs to roll to the next size up, and add a "digit". This special condition is checked at the beginning of the method: if the string is composed of N letters 'z', a string of N+1 letter 'a's is returned.
Here is a link to a quick demonstration of this code on ideone.
Each iteration of Your for loop is completely
overwriting what is in "item" - the for loop is just assigning one character "i" at a time
If item is a String, Use something like this:
item = "";
for (int i = 97; i <= 122; i++)
{
item += (char)i;
}
something to the affect of
public string IncrementString(string value)
{
if (string.IsNullOrEmpty(value)) return "a";
var chars = value.ToArray();
var last = chars.Last();
if(char.ToByte() == 122)
return value + "a";
return value.SubString(0, value.Length) + (char)(char.ToByte()+1);
}
you'll probably need to convert the char to a byte. That can be encapsulated in an extension method like static int ToByte(this char);
StringBuilder is a better choice when building large amounts of strings. so you may want to consider using that instead of string concatenation.
Another way to look at this is that you want to count in base 26. The computer is very good at counting and since it always has to convert from base 2 (binary), which is the way it stores values, to base 10 (decimal--the number system you and I generally think in), converting to different number bases is also very easy.
There's a general base converter here https://stackoverflow.com/a/3265796/351385 which converts an array of bytes to an arbitrary base. Once you have a good understanding of number bases and can understand that code, it's a simple matter to create a base 26 counter that counts in binary, but converts to base 26 for display.

Categories