I have here a C# Console application, in which when I allow the user to input a certain number of records, the program will generate a quote number. This is for me to test the algorithm I formulated before I implement this in my program.
Example, when I input 23 (assuming this is the current record count in the database), the program will output "CQ-13-04-0023". But I got an output of "CQ-13-04-0051". My objective is when the series number in the given quote number reaches 9999, it will reset to 0001 when the number of records in the database reaches 10000 and above.
Here's my code:
class Program
{
static void Main(string[] args)
{
string QuoteRefNum = "";
string seriesCount = "";
DateTime year = DateTime.Now;
string strYear = year.ToString("yy");
string strMonth = year.ToString("MM");
Console.Write("Input the number of records: ");
int numberOfRecords = Convert.ToInt32(Console.Read());
numberOfRecords++;
if (numberOfRecords == 0)
{
seriesCount = "000" + numberOfRecords++;
}
else if (numberOfRecords >= 1 && numberOfRecords <= 9)
{
seriesCount = "000" + numberOfRecords;
}
else if (numberOfRecords >= 10 && numberOfRecords <= 99)
{
seriesCount = "00" + numberOfRecords;
}
else if (numberOfRecords >= 100 && numberOfRecords <= 999)
{
seriesCount = "0" + numberOfRecords;
}
else if (numberOfRecords >= 1000 && numberOfRecords <= 9999)
{
seriesCount = numberOfRecords.ToString();
}
else if (numberOfRecords >= 10000 && numberOfRecords <= 99999)
{
string newSetOfRecords = numberOfRecords.ToString();
int tempNumber = 0;
newSetOfRecords.Remove(0, 1);
tempNumber = Convert.ToInt32(newSetOfRecords);
if (tempNumber == 0)
{
seriesCount = "000" + tempNumber++;
}
else if (tempNumber >= 1 && tempNumber <= 9)
{
seriesCount = "000" + tempNumber;
}
else if (tempNumber >= 10 && tempNumber <= 99)
{
seriesCount = "00" + tempNumber;
}
else if (tempNumber >= 100 && tempNumber <= 999)
{
seriesCount = "0" + tempNumber;
}
else if (tempNumber >= 1000 && tempNumber <= 9999)
{
seriesCount = tempNumber.ToString();
}
}
QuoteRefNum = "CQ" + strYear + "-" + strMonth + "-" + seriesCount;
Console.WriteLine("The quote reference number is: " + QuoteRefNum);
}
}
This line is the problem:
int numberOfRecords = Convert.ToInt32(Console.Read());
It is returning the ASCII value.
Change it to:
int numberOfRecords;
Int32.TryParse(Console.ReadLine(), out numberOfRecords);
And remove numberOfRecords++
Explanation of what's going on:
The reason why you are getting 51 is because when you enter 23 number of records is set to 50 and then you increment the variable to 51 via numberOfRecords++
Problem is Console.Read(); when you type 23 end enter key Read() will return key value of first input character that is 2. ASCII Character value of 2 is 50
So you will get 51 after numberOfRecords++ as result
change Console.Read(); to Console.ReadLine(); and remove numberOfRecords++
Related
I have an application where I need the ones, tens and hundreds values from numbers between 10 and 120. I tested my theories out in a small program but I cant get tens to work without using conditional statements. This program generates numbers and tells you the ones, tens and hundreds values of the number with if statements. (I only want even numbers)
Is there any way to achieve these results without using an If or a Switch statement? (I couldn't figure out how to use the latter with 2 conditions)
using System;
namespace Digit_tests
{
class Program
{
static int digit; static int tens; static int ones; static int hundrds;
public static void Main()
{
hundrds = 0;
Random rnd = new Random();
digit = rnd.Next(10,121);
if (digit % 2 != 0)
{
random();
}
else {}
if (digit >= 10 && digit < 20)
{
tens = 1;
}
else if (digit >= 20 && digit < 30)
{
tens = 2;
}
else if (digit >= 30 && digit < 40)
{
tens = 3;
}
else if (digit >= 40 && digit < 50)
{
tens = 4;
}
else if (digit >= 50 && digit < 60)
{
tens = 5;
}
else if (digit >= 60 && digit < 70)
{
tens = 6;
}
else if (digit >= 70 && digit < 80)
{
tens = 7;
}
else if (digit >= 80 && digit < 90)
{
tens = 8;
}
else if (digit >= 90 && digit < 100)
{
tens = 9;
}
else if (digit >= 100 && digit < 110)
{
tens = 0;
hundrds = 1;
}
else if (digit >= 110 && digit < 120)
{
tens = 1;
hundrds = 1;
}
else if (digit >= 120)
{
tens = 2;
hundrds = 1;
}
ones = digit - tens * 10;
if (hundrds == 1)
{
ones = ones - 100;
}
Console.WriteLine(digit + "\n" + hundrds + "-" + tens + "-" + ones);
Console.ReadKey();
Main();
}
public static void random()
{
Random rnd = new Random();
digit = rnd.Next(10,121);
Main();
}
}
}
You can use the remainder operator:
int number = 345;
int tens = (number / 10) % 10;
So 345 / 10 == 34, and 34 % 10 = 4.
Try it online
int number = 12345;
int ones = number % 10; // 5
number /= 10; // 1234
int tens = number % 10; // 4
number /= 10; // 123
int hundreds = number % 10; // 3
You could use the remainder operator (as per the other answer, which is probably better!), but honestly, for your use case I think a simple conversion to string is easier!
int number = 421; //The random number
string numStr = number.ToString(); //Convert to string
//Now we need to pad with zeros at the beginning if the number is < 100
//A StringBuilder would be more efficient.
int padd = 3 - numStr.Length;
for(int i=0; i < padd; i++)
numStr = "0" + numStr;
//And output
Console.WriteLine($"Hundreds {numStr[0]} : Tens {numStr[1]} : Ones {numStr[2]}");
This will only work for numbers up to 999, but you could expand it if you wanted to.
I can't figure out why I keep getting the "Index was outside the
bounds of the array" error. I am trying to tally up the salaries to
display.
Is there are any someone who could explain to me how the error message works.
namespace sales_commission {
class Program {
static void Main (string[] args) {
const int ARRAY_LENGTH = 8;
int[] salaries = { 210, 400, 450, 950, 800, 330, 430, 233, 223, 590, 679, 1000 };
var salary = new int[ARRAY_LENGTH];
foreach(int number in salaries) {
try {
if (number >= 200 && number <= 299) {
salary[0]++;
} else if (number >= 300 && number <= 399) {
salary[1]++;
} else if (number >= 400 && number <= 499) {
salary[2]++;
} else if (number >= 500 && number <= 599) {
salary[3]++;
} else if (number >= 600 && number <= 699) {
salary[4]++;
} else if (number >= 700 && number <= 799) {
salary[5]++;
} else if (number >= 800 && number <= 899) {
salary[6]++;
} else if (number >= 900 && number <= 999) {
salary[7]++;
} else if (number >= 1000) {
salary[8]++;
}
} catch (IndexOutOfRangeException ex) {
Console.WriteLine (ex.Message);
Console.WriteLine ($"salaries[{number}] = {salary[number]}");
}
}
for (var result = 0; result <= salary.Length; ++result) {
Console.WriteLine ($"{result* 100 + 200} - {result * 100 + 200 + 99} {salary[result],15}");
}
}
}
}
You have 9 salary brackets. 200-299, 300-399, 400-499, 500-599, 600-699, 700-799, 800-899, 900-999 and >= 1000. That means you need 9 storage spaces for the counts. Array indexes start at 0, so your array length needs to be 9, this gives you [0 to 8] indexes.
const int ARRAY_LENGTH = 8; // This needs to be 9.
You get an array out of bounds because:
} else if (number >= 1000) {
salary[8]++; // Index 8 doesn't exist, only [0 to 7] for an ARRAY_LENGTH of 8.
Your loop also accesses data outside of the array bounds. This is because the condition of your loop runs until it reaches and includes the index of the length itself. So if your array has 8 spaces [0 to 7], your loop runs from [0 to 8] and the moment it access index 8, you're out of bounds. This can easily be fixed as below:-
for (var result = 0; result <= salary.Length; ++result) { // Change this to result < salary.Length
Console.WriteLine ($"{result* 100 + 200} - {result * 100 + 200 + 99 {salary[result],15}");
}
I'm making an idle/click game in unity, and have a custom format that I'd like all the numbers in the game to display as. K for thousands, M for millions, B for billions, etc. See below example from a game called Tower of Heroes.
example
The displaying of these numbers and units works great. However, where I am running into an issue is with my decision to have arbitrarily large numbers in the game. I did not want to be limited by the constraints of double, and wanted the challenge of coming up with my own solution. I was able to do so, and even get most math operations to work with my solution. Addition, subtraction, multiplication, and exponents all work well enough. But I cannot figure out the logic/math for division...
So, I am using a list of doubles for each of my game variables.
Example: List<double> money = new List<double>(); would be a list containing the money the player currently has. Every position is limited to 0-999. Position 0 represents the "1's", position 1 the thousands, position 2 the millions, etc, with the list growing as large as it needs to. So if we had:
List<double> money = new List<double>()
{
10, //1's
50, //thousands (K)
200 //millions (M)
//etc.
};
that would be $200,050,010, or in my game's notation: 200M050K. (I only display the largest unit, or sometimes the largest two units)
For example, here is the addition method I have working:
//SuperAdd
public List<double> SuperAdd(List<double> baseValue, List<double> valueBeingAdded)
{
//declairing a new list to house the result
List<double> resultValue = new List<double>();
//making copies to not affect originals
List<double> baseValueCopy = baseValue;
List<double> valueBeingAddedCopy = valueBeingAdded;
//increase the # of tiers in our result list until it matches the largest of the two being added
while (resultValue.Count < Mathf.Max(valueBeingAddedCopy.Count, baseValueCopy.Count))
{
resultValue.Add(0);
//if needed adjust the size of the two lists being added together so they match
if (valueBeingAddedCopy.Count < baseValueCopy.Count) valueBeingAddedCopy.Add(0);
if (valueBeingAddedCopy.Count > baseValueCopy.Count) baseValueCopy.Add(0);
}
//add all the respective tiers together
for (int i = 0; i < resultValue.Count; i++)
{
//add all the tiers together
resultValue[i] = baseValueCopy[i] + valueBeingAddedCopy[i];
}
//check for any carry overs needed (>=1000)
for (int i = 0; i < resultValue.Count; i++)
{
//where this is true we need to carry over to next tier
if(resultValue[i] >= 1000)
{
//check if we are on the last existing tier
if(i + 1 == resultValue.Count)
{
//add an empty tier
resultValue.Add(0);
}
//calculate how many thousands need to be carried over, and what the remainder is
double nextTierAdder = Math.Floor(resultValue[i] / 1000);
double currentTierRemainder = resultValue[i] % 1000;
//apply both
resultValue[i] = currentTierRemainder;
resultValue[i + 1] += nextTierAdder;
}
}
//remove any empty blanks from the ends of the resultValue list
for (int i = resultValue.Count - 1; i > 0; i--)
{
if (resultValue[i] == 0) resultValue.RemoveAt(i);
else break;
}
//return resultValue
return resultValue;
}
So, what I'm looking to achieve is a similar method for division, pseudo code:
public List<double> SuperDivide(List<double> baseValue1, List<double> baseValue2)
{
//code goes here
return result;
}
What I have so far is some junk code as a placeholder until I figure out a correct solution that will return a List.
//SuperDivide result = bv1 / bv2
//this is currently only useful when the values are near one another in size
public double SuperDivide(List<double> baseValue1, List<double> baseValue2)
{
double result;
//check if one input list is way bigger than the other, and return a simplified result
//the 100 is because double has a max of 1.7x10^308, each position in our lists holds 1x10^3
if(baseValue1.Count - 100 > baseValue2.Count)
{
result = Math.Pow(10, 300);
return result;
}
if(baseValue2.Count - 10 > baseValue1.Count)
{
result = 0.00000000001; //arbitrary small # that isn't quite 0
return result;
}
//get the stopping position for the for loops (clamped at 5 due to double having a precision of 15 digits)
int stopPos1 = baseValue1.Count - Mathf.Clamp(baseValue1.Count, 1, 5);
int stopPos2 = baseValue2.Count - Mathf.Clamp(baseValue2.Count, 1, 5);
//empty strings to hold the #'s
string bv1String = "";
string bv2String = "";
//create a string of the largest digits in bv1
if (stopPos1 > 1)
{
//create a string of the largest digits in bv1
for (int i = baseValue1.Count - 1; i >= stopPos1; i--)
{
if (i == baseValue1.Count - 1)
{
bv1String = baseValue1[i].ToString();
}
else
{
if (baseValue1[i] < 10) bv1String = bv1String + "00" + baseValue1[i].ToString();
else if (baseValue1[i] < 100) bv1String = bv1String + "0" + baseValue1[i].ToString();
else bv1String = bv1String + baseValue1[i].ToString();
}
}
}
else
{
//create a string of the largest digits in bv1
for (int i = baseValue1.Count - 1; i >= 0; i--)
{
if (i == baseValue1.Count - 1)
{
bv1String = baseValue1[i].ToString();
}
else
{
if (baseValue1[i] < 10) bv1String = bv1String + "00" + baseValue1[i].ToString();
else if (baseValue1[i] < 100) bv1String = bv1String + "0" + baseValue1[i].ToString();
else bv1String = bv1String + baseValue1[i].ToString();
}
}
}
//create a string of the largest digits in bv1
if (stopPos2 > 1)
{
//create a string of the largest digits in bv2
for (int i = baseValue2.Count - 1; i >= stopPos2; i--)
{
if (i == baseValue2.Count - 1)
{
bv2String = baseValue2[i].ToString();
}
else
{
if (baseValue2[i] < 10) bv2String = bv2String + "00" + baseValue2[i].ToString();
else if (baseValue2[i] < 100) bv2String = bv2String + "0" + baseValue2[i].ToString();
else bv2String = bv2String + baseValue2[i].ToString();
}
}
}
else
{
//create a string of the largest digits in bv2
for (int i = baseValue2.Count - 1; i >= 0; i--)
{
if (i == baseValue2.Count - 1)
{
bv2String = baseValue2[i].ToString();
}
else
{
if (baseValue2[i] < 10) bv2String = bv2String + "00" + baseValue2[i].ToString();
else if (baseValue2[i] < 100) bv2String = bv2String + "0" + baseValue2[i].ToString();
else bv2String = bv2String + baseValue2[i].ToString();
}
}
}
//create numbers for the input lists
double bv1Double = double.Parse(bv1String);
double bv2Double = double.Parse(bv2String);
//adjust for one being bigger than the other, only by relative amount though
//only needed when one of them has 6+ tiers
if (baseValue1.Count > 5 && baseValue2.Count > 5)
{
if (baseValue1.Count > baseValue2.Count)
{
bv1Double *= Math.Pow(1000, baseValue1.Count - baseValue2.Count);
}
else if (baseValue1.Count < baseValue2.Count)
{
bv1Double *= Math.Pow(1000, baseValue2.Count - baseValue1.Count);
}
}
//calculate result
result = bv1Double / bv2Double;
return result;
}
Questions:
(1) If anyone can point me in the right direction for the math/logic of the special division, I can probably handle the coding.
(2) Would it be appropriate to make another post / add to this one my other math methods, looking for code suggestions? (I'm a self-taught novice and know there are a lot of improvements I could make to these methods)
If you want to keep your custom formatting and not switch to BigInteger, there might be a viable way to divide by using your existing addition and subtraction operators.
Since your values are stored in a list of integers, you should run through that list for each number and perform long divison.
I'm on my phone so I can't provide a code example, but the logic is somewhat straightforward.
https://en.wikipedia.org/wiki/Long_division
Let's say the calculation is 300/20
First step is to find the first subset of 300 that is equal to or larger than the 20.
That will be 30.
Then you find the qoutient and calculate the remainder, which is 1 and 10 respectively.
You then append the next number from the 300 (which is a 0) to the remainder (10). This will give you 100.
Then you do the same thing resulting in a qoutient of 5 and remainder of 0.
The remainder being zero means that the calculation is complete.
Then you append all the qoutients you've calculated and you have the result ("1" + "5" = "15")
For finding the qoutient and remainder you can use Euclidean Division that also only uses your existing addition and subtraction operators.
https://en.wikipedia.org/wiki/Division_algorithm
N / D = (Quotient, Remainder)
Algorithm:
R = N, Q = 0
while(N > D)
{
R= R - D
Q ++
}
Wikipedia has some nice visualisations and probably explains it clearer.
The main takeaway is that you should be able to implement this algorithm using your existing operators while only using addition and subtraction.
With the suggestion from Nicklas, I was able to put together the following chunk of code. I did a fair bit of testing and am fairly confident it is mostly / all correct. The follow-up question was going to be that during testing I found that operations resulting in a very large answer (ex: 10 trillion / 5) would take a long time. After thinking for a few minutes I came up with a decent solution for massive time savings. Now it will spit out stupidly big results instantly.
//assumes both inputs are positive and > 0
public List<double> SuperDivide(List<double> numerator, List<double> denominator)
{
//here we are going to adopt the notation used on the wiki page for long division
//inputs are numerator/denominator
//outputs are (Q,R) quotient and remainder
//create and set the Q to 0
List<double> quotient = new List<double>
{
0
};
//create a list of value 1
List<double> one = new List<double>
{
1
};
//declairing a new list to house the result
List<double> resultValue = new List<double>();
//empty strings to hold the #'s
string denomString = "";
string remainderString = "";
//create and set the R = N
List<double> remainder = new List<double>();
for (int i = 0; i < numerator.Count; i++)
{
remainder.Add(numerator[i]);
}
//getting a starting value
string compareResult = WhichIsBigger(remainder, denominator);
//calculate Q and R: while R >= D
while(compareResult =="A" || compareResult == "Equal")
{
//get the multiplier we can use to save calcs on big # results (xxxxxxxxxxxxxxxxxxx / yyyy)
List<double> testResult = DivTester(remainder, denominator);
//create a var for D * X, where X is the testResult
List<double> denomMult = SuperMultiply(denominator, testResult);
//Q = Q + X
quotient = SuperAdd(quotient, testResult);
//R = R - DX
remainder = SuperSubtract(remainder, denomMult);
compareResult = WhichIsBigger(remainder, denominator);
}
//if R = 0, return Q
if(remainder.Count == 1 && remainder[0] == 0)
{
return quotient;
}
//else return Q + (R/D)
else
{
//get the stopping position for the for loops (clamped at 5 due to double having a precision of 15 digits)
int stopPosR = remainder.Count - Mathf.Clamp(remainder.Count, 1, 5);
int stopPosD = denominator.Count - Mathf.Clamp(denominator.Count, 1, 5);
//create a string of the largest digits in R
if (stopPosR > 1)
{
for (int i = remainder.Count - 1; i >= stopPosR; i--)
{
//starting tier (largest #)
if (i == remainder.Count - 1)
{
remainderString = remainder[i].ToString();
}
else
{
if (remainder[i] < 10) remainderString = remainderString + "00" + remainder[i].ToString();
else if (remainder[i] < 100) remainderString = remainderString + "0" + remainder[i].ToString();
else remainderString = remainderString + remainder[i].ToString();
}
}
}
else
{
for (int i = remainder.Count - 1; i >= 0; i--)
{
//starting tier (largest #)
if (i == remainder.Count - 1)
{
remainderString = remainder[i].ToString();
}
else
{
if (remainder[i] < 10) remainderString = remainderString + "00" + remainder[i].ToString();
else if (remainder[i] < 100) remainderString = remainderString + "0" + remainder[i].ToString();
else remainderString = remainderString + remainder[i].ToString();
}
}
}
//create a string of the largest digits in D
if (stopPosD > 1)
{
for (int i = denominator.Count - 1; i >= stopPosD; i--)
{
if (i == denominator.Count - 1)
{
denomString = denominator[i].ToString();
}
else
{
if (denominator[i] < 10) denomString = denomString + "00" + denominator[i].ToString();
else if (denominator[i] < 100) denomString = denomString + "0" + denominator[i].ToString();
else denomString = denomString + denominator[i].ToString();
}
}
}
else
{
for (int i = denominator.Count - 1; i >= 0; i--)
{
if (i == denominator.Count - 1)
{
denomString = denominator[i].ToString();
}
else
{
if (denominator[i] < 10) denomString = denomString + "00" + denominator[i].ToString();
else if (denominator[i] < 100) denomString = denomString + "0" + denominator[i].ToString();
else denomString = denomString + denominator[i].ToString();
}
}
}
//create numbers for divsion of R/D
double remainderDoub = double.Parse(remainderString);
double denomDoub = double.Parse(denomString);
//adjust for one being bigger than the other, only by relative amount though
//only needed when one of them has 6+ tiers
if (remainder.Count > 5 && denominator.Count > 5)
{
if (remainder.Count > denominator.Count)
{
remainderDoub *= Math.Pow(1000, remainder.Count - denominator.Count);
}
else if (remainder.Count < denominator.Count)
{
denomDoub *= Math.Pow(1000, denominator.Count - remainder.Count);
}
}
resultValue.Add(remainderDoub / denomDoub);
resultValue = SuperAdd(resultValue, quotient);
return resultValue;
}
}
And the DivTester method:
//I'm sure there are much more effecient ways to determine this multiplier...
private List<double> DivTester(List<double> rem, List<double> denom)
{
//declairing a new list for testing, starting value of 1
List<double> ten = new List<double>()
{
10
};
//create and set the dCopy = denom
List<double> dCopy = new List<double>();
for (int i = 0; i < denom.Count; i++)
{
dCopy.Add(denom[i]);
}
//create and set the testerPass = 1
List<double> testerPass = new List<double>()
{
1
};
//getting a starting value
string compareResult = WhichIsBigger(rem, dCopy);
while(compareResult == "A")
{
dCopy = SuperMultiply(dCopy, ten);
//check and see if it is still successfull
compareResult = WhichIsBigger(rem, dCopy);
//if it passes, multiple testerPass by ten
if (compareResult == "A")
{
testerPass = SuperMultiply(testerPass, ten);
}
}
//return the largest multipler (10^X) that can be safely used
return testerPass;
}
I'm working on Visual Studio about binary search in c#. My project about the computer find the user's guess number. So, I use tihs code in the main;
int min = 0; // minimum number in the array
int max = 100; // maximum number in the array
int middle = 50; // middle number in the array
int counter = 1;
string name, input;
int guess_number;
Console.WriteLine("Hello, this is a game that finding the number of in your mind. If you want to play so let me know you! ");
name = Console.ReadLine();
Console.WriteLine("Awesome welcome to the game " + name + " guess a number between " + min + " and " + max + " Please! ");
Console.WriteLine("Is your guess " + middle + " ?\nIf it's your guess then write (0) please!\nIf it's too high then write (1) please!\nIf it's too low then write (2) please!");
input = Console.ReadLine();
guess_number = Convert.ToInt32(input);
Console.WriteLine(" You select " + guess_number + " so, ");
do
{
counter += 1;
if (guess_number == 2)
{
min = middle + 1;
}
else if (guess_number == 1)
{
max = middle - 1;
}
else if (guess_number != 1 || guess_number != 2 || guess_number != 0)
{
Console.WriteLine(" Please write 0, 1 or 2 " + name);
}
middle = (min + max) / 2;
Console.WriteLine("Is your guess " + middle + " ?\nIf it's your guess then write (0) please!\nIf it's too high then write (1) please!\nIf it's too low then write (2) please!");
Console.WriteLine(counter + " times I tried for finding your number ");
} while (guess_number != 0);
Console.ReadKey();
However, output always repeat after the user write anything, why the reason about that, is there anyway to get the number?
from your description, I think you need to let user input new value to guess_number variable in the loop end otherwise the loop will not end from the condition guess_number != 0.
do
{
counter += 1;
if (guess_number == 2)
{
min = middle + 1;
}
else if (guess_number == 1)
{
max = middle - 1;
}
else if (guess_number != 1 || guess_number != 2 || guess_number != 0)
{
Console.WriteLine(" Please write 0, 1 or 2 " + name);
}
middle = (min + max) / 2;
Console.WriteLine("Is your guess " + middle + " ?\nIf it's your guess then write (0) please!\nIf it's too high then write (1) please!\nIf it's too low then write (2) please!");
Console.WriteLine(counter + " times I tried for finding your number ");
input = Console.ReadLine(); // let user key in new value.
guess_number = Convert.ToInt32(input);
} while (guess_number != 0);
the last readKey should be inside the while.
do
{
counter += 1;
if (guess_number == 2)
{
min = middle + 1;
}
else if (guess_number == 1)
{
max = middle - 1;
}
else if (guess_number != 1 || guess_number != 2 || guess_number != 0)
{
Console.WriteLine(" Please write 0, 1 or 2 " + name);
}
middle = (min + max) / 2;
Console.WriteLine("Is your guess " + middle + " ?\nIf it's your guess then write (0) please!\nIf it's too high then write (1) please!\nIf it's too low then write (2) please!");
input = Console.ReadLine();
guess_number = Convert.ToInt32(input);
Console.WriteLine(counter + " times I tried for finding your number ");
} while (guess_number != 0);
I'm personally tired of reimplementing "a ticket" mechanism for my web projects for some one-time operations like account activation or password reset. I know it's simple but it requires me to keep (and persist!) two pieces of data: a ticket itself and an expiration date.
So I have this idea, to generate a unique string with embedded datetime (expiration date) in it, which we can check upon receiving as a part of url-request.
I've started with this:
var clearTicket = Convert.ToInt64(expiration.ToString("yyyyMMddhhmm")).ToString("x12") + key.ToString("N");
But I want it to be more compact. Something BaseXX-ish I suppose.
Any ideas how to implement this encoding/decoding efficiently (considering url-safe charset)?
It took me some time, so I hope it helps:
First of all, you should substract 200000000000 from "yyyyMMddhhmm", because you actually don't need the first two digits for the next 88 years.
Here is the implementation for encoding and decoding Base64, using only URL-safe characters.
If you have any questions, feel free to ask.
public string Base64Encode (Int64 Number)
{
string HelpString = "";
if (Number >= 64)
{
HelpString = Base64Encode(Number / 64);
}
return (HelpString += Base64EncodeHelper(Number % 64));
}
public string Base64EncodeHelper(Int64 Number)
{
string HelpString = "";
Number += 65;
if ((Number >= 65 && Number <= 90) || (Number >= 97 && Number <= 122)) // 0 - 25 and 32 - 57
{
HelpString = Convert.ToString((char)Number);
}
else if (Number >= 91 && Number <= 96) // 26 - 31
{
HelpString = Convert.ToString((char)(Number - 43));
}
else if (Number >= 123 && Number <= 126) // 58 - 61
{
HelpString = Convert.ToString((char)(Number - 69));
}
else if (Number == 127) // 62
{
HelpString = "-";
}
else // 63
{
HelpString = "_";
}
return (HelpString);
}
public Int64 Base64Decode(string Encoded)
{
Int64 Result = 0, HelpInt = 0;
int i = Encoded.Length - 1;
foreach (char Character in Encoded)
{
int CharInInt = (int)Character;
if (Character == '_')
{
HelpInt = 63;
}
else if (Character == '-')
{
HelpInt = 62;
}
else if (((CharInInt + 69) >= 123) && ((CharInInt + 69) <= 126))
{
HelpInt = CharInInt + 4;
}
else if (((CharInInt + 43) >= 91) && ((CharInInt + 43) <= 96))
{
HelpInt = CharInInt - 22;
}
else
{
HelpInt = CharInInt - 65;
}
Result += Convert.ToInt64((Math.Pow(64, Convert.ToDouble(i))) * HelpInt);
i--;
}
return Result;
}
You can extend string like this:
public static string ToURLParameter(this string text)
{
if (String.IsNullOrEmpty(text)) return "";
// to lowercase, trim extra spaces
text = text.Trim();
var len = text.Length;
var sb = new StringBuilder(len);
bool prevdash = false;
char c;
//
text = text.Replace('Å', 'A');
text = text.Replace('å', 'a');
text = text.Replace('Ä', 'A');
text = text.Replace('ä', 'a');
text = text.Replace('Ö', 'O');
text = text.Replace('ö', 'o');
for (int i = 0; i < text.Length; i++)
{
c = text[i];
if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-')
{
if (!prevdash)
{
sb.Append('-');
prevdash = true;
}
}
else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'))
{
sb.Append(c);
prevdash = false;
}
if (i == 80) break;
}
text = sb.ToString();
// remove trailing dash, if there is one
if (text.EndsWith("-"))
text = text.Substring(0, text.Length - 1);
return text;
}
and then you can use it on any variable that is string like:
string something = "asdfljasdklf";
<%= something.ToUrlParameter() %>
I've finally created a solution using techniques described in these answers:
Compressing big number (or string) to small value
How do you convert Byte Array to Hexadecimal String, and vice versa?
Works great!
Thanks you all for your help!