Encode numbers with letters with fixed lentgh? - encryption

I have two unique numbers, 100000 - 999999 (fixed 6 chars length [0-9]), second
1000000 - 9999999 (fixed 7 char length [0-9]). How can i encode/decode this numbers (they need to remain separate after decoding), using only uppercase letters [A-Z] and [0-9] digits and have a fixed length of 8 chars in total?
Example:
input -> num_1: 242404, num_2 : 1002000
encode -> AX3B O3XZ
decode -> 2424041002000
Is there any algorithm for this type of problem?

This is just a simple mapping from one set of values to another set of values. The procedure is always the same:
List all possible input and output values.
Find the index of the input.
Return the value of the output list at that index.
Note that it's often not necessary to make an actual list (i.e. loading all values into some data structure). You can typically compute the value for any index on-demand. This case is no different.
Imagine a list of all possible input pairs:
0 100'000, 1'000'000
1 100'000, 1'000'001
2 100'000, 1'000'002
...
K 100'000, 9'999'999
K+1 100'001, 1'000'000
K+2 100'001, 1'000'001
...
N-1 999'999, 9'999'998
N 999'999, 9'999'999
For any given pair (a, b), you can compute its index i in this list like so:
// Make a and b zero-based
a -= 100'000
b -= 1'000'000
i = a*1'000'000 + b
Convert i to base 36 (A-Z and 0-9 gives you 36 symbols), pad on the left with zeros as necessary1, and insert a space after the fourth digit.
encoded = addSpace(zeroPad(base36(i)))
To get back to the input pair:
Convert the 8-character base 36 string to base 10 (this is the index into the list, remember), then derive a and b from the index.
i = base10(removeSpace(encoded))
a = i/1'000'000 + 100'000 // integer divison (i.e. ignore remainder)
b = i%1'000'000 + 1'000'000
Here is an implementation in Go: https://play.golang.org/p/KQu9Hcoz5UH
1 If you don't like the idea of zero padding you can also offset i at this point. The target set of values is plenty big enough, you need only about 32% of all base 36 numbers with eight digits or less.

Related

How to express a large number as a formula of smaller numbers

I need to represent very large numbers (on the order of 8 kB or more) using a mathematical expression consisting of smaller numbers. One form of this would be factoring, as in 81 = 9 * 9. But for some numbers, factoring would not work. In that case, a more complex expression would be required.
For example, the number 78125 can be represented by two smaller numbers 78125 = 5 ^ 7. But 78121 can not be factored. So the expression would be 78121 = 5 ^ 7 - 4. For the number sizes I'm interested in, the expression might be something like n = (511 ^ 213) * (327 ^ 400)
What type of algorithm would allow me calculate these types of short-cut expressions?
(Edited to try to make it more clear)

How many unique strings is possible with set amount of characters and length?

If I have two characters (a, b) and a length of three (aaa, aab ...), how do I count how many unique strings I can make of that (and what is the math method called)?
Is this correct?
val = 1, amountCharacters = 2, length = 3;
for (i = 1; i <= length; ++i) { val = amountCharacters*val; uniqueStrings = val }
This example returns 8 which is correct. If I try with something higher, like amountCharacters = 10 it returns 1000. Is it still correct?
If you have n different characters and the length is k, there are exactlty nk possible strings you can form. Each character independently of the rest can be one of n different options and there are k total choices to make. Your code is correct.
For 2 possible characters and 10 letters, there are exactly 1024 possible strings.
Hope this helps!
The same rules than Base mathematics concept applies.
So the short answer is amountCharacters ^ length.
Longest natural answer.
The first letter will have X possible values
The second letter will have X*X possible values
and so on ..
X equals the number of possible values, i-e the amount of characters in your question
If I understand your question correctly, if you have N characters and want to construct a string of length L, the number of combinations is just N^L (e.g. N to the power of L).
There are various other results you can get if there are different limitations on what the string can contain, e.g. combinations or permutations.

Completing a list of possible binary sequences give a binary sequence with gaps

So, I am working on a program in Scilab which solves a binary puzzle. I have come across a problem however. Can anyone explain to me the logic behind solving a binary sequence with gaps (like [1 0 -1 0 -1 1 -1] where -1 means an empty cell. I want all possible solutions of a given sequence. So far I have:
function P = mogelijkeCombos(V)
for i=1:size(V,1)
if(V(i) == -1)
aantalleeg = aantalleeg +1
end
end
for i=1:2^aantalleeg
//creating combos here
end
endfunction
sorry that some words are in dutch
aantalleeg means amountempty by which I mean the amount of empty cells
I hope I gave you guys enough info. I don't need any code written, I'd just like ideas of how I can make every possible rendition as I am completely stuck atm.
BTW this is a school assignment, but the assignment is way bigger than this and it's just a tiny part I need some ideas on
ty in advance
Short answer
You could create the combos by extending your code and create all possible binary words of the length "amountempty" and replacing them bit-for-bit in the empty cells of V.
Step-by-step description
Find all the empty cell positions
Count the number of positions you've found (which equals the number of empty cells)
Create all possible binary numbers with the length of your count
For each binary number you generate, place the bits in the empty cells
print out / store the possible sequence with the filled in bits
Example
Find all the empty cell positions
You could for example check from left-to-right starting at 1 and if a cell is empty add the position to your position list.
V = [1 0 -1 0 -1 1 -1]
^ ^ ^
| | |
1 2 3 4 5 6 7
// result
positions = [3 5 7]
Count the number of positions you've found
//result
amountempty = 3;
Create all possible binary numbers with the length amountempty
You could create all possible numbers or words with the dec2bin function in SciLab. The number of possible words is easy to determine because you know how much separate values can be represented by a word of amountempty bits long.
// Create the binary word of amountEmpty bits long
binaryWord = dec2bin( i, amountEmpty );
The binaryWord generated will be a string, you will have to split it into separate bits and convert it to numbers.
For each binaryWord you generate
Now create a possible solution by starting with the original V and fill in every empty cell at the position from your position list with a bit from binaryWordPerBit
possibleSequence = V;
for j=1:amountEmpty
possibleSequence( positions(j) ) = binaryWordPerBit(j);
end
I wish you "veel succes met je opdracht"

how do I generate 2 random prime numbers that when multiplied, yield a number with X bits? (X given as argument))

