I know there are similar questions so please bear with me.
I wish to generate approximately 50K codes for people to place orders - ideally no longer than 10 chars and can include letters and digits. They are not discount codes so I am not worried about people trying to guess codes. What I am worried about is somebody accidentally entering a wrong digit (ie 1 instead of l or 0 instead of O) and then the system will fail if by chance it is also a valid code.
As the codes are constantly being generated, ideally I don't want a table look-up validation, but an formula (eg if it contains an A the number element should be divisable by 13 or some such).
Select some alphabet (made of digits and letters) of size B such that there are no easy confusions. Assign every symbol a value from 0 to B-1, preferably in random order. Now you can use sequential integers, convert them to base B and assign the symbols accordingly.
For improved safety, you can append one or two checksum symbols for error detection.
With N=34 (ten digits and twenty four letters 9ABHC0FVW3YGJKL1N2456XRTS78DMPQEUZ), 50K codes require codes of length only four.
If you don't want the generated codes to be consecutive, you can scramble the bits before the change of base.
Before you start generating random combinations of characters, there are a couple of things you need to bear in mind:
1. Profanity
If your codes include every possible combination of four letters from the alphabet, they will inevitably include every four-letter word. You need to be absolutely sure that you never ask customers to enter anything foul or offensive.
2. Human error
People often make mistakes when entering codes. Confusing similar characters like O and 0 is only part of the problem. Other common mistakes include transposing adjacent characters (e.g. the → teh) and hitting the wrong key on the keyboard (e.g., and → amd)
To avoid these issues, I would recommend that you generate codes from a restricted alphabet that has no possibility of spelling out anything unfortunate, and use the Luhn algorithm or something similar to catch accidental data entry errors.
For example, here's some Python code that generates hexadecimal codes using an alphabet of 16 characters with no vowels. It uses a linear congruential generator step to avoid outputting sequential numbers, and includes a base-16 Luhn checksum to detect input errors. The code2int() function will return −1 if the checksum is incorrect. Otherwise it will return an integer. If this integer is less than your maximum input value (e.g., 50,000), then you can assume the code is correct.
def int2code(n):
# Generates a 7-character code from an integer value (n > 0)
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
mul = 0xc36572 # Randomly selected multiplier
add = 0x5d48ca # Randomly selected addend
# Convert the input number `n` into a non-sequential 6-digit
# hexadecimal code by means of a linear congruential generator
c = "%06x" % ((n * mul + add) % mod)
# Replace each hex digit with the corresponding character from alph.
# and generate a base-16 Luhn checksum at the same time
luhn_sum = 0
code = ''
for i in range(6):
d = int(c[i], 16)
code += alph[d]
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
# Append the checksum
checksum = (16 - (luhn_sum % 16)) % 16
code += alph[checksum]
return code
def code2int(code):
# Converts a 7-character code back into an integer value
# Returns -1 if the input is invalid
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
inv = 0x111548 # Modular multiplicative inverse of 0xc36572
sub = 0xa2b733 # = 0xfffffd - 0x5d48ca
if len(code) != 7:
return -1
# Treating each character as a hex digit, convert the code back into
# an integer value. Also make sure the Luhn checksum is correct
luhn_sum = 0
c = 0
for i in range(7):
if code[i] not in alph:
return -1
d = alph.index(code[i])
c = c * 16 + d
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
if luhn_sum % 16 != 0:
return -1
# Discard the last digit (corresponding to the Luhn checksum), and undo
# the LCG calculation to retrieve the original input value
c = (((c >> 4) + sub) * inv) % mod
return c
# Test
>>> print('\n'.join([int2code(i) for i in range(10)]))
HWGMTPX
DBPXFZF
XGCFRCN
PKKNDJB
JPWXNRK
DXGGCBR
ZCPNMDD
RHBXZKN
KMKGJTZ
FRWNXCH
>>> print(all([code2int(int2code(i)) == i for i in range(50000)]))
True
Related
I am doing research work. for which I need to compute and store the square root of 2 up to 10^6 places. I have googled for this but I got only a NASA page but how they computed that I don't know. I used set_precision of c++. but that is giving the result up to around 50 places only.what should I do?
NASA page link: https://apod.nasa.gov/htmltest/gifcity/sqrt2.1mil
I have tried binary search also but not fruitful.
long double ans = sqrt(n);
cout<<fixed<<setprecision(50)<<ans<<endl;
You have various options here. You can work with an arbitrary-precision floating-point library (for example MPFR with C or C++, or mpmath or the built-in decimal library in Python). Provided you know what error guarantees that library gives, you can ensure that you get the correct decimal digits. For example, both MPFR and Python's decimal guarantee correct rounding here, but MPFR has the disadvantage (for your particular use-case of getting decimal digits) that it works in binary, so you'd also need to analyse the error induced by the binary-to-decimal conversion.
You can also work with pure integer methods, using an arbitrary-precision integer library (like GMP), or a language that supports arbitrary-precision integers out of the box (for example, Java with its BigInteger class: recent versions of Java provide a BigInteger.sqrt method): scale 2 by 10**2n, where n is the number of places after the decimal point that you need, take the integer square root (i.e., the integer part of the exact mathematical square root), and then scale back by 10**n. See below for a relatively simple but efficient algorithm for computing integer square roots.
The simplest out-of-the-box option here, if you're willing to use another language, is to use Python's decimal library. Here's all the code you need, assuming Python 3 (not Python 2, where this will be horribly slow).
>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 10**6 + 1 # number of significant digits needed
>>> sqrt2_digits = str(Decimal(2).sqrt())
The str(Decimal(2).sqrt()) operation takes less than 10 seconds on my machine. Let's check the length, and the first and last hundred digits (we obviously can't reproduce the whole output here):
>>> len(sqrt2_digits)
1000002
>>> sqrt2_digits[:100]
'1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157'
>>> sqrt2_digits[-100:]
'2637136344700072631923515210207475200984587509349804012374947972946621229489938420441930169048412044'
There's a slight problem with this: the result is guaranteed to be correctly rounded, but that's rounded, not truncated. So that means that that final "4" digit could be the result of a final round up - that is, the actual digit in that position could be a "3", with an "8" or "9" (for example) following it.
We can get around this by computing a couple of extra digits, and then truncating them (after double checking that rounding of those extra digits doesn't affect the truncation).
>>> getcontext().prec = 10**6 + 3
>>> sqrt2_digits = str(Decimal(2).sqrt())
>>> sqrt2_digits[-102:]
'263713634470007263192351521020747520098458750934980401237494797294662122948993842044193016904841204391'
So indeed the millionth digit after the decimal point is a 3, not a 4. Note that if the last 3 digits computed above had been "400", we still wouldn't have known whether the millionth digit was a "3" or a "4", since that "400" could again be the result of a round up. In that case, you could compute another two digits and try again, and so on, stopping when you have an unambiguous output. (For further reading, search for "The table maker's dilemma".)
(Note that setting the decimal module's rounding mode to ROUND_DOWN does not work here, since the Decimal.sqrt method ignores the rounding mode.)
If you want to do this using pure integer arithmetic, Python 3.8 offers a math.isqrt function for computing exact integer square roots. In this case, we'd use it as follows:
>>> from math import isqrt
>>> sqrt2_digits = str(isqrt(2*10**(2*10**6)))
This takes a little longer: around 20 seconds on my laptop. Half of that time is for the binary-to-decimal conversion implicit in the str call. But this time, we got the truncated result directly, and didn't have to worry about the possibility of rounding giving us the wrong final digit(s).
Examining the results again:
>>> len(sqrt2_digits)
1000001
>>> sqrt2_digits[:100]
'1414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572'
>>> sqrt2_digits[-100:]
'2637136344700072631923515210207475200984587509349804012374947972946621229489938420441930169048412043'
This is a bit of a cheat, because (at the time of writing) Python 3.8 hasn't been released yet, although beta versions are available. But there's a pure Python version of the isqrt algorithm in the CPython source, that you can copy and paste and use directly. Here it is in full:
import operator
def isqrt(n):
"""
Return the integer part of the square root of the input.
"""
n = operator.index(n)
if n < 0:
raise ValueError("isqrt() argument must be nonnegative")
if n == 0:
return 0
c = (n.bit_length() - 1) // 2
a = 1
d = 0
for s in reversed(range(c.bit_length())):
# Loop invariant: (a-1)**2 < (n >> 2*(c - d)) < (a+1)**2
e = d
d = c >> s
a = (a << d - e - 1) + (n >> 2*c - e - d + 1) // a
return a - (a*a > n)
The source also contains an explanation of the above algorithm and an informal proof of its correctness.
You can check that the results by the two methods above agree (modulo the extra decimal point in the first result). They're computed by completely different methods, so that acts as a sanity check on both methods.
You could use big integers, e.g. BigInteger in Java. Then you calculate the square root of 2e12 or 2e14. Note that sqrt(2) = 1.4142... and sqrt(200) = 14.142... Then you can use the Babylonian method to get all the digits: E.g. S = 10^14. x(n+1) = (x(n) + S / x(n)) / 2. Repeat until x(n) doesn't change. Maybe there are more efficient algorithms that converge faster.
// Input: a positive integer, the number of precise digits after the decimal point
// Output: a string representing the long float square root
function findSquareRoot(number, numDigits) {
function get_power(x, y) {
let result = 1n;
for (let i = 0; i < y; i ++) {
result = result * BigInt(x);
}
return result;
}
let a = 5n * BigInt(number);
let b = 5n;
const precision_digits = get_power(10, numDigits + 1);
while (b < precision_digits) {
if (a >= b) {
a = a - b;
b = b + 10n;
} else {
a = a * 100n;
b = (b / 10n) * 100n + 5n;
}
}
let decimal_pos = Math.floor(Math.log10(number))
if (decimal_pos == 0) decimal_pos = 1
let result = (b / 100n).toString()
result = result.slice(0, decimal_pos) + '.' + result.slice(decimal_pos)
return result
}
I am looking for a way to generate a de Bruijn sequence iteratively instead of with recursion. My goal is to generate it character by character.
I found some example code in Python for generating de Bruijn sequences and translated it into Rust. I am not yet able to comprehend this technique well enough to create my own method.
Translated into Rust:
fn gen(sequence: &mut Vec<usize>, a: &mut [usize], t: usize, p: usize, k: usize, n: usize) {
if t > n {
if n % p == 0 {
for x in 1..(p + 1) {
sequence.push(a[x])
}
}
} else {
a[t] = a[t - p];
gen(sequence, a, t + 1, p, k, n);
for x in (a[t - p] + 1)..k {
a[t] = x;
gen(sequence, a, t + 1, t, k, n);
}
}
}
fn de_bruijn<T: Clone>(alphabet: &[T], n: usize) -> Vec<T> {
let k = alphabet.len();
let mut a = vec![0; n + 1];
let vecsize = k.checked_pow(n as u32).unwrap();
let mut sequence = Vec::with_capacity(vecsize);
gen(&mut sequence, &mut a, 1, 1, k, n);
sequence.into_iter().map(|x| alphabet[x].clone()).collect()
}
However this is not able to generate iteratively - it goes through a whole mess of recursion and iteration which is impossible to untangle into a single state.
Consider this approach:
Choose the first (lexicographically) representative from every necklace class
Here is Python code for generation of representatives for (binary) necklaces containing d ones (it is possible to repeat for all d values). Sawada article link
Sort representatives in lexicographic order
Make periodic reduction for every representative (if possible): if string is periodic s = p^m like 010101, choose 01
To find the period, it is possible to use string doubling or z-algorithm (I expect it's faster for compiled languages)
Concatenate reductions
Example for n=3,k=2:
Sorted representatives: 000, 001, 011, 111
Reductions: 0, 001, 011, 1
Result: 00010111
The same essential method (with C code) is described in Jörg Arndt's book "Matters Computational", chapter 18
A similar way is mentioned in the wiki
An alternative construction involves concatenating together, in
lexicographic order, all the Lyndon words whose length divides n
You might look for effective way to generate appropriate Lyndon words
I am not familiar with Rust, so I programmed and tested it in Python. Since the poster translated the version in the question from a Python program, I hope it will not be a big issue.
# the following function treats list a as
# k-adic number with n digtis
# and increments this number returning
# the index of the leftmost digit changed
def increment_a7(a, k, n):
digit= n-1
a[digit]+= 1
while a[digit] >= k and digit> 0:
#a[digit]= 0
a[digit]= a[0]+1
a[digit-1]+= 1
digit-= 1
return digit
# the following function adds a to the sequence
# and takes into account, that the beginning of a
# could overlap with the end of sequence
# in that case, it just removes the overlapping digits
# from a before adding the remaining digits to sequence
def append_to_sequence(sequence, a, n):
# here we can assume safely, that a
# does not overlap completely with sequence[-n:]
i= -1
for i in range(n-1, -1, -1):
found= True
# check if the last i digits in sequence
# overlap with the first i digits in a
for j in range(i):
if a[j] != sequence[-i+j]:
# no, they don't overlap
found= False
break
if found:
# yes they overlap, so no need to
# continue the check with a smaller i
break
# now we can just append everything from
# digit i (digit 0 - i-1 are swallowed)
sequence.extend(a[i:])
return n-i
# during the operation we have to keep track of
# the k-adic numbers a, that already occured in
# the sequence. We store them in a set called used
# everytime we add something to the sequence
# we have to update it and add one entry for each
# digit inserted
def update_used(sequence, used, n, num_inserted):
l= len(sequence)
for i in range(num_inserted):
used.add(tuple(sequence[-n-i:l-i]))
# the main work is done in the following function
# it creates and returns the generated sequence
def gen4(k, n):
a= [0]*n
sequence= a[:]
used= set()
# create a fake sequence to add the segments obtained by the cyclic nature
fake= ([k-1] * (n-1))
for i in range(n-1):
fake.append(0)
update_used(fake, used, n, 1)
update_used(sequence, used, n, 1)
valid= True
while valid:
# a is still a valid k-adic number
# this means the generation process
# has not ended
# so construct a new number from the n-1
# last digits of sequence
# followed by a zero
a= sequence[-n+1:]
a.append(0)
while valid and tuple(a) in used:
# the constructed k-adict number a
# was already used, so increment it
# and try again
increment_a(a, k, n)
valid= a[0]<k
if valid:
# great, the number is still valid
# and is not jet part of the sequence
# so add it after removing the overlapping
# digits and update the set with the segments
# we already used
num_inserted= append_to_sequence(sequence, a, n)
update_used(sequence, used, n, num_inserted)
return sequence
I tested the code above by generating some sequences with the original version of gen and this one using the same parameters. For all sets of parameters I tested, the result was the same in both versions.
Please note that this code is less efficient than the original version, especially if the sequence gets long. I guess the costs of the set operations has a non-linear influence on the runtime.
If you like, you can improve it further such as by using a more efficient way to store the used segments. Instead of operating on the k-adic representation (the a-list), you could use a multidimensional array instead.
consider this number:785462454105,I need an algorithm that first separates the number into groups with maximum length of three(starting from the right side) ,it would look something like:
a = 105
b = 454
c = 462
d = 785
Of course I know I can convert the number to string but I want to do this without any conversion. Also I'm not allowed to use any arrays and any special methods or class which exist in the programming language use(I'm using java but as I said I'm not allowed to use the functions).The only tools I have are loops,conditional clauses and mathematical,arithmetic and logical operators.
Also it is possible to get 454000 or 462000000 out using loops but how can I get rid of the zeros?
Note that something like 1234 should turn to:
a = 234
b = 1
It's easy to get a group of last 3 digits if you take a remainder while dividing by 1000.
785462454105 % 1000 == 105
Then you could get rid of last 3 digits dividing by 1000:
785462454105 / 1000 == 785462454
Repeat this in a loop until the number becomes zero and you're done.
The only issue left is to print leading zeros:
123045 % 1000 = 45 but we want to print 045.
Usually you'll need a separate inner loop, for example, to count decimal digits (dividing by 10 until it becomes zero) and then print number of missing zeros (it's equal to number of digits you want minus number of digits in your number).
But here it's a simple case, you could just sole it via couple of ifs:
long a = 785462454105;
while (a > 0) {
long x = a % 1000;
a /= 1000;
if (x < 10) {
System.out.print("00");
} else if (x < 100) {
System.out.print("0");
}
System.out.println(x);
}
This is a homework assignment that I've been working on to compute if a credit card number is valid. It has many steps and uses 2 other helper functions.
The first helper function makes a list consisting of each digit in n:
def intToList(n):
strr = [num for num in str(n)]
theList = list(map(int, strr))
return theList
The second helper function adds the sum of digits in a number. For example:
def addDigits(n):
sums = 0
while n:
if n > 0:
sums += n % 10
n //= 10
else:
return
return sums
>>>(332) #(3+3+2) = 7
>>> 7
So the function I am working on is suppose to validate a 16 digit credit card number. It has specific orders to follow in the order given.
Verifies that it contains only digits. #Done.
Verifies that it is 16 digits long. #Done.
if n is a string, it converts it to an integer.
creates a list using the function intToList(n).
Multiplies the odd indices of the list made by intToList(n) by 2 and any products that produce two-digit numbers are replaced by the sum of the digits using the function addDigits(n).
Computes the sum of all the single digits in the list made my intToList(n). If the sum is equal to 0 modulo 10, the original value, n, is a valid credit card number.
As of right now I have this:
def checkCreditCard(n):
#Suppose to convert n to int.
n = int(n)
#Helper function 1 to make a list.
myList = intToList(n)
#For loop to apply the math to each odd indices.*
for ele in myList:
if ele % 2 == 1:
ele *= 2
if ele >= 10:
single = addDigits(?) #not sure what to put I've tried everything
if sum(myList) % 10 == 0:
return True
return False
Here is my issue, I am unsure where to go from here. I am pretty sure the code above is correct so far, but I don't know how to make the products that produce two-digit numbers compute to single digit ones using my function and computes the sum of all the single digits in the list.
Any help would be greatly appreciated. Let me know if I can clear anything up.
added what I've worked on.
Simple trick: The sum of the digits of all numbers from 10 to 18 (the possible two digit values for doubling or adding single digit values) can be computed simply by subtracting 9. So if you have a possible single, possibly double digit value, you can use it as a single digit with:
singledigit = maybetwodigit - 9 * (maybetwodigit >= 10)
For the record, your code as written is not correct:
def checkCreditCard(n):
#My checks for length and digits.
if len(str(n)) == 16 and str(n).isdigit():
return True
else:
return False
# nothing at this line or below will ever execute, because both your if
# and else conditions return
Also, your (currently unused) loop will never work, because you don't assign what you've calculated. You probably want something like this:
for i, ele in enumerate(myList):
if i % 2 == 1:
ele *= 2
myList[i] = ele - 9 * (ele >= 10) # Seamlessly sum digits of two digit nums
I have a rather unorthodox homework assignment where I am to write a simple function where a double value is rounded to an integer with using only a while loop.
The main goal is to write something similar to the round function.
I made some progress where I should add or subtract a very small double value and I would eventually hit a number that will become an integer:
while(~isinteger(inumberup))
inumberup=inumberup+realmin('double');
end
However, this results in a never-ending loop. Is there a way to accomplish this task?
I'm not allowed to use round, ceil, floor, for, rem or mod for this question.
Assumption: if statements and the abs function are allowed as the list of forbidden functions does not include this.
Here's one solution. What you can do is keep subtracting the input value by 1 until you get to a point where it becomes less than 1. The number produced after this point is the fractional component of the number (i.e. if our number was 3.4, the fractional component is 0.4). You would then check to see if the fractional component, which we will call f, is less than 0.5. If it is, that means you need to round down and so you would subtract the input number with f. If the number is larger than 0.5 or equal to 0.5, you would add the input number by (1 - f) in order to go up to the next highest number. However, this only handles the case for positive values. For negative values, round in MATLAB rounds towards negative infinity, so what we ought to do is take the absolute value of the input number and do this subtraction to find the fractional part.
Once we do this, we then check to see what the fractional part is equal to, and then depending on the sign of the number, we either add or subtract accordingly. If the fractional part is less than 0.5 and if the number is positive, we need to subtract by f else we need to add by f. If the fractional part is greater than or equal to 0.5, if the number is positive we need to add by (1 - f), else we subtract by (1 - f)
Therefore, assuming that num is the input number of interest, you would do:
function out = round_hack(num)
%// Repeatedly subtract until we get a value that less than 1
%// i.e. the fractional part
%// Also make sure to take the absolute value
f = abs(num);
while f > 1
f = f - 1;
end
%// Case where we need to round down
if f < 0.5
if num > 0
out = num - f;
else
out = num + f;
end
%// Case where we need to round up
else
if num > 0
out = num + (1 - f);
else
out = num - (1 - f);
end
end
Be advised that this will be slow for larger values of num. I've also wrapped this into a function for ease of debugging. Here are a few example runs:
>> round_hack(29.1)
ans =
29
>> round_hack(29.6)
ans =
30
>> round_hack(3.4)
ans =
3
>> round_hack(3.5)
ans =
4
>> round_hack(-0.4)
ans =
0
>> round_hack(-0.6)
ans =
-1
>> round_hack(-29.7)
ans =
-30
You can check that this agrees with MATLAB's round function for the above test cases.
You can do it without loop: you can use num2str to convert the number into a string, then find the position of the . in the string and extract the string fron its beginning up to the position of the .; then you convert it back to a numebr with str2num
To round it you have to check the value of the first char (converted into a number) after the ..
r=rand*100
s=num2str(r)
idx=strfind(num2str(r),'.')
v=str2num(s(idx+1))
if(v <= 5)
rounded_val=str2num(s(1:idx-1))
else
rounded_val=str2num(s(1:idx-1))+1
end
Hope this helps.
Qapla'