I've got a function that extracts the month from a given number of days( days > 0 && days < 366):
int findMonth(int days)
{
int i, months[] = {31,28,31,30,31,30,31,31,30,31,30,31};
for (i = 0; i < 12 && days > 0;i++)
days -= months[i];
return i;
}
Is there any more rational way to deduce it?(I am ignoring the leap year)
If you are trying to make it shorter I think you can't. If you just want something different and maybe more close to C++, you can try this:
int findMonth(int days) {
int i = 0, months[] = {31,28,31,30,31,30,31,31,30,31,30,31};
return std::count_if(std::begin(months), std::end(months), [&i, &days](int x) { return (i += x) - x <= days; });
}
or using std::vector:
int findMonth(int days) {
int i = 0;
std::vector<int> months = {31,28,31,30,31,30,31,31,30,31,30,31};
return std::count_if(months.begin(), months.end(), [&i, &days](int x) { return (i += x) - x <= days; });
}
Related
when the first date is bigger than the second, it doesent calculate.
for example: first date 22/10/2022
second date: 15/10/2022
#include <iostream>
#include <cstdlib>
using namespace std;
class Date {
public:
Date(int d, int m, int y);
void set_date(int d, int m, int y);
void print_date();
void inc_one_day();
bool equals(Date d);
int get_day() { return day; }
int get_month() { return month; }
int get_year() { return year; }
private :
int day;
int month;
int year;
};
bool is_leap_year(int year)
{
int r = year % 33;
return r == 1 || r == 5 || r == 9 || r == 13 || r == 17 || r == 22 || r == 26 || r == 30;
}
int days_of_month(int m, int y){
if (m < 7)
return 31;
else if (m < 12)
return 30;
else if (m == 12)
return is_leap_year(y) ? 30 : 29;
else
abort();
}
void Date::inc_one_day(){
day++;
if (day > days_of_month(month, year)) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
bool Date::equals(Date d) {
return day == d.day && month == d.month && year == d.year;
}
int days_between(Date d1, Date d2){
int count = 1;
while (!d1.equals(d2)){
d1.inc_one_day();
count++;
}
return count;
}
Date::Date(int d, int m, int y){
cout << "constructor called \n";
set_date(d, m, y);
}
void Date::set_date(int d, int m, int y){
if (y < 0 || m < 1 || m>12 || d < 1 || d > days_of_month(m, y))
abort();
day = d;
month = m;
year = y;
}
void Date::print_date(){
cout << day << '/' << month << '/' << year<<endl;
}
int main(){
Date bd(22, 12, 1395);
Date be(15, 12, 1395);
cout << '\n';
int i;
i= days_between(bd, be);
cout << i << endl;
}
here's my code.
I've seen many codes that calculate the days between two dates, but they didn't use class Date.
how can i solve this problem? could you guys help me please.I'm sorry i'm new in c++ so, my problem might be so basic.
It is clear why your algorithm does not work - you are incrementing the later date so it will never equal the earlier date. The solution is simply to compare the dates and swap the operands if necessary so that you are always incrementing the earlier date toward the later date.
int days_between(Date d1, Date d2)
{
int count = 0 ;
// Initially assume d2 >= d1
Date* earlier = &d1 ;
Date* later = &d2 ;
// Test if d1 > d2...
int year_diff = d2.get_year() - d1.get_year() ;
int mon_diff = d2.get_month() - d1.get_month() ;
int day_diff = d2.get_day() - d1.get_day() ;
if( year_diff < 0 ||
(year_diff == 0 && (mon_diff < 0 || (mon_diff == 0 &&
day_diff < 0 ))))
{
// d1 > d2, so swap
earlier = &d2 ;
later = &d1 ;
}
while (!earlier->equals(*later))
{
earlier->inc_one_day();
count++;
}
return count;
}
Note that it is not clear why you start with a count of 1. If the dates start equal, surely that should return a zero? That is how I have written it in any case.
If it is required to indicate whether the dates were reversed or not, you might want to return a signed value. In that case:
return earlier == &d2 ? -count : count ;
Which for the dates in your example will return -7.
Your solution is a good candidate for operator overloading so you could simply and more intuitively write:
if( d1 > d2 )
{
earlier = &d2 ;
later = &d1 ;
}
while( *earlier != *later))
{
earlier++ ;
count++ ;
}
return earlier == &d2 ? -count : count ;
and even ultimately:
i = be - bd;
What would be easier is to write a function that calculates the total number of days that have occurred since the year 0000. After that you can simply subtract them from each other and return the total number of days between them.
Strong number is the number that the sum of the factorial of its digits is equal to number itself.
For example: 145, since
1! + 4! + 5! = 1 + 24 + 120 = 145
Here is my code, It passes most of the test except one test
#include <string>
using namespace std;
string strong_num (int number )
{
int sum = 0;
while(number != 0) {
int last = number % 10;
number /= 10;
sum+= last * (last-1);
}
if(sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}
What is wrong with my code?
I'm surprised you're passing any test cases at all. For one thing, you are destroying number before you compare it to sum, and for another your logic is flawed.
Try this:
int factorial (int x)
{
int result = 1;
while (x > 1)
{
result *= x;
x--;
}
return result;
}
string strong_num (int number)
{
int sum = 0;
int x = number;
while (x != 0) {
int digit = x % 10;
sum += factorial (digit);
x /= 10;
}
if (sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}
Live demo
Replace int by long long to be able to test larger numbers.
There are two problems:
first - you are changing the value of number before comparing it to sum,
second - the thing you used last * (last-1) is not a definition of factorial, the definition of factorial is factorial(x) = 1 * 2 * 3 * ... * x
int factorial (int x) {
if(x < 2) return 1;
return x * factorial(x - 1);
}
string strong_num (int number)
{
int sum = 0;
int x = number;
while (x != 0) {
int last = x % 10;
sum += factorial (last);
x /= 10;
}
if (sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}
I want to solve this with recursion, but I am having trouble figuring out whats wrong. Create a function where given n days as an argument, return the total amount of items received throughout Christmas days as an integer.
xmasItems(1) = 1
xmasItems(3) = 10 : Day1 = (1), Day2 = (1+2), Day3 = (1+2+3) | Day 3 total = (1)+ (1+2) + (1+2+3) = 10
int xmasItems(int n) {
if (n == 0) { return 0; }
else {
int forThatDay = 0;
while (n != 0) {
forThatDay += n;
n--;
}
return forThatDay + xmasItems(n - 1);
}
}
In the while loop of your else branch, you are decrementing n all the way to 0. So you are computing only the first day's value.
Instead, you could use a copy of n for the forThatDay calculation, so you can make the recursive call correctly:
int xmasItems(int n) {
if (n == 0) { return 0; }
else {
int forThatDay = 0;
int m = n; // copy n and use it
while (m != 0) {
forThatDay += m;
m--;
}
return forThatDay + xmasItems(n - 1); // now n is correct
}
}
Aside: there is a closed form solution for the sum of n natural numbers, so you shouldn't need a loop anyway.
I have a decimal string like this (length < 5000):
std::string decimalString = "555";
Is there a standard way to convert this string to binary representation? Like this:
std::string binaryString = "1000101011";
Update.
This post helps me.
As the number is very large, you can use a big integer library (boost, maybe?), or write the necessary functions yourself.
If you decide to implement the functions yourself, one way is to implement the old pencil-and-paper long division method in your code, where you'll need to divide the decimal number repeatedly by 2 and accumulate the remainders in another string. May be a little cumbersome, but division by 2 should not be so hard.
Since 10 is not a power of two (or the other way round), you're out of luck. You will have to implement arithmetics in base-10. You need the following two operations:
Integer division by 2
Checking the remainder after division by 2
Both can be computed by the same algorithm.
Alternatively, you can use one of the various big integer libraries for C++, such as GNU MP or Boost.Multiprecision.
I tried to do it.. I don't think my answer is right but here is the IDEA behind what I was trying to do..
Lets say we have 2 decimals:
100 and 200..
To concatenate these, we can use the formula:
a * CalcPower(b) + b where CalcPower is defined below..
Knowing this, I tried to split the very long decimal string into chunks of 4. I convert each string to binary and store them in a vector..
Finally, I go through each string and apply the formula above to concatenate each binary string into one massive one..
I didn't get it working but here is the code.. maybe someone else see where I went wrong.. BinaryAdd, BinaryMulDec, CalcPower works perfectly fine.. the problem is actually in ToBinary
#include <iostream>
#include <bitset>
#include <limits>
#include <algorithm>
std::string BinaryAdd(std::string First, std::string Second)
{
int Carry = 0;
std::string Result;
while(Second.size() > First.size())
First.insert(0, "0");
while(First.size() > Second.size())
Second.insert(0, "0");
for (int I = First.size() - 1; I >= 0; --I)
{
int FirstBit = First[I] - 0x30;
int SecondBit = Second[I] - 0x30;
Result += static_cast<char>((FirstBit ^ SecondBit ^ Carry) + 0x30);
Carry = (FirstBit & SecondBit) | (SecondBit & Carry) | (FirstBit & Carry);
}
if (Carry)
Result += 0x31;
std::reverse(Result.begin(), Result.end());
return Result;
}
std::string BinaryMulDec(std::string value, int amount)
{
if (amount == 0)
{
for (auto &s : value)
{
s = 0x30;
}
return value;
}
std::string result = value;
for (int I = 0; I < amount - 1; ++I)
result = BinaryAdd(result, value);
return result;
}
std::int64_t CalcPowers(std::int64_t value)
{
std::int64_t t = 1;
while(t < value)
t *= 10;
return t;
}
std::string ToBinary(const std::string &value)
{
std::vector<std::string> sets;
std::vector<int> multipliers;
int Len = 0;
int Rem = value.size() % 4;
for (auto it = value.end(), jt = value.end(); it != value.begin() - 1; --it)
{
if (Len++ == 4)
{
std::string t = std::string(it, jt);
sets.push_back(std::bitset<16>(std::stoull(t)).to_string());
multipliers.push_back(CalcPowers(std::stoull(t)));
jt = it;
Len = 1;
}
}
if (Rem != 0 && Rem != value.size())
{
sets.push_back(std::bitset<16>(std::stoull(std::string(value.begin(), value.begin() + Rem))).to_string());
}
auto formula = [](std::string a, std::string b, int mul) -> std::string
{
return BinaryAdd(BinaryMulDec(a, mul), b);
};
std::reverse(sets.begin(), sets.end());
std::reverse(multipliers.begin(), multipliers.end());
std::string result = sets[0];
for (std::size_t i = 1; i < sets.size(); ++i)
{
result = formula(result, sets[i], multipliers[i]);
}
return result;
}
void ConcatenateDecimals(std::int64_t* arr, int size)
{
auto formula = [](std::int64_t a, std::int64_t b) -> std::int64_t
{
return (a * CalcPowers(b)) + b;
};
std::int64_t val = arr[0];
for (int i = 1; i < size; ++i)
{
val = formula(val, arr[i]);
}
std::cout<<val;
}
int main()
{
std::string decimal = "64497387062899840145";
//6449738706289984014 = 0101100110000010000100110010111001100010100000001000001000001110
/*
std::int64_t arr[] = {644, 9738, 7062, 8998, 4014};
ConcatenateDecimals(arr, 5);*/
std::cout<<ToBinary(decimal);
return 0;
}
I found my old code that solve sport programming task:
ai -> aj
2 <= i,j <= 36; 0 <= a <= 10^1000
time limit: 1sec
Execution time was ~0,039 in worst case. Multiplication, addition and division algorithms is very fast because of using 10^9 as numeration system, but implementation can be optimized very well I think.
source link
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define sz(x) (int((x).size()))
typedef vector<int> vi;
typedef long long llong;
int DigToNumber(char c) {
if( c <= '9' && c >= '0' )
return c-'0';
return c-'A'+10;
}
char NumberToDig(int n) {
if( n < 10 )
return '0'+n;
return n-10+'A';
}
const int base = 1000*1000*1000;
void mulint(vi& a, int b) { //a*= b
for(int i = 0, carry = 0; i < sz(a) || carry; i++) {
if( i == sz(a) )
a.push_back(0);
llong cur = carry + a[i] * 1LL * b;
a[i] = int(cur%base);
carry = int(cur/base);
}
while( sz(a) > 1 && a.back() == 0 )
a.pop_back();
}
int divint(vi& a, int d) { // carry = a%d; a /= d; return carry;
int carry = 0;
for(int i = sz(a)-1; i >= 0; i--) {
llong cur = a[i] + carry * 1LL * base;
a[i] = int(cur/d);
carry = int(cur%d);
}
while( sz(a) > 1 && a.back() == 0 )
a.pop_back();
return carry;
}
void add(vi& a, vi& b) { // a += b
for(int i = 0, c = 0, l = max(sz(a),sz(b)); i < l || c; i++) {
if( i == sz(a) )
a.push_back(0);
a[i] += ((i<sz(b))?b[i]:0) + c;
c = a[i] >= base;
if( c ) a[i] -= base;
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int from, to; cin >> from >> to;
string s; cin >> s;
vi res(1,0); vi m(1,1); vi tmp;
for(int i = sz(s)-1; i >= 0; i--) {
tmp.assign(m.begin(), m.end());
mulint(tmp,DigToNumber(s[i]));
add(res,tmp); mulint(m,from);
}
vi ans;
while( sz(res) > 1 || res.back() != 0 )
ans.push_back(divint(res,to));
if( sz(ans) == 0 )
ans.push_back(0);
for(int i = sz(ans)-1; i >= 0; i--)
cout << NumberToDig(ans[i]);
cout << "\n";
return 0;
}
How "from -> to" works for string "s":
accumulate Big Number (vector< int >) "res" with s[i]*from^(|s|-i-1), i = |s|-1..0
compute digits by dividing "res" by "to" until res > 0 and save them to another vector
send it to output digit-by-digit (you can use ostringstream instead)
PS I've noted that nickname of thread starter is Denis. And I think this link may be useful too.
How to find the sum of elements on even position without usage of arrays etc, only normal operations?
For example:
159
Sum = 5.
159120
Sum = 5+1+0 = 6.
My work:
int sumofdigits(int x)
{
int sum = 0;
while(x > 0){
if (x % 100 != 0)
sum += x % 100;
x /= 100;
}
return sum;
}
Since you're counting "even" digits from the left, you first need to count the number of digits in order to know whether the least significant digit is even or not:
int sumOfEvenDigits(int x)
{
// First, count the number of digits
int digitCount = 0;
int tmp = x;
while(tmp) {
tmp /= 10;
digitCount++;
}
// If the number of digits is odd, throw away the least significant digit
if(digitCount % 2 == 1)
x /= 10;
// Keep adding the least significant digit, and throwing away two digits until you're done.
int sum = 0;
while(x){
sum += x % 10;
x /= 100;
}
return sum;
}
int accumulateIfEvenPos(int num, int pos) {
if (num == 0) return 0;
int digit = num % 10;
int next = num / 10;
return pos & 1 ? digit + accumulateIfOdd(next, ++pos) : accumulateIfOdd(next, ++pos);
}
You call it with pos 1 initially - demo here.
Well simple modification should do the trick.
int main()
{
int x = 1549;
//Get the number of digits
int length = snprintf(NULL, 0, "%i", x);
int sum = 0;
while(x > 0){
if (x % 100 != 0) {
//check if the number of digits is even to start from the last digit
if (length % 2 == 0) {
sum += x % 10;
x /= 10;
}
else {
x /= 10;
sum += x % 10;
}
x /= 10;
}
}
cout << sum << endl;
return 0;
}
EDIT: Solved the problem/bug in the algorithm. This might not be the best answer but I didn't want to completely write a different one(than the answer before edit).
You will need to have an index variable that keeps track of the position:
unsigned int digit_position = 0;
while (x > 0)
{
unsigned int digit_value = x % 10;
if (digit_position is even)
{
// Add digit_value to sum
}
// Shift value right one digit
x /= 10;
++digit_position;
}
There may be other methods using a position variable and the pow() function. But that is left as an exercise for the reader.