Convert Biginteger to Base95 value vice versa - c#

I want to convert a BigInteger to a text string in the optimal way. There are 95 printable ASCII characters, numbered 32 to 126. I want to use these characters to convert BigInteger to text. Same as this code, but is for Uint:
static string ConvertToBase64Arithmetic(uint i)
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
StringBuilder sb = new StringBuilder();
do
{
sb.Insert(0, alphabet[(int)(i % 64)]);
i = i / 64;
} while (i != 0);
return sb.ToString();
}
My goal is to make a smaller text. It is clear that if it is done as byte storage( BigInteger.ToByteArray()), it is the most optimal mode. But I'm just looking for a shorter text string lenght and Base95 is just a suggestion. my code:
static string ConvertToBase95Arithmetic(BigInteger i)
{
const string alphabet = "mcW=2`R\\.5+46L\" !#$%&'()*,-/013789:;<=?#ABCDEFGHIJKMNOPQSTUVXYZ[]^_abdefghijklnopqrstuvwxyz{|}~";
StringBuilder sb = new StringBuilder();
do
{
sb.Insert(0, alphabet[(BigInteger)(i % 95)]);
i = i / 64;
} while (i != 0);
return sb.ToString();
}
It is natural that this text string can be converted back to the original number and the data will not be lost.

Related

repeating the Encrypt function along the length of the bina function

I want to repeat the Encrypt function along the entire length of the bina / how to do it?
private void carbonFiberButton11_Click_1(object sender, EventArgs e)
{
textBox1.Text = PairConcat(Encrypt(), bina());
}
public static string PairConcat(string Encrypt, string bina)
{
StringBuilder result = new StringBuilder();
int i = 0;
for(; i<Encrypt.Length & i < bina.Length; i++)
{
result.Append(Encrypt[i].ToString());
result.Append(bina[i].ToString());
}
result.Append(Encrypt.Substring(i));
result.Append(bina.Substring(i));
return result.ToString();
}
For example:
string bina = "1234567";
string Encrypt = "abcdefg";
textbox1.text = 1a2b3c4d.. ;but it is doesn't works if I have different length:
string bina = "12345"
string Encrypt = "abc"
textbox1.text = 1a2b3c45 , but I need - 1a2b3c4a5b.
Encrypt function:
string Encrypt() //random to binary
{
var encrypt = textBox4.Text;
StringBuilder binary = new StringBuilder();
for (int i = 0; i < encrypt.Length; i++)
{
binary.Append(Convert.ToString(encrypt[i], 2).PadLeft(8, '0'));
}
return binary.ToString();
}
I can't understand what to do/ Help me, please
Just make the Encrypt string in minimum as long as the bina string.
// Calculate smallest multiple of Encrypt.Length at least as long as bina.Length
int lb = bina.Length;
int le = Encrypt.Length;
int bufferLength = (lb + le - 1) / le * le;
var sb = new StringBuilder(Encrypt, bufferLength);
while (sb.Length < lb) {
sb.Append(Encrypt);
}
Encrypt = sb.ToString();
string result = String.Join("", bina.Zip(Encrypt, (a, b) => a.ToString() + b));
The LINQ Zip method combines 2 sequences by providing pairs of items from the two sequences until one sequence ends. Here the sequences consist of chars.
The StringBuilder works most efficiently if does not have to resize its internal buffer. I calculate it by using integer arithmetic.

How to get ASCII value of characters in C#

