It was an interview question asked to me - write itoa conversion without using any builtin functions.
The following is the algorithm I am using. But ('0' + n % 10); is throwing an error:
cannot convert string to int
private static string itoa(int n)
{
string result = string.Empty;
char c;
bool sign = n > 0 ? true : false;
while (true)
{
result = result + ('0' + n % 10); //'0'
n = n / 10;
if(n <= 0)
{
break;
}
}
if(sign)
{
result = result + '-';
}
return strReverse(result);
}
I'm unclear why you'd want to do this; just call ToString on your integer. You can specify whatever formatting you need with the various overloads.
As #minitech commented, we usually just use ToString() to do that in C#. If you really want to write the algorithm on your own, the following is an implementation:
public static partial class TestClass {
public static String itoa(int n, int radix) {
if(0==n)
return "0";
var index=10;
var buffer=new char[1+index];
var xlat="0123456789abcdefghijklmnopqrstuvwxyz";
for(int r=Math.Abs(n), q; r>0; r=q) {
q=Math.DivRem(r, radix, out r);
buffer[index-=1]=xlat[r];
}
if(n<0) {
buffer[index-=1]='-';
}
return new String(buffer, index, buffer.Length-index);
}
public static void TestMethod() {
Console.WriteLine("{0}", itoa(-0x12345678, 16));
}
}
It works only for int. The range int is -2147483648 to 2147483647, the length in the string representation would be max to 11.
For the signature of itoa in C is char * itoa(int n, char * buffer, int radix);, but we don't need to pass the buffer in C#, we can allocate it locally.
The approach that add '0' to the remainder may not work when the radix is greater than 10; if I recall correctly, itoa in C supports up to 36 based numbers, as this implementation is.
('0' + n % 10) results in an int value, so you should cast it back to char. There are also several other issues with your code, like adding - sign on the wrong side, working with negative values, etc.
My version:
static string itoa(int n)
{
char[] result = new char[11]; // 11 = "-2147483648".Length
int index = result.Length;
bool sign = n < 0;
do
{
int digit = n % 10;
if(sign)
{
digit = -digit;
}
result[--index] = (char)('0' + digit);
n /= 10;
}
while(n != 0);
if(sign)
{
result[--index] = '-';
}
return new string(result, index, result.Length - index);
}
Related
I'm looking for the algorithm to convert a lotto ticket number to an integer value an back again.
Let's say the lotto number can be between 1 and 45 and a tickets contains 6 unique numbers. This means there are a maximum of 8145060 unique lotto tickets.
eg:
01-02-03-04-05-06 = 1
01-02-03-04-05-07 = 2
.
.
.
39-41-42-43-44-45 = 8145059
40-41-42-43-44-45 = 8145060
I'd like to have a function (C# preferable but any language will do) which converts between a lotto ticket and an integer and back again. At the moment I use the quick and dirty method of pre-calculating everything, which needs a lot of memory.
For enumerating integer combinations, you need to use the combinatorial number system. Here's a basic implementation in C#:
using System;
using System.Numerics;
using System.Collections.Generic;
public class CombinatorialNumberSystem
{
// Helper functions for calculating values of (n choose k).
// These are not optimally coded!
// ----------------------------------------------------------------------
protected static BigInteger factorial(int n) {
BigInteger f = 1;
while (n > 1) f *= n--;
return f;
}
protected static int binomial(int n, int k) {
if (k > n) return 0;
return (int)(factorial(n) / (factorial(k) * factorial(n-k)));
}
// In the combinatorial number system, a combination {c_1, c_2, ..., c_k}
// corresponds to the integer value obtained by adding (c_1 choose 1) +
// (c_2 choose 2) + ... + (c_k choose k)
// NOTE: combination values are assumed to start from zero, so
// a combination like {1, 2, 3, 4, 5} will give a non-zero result
// ----------------------------------------------------------------------
public static int combination_2_index(int[] combo) {
int ix = 0, i = 1;
Array.Sort(combo);
foreach (int c in combo) {
if (c > 0) ix += binomial(c, i);
i++;
}
return ix;
}
// The reverse of this process is a bit fiddly. See Wikipedia for an
// explanation: https://en.wikipedia.org/wiki/Combinatorial_number_system
// ----------------------------------------------------------------------
public static int[] index_2_combination(int ix, int k) {
List<int> combo_list = new List<int>();
while (k >= 1) {
int n = k - 1;
if (ix == 0) {
combo_list.Add(n);
k--;
continue;
}
int b = 0;
while (true) {
// (Using a linear search here, but a binary search with
// precomputed binomial values would be faster)
int b0 = b;
b = binomial(n, k);
if (b > ix || ix == 0) {
ix -= b0;
combo_list.Add(n-1);
break;
}
n++;
}
k--;
}
int[] combo = combo_list.ToArray();
Array.Sort(combo);
return combo;
}
}
The calculations are simpler if you work with combinations of integers that start from zero, so for example:
00-01-02-03-04-05 = 0
00-01-02-03-04-06 = 1
.
.
.
38-40-41-42-43-44 = 8145058
39-40-41-42-43-44 = 8145059
You can play around with this code at ideone if you like.
there seem to be actually 45^6 distinct numbers, a simple way is to treat the ticket number as a base-45 number and convert it to base 10:
static ulong toDec(string input){
ulong output = 0;
var lst = input.Split('-').ToList();
for (int ix =0; ix< lst.Count; ix++)
{
output = output + ( (ulong.Parse(lst[ix])-1) *(ulong) Math.Pow(45 , 5-ix));
}
return output;
}
examples:
01-01-01-01-01-01 => 0
01-01-01-01-01-02 => 1
01-01-01-01-02-01 => 45
45-45-45-45-45-45 => 8303765624
I am having trouble calculating Knuth's arrow notation, which is ↑ and can be found here, within a function. What I've made so far is:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = r;
b = a;
}
with power being
BigInteger Power(BigInteger Base, BigInteger Pow)
{
BigInteger x = Base;
for(int i = 0; i < (Pow-1); i++)
{
x *= Base;
}
return x;
}
but it's incorrect with it's values and I can't figure out a way to fix it. It can handle 1 arrow problems like 3↑3 (which is 3^3 = 9), but it can't handle any more arrows than that.
I need a way to figure out more arrows, such as 3↑↑3,
which should be 7625597484987 (3^27) and I get 19683 (27^3). If you could help me to figure how I could get the proper output and explain what it is I'm doing wrong, I would greatly appreciate it.
I wrote it in java, and use double for input parameter:
private static double knuthArrowMath(double a, double b, int arrowNum)
{
if( arrowNum == 1)
return Math.pow(a, b);
double result = a;
for (int i = 0; i < b - 1; i++)
{
result = knuthArrowMath(a, result, arrowNum - 1);
}
return result;
}
If you expect 7625597484987 (3^27) but get 19683 (27^3), isn't it then a simple matter of swapping the arguments when calling your power function?
Looking at your Power function your code snippet seems to call Power with temp as base and b as power:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = result;
b = a;
}
Shouldn't temp an b be swapped so you get result = Power(b, temp) to get the desired result?
So pass 1 results calls Power(3, 3) resulting in temp = 27 and pass 2 calls Power(3, 27). The reason it only works for single arrow now is because swapping arguments for the first Power(base, power) call doesn't matter.
As you point out in your answer this doesn't cover all situations. Given the examples you provided I created this little console application:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Arrow(3, 3));
Console.WriteLine(Arrow(4, 4, 1));
Console.WriteLine(Arrow(3, 4, 1));
Console.ReadKey();
}
private static BigInteger Arrow(BigInteger baseNumber, BigInteger arrows)
{
return Arrow(baseNumber, baseNumber, arrows-1);
}
private static int Arrow(BigInteger baseNumber, BigInteger currentPower, BigInteger arrows)
{
Console.WriteLine("{0}^{1}", baseNumber, currentPower);
var result = Power(baseNumber, currentPower);
if (arrows == 1)
{
return result;
}
else
{
return Arrow(baseNumber, result, arrows - 1);
}
}
private static BigInteger Power(BigInteger number, BigInteger power)
{
int x = number;
for (int i = 0; i < (power - 1); i++)
{
x *= number;
}
return x;
}
}
I came up with a way to use the BigInteger.Pow() function.
It might look a little odd, but that is because the C# BigInterger.Pow(x, y) only accepts an int for y, and teterations have HUGE exponents. I had to "flip the script" and convert x^y = y^x for this specific case.
I didn't add in any error checking, and it expects all numbers to be positive ints.
I know this works for x^^2 and x^^3. I also know it works for 2^^4 and 2^^5. I don't have the computing power/memory/math knowledge to know if it works for any other numbers. 2^^4 and 2^^5 were the only ones I could check and test. It may work for other numbers but I was not able to confirm that.
int baseNum = 4;
int exp = 3;
// this example is 4^^3
BigInteger bigAnswer = tetration(baseNum, exp);
// Here is what the method that "does the work" looks like.
// This looks a little odd but that is because I am using BigInteger.Pow(x,y)
// Unfortunately, y can only be an int. Tetrations have huge exponents, so I had to figure out a
// way to have x^y work as y^x for this specific application
// no error checking in here, and it expects positive ints only
// I *know* this works for x^^2, x^^3, but I don't know if it works for
// any other number than 2 at ^^4 or higher
public static BigInteger tetration(int baseNum, int exp)
{
if (exp > 2)
{
exp = (int)Math.Pow(baseNum, (exp - 3));
}
else
{
exp = exp - 2;
}
Func<BigInteger, int, BigInteger> bigPowHelper = (x, y) => BigInteger.Pow(x, y);
BigInteger bigAnswer = baseNum;
for (int i = 0; i < Math.Pow(baseNum, exp); i++)
{
bigAnswer = bigPowHelper(bigAnswer, baseNum);
}
return bigAnswer;
}
I am currently having issues reassigning a value to a character array. Below is my code (unfinished solution to find the next smallest palindrome):
public int nextSmallestPalindrome(int number)
{
string numberString = number.ToString();
// Case 1: Palindrome is all 9s
for (int i = 0; i < numberString.Length; i++)
{
if (numberString[i] != '9')
{
break;
}
int result = number + 2;
return result;
}
// Case 2: Is a palindrome
int high = numberString.Length - 1;
int low = 0;
bool isPalindrome = true;
for (low = 0; low <= high; low++, high--)
{
if (numberString[low] != numberString[high])
{
isPalindrome = false;
break;
}
}
char[] array = numberString.ToCharArray();
if (isPalindrome == true)
{
// While the middle character is 9
while (numberString[high] == '9' || numberString[low] == '9')
{
array[high] = '0';
array[low] = '0';
high++;
low--;
}
int replacedvalue1 = (int)Char.GetNumericValue(numberString[high]) + 1;
int replacedvalue2 = (int)Char.GetNumericValue(numberString[low]) + 1;
StringBuilder result = new StringBuilder(new string(array));
if (high == low)
{
result[high] = (char)replacedvalue1;
}
else
{
Console.WriteLine(result.ToString());
result[high] = (char)replacedvalue1;
Console.WriteLine(result.ToString());
result[low] = (char)replacedvalue2;
}
return Int32.Parse(result.ToString());
}
else return -1;
}
Main class runs:
Console.WriteLine(nextSmallestPalindrome(1001));
This returns 1001, then 101 and then gives a formatexception at the return Int32.Parse(result.ToString()); statement.
I am very confused, as I believe "result" should be 1101 after I assign result[high] = (char)replacedvalue1;. Printing replacedvalue1 gives me "1" as expected. However, debugging it line by line shows that "1001" turns into "1 1" at the end, signifying strange characters.
What could be going wrong?
Thanks
Characters and numbers aren't the same thing. I find it easiest to keep an ASCII chart open when doing this sort of thing.
If you look at one of those charts, you'll see that the character 0 actually has a decimal value of 48.
char c = (char)48; // Equals the character '0'
The reverse is also true:
char c = '0';
int i = (int)c; // Equals the number 48
You managed to keep chars and ints separate for the most part, but at the end you got them mixed up:
// Char.GetNumericValue('0') will return the number 0
// so now replacedvalue1 will equal 1
int replacedvalue1 = (int)Char.GetNumericValue(numberString[high]) + 1;
// You are casting the number 1 to a character, which according to the
// ASCII chart is the (unprintable) character SOH (start of heading)
result[high] = (char)replacedvalue1;
FYI you don't actually need to cast a char back-and-forth in order to perform operations on it. char c = 'a'; c++; is valid, and will equal the next character on the table ('b'). Similarly you can increment numeric characters:
char c = '0'; c++; // c now equals '1'
Edit: The easiest way to turn an integer 1 into the character '1' is to "add" the integer to the character '0':
result[high] = (char)('0' + replacedvalue1);
Of course there are much easier ways to accomplish what you are trying to do, but these techniques (converting and adding chars and ints) are good tools to know.
You do not have write that much code to do it.
Here is your IsPalindrome method;
private static bool IsPalindrome(int n)
{
string ns = n.ToString(CultureInfo.InvariantCulture);
var reversed = string.Join("", ns.Reverse());
return (ns == reversed);
}
private static int FindTheNextSmallestPalindrome(int x)
{
for (int i = x; i < 2147483647; i++)
{
if (IsPalindrome(i))
{
return i;
}
}
throw new Exception("Number must be less than 2147483647");
}
This is how you call it. You do not need an array to call it. You can just enter any number which is less than 2147483647(max value of int) and get the next palindrome value.
var mynumbers = new[] {10, 101, 120, 110, 1001};
foreach (var mynumber in mynumbers)
{
Console.WriteLine(FindTheNextPalindrome(mynumber));
}
I have the following method which should found the total number of 9 in an integer, the method is used to retrieve the employees' contract type based on the number of 9. i tried the below class:-
public class EmployeeCreditCards
{
public uint CardNumber(uint i)
{
byte[] toByte = BitConverter.GetBytes(i);
uint number = 0;
for (int n = 0; n < toByte.Length; n++)
{
if (toByte[i] == 9)
{
number = number + 1;
}
}
return number;
}
}
In which i am trying to find how many 9 are in the passed integer, but the above method will always return zero. Any idea what is going wrong?
You can do this simple with a little linq:
public int GetAmountOfNine(int i)
{
return i.ToString().Count(c => c.Equals('9'));
}
But do add using System.Linq; to the cs file.
Your answer isn't working because you are converting to bytes, converting the number to bytes does not generate a byte for each digit (via #Servy). Therefor if you would write every byte in your array to console/debug you wouldn't see your number back.
Example:
int number = 1337;
byte[] bytes = BitConverter.GetBytes(number);
foreach (var b in bytes)
{
Console.Write(b);
}
Console:
57500
You can however convert the int to a string and then check for every character in the string if it is a nine;
public int GetAmountOfNineWithOutLinq(int i)
{
var iStr = i.ToString();
var numberOfNines = 0;
foreach(var c in iStr)
{
if(c == '9') numberOfNines++;
}
return numberOfNines;
}
A classic solution is as follows: (Probably this is the fastest algorithm to find solution, it takes only O(log n) time.)
private int count9(int n)
{
int ret = 0;
if (n < 0)
n = -n;
while (n > 0)
{
if (n % 10 == 9) ++ret;
n /= 10; // divide the number by 10 (delete the most right digit)
}
return ret;
}
How does that work?
Consider an example, n = 9943
now ret = 0.
n % 10 = 3, which != 9
n = n / 10 = 994
n % 10 = 4 != 9
n = 99
n % 10 = 9, so ret = 1
n = 9
n % 10 = 9, so ret = 2
n = 0
Try
int numberOfNines = number.ToString().Where(c => c == '9').Count();
Since a string implements IEnumerable<char>, you can apply LINQ directly to the string without converting it to an enumeration of chars first.
UPDATE
Converting the uint to a byte array won't work the expected way, since the uint does not store the decimal digits of your number directly. The number is stored as a binary number that streches over four bytes. A unit has always four bytes, even if your number has 9 decimal digits.
You can convert the number to a string in order to get its decimal representation.
This sounds like homework, yes it is (of someone else), I asked a friend of mine who is learning C# to lend me some of his class exercises to get the hang of it.
So as the title says: How can I check if a number is a Palindrome?
I'm not asking for source code (although its very useful), but rather that someone explained how should the code should work, so that it can be applied to many different languages.
The Solution:
#statikfx searched SO for this and found the solution.
n = num;
while (num > 0)
{
dig = num % 10;
rev = rev * 10 + dig;
num = num / 10;
}
// If (n == rev) then num is a palindrome
I check for palindromes by converting the integer to a string, then reversing the string, then comparing equality. This will be the best approach for you since you're just starting out.
Since you're working in C# and this is homework, I'll use very obscure-looking Python that won't help you:
def is_palindrome(i):
s = str(i)
return s[::-1] == s
Convert that to C# and you'll have your answer.
Main idea:
Input number: 12321
Splitting the digits of the number, put them into an array
=> array [1, 2, 3, 2, 1]
Check if array[x] = array[arr_length - x] for all x = 0..arr_length / 2
If check passed => palindrome
There are many ways. Probably the simplest is to have 2 indexes, i at beginning and j at end of number. You check to see if a[i] == a[j]. If so, increment i and decrement j. You stop when i > j. When looping if you ever reach a point where a[i] != a[j], then it's not a palindrome.
Here's some working code. The first function tests if a number is palidromic by converting it to a string then an IEnumerable and testing if it is equal to its reverse. This is enough to answer your question. The main function simply iterates over the integers testing them one by one.
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static bool IsPalindromic(long l)
{
IEnumerable<char> forwards = l.ToString().ToCharArray();
return forwards.SequenceEqual(forwards.Reverse());
}
public static void Main()
{
long n = 0;
while (true)
{
if (IsPalindromic(n))
Console.WriteLine("" + n);
n++;
}
}
}
Update: Here is a more direct method of generating palindromes. It doesn't test numbers individually, it just generates palindromes directly. It's not really useful for answering your homework, but perhaps you will find this interesting anyway:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static void Main()
{
bool oddLength = true;
ulong start = 1;
while (true)
{
for (ulong i = start; i < start * 10; ++i)
{
string forwards = i.ToString();
string reverse = new string(forwards.ToCharArray()
.Reverse()
.Skip(oddLength ? 1 : 0)
.ToArray());
Console.WriteLine(forwards + reverse);
}
oddLength = !oddLength;
if (oddLength)
start *= 10;
}
}
}
My solution:
bool IsPalindrome(string str)
{
if(str.Length == 1 || str.Length == 0) return true;
return str[0] == str[str.Length-1] && IsPalindrome(str.Substring(1,str.Length-2));
}
Here's some pseudocode:
function isPalindrome(number) returns boolean
index = 0
while number != 0
array[index] = number mod 10
number = number div 10
index = index + 1
startIndex = 0;
endIndex = index - 1
while startIndex > endIndex
if array[endIndex] != array[startIndex]
return false
endIndex = endIndex - 1
startIndex = startIndex + 1
return true
Note that that's for base 10. Change the two 10s in the first while loop for other bases.
The following function will work for both numbers as well as for strings.
public bool IsPalindrome(string stringToCheck)
{
char[] rev = stringToCheck.Reverse().ToArray();
return (stringToCheck.Equals(new string(rev), StringComparison.OrdinalIgnoreCase));
}
zamirsblog.blogspot.com
in theory you want to convert the number to a string. then convet the string to an array of characters and loop the array comparing character (i) with character (array length - i) if the two characters are not equal exit the loop and return false. if it makes it all the way through the loop it is a Palindrome.
Interesting. I'd probably convert the number to a string, and then write a recursive function to decide whether any given string is a palendrome.
int n = check_textbox.Text.Length;
int check = Convert.ToInt32(check_textbox.Text);
int m = 0;
double latest=0;
for (int i = n - 1; i>-1; i--)
{
double exp = Math.Pow(10, i);
double rem = check / exp;
string rem_s = rem.ToString().Substring(0, 1);
int ret_rem = Convert.ToInt32(rem_s);
double exp2 = Math.Pow(10, m);
double new_num = ret_rem * exp2;
m=m+1;
latest = latest + new_num;
double my_value = ret_rem * exp;
int myvalue_int = Convert.ToInt32(my_value);
check = check - myvalue_int;
}
int latest_int=Convert.ToInt32(latest);
if (latest_int == Convert.ToInt32(check_textbox.Text))
{
MessageBox.Show("The number is a Palindrome number","SUCCESS",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
else
{
MessageBox.Show("The number is not a Palindrome number","FAILED",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
}
public class Main {
public static boolean Ispalindromic(String word) {
if (word.length() < 2) {
return true;
}
else if (word.charAt(0) != word.charAt(word.length() - 1)) {
return false;
} else {
Ispalindromic(word.substring(1, word.length() - 1));
}
return true;
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String word = sc.nextLine();
System.out.println(Ispalindromic(word) ? "it is palidromic" : "it is not palidromic");
}
}
This is my solution coming from a beginner:
Console.Write("Enter a number to check if palindrome: ");
bool palindrome = true;
int x = int.Parse(Console.ReadLine());
/* c is x length minus 1 because when counting the strings
length it starts from 1 when it should start from 0*/
int c = x.ToString().Length - 1;
string b = x.ToString();
for (int i = 0; i < c; i++)
if (b[i] != b[c - i])
palindrome = false;
if (palindrome == true)
Console.Write("Yes");
else Console.Write("No");
Console.ReadKey();
You need to reverse the number then compare the result to the original number.
If it matches, you have a palindrome. It should work irrespective of the number being even, odd or symmetric.
public static bool IsNumberAPalindrome(long num)
{
return long.Parse(string.Join("", num.ToString().ToCharArray().Reverse().ToArray())) == num ? true : false;
}
The implementation is bellow:
public bool IsPalindrome(int x) {
string test = string.Empty;
string res = string.Empty;
test = x.ToString();
var reverse = test.Reverse();
foreach (var c in reverse)
{
res += c.ToString();
}
return test == res;
}
You have a string, it can have integers, it can have characters, does not matter.
You convert this string to an array, depending on what types of characters the strings consist of, this may use to toCharArray method or any other related method.
You then use the reverse method that .NET provides to reverse your array, now you have two arrays, the original one and the one you reversed.
You then use the comparison operator (NOT THE ASSIGNMENT OPERATOR!) to check if the reversed one is the same as the original.
something like this
bool IsPalindrome(int num)
{
var str = num.ToString();
var length = str.Length;
for (int i = 0, j = length - 1; length/2 > i; i++, j-- ){
if (str[i] != str[j])
return false;
}
return true;
}
you could even optimise it