I'd like to generate a random number with each digit being in range from 0-9 and not repeating itself. Assume finite length of 4.
1234 qualifies, each composite digit is unique.
1123 does not, 1 is repeated
How can this be done please?
To generate the digits:
std::vector<int> vec = {0,1,2,3,4,5,6,7,8,9}; // or initialize from array if not c++11
std::random_shuffle(vec.begin(), vec.end());
vec.resize(4);
And to join the digits into a single number:
int number = 0;
for (auto i = vec.begin(); i != vec.end(); ++i) {
number = 10 * number + (*i);
}
I believe you are talking about generating permutations.
Try something like this:
int used[10] = {0};
int n = 0;
int number = 0;
while( n < 10 ) {
int d = rand() % 10;
if( used[d] ) continue;
used[d] = 1;
number = number * 10 + d;
n++;
}
Not the most efficient... It simply tracks what digits have been used, and rerolls any time a used digit is encountered.
The above does have the side-effect that zero is technically not used if it's the first number chosen. You could explicitly prevent this, or simply accept that some numbers will be 9 digits long.
If you'd rather avoid needless use of std::vector and the memory allocations it brings, excessive randomisation calls presumably used within random_shuffle, there's a simpler approach if you play with some math.
If you can count how many valid (i.e. acceptable) sequences exist, C, and you can devise a bijective function that maps from this counter to each valid sequence instance then things become trivial. Generate a random integer in the range [0,C), plug that into your function which returns the valid output.
If I understand your example correctly, you want to generate a random 4 digit sequence ABCD (representing an integer in the range [0,9999]) where digits A, B, C and D are different from one another.
There are 5040 such valid sequences: 10 * 9 * 8 * 7.
Given any integer in the range [0, 5039], the following function will return a valid sequence (i.e. one in which each digit is unique), represented as an integer:
int counter2sequence(int u) {
int m = u/504;
u %= 504;
int h = u/56;
u %= 56;
int t = u/7;
u %= 7;
const int ih = h;
const int it = t;
if (ih >= m) ++h;
if (it >= ih) ++t;
if (t >= m) ++t;
if (u >= it) ++u;
if (u >= ih) ++u;
if (u >= m) ++u;
return ((m*10 + h)*10 + t)*10 + u;
}
E.g.
counter2sequence(0) => 0123
counter2sequence(5039) => 9876
Related
I am new to competitive programming. I recently gave the Div 3 contest codeforces. Eventhough I solved the problem C, I really found this code from one of the top programmers really interesting. I have been trying to really understand his code, but it seems like I am too much of a beginner to understand it without someone else explaining it to me.
Here is the code.
void main(){
int S;
cin >> S;
int ans = 1e9;
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
if (sum != S)
continue;
ans = min(ans, stoi(num));
}
cout << ans << '\n';
}
The problem is to find the minimum number whose sum of digits is equal to given number S, such that every digit in the result is unique.
Eq. S = 20,
Ans = 389 (3+8+9 = 20)
Mask is 9-bits long, each bit represents a digit from 1-9. Thus it counts from 0 and stops at 512. Each value in that number corresponds to possible solution. Find every solution that sums to the proper value, and remember the smallest one of them.
For example, if mask is 235, in binary it is
011101011 // bit representation of 235
987654321 // corresponding digit
==> 124678 // number for this example: "digits" with a 1-bit above
// and with lowest digits to the left
There are a few observations:
you want the smallest digits in the most significant places in the result, so a 1 will always come before any larger digit.
there is no need for a zero in the answer; it doesn't affect the sum and only makes the result larger
This loop converts the bits into the corresponding digit, and applies that digit to the sum and to the "num" which is what it'll print for output.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) { // check bit i in the mask
sum += i + 1; // numeric sum
num += char('0' + (i + 1)); // output as a string
}
(mask >> i) ensures the ith bit is now shifted to the first place, and then & 1 removes every bit except the first one. The result is either 0 or 1, and it's the value of the ith bit.
The num could have been accumulated in an int instead of a string (initialized to 0, then for each digit: multiply by 10, then add the digit), which is more efficient, but they didn't.
The way to understand what a snippet of code is doing is to A) understand what it does at a macro-level, which you have done and B) go through each line and understand what it does, then C) work your way backward and forward from what you know, gaining progress a bit at a time. Let me show you what I mean using your example.
Let's start by seeing, broadly (top-down) what the code is doing:
void main(){
// Set up some initial state
int S;
cin >> S;
int ans = 1e9;
// Create a mask, that's neat, we'll look at this later.
for (int mask = 0; mask < 1 << 9; mask++) {
// Loop state
int sum = 0;
string num;
// This loop seems to come up with candidate sums, somehow.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// Stop if the sum we've found isn't the target
if (sum != S)
continue;
// Keep track of the smallest value we've seen so far
ans = min(ans, stoi(num));
}
// Print out the smallest value
cout << ans << '\n';
}
So, going from what we knew about the function at a macro level, we've found that there are really only two spots that are obscure, the two loops. (If anything outside of those are confusing to you, please clarify.)
So now let's try going bottom-up, line-by-line those loops.
// The number 9 appears often, it's probably meant to represent the digits 1-9
// The syntax 1 << 9 means 1 bitshifted 9 times.
// Each bitshift is a multiplication by 2.
// So this is equal to 1 * (2^9) or 512.
// Mask will be 9 bits long, and each combination of bits will be covered.
for (int mask = 0; mask < 1 << 9; mask++) {
// Here's that number 9 again.
// This time, we're looping from 0 to 8.
for (int i = 0; i < 9; i++) {
// The syntax mask >> i shifts mask down by i bits.
// This is like dividing mask by 2^i.
// The syntax & 1 means get just the lowest bit.
// Together, this returns true if mask's ith bit is 1, false if it's 0.
if (mask >> i & 1) {
// sum is the value of summing the digits together
// So the mask seems to be telling us which digits to use.
sum += i + 1;
// num is the string representation of the number whose sum we're finding.
// '0'+(i+1) is a way to convert numbers 1-9 into characters '1'-'9'.
num += char('0' + (i + 1));
}
}
}
Now we know what the code is doing, but it's hard to figure out. Now we have to meet in the middle - combine our overall understanding of what the code does with the low-level understanding of the specific lines of code.
We know that this code gives up after 9 digits. Why? Because there are only 9 unique non-zero values (1,2,3,4,5,6,7,8,9). The problem said they have to be unique.
Where's zero? Zero doesn't contribute. A number like 209 will always be smaller than its counterpart without the zero, 92 or 29. So we just don't even look at zero.
We also know that this code doesn't care about order. If digit 2 is in the number, it's always before digit 5. In other words, the code doesn't ever look at the number 52, only 25. Why? Because the smallest anagram number (numbers with the same digits in a different order) will always start with the smallest digit, then the second smallest, etc.
So, putting this all together:
void main(){
// Read in the target sum S
int S;
cin >> S;
// Set ans to be a value that's higher than anything possible
// Because the largest number with unique digits is 987654321.
int ans = 1e9;
// Go through each combination of digits, from 1 to 9.
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
// If this combination includes the digit i+1,
// Then add it to the sum, and append to the string representation.
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// If this combination does not yield the right sum, try the next combination.
if (sum != S)
continue;
// If this combination does yield the right sum,
// see if it's smaller than our previous smallest.
ans = min(ans, stoi(num));
}
// Print the smallest combination we found.
cout << ans << '\n';
}
I hope this helps!
The for loop is iterating over all 9-digit binary numbers and turning those binary numbers into a string of decimal digits such that if nth binary digit is on then a n+1 digit is appended to the decimal number.
Generating the numbers this way ensures that the digits are unique and that zero never appears.
But as #Welbog mentions in comments this solution to the problem is way more complicated than it needs to be. The following will be an order of magnitude faster, and I think is clearer:
int smallest_number_with_unique_digits_summing_to_s(int s) {
int tens = 1;
int answer = 0;
for (int n = 9; n > 0 && s > 0; --n) {
if (s >= n) {
answer += n * tens;
tens *= 10;
s -= n;
}
}
return answer;
}
Just a quick way to on how code works.
First you need to know sum of which digits equal to S. Since each digit is unique, you can assign a bit to them in a binary number like this:
Bit number Digit
0 1
1 2
2 3
...
8 9
So you can check all numbers that are less than 1 << 9 (numbers with 9 bits corresponding 1 to 9) and check if sum of bits if equal to your sum based on their value. So for example if we assume S=17:
384 -> 1 1000 0000 -> bit 8 = digit 9 and bit 7 = digit 8 -> sum of digits = 8+9=17
Now that you know sum if correct, you can just create number based on digits you found.
I tried to solve Multiply Strings by c++ by this approach, but I cannot avoid integer overflow by change type from int to long long int or double. Python won't overflow, so my code works like below.
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.
Python works:
class Solution:
def multiply(self, num1: str, num2: str) -> str:
n = len(num1) # assume n >= m
m = len(num2)
if n < m:
num1, num2 = num2, num1
n, m = m, n
product = 0
for i in range(1, m + 1):
multiplier = int(num2[m - i]) # current character of num2
sum_ = 0
for j in range(0, n): # multiply num1 by multiplier
multiplicand = int(num1[n - j - 1])
num = multiplicand * (10 ** j) * multiplier
sum_ += num
product += sum_ * (10 ** (i - 1))
return str(product)
C++ failed:
string multiply(string num1, string num2) {
int n = num1.size();
int m = num2.size();
if (n < m) {
std::swap(num1, num2);
std::swap(n, m);
}
long long int product = 0;
for (int i = 1; i <= m; ++i) {
int multiChar = num2[m - i] - '0';
long long int sum = 0;
for (int j = 0; j < n ; ++j) {
int charCand = num1[n - j - 1] - '0';
long long int num = charCand * ((pow(10, j))) * multiChar;
sum += num;
}
product += sum * ((pow(10, i - 1)));
}
return std::to_string(product);
}
As far as I have tested, some cases are OK, but overflow seems unavoidable if the number is too big. Is there any way to fix my code?
Testcase:
"12323247989"
"98549324321"
runtime error: 1.05355e+20 is outside the range of representable values of type 'long long' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:28:17
Expected:
"1214447762756072040469"
You are not on the right way. Imagine how you would do that by hand:
abc*def
-------
xxxx
xxxx0
xxxx00
-------
You just add single digits as well, don't you? Only those of same significance – possibly considering some carry.
You might rather reproduce the same in code, too. Producing overflow that way is much less likely (I assume that after multiplying single digits summing up the results in a single integer – recommending an unsigned type for – is acceptable; if not, you'd have to build up a std::string again). The sign you calculate independently, just as you'd do by hand as well.
One difference to multiplication by hand we'll have, though: By hand you would create rather large intermediate numbers by multiplying one number with each digit
of the other number. That would require to store these intermediate numbers as strings again, e. g. in a vector. More efficient, though, is identifying those digit pairs of which the multiplication results in the same significance.
These will be 0|0 -> 0; 0|1, 1|0 -> 1; 0|2, 1|1, 2|0 -> 2, and so on. You produce these pairs by:
for(size_t i = 0, max = std::max(num1.length(), num2.length); i < max; ++i)
{
for(size_t j = 0; j < i; ++j)
{
if(j < num1.length() && i - j < num2.length())
{
// iterate backwards for easy carry handling
size_t idx1 = num1.length() - j;
size_t idx2 = num2.length() - (i - j);
// multiply characters at num1[idx1] and num2[idx2] and add result to sum
}
}
// add carry
// calculate last digit and a p p e n d to a result string
// update carry
}
// append '-' sign, if result is negative
std::reverse(result.begin(), result.end());
Building up the string in reverse order is more efficient, as you do not need to move the subsequent characters all the time. (Untested code, if you find a bug, please fix it yourself).
The loops are in my preferred variant; if you feel better with another, feel free to change; just be aware that with signed types you can produce endless loops if you try e. g. for(unsigned i = n; n >= 0; --i /* overflows to UINT_MAX */).
Side note: You should accept the input strings by reference (std::string const& num1, std::string const& num2), that avoids the needless copies arising by accepting by value.
There is a number N
every iteration it becomes equal to (N*2)-1
I need to find out how many steps the number will be a multiple of the original N;
( 1≤ N ≤ 2 · 10 9 )
For example:
N = 7; count = 0
N_ = 7*2-1 = 13; count = 1; N_ % N != 0
N_ = 13*2-1 = 25; count = 2; N_ % N != 0
N_ = 25*2-1 = 49; count = 3; N_ % N == 0
Answer is 3
if it is impossible to decompose in this way, then output -1
#include <iostream>
using namespace std;
int main(){
int N,M,c;
cin >> N;
if (N%2==0) {
cout << -1;
return 0;
}
M = N*2-1;
c = 1;
while (M%N!=0){
c+=1;
M=M*2-1;
}
cout << c;
return 0;
}
It does not fit during (1 second limit). How to optimize the algorithm?
P.S All the answers indicated are optimized, but they don’t fit in 1 second, because you need to change the algorithm in principle. The solution was to use Euler's theorem.
The problem, as other answers have suggested, is equivalent to finding c such that pow(2, c) = 1 mod N. This is impossible if N is even, and possible otherwise (as your code suggests you know).
A linear-time approach is:
int c = 1;
uint64_t m = 2;
while (m != 1){
c += 1;
m = (2*m)%N;
}
printf("%d\n", c);
To solve this in 1 second, I don't think you can use a linear-time algorithm. The worst cases will be when N is prime and large. For example 1999999817 for which the above code runs in around 10 seconds on my laptop.
Instead, factor N into its prime factors. Solve 2^c = 1 mod p^k for each prime factor (where p^k appears in the prime factorization of N. Then combine the results using the Chinese Remainder theorem.
When finding the c for a given prime power, if k=1, the solution is c=p-1. When k is larger, the details are quite messy, but you can find a written solution here: https://math.stackexchange.com/questions/1863037/discrete-logarithm-modulo-powers-of-a-small-prime
The problem is that you're overflowing, the int data type only has 32 bits, and overflows 2^31-1 , in this problem you don't need to keep the actual value of M, you can just keep the modulo of n.
while (M%N!=0){
c+=1;
M=M*2-1;
M%=N
}
Edit:In addition, you don't actually need more than N iterations to check if a 0 mod exists, as there are only N different mods to N and it just keeps cycling. so you also need to keep that in mind in case there is no 0 mod.
There is no doubt that the main problem with your code is signed integer overflow
I added a print of M whenever M was changed (i.e. cout << M << endl;) and gave it the input 29. This is what I got:
57
113
225
449
897
1793
3585
7169
14337
28673
57345
114689
229377
458753
917505
1835009
3670017
7340033
14680065
29360129
58720257
117440513
234881025
469762049
939524097
1879048193
-536870911
-1073741823
-2147483647
1
1
1
1
... endless loop
As you see you have signed integer overflow. That is undefined behavior in C so anything may happen!! On my machine I ended up with a nasty endless loop. That must be fixed before considering performance.
The simple fix is to add a line like
M = M % N;
whenever M is changed. See the answer from #Malek
Besides that you shall also use an unsigned integer, i.e. use uint32_t for all variables.
However, that will not improve performance.
If you still have performance issue after the above fix, you can try this instead:
uint32_t N;
cin >> N;
if (N%2==0) {
cout << -1;
return 0;
}
// Alternative algorithm
uint32_t R,c;
R = 1;
c = 1;
while (R != N){
R = 2*R + 1;
if (R > N) R = R - N;
++c;
}
cout << c;
On my laptop this algorithm is 2.5 times faster when testing on all odd numbers in the range 1..100000. However, it might not be sufficient for all numbers in the range 1..2*10^9.
Also notice the use of uint32_t to avoid integer overflow.
I'm trying to add two octal numbers by adding the corresponding digits but, I'm stuck when the case is that the sum of digits is greater than 7. I'll have to take a carry and add it to the next addition cycle. I'm unable to find the right expression to consider the carry and compute the final sum.
Another case to consider is when the octal numbers a and b do not have same number of digits, ex: 6 and 13 (6+13=21 in octal). I'm unable to establish a condition for the while loop for such a condition (if both have same number of digits I can run the while loop till either of them or both of them become zero)
Can somebody please help/complete the following code:
int octal_sum(int a,int b) //a and b and octal numbers
{
int sum=0,carry=0,d=0;
while(**???**)
{
d=0;
d=carry+(a%10)+(b%10);
a/=10;b/=10;
if(d>7)
{
carry=1;
d=d%8;
}
sum= **???**
}
return sum; //returns octal sum of a and b
}
Since you are passing ints, I assume that you are using decimal-coded octals*, i.e. decimal numbers that use only digits 0 through 7, inclusive. For example, number 1238 which is actually 8310 would be coded as 12310 using your scheme.
Deciding on the stopping condition - you want your while loop to continue until both numbers a, b, and carry turn zero. In other words, the condition should be a || b || carry
Adding the next digit to the sum - since the result is coded as decimal, you need to multiply digit d by the next consecutive power of ten. A simple way of doing that would be adding a new variable m which starts at 1 and gets multiplied by ten each iteration.
The result would look like this:
int octal_sum(int a,int b) {
int sum=0, carry=0, d=0, m = 1;
while(a || b || carry) {
d=0;
d=carry+(a%10)+(b%10);
a/=10;b/=10;
if(d>7) {
carry=1;
d=d%8;
} else {
carry = 0;
}
sum += d*m;
m *= 10;
}
return sum; //returns octal sum of a and b
}
Demo.
* This would be similar to Binary-Coded Decimal (BCD) representation, when a representation capable of storing hex digits is used to store decimal digits.
Here is the function I made. It is important to remember about the carry. Because if your numbers add up to be longer (ex: 7777 + 14 = 10013) if you ignore the carry, the code will only return four digits (your longest lenght of number), so 0013, which is 13. Not good. So we need to account for the carry. We must continue our loop until both our numbers and the carry are all 0.
Further more, if the digit you obtain by calculating a%10 + b%10 + carry is smaller than 8, then we no longer need to carry again, so we need to reset the value.
Note I'm using a digit rank integer, which basically allows me to add the digit to the beginning of the sum by multiplying by powers of ten and then adding it to the sum.
The final code looks like this.
int octal_sum(int a, int b)
{
int sum = 0, digit = 0, carry = 0, digit_rank = 1;
// Calculate the sum
while (a > 0 || b > 0 || carry)
{
// Calculate the digit
digit = a % 10 + b % 10 + carry;
// Determine if you should carry or not
if (digit > 7)
{
carry = 1;
digit %= 8;
}
else
carry = 0;
// Add the digit at the beggining of the sum
sum += digit * digit_rank;
digit_rank *= 10;
// Get rid of the digits of a and b we used
a /= 10;
b /= 10;
}
return sum;
}
Hope it helped you!
I am using StringBuilder to append character, which is better than using Strings, it's immutable.
2.read the char from String by converting String to char array, converting char to an integer by subtracting from its ASCII value '0'
make sure handle the carryforward case too
private static String OctaNumberAddition(String o1, String o2) {
StringBuilder sb = new StringBuilder();
int carry = 0;
for(int i = o1.length() - 1, j =o2.length()-1;i >= 0 || j >= 0;i--,j--){
int sum = carry + (i >= 0 ? o1.charAt(i) - '0':0)+(j >= 0 ? o2.charAt(j) - '0':0);
sb.insert(0,sum%8);
carry = sum /8;
}
if(carry > 0){
sb.insert(0,carry);
}
return sb.toString();
}
Is there a way to split a number and store digits in an int array?
I am looking for a way to remove some digits from a number (for a divisible algorithm proof).
for example, if I have a number 12345, I need to perform this operation:
1234 - 5 = 1229
Is there a way to do this?
Use n % 10 to get the last digit and n / 10 to get the others. For example, 5=12345%10, 1234=12345/10.
Convert integer to array:
int array[6];
int n = 123456;
for (int i = 5; i >= 0; i--) {
array[i] = n % 10;
n /= 10;
}
In general, vectors are preferred in C++, especially in this case since you probably don't know in advance the number of digits.
int n = 123456;
vector<int> v;
for(; n; n/=10)
v.push_back( n%10 );
Then v contains {6,5,4,3,2,1}. You may optionally use std::reverse to reverse it.
I am going to give you an answer in sudo code.
int [] makeArrayFromInt (int input){
arr = new int [floor(log(input)/log(10)) + 1]
int index = 0
while(input>0){
arr[index]=input%10
input=input/10
index++
}
return arr
}
The basic idea is to use mod 10 to get the value in a particular digits place and divide by 10 to get to the next digit. Repeat this process until dividing by 10 gives you zero, as this is when you have reached the end of your number. Floor(log(input)/log(10)) + 1 is a trick to find out how many digits a number possesses.