I have integer num, which can be negative or positive and also I have number P (1 < P <= 9).
What I want to do is to convert num to base-P.
I easily do it when num > 0:
int i = 0;
int A[10000];
while (num != 0)
{
A[i] = num % p;
num /= p;
i++;
}
But I don't know how to achieve it when num < 0.
Check if number is positive or negative, and remember this in the code. If it's negative - multiply the number by -1 and do the same you did to a positive number. When you output the number, you should do this before:
if (sign == -1)
cout << '-';
And then write the rest of the number.
The - sign is not something special to base 10. In general if 90base{10} = 1011010base{2} then -90base{10} = -1011010base{2}. What you are doing here is an extension of two's complement. Two's complement is a method to represent both positive and negative numbers in binary without using a - and is used in computing. Just check whether number is positive or negative and put negative sign. You can use for checking Adrian's answer. But, you can also use the function code that returns -1 for negative values, 0 for zero, 1 for positive values of x
int status (int x) {
int sign = (x > 0) - (x < 0);
return sign;
}
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 am using a Constructor to take an unsigned int as an argument, break it into digits and assign the appropriate true and false values to a vector object. But the problem is that, my poor logic assigns the values in reverse order as the last digit is separated first and so on. The Code I have written is:
vector<bool> _bits;
uBinary(unsigned int num){
int i = 1;
while(num > 0)
{
int d = num%10;
num /= 10;
_bits.resize(i++);
if(d == 1)
{
_bits[_bits.size() - 1] = true;
}
else if(d==0)
{
_bits[_bits.size() - 1] = false;
}
}
}
For example: if argument 10011 is passed to the function uBinary() the vector object will be assigned the values in this order 11001 or true,true,false,false,true which is reversed.
All I need to do here is that, I want to assign the values without reversing the order and I don't want to use another loop for this purpose.
One way is to start at the highest possible digit (unsigned int can only hold values up to 4294967295 on most platforms) and ignore leading zeros until the first actual digit is found:
for (uint32_t divisor = 1000000000; divisor != 0; divisor /= 10) {
uint32_t digit = num / divisor % 10;
if (digit == 0 && _bits.size() == 0 && divisor != 1)
continue; // ignore leading zeros
_bits.push_back(digit == 1);
}
But finding the digits in reverse and then simply reversing them is much simpler (and at least as efficient):
do {
_bits.push_back(num % 10 == 1);
num /= 10;
} while (num != 0);
std::reverse(_bits.begin(), _bits.end());
One way you can do the reversing with another loop or std::reverse is to use recursion. With recursion you can walk down the int until you hit the last digit and then you add the values to the vector as the calls return. That would look like
void uBinary(unsigned int num)
{
if (num == 0)
return;
uBinary(num / 10);
_bits.push_back(num % 10 ? true : false);
}
Which you can see working with
int main()
{
uBinary(10110);
for (auto e : _bits)
std::cout << e << " ";
}
Live Example
Do note that it is advisable not to use leading underscores in variables names. Some names are reserved for the implementation and if you use one it is undefined behavior. For a full explanation of underscores in names see: What are the rules about using an underscore in a C++ identifier?
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();
}
I wanna find out the number of digits of a number in c++ but I don't know what can I do? for example number of digits 7676575.
Take the ceiling of the base-10 logarithm of the number. (Or more generally "base-N" for the number of digits in base N.)
In code: std::ceil(std::log10(n + 1)), and make sure to #include <cmath>.
(You'll get the answer 0 for input 0 as a special case. It's up to you what to do about negative numbers.)
The code in #Knaģis's answer is possibly more efficient, since divisions by the constant 10 can be turned into multiplications by the compiler and are fairly cheap. You have to profile and compare if this is performance-critical, and if this applies to integral types only. The logarithm approach also lets you compute the number of digits in a hypothetical decimal expansion of very large floating point numbers.
int i = 7676575;
int digits = i == 0 ? 1 : 0;
i = abs(i); // handle negative numbers as well
while (i > 0)
{
digits++;
i /= 10;
}
// -or- if you prefer do/while then a shorter sample (by Kerrek SB)
int i = 7676575;
int digits = 0;
i = abs(i); // handle negative numbers as well
do { digits++; } while (i /= 10);
Just put it in a string and get its length;
int number = getNumberFromSomewhere();
stringstream ss;
ss << number;
size_t numDigits = ss.str().length();
template <typename T>
int getdigits(T v)
{
T i = std::abs(v);
if (i < 10) return 1;
else if (i < 100) return 2;
...
else if (i < 100000000) return 8;
else if (i < 1000000000) return 9;
}
And so on, you can extend to include long range, not only int. I'm not sure if this is faster than divide, but why not - it's just 10 comparisons.
I suppose templates black magic can be used to generate functions with only needed number of ifs, but who really cares. But you can ensure T is integer using std::enable_if<std::is_integer<T>::value>.
You can convert to string and check the length of the string:
std::to_string(number).size()
I an using the following function to calculate the set bits in an integer, and it works for positive numbers, but not for negative numbers. Can anyone explain why?
int CountSetBits(int number)
{
int count = 0;
while (number > 0)
{
count += (number & 0x01);
number >>= 1;
}
return count;
}
while (number > 0)
Will immediately end (since number < 0 from the onset)
You can force it to treat the number as unsigned:
unsigned int new_number = number;
And then it should work with new_number (this works because of how the sign bit is implemented)