Below is my string in C# which I am converting it to Character array & in need to get the ASCII value of each character in the string.
static void Main(string[] args)
{
string s = "Test";
var arr = s.ToCharArray();
foreach(var a in arr)
{
var n = Encoding.ASCII.GetByteCount(a.ToString());
Console.WriteLine(a);
Console.WriteLine(n);
}
}
This outputs as
T
1
e
1
s
1
t
1
On googling I got number of links but none of them suffice my need.
How to get ASCII value of string in C#
https://www.codeproject.com/Questions/516802/ConvertingpluscharsplustoplusASCIIplusinplusC
I am in need to get the ASCII value of each character in string.???
Any help/suggestion highly appreciated.
A string can be directly enumerated to a IEnumerable<char>. And each char can be casted to a integer to see its UNICODE "value" (code point). UTF-16 maps the 128 characters of ASCII (0-127) to the UNICODE code points 0-127 (see for example https://en.wikipedia.org/wiki/Code_point), so you can directly print this number.
string s = "Test";
foreach (char a in s)
{
if (a > 127)
{
throw new Exception(string.Format(#"{0} (code \u{1:X04}) is not ASCII!", a, (int)a));
}
Console.WriteLine("{0}: {1}", a, (int)a);
}
GetByteCount will return the count of bytes used, so for each character it will be 1 byte.
Try GetBytes
static void Main(string[] args)
{
string s = "Test";
var n = ASCIIEncoding.ASCII.GetBytes(s);
for (int i = 0; i < s.Length; i++)
{
Console.WriteLine($"Char {s[i]} - byte {n[i]}");
}
}
Every character is represented in the ASCII table with a value between 0 and 127. Converting the chars to an Integer you will be able to get the ASCII value.
static void Main(string[] args)
{
string s = "Test";
for (int i = 0; i < s.Length; i++)
{
//Convert one by one every leter from the string in ASCII value.
int value = s[i];
Console.WriteLine(value);
}
}
You're asking for the byte count when you should be asking for the bytes themselves. Use Encoding.ASCII.GetBytes instead of Encoding.ASCII.GetByteCount. Like in this answer: https://stackoverflow.com/a/400777/3129333
Console.WriteLine(a);
Console.WriteLine(((int)a).ToString("X"));
You need to convert in int and then in hex.
GetByteCount will return the count of bytes used, so for each character it will be 1.
You can read also: Need to convert string/char to ascii values

How could I encode a long number using uppercase letters and numbers to make it shorter to type?

Is there a way I could encode a long number (e.g. 12349874529768521) as lower-case letters AND numbers for the purposes of reducing its length? The idea is that a user might have a long number on a piece of paper.
It seems to me that if there are more symbols available, that the resulting number could be made shorter. So I'm looking for something like hexadecimal but using the larger symbol space of A-Z instead of just A-F.
This would be in C# (if it matters)
Base32 encoding is designed to produce an unambiguous, compact, human-readable (and non-obscene!) representation. From Wikipedia:
Base32 has a number of advantages over Base64:
The resulting character set is all one case, which can often be beneficial when using a case-insensitive filesystem, spoken language, or human memory.
The
result can be used as a file name because it can not possibly contain the '/' symbol, which is the Unix path separator.
The alphabet can be selected to avoid similar-looking pairs of different symbols, so the strings can be accurately transcribed by hand. (For example, the RFC 4648 symbol set omits the digits for one, eight and zero, since they could be confused with the letters 'I', 'B', and 'O'.)
A result excluding padding can be included in a URL without encoding any characters.
Base32 also has advantages over hexadecimal/Base16: Base32
representation takes roughly 20% less space. (1000 bits takes 200
characters, compared to 250 for Base16)
Douglas Crockford's original article on Base32 encoding is also well worth a read.
EDIT: here's a bit of C# that'll do base-N encoding of integers:
class Program {
private const string BINARY = "01";
private const string DECIMAL = "0123456789";
private const string HEX = "0123456789abcdef";
private const string BASE32 = "0123456789abcdefghjkmnpqrstvwxyz";
static string EncodeInt32(string alphabet, int value) {
var sb = new StringBuilder();
while (value > 0) {
sb.Insert(0, alphabet[value % alphabet.Length]);
value = value / alphabet.Length;
}
return sb.ToString();
}
static int DecodeInt32(string alphabet, string value) {
int result = 0;
int b = alphabet.Length;
int pow = 0;
for (var i = value.Length-1; i >= 0; i--) {
result += (int)(Math.Pow(b, pow++)) * alphabet.IndexOf(value[i]);
}
return (result);
}
static void Main(string[] args) {
for (var i = 0; i < 1234567890; i += 1234567) {
Console.WriteLine("{0} {1} {2}", i, EncodeInt32(BASE32, i), DecodeInt32(BASE32, EncodeInt32(BASE32, i)));
}
Console.ReadKey(false);
}
}
Example output showing typical reduction in string length:
1227159598 14j9y1e 1227159598
1228394165 14kfknn 1228394165
1229628732 14mn99w 1229628732
1230863299 14ntyy3 1230863299
1232097866 14q0mja 1232097866
1233332433 14r6a6h 1233332433
1234567000 14sbztr 1234567000
How about a BaseN Method to encode/decode your long into a string with characters you defined on your own
public static class BaseN
{
private const string CharList = "0123456789abcdefghijklmnopqrstuvwxyz";
public static String Encode(long input)
{
if (input < 0) throw new ArgumentOutOfRangeException("input", input, "input cannot be negative");
var result = new System.Collections.Generic.Stack<char>();
while (input != 0)
{
result.Push(CharList[(int)(input % CharList.Length)]);
input /= CharList.Length;
}
return new string(result.ToArray());
}
public static long Decode(string input)
{
long result = 0, pos = 0;
foreach (char c in input.Reverse())
{
result += CharList.IndexOf(c) * (long)Math.Pow(CharList.Length, pos);
pos++;
}
return result;
}
}
Usage:
long number = 12349874529768521;
string result = BaseN.Encode(number);
Sample:
https://dotnetfiddle.net/odwFlk
Here's a similar approach to the others, using a Base-N conversion:
using System;
using System.Text;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
long n = 12349874529768521;
string baseChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz##";
var encoded = AsBaseN(n, baseChars.ToCharArray());
Console.WriteLine(encoded); // Prints "9HXNyK2uh"
long decoded = AsLong(encoded, baseChars.ToCharArray());
Console.WriteLine(decoded); // Prints "12349874529768521"
}
public static string AsBaseN(long value, char[] baseChars)
{
var result = new StringBuilder();
int targetBase = baseChars.Length;
do
{
result.Append(baseChars[value % targetBase]);
value /= targetBase;
}
while (value > 0);
return result.ToString();
}
public static long AsLong(string number, char[] baseChars)
{
long result = 0;
int numberBase = baseChars.Length;
long multiplier = 1;
foreach (char c in number)
{
result += multiplier * Array.IndexOf(baseChars, c);
multiplier *= numberBase;
}
return result;
}
}
}
If you want a different set of allowable characters, just change baseChars as appropriate. For example, if you just want 0-9 and A-Z:
string baseChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
This gives a result of T3OPA1YNLD3 (base 36) instead of 9HXNyK2uh (base 64).
I presume you mean you want to represent the number with fewer characters.
Base 36 will do this (0-9, a-z).
You can use a base 36 encoder.
Base36 is a binary-to-text encoding scheme that represents binary data in an ASCII string format by translating it into a radix-36 representation. The choice of 36 is convenient in that the digits can be represented using the Arabic numerals 0–9 and the Latin letters A–Z1 (the ISO basic Latin alphabet).
Here's an example of one, but any should work: https://github.com/thewindev/csharpbase36
Example Usage
// Encoding
Base36.Encode(10); // returns "A"
Base36.Encode(10000); // returns "7PS"
// Decoding
Base36.Decode("Z"); // returns 35L
Base36.Decode("10"); // returns 36L
Base36.Decode("7PS"); // returns 10000L
By default uppercase letters are used. If you really wanted to lowercase then a simple string.ToLowerInvarient() can change that.
However, uppercase is usually easier to read, which is why it's used by default, so you might want to consider using uppercase rather than lowercase.
You could look to Base64 encoding. It uses 0-9, A-Z, a-z, + and / characters. Or Base36, if you're interested only in 0-9 and A-Z.