I lack the math skills to make this function.
basically, i want to return 2 random prime numbers that when multiplied, yield a number of bits X given as argument.
for example:
if I say my X is 3 then a possible solution would be:
p = 2 and q = 3 becouse 2 * 3 = 6 (110 has 3 bits).
A problem with this statement is that it starts by asking for two "random" prime numbers. Without any explicit statement of the distribution of the required random primes, we are already stuck. (This is the beginning of a classic paradox, where we are asked to generate a "random" integer.)
But suppose that we change the statement to finding any two arbitrary primes, that yield the desired product with a given number of bits x. The answer is trivial.
The set of numbers that have exactly x bits in their binary representation is the half open set of integers [2^(x-1),2^x-1].
Choose an arbitrary prime number that is less than or equal to (2^x-1)/2. Call it p1.
Next, choose a second prime number that lies in the interval (2^(x-1)/p1,(2^x-1)/p1). Call it p2.
It must be true that p1*p2 will be in the desired interval.
For example, given x = 10, so the product must lie in the interval [512,1023], the set of integers with exactly 10 bits. (Note, there are apparently 147 such numbers in that interval, with exactly two prime factors.)
Step 1:
Choose p1 as any prime no larger than 1023/2 = 511.5. I'll pick p1 = 137. Then the second prime factor must be a prime that lies in the interval
[512 1023]/137
ans =
3.7372 7.4672
thus either 5 or 7.
dec2bin(137*[5 7])
ans =
1010101101
1110111111
If you know the number of bits, you can generate a number 2^(x-2) < x < 2^(x-1). Then take the square root and find the closest primes on either side of it. Multiplying them together will, in most cases, get you a number in the correct range. If it's too high, you can take the two primes directly on the lower side of it.
pseudocode:
x = bits
primelist[] = makeprimelist()
rand = randnum between 2^(x-2) and 2^(x-1)
n = findposition(primelist, rand)
do
result = primelist[n]*primelist[n+1]
n--
while result > 2^(x-1)
Note that numbers generated this way will allways have '1' as the highest significant bit, so would be possible to generate a number of x-1 bits and just tack the 1 onto the end.

Probability of 3-character string appearing in a randomly generated password

If you have a randomly generated password, consisting of only alphanumeric characters, of length 12, and the comparison is case insensitive (i.e. 'A' == 'a'), what is the probability that one specific string of length 3 (e.g. 'ABC') will appear in that password?
I know the number of total possible combinations is (26+10)^12, but beyond that, I'm a little lost. An explanation of the math would also be most helpful.
The string "abc" can appear in the first position, making the string look like this:
abcXXXXXXXXX
...where the X's can be any letter or number. There are (26 + 10)^9 such strings.
It can appear in the second position, making the string look like:
XabcXXXXXXXX
And there are (26 + 10)^9 such strings also.
Since "abc" can appear at anywhere from the first through 10th positions, there are 10*36^9 such strings.
But this overcounts, because it counts (for instance) strings like this twice:
abcXXXabcXXX
So we need to count all of the strings like this and subtract them off of our total.
Since there are 6 X's in this pattern, there are 36^6 strings that match this pattern.
I get 7+6+5+4+3+2+1 = 28 patterns like this. (If the first "abc" is at the beginning, the second can be in any of 7 places. If the first "abc" is in the second place, the second can be in any of 6 places. And so on.)
So subtract off 28*36^6.
...but that subtracts off too much, because it subtracted off strings like this three times instead of just once:
abcXabcXabcX
So we have to add back in the strings like this, twice. I get 4+3+2+1 + 3+2+1 + 2+1 + 1 = 20 of these patterns, meaning we have to add back in 2*20*(36^3).
But that math counted this string four times:
abcabcabcabc
...so we have to subtract off 3.
Final answer:
10*36^9 - 28*36^6 + 2*20*(36^3) - 3
Divide that by 36^12 to get your probability.
See also the Inclusion-Exclusion Principle. And let me know if I made an error in my counting.
If A is not equal to C, the probability P(n) of ABC occuring in a string of length n (assuming every alphanumeric symbol is equally likely) is
P(n)=P(n-1)+P(3)[1-P(n-3)]
where
P(0)=P(1)=P(2)=0 and P(3)=1/(36)^3
To expand on Paul R's answer. Probability (for equally likely outcomes) is the number of possible outcomes of your event divided by the total number of possible outcomes.
There are 10 possible places where a string of length 3 can be found in a string of length 12. And there are 9 more spots that can be filled with any other alphanumeric characters, which leads to 36^9 possibilities. So the number of possible outcomes of your event is 10 * 36^9.
Divide that by your total number of outcomes 36^12. And your answer is 10 * 36^-3 = 0.000214
EDIT: This is not completely correct. In this solution, some cases are double counted. However they only form a very small contribution to the probability so this answer is still correct up to 11 decimal places. If you want the full answer, see Nemo's answer.

Resources