Reverse a foreach loop action

I want to convert/find each of my string characters to (int) and reverse this operation.
I manage to do the first part,but the seconds one is giving me some problems.
string input;
string encrypt = ""; string decrypt = "";
input = textBox.Text;
foreach (char c in input)
{
int x = (int)c;
string s = x.ToString();
encrypt += s;
}
MessageBox.Show(encrypt);
foreach (int i in encrypt)
{
char c = (char)i;
string s = c.ToString();
decrypt += c;
}
MessageBox.Show(decrypt);
Thanks!
Here is a fixed program according to my advise above
string encrypt = ""; string decrypt = "";
string input = Console.ReadLine();
var length = input.Length;
int[] converted = new int[length];
for (int index = 0; index < length; index++)
{
int x = input[index];
string s = x.ToString();
encrypt += s;
converted[index] = x;
}
Console.WriteLine(encrypt);
for (int index = 0; index < converted.Length; index++)
{
char c = (char)converted[index];
string s = c.ToString();
decrypt += s;
}
Console.WriteLine(decrypt);
This will not work as is, because you're adding numbers to a string with no padding.
Let's assume the first three letter's values are '1','2','3', you'll have a string with "123".
Now, if you know each letter is 1 int length, you're good, but what happens if 12 is valid? and 23?
This might not be a "real" issues in your case because the values will probably be all 2 ints long, but it's very lacking (unless it's homework, in which case, oh well ...)
The ascii values for the alphabet will go from 65 for A to 122 z.
You can either pad them (say 3 chars per number, so 065 for A, and so on), delimit them (have ".", and split the string on that), use an array (like shahar's suggestion), lists, etc etc ...
In Your scenario, encryption may give output as you expected but its hard to decrypt the encrypted text using such mechanism. so I just do some customization on your code and make it workable here.
i suggest a similar one here:
string input;
string encrypt = ""; string decrypt = "";
int charCount = 0;
input = "textBox.Text";
foreach (char c in input)
{
int x = (int)c;
string s = x.ToString("000");
encrypt += s;
charCount++;
}
// MessageBox.Show(encrypt);
while (encrypt.Length > 0)
{
int item = Int32.Parse(encrypt.Substring(0, 3));
encrypt = encrypt.Substring(3);
char c = (char)item;
string s = c.ToString();
decrypt += c;
}
Reason for your code is not working:
You have declared encrypt as string and iterate through each integer in that string value, it is quiet not possible.
if you make that loop to iterate through each characters in that string value again it gives confusion. as :
lets take S as your input. its equivalent int value is 114 so if you make a looping means it will give 1,1,4, you will not get s back from it.

code translation: repeating a string until some maximum

I was wondering if you could tell me what the most efficient way to repeat a string would be. I need to create a string 33554432 bytes long, repeating the string "hello, world" until it fills that buffer. What is the best way to do it, C is easy in this case:
for (i = 0; i < BIGSTRINGLEN - step; i += step)
memcpy(bigstring+i, *s, step);
Thanks.
An efficient way would be to use a StringBuilder:
string text = "hello, world";
StringBuilder builder = new StringBuilder(BIGSTRINGLEN);
while (builder.Length + text.Length <= BIGSTRINGLEN) {
builder.Append(text);
}
string result = builder.ToString();
First, do you want the string to be 33554432 bytes long, or characters long? .NET and C# use 16-bit characters, so they are not equivalent.
If you want 33554432 characters, naive solution would be string concatenation. See Frédéric Hamidi's answer.
If you want bytes, you will need to do something a bit more interesting:
int targetLength = 33554432;
string filler = "hello, world";
byte[] target = new byte[targetLength];
// Convert filler to bytes. Can use other encodings here.
// I am using ASCII to match C++ output.
byte[] fillerBytes = Encoding.ASCII.GetBytes(filler);
//byte[] fillerBytes = Encoding.Unicode.GetBytes(filler);
//byte[] fillerBytes = Encoding.UTF8.GetBytes(filler);
int position = 0;
while((position + fillerBytes.Length) < target.Length)
{
fillerBytes.CopyTo(target, position);
position += fillerBytes.Length;
}
// At this point, need to possibly do a partial copy.
if (position < target.Length)
{
int bytesNecessary = target.Length - position;
Array.Copy(fillerBytes, 0, target, position, bytesNecessary);
}
I don't know if it's the most efficient way, but if you're using .NET 3.5 or later, this could work:
String.Join("", System.Linq.Enumerable.Repeat("hello, world", 2796203).ToArray()).Substring(0, 33554432);
If the length you want is dynamic, then you can replace some of the hard-coded numbers with simple math.
What about this? Set the StringBuilder to the max expected size and then add the desired string as long as adding another one will not exceed the desired max size.
StringBuilder sb = new StringBuilder(33554432);
int max = sb.MaxCapacity;
String hello = "hello, world";
while (sb.Length + hello.Length <= max)
{
sb.Append(hello);
}
string longString = sb.ToString();
This avoids a loop that repeatedly adds the string. Instead, I "double" the string until it gets close to the right length and then I put the "doubled" pieces together appropriately.
static string Repeat(string s, int length) {
if (length < s.Length) {
return s.Substring(0, length);
}
var list = new List<string>();
StringBuilder t = new StringBuilder(s);
do {
string temp = t.ToString();
list.Add(temp);
t.Append(temp);
} while(t.Length < length);
int index = list.Count - 1;
StringBuilder sb = new StringBuilder(length);
while (sb.Length < length) {
while (list[index].Length > length) {
index--;
}
if (list[index].Length <= length - sb.Length) {
sb.Append(list[index]);
}
else {
sb.Append(list[index].Substring(0, length - sb.Length));
}
}
return sb.ToString();
}
So, for example, on input ("Hello, world!", 64) we build the strings
13: Hello, World!
26: Hello, World!Hello, World!
52: Hello, World!Hello, World!Hello, World!Hello, World!
Then we would build the result by concatenating the string of length 52 to the substring of length 12 of the string of length 13.
I am, of course, assuming that by bytes you meant length. Otherwise, you can easily modify the above using encodings to get what you want in terms of bytes.

Categories

Resources