How to split a number into digits in C++ [duplicate] - c++

This question already has answers here:
Converting integer into array of digits [closed]
(4 answers)
Closed 2 years ago.
I know there are similar questions on Stack overflow about this. I already checked them. Here are two points:
The number will be an input from the user, so I won't know how many digits the number may actually contain
I DON'T want to directly print the digits, I need to do some further process on every digit, so I need a way to save or assign every single digit.
So fore example, if the user enters 1027, I'll need 1, 0, 2, 7 returned, and not printed. That's where my problem starts.
Here's how I'd write it if it could be printed:
int x;
cin>>x;
while(x != 0)
{
cout<<x%10<<endl;
x/=10;
}
Any hints or help is in advance appreciated.

It depends what order you need it in. If you need least-significant digit (rightmost) to most-significant (leftmost), then your solution is almost there
int x = ...
while(x != 0)
{
int current = x % 10; // get rightmost digit
x /= 10;
// process 'current', or store in a container for later processing
}
If you need most-significant (leftmost) to least-significant (rightmost), then you can do this recursively:
void for_each_digit(int input)
{
// recursive base case
if (input == 0) { return; };
int current = input % 10
for_each_digit(input / 10); // recurse *first*, then process
// process 'current', add to container, etc
}
// ...
int x = ...
for_each_digit(x);
Edit: I apparently missed the part about returning a sequence of digits.
Either approach works. If you go right-to-left, you will need to reverse the container first. If you go recursive, you will need to append each value to the container.

Use a std::string:
std::string input;
std::cin >> input;
Now input[i] is the i-th digit. input.size() is the number of digits.

Well you can use vector. It can take variable length input. You need not declare the size beforehand. Learn more about vector here: vector
#include<iostream>
#include<vector>
#include <algorithm> // std::reverse
using namespace std;
int main(void)
{
vector<int>digits;
int x;
cin >> x;
while(x)
{
digits.push_back(x % 10);
x = x / 10;
}
// reversing the order of the elements inside vector "digits" as they are collected from last to first and we want them from first to last.
reverse(digits.begin(), digits.end());
// Now the vector "digits" contains the digits of the given number. You can access the elements of a vector using their indices in the same way you access the elements of an array.
for(int i = 0; i < digits.size(); i++) cout << digits[i] << " ";
return 0;
}

You may try std::vector<int> to store unknown number of integers as shown:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> digits;
std::string s;
std::cout << "Enter the number: ";
std::cin >> s;
size_t len = s.length();
for (size_t i = 0; i < len; i++) {
digits.push_back(s[i] - '0');
}
// Comment next 3 code to stop getting output
for (size_t i = 0; i < len; i++)
std::cout << digits[i] << ' ';
std::cout << std::endl;
return 0;
}
Note: This approach doesn't performs any mathematical operations (i.e. operation of division and getting remainders). It simply stores each integer in a vector using a for loop.

Related

Output numbers in reverse (C++) w/ vectors

I'm stuck for the first time on a lab for this class. Please help!
The prompt is:
Write a program that reads a list of integers, and outputs those integers in reverse. The input begins with an integer indicating the number of integers that follow. For coding simplicity, follow each output integer by a comma, including the last one.
Ex: If the input is:
5 2 4 6 8 10
the output is:
10,8,6,4,2,
2 questions: (1) Why does the vector not take user input unless the const int is included? (2) Why does the code not work in general? It seems to properly output, but with an error, and does not include the end line?
#include <iostream>
#include <vector>
using namespace std;
int main() {
const int MAX_ELEMENTS = 20;
vector<int> userInts(MAX_ELEMENTS);
unsigned int i;
int numInts;
cin >> numInts;
for (i = 0; i < numInts; ++i) {
cin >> userInts.at(i);
}
for (i = (numInts - 1); i >= 0; --i) {
cout << userInts.at(i) << ",";
}
cout << endl;
return 0;
}
Firstly, you need to specify the size because you are not using the vector's push_back functionality. Since you are only using at, you must specify the size ahead of time. Now, there's a few ways to do this.
Example 1:
cin >> numInts;
vector<int> userInts(numInts); // set the size AFTER the user specifies it
for (i = 0; i < numInts; ++i) {
cin >> userInts.at(i);
}
Alternatively, using push_back you can do:
vector<int> userInts; // set the size AFTER the user specifies it
for (i = 0; i < numInts; ++i) {
int t;
cin >> t;
userInts.push_back(t);
}
As for looping backwards, i >= 0 will always be true for unsigned numbers. Instead, you can use iterators.
for ( auto itr = userInts.rbegin(); itr != userInts.rend(); ++itr ) {
cout << *itr;
}
If you need to use indexes for the reverse loop, you can do:
for ( i = numInts - 1; i != ~0; --i ) { // ~0 means "not 0", and is the maximum value, I believe this requires c++17 or 20 though
cout << userInts.at(i);
}
with unsigned int i; the condition i >= 0 is always true. Eventually you will access an out-of-range element, which will throw std::out_of_range.
To answer your other question
std::vector userInts;
create a vector with no entries
userInts.at(i)
tries to access the (non existnat) ith entry.
You have 2 choices
create vector with a lot of empty etries
ask the vector to dynamically grow
The first one is what you did
const int MAX_ELEMENTS = 20;
vector<int> userInts(MAX_ELEMENTS);
Or you can do
userInts.push_back(x);
this will make sure there is enough space in the vector and add the new element to the end.

C++ How to optimize this algorithm ? (std::map)

The problem is the following: We are given a number 's', s ∈ [0, 10^6], and a number 'n', n ∈ [0, 50000], then n numbers, and we have to find how many number pairs' sum is equal to the 's' number (and we must use either maps or sets to solve it)
Here is the example:
Input:
5 (this is s)
6 (this is n)
1
4
3
6
-1
5
Output:
2
explanation : these are the (1,4) and (6,−1) pairs. (1 +4 = 5 and 6 + (-1) = 5)
Here is my "solution" , I don't even know if it's correct, but it works for the example that we got.
#include <iostream>
#include <map>
#include <iterator>
using namespace std;
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
int s;
cin >> s;
int n;
cin >> n;
map<int, int> numbers;
int element;
int counter = 0;
for(int i=0; i<n;i++)
{
cin >> element;
numbers.insert(pair<int, int>(element, s-element));
}
for(map<int, int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
map<int, int>::iterator it2 = it;
while(it2 != numbers.end())
{
if(it->second == it2->first)
{
counter++;
break;
}
it2++;
}
}
cout << counter << "\n";
return 0;
}
Thanks for the answers in advance! I'm still a beginner and I'm learning, sorry.
element, s-element is a good idea but there is no reason to store all the pairs and only then check for duplicates. This removes the O(n^2) loop you have there at the end.
The standard way using hashing would be:
seen=unordered_map<number,count>()
for 1...n:
e = read_int()
if (s-e) in seen:
duplicates+=seen[s-e] # Found new seen[s-e] duplicates.
if e in seen:
seen[e]+=1
else:
seen.insert(e,1)
return duplicates
Here's a brute-force method, using a vector:
int target_s = 0;
int quantity_numbers = 0;
std::cin >> target_s >> quantity_numbers;
std::vector<int> data(quantity_numbers);
for (int i = 0; i < quantity_numbers; ++i)
{
cin >> data[i];
}
int count = 0;
for (int i = 0; i < quantity_numbers; ++i)
{
for (j = 0; j < quantity_numbers; ++j)
{
if (i == j) continue;
int pair_sum = data[i] + data[j];
if (pair_sum == target_s) ++count;
}
}
std::cout << count;
The above code includes the cases where pair <a,b> == s and pair <b,a> == s. Not sure if the requirement only wants pair <a,b> in this case.
As always with this kind of questions, the selection of the appropriate algorithm will improve your solution. Writing some "better" C++ code, will nearly never help. Also, brute forcing is nearly never a solution for such an algorithm.
With the following described approach (which was of course not invented by me), we need just one std::map (or even better, a std::unordered_map) and one for loop. We do not need to store the read values in an additional std::vector or such alike. So, we can come up with low memory condumption and fast computation.
Approach. Any time, after reading a value, we will calculate the delta from the desired sum.
If we look at the required condition that the current value and some previuosly read value, should add up to the desired sum, we can write the following mathematical equations:
currentValue + previouslyReadValue = desiredSum
or
desiredSum - currentValue = previouslyReadValue
or with
delta = desiredSum - currentValue
-->
delta == previouslyReadValue
So, we need to look at the already read values and if they are equal to the delta (Because then they would add up the the desired sum), add their count of occurence the the resulting count of valid pairs.
The already read values and their count of occurence will be stored in a std::unordered_map.
All this will result in a 10 line solution:
#include <iostream>
#include <unordered_map>
int main() {
// Initialize our working variables
int numberOfValues{}, desiredSum{}, currentValue{}, resultingCount{};
// Read basic parameters. Desired sum and overall number of input values.
std::cin >> desiredSum >> numberOfValues;
// Here, we will store all values and their count of occurence
std::unordered_map<int, int> valuesAndCount{};
// Read all values and operate on them
for (int i{}; i < numberOfValues; ++i) {
std::cin >> currentValue; // Read from cin
const int delta{ desiredSum - currentValue }; // Calculate the delta from the desired sum
// Look, if the calculated delta is already in the map. Becuase, if the delta and the
// current value sum up to our desired sum, then we found a valid pair.
if (valuesAndCount.find(delta) != valuesAndCount.end())
// Increase the resulting count, by the number of times that this delta value has already been there
resultingCount += valuesAndCount[delta];
// Nothing special, Just cound the occurence of this value.
valuesAndCount[currentValue]++;
}
return !!(std::cout << resultingCount);
}

How to find the sum of numbers that have digits higher than 5 [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
so I want to write a function that returns the sum of all numbers in an array who's digits are higher then 5 so for example if the array is [12, 66, 23, 67] the answer would be 66+67
This code summs all the numbers in the array and I can'\t figure out why
using namespace std;
int func(int n[], int size){
int digit, S=0, a;
for(int i=0; i<size; i++){
a= n[i];
while( n[i]!=0){
digit= n[i]%10;
if(digit>=5){
n[i]= n[i]/10;
}
else break;
}
S=S+a;
}
return S;
}
int main()
{
int n[3], i;
for(int i=0; i<3; i++){
cin>>n[i];
}
cout<<func(n, 3)<<endl;
return 0;
}```
S=S+a This piece of code is out of your while loop and inside for loop, this will add all the elements in the array
The main problem is that you are not checking when you should add a to S.
These lines are causing the problem:
int func(int n[], int size){
int digit, S=0, a;
for(int i=0; i<size; i++){
a= n[i];
while( n[i]!=0){
digit= n[i]%10;
if(digit>=5){ // Wrong. Do "digit > 5"
n[i]= n[i]/10;
}
else break; <--- exiting this while loop
}
S=S+a; <--- ...but still adding?
}
return S;
}
You are breaking the loop, but still adding to the sum.
You should use a flag. Your inner loop would look something like this:
// We need to check if each digit is valid
bool each_digit_greater_than_5 = true;
// As long as we have digits left and all previous digits were valid
while(n[i] != 0 && each_digit_greater_than_5)
{
// Extract a digit
digit = n[i] % 10;
// If valid, get next digit to extract
if(digit > 5)
{
n[i] /= 10;
}
// Else, exit the loop
else
{
each_digit_greater_than_5 = false;
}
}
And then, simply check if each_digit_greater_than_5:
// If number was valid
if(each_digit_greater_than_5)
{
// Add to sum
S = S + a;
}
Extra Notes:
How you write the code is often more important than what you write.
Here are (some) food for thoughts.
Use better formatting: The whole block of code should be uniformly indented. This:
...
for(int i=0; i<size; i++){
a= n[i];
while( n[i]!=0){
digit= n[i]%10;
...
is both confusing and unclear. Use same indentation for each separate block:
...
for(int i=0; i<size; i++){ // The base block
a= n[i]; // new block start, add indent
while( n[i]!=0){ // same block, same indent
digit= n[i]%10; // new block, add indent
...
Use better naming: Don't use S, a and n unless they are very clear.
digit is a good choice, so credits for that!
Here, it is better to use:
sum_of_special_numbers
and
array
and
current_number
instead of S, n and a.
Comment!: Another very important part of programming (Note: not coding).
Are you coding?
Don't care if anyone understands it or not, just doing it cause they said so.
Or programming?
Making a clear, maintainable and debuggable code.
You decide!
Since this question is tagged with C++, I want to give an additional answer that uses C++ and especially modern C++ algorithms. I added also comments to the code and used meaningful variable names. I recommend that you try to do the same in the future.
What is the example code doing?
First, it informs the user about the software and asks, how many values should be checked and added. The values will be stored in a std::vector. With std::copy_n and the std::istream_iterator we read the values given by the user. The std::istream_iterator simply calls the extractor operator >> in the copy loop.
Then we call the subfunction to calculate the sum and show it to the user.
The subfunction consists of one Lampda definition and one std::accumulate statement. That's all.
The lambda converts the int to a std::string and then checks if any of the characters in the number is lower than '5'. Then it returns an inverted result.
So, you see, with C++, the implementation get's very simple:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <numeric>
int sumOfNumbersWithDigitsGreaterThan5(const std::vector<int>& v) {
// Create a lambda that checks, if all digits are greater than 5
auto check5 = [](const int i) -> bool { std::string s{ std::to_string(i) };
return !std::any_of(s.begin(), s.end(), [](const char c) { return c <= '5'; }); };
// Calculate the sume of all given values in the vector with all digits greater than 5
return std::accumulate(v.begin(), v.end(), 0,
[&](const int init, const int i) { return init + (check5(i) ? i : 0); });
}
int main() {
// Inform the user, what to do
std::cout << "Sum of all numbers having all digits greater than 5\n\nHow many numbers to you want to sum?: ";
// Get the number of values that we want to sum up. Check plausibility
if (int numberOfValuesToCheck{}; (std::cin >> numberOfValuesToCheck) && (numberOfValuesToCheck > 0)) {
// Create a std::vector for our values having the requested number of elements
std::vector<int> values(numberOfValuesToCheck);
// Read the requested number of elements from std::cin to the values vector
std::copy_n(std::istream_iterator<int>(std::cin), numberOfValuesToCheck, values.begin());
// Show result
std::cout << "\n\nThe sum for all numbers with all digits greater 5 is: " <<
sumOfNumbersWithDigitsGreaterThan5(values) << "\n";
}
else {
std::cerr << "\n\n*** Error: Wrong input\n";
}
return 0;
}
Of course there are many many other possible solutions . . .

Did a competitive-like problem right but need help on improving its efficiency

The problem is simple. I'm given N - the number of digits in a number and then N digits of a number. I need to do exactly one digit-switch and get the highest number possible. I did do the problem right (as in gives out the right number) but it will be hitting the 1 second time restriction afaik. How do I improve on the efficiency of my program so it would go under the 1 second time restriction with N <= 10^6. New on Stack overflow so tell me if I did something wrong
with asking the question so I can fix it. Thanks. Here's my solution:
main:
int n;
cin >> n;
int a[n+1];
for(int i=0;i<n;++i)
cin >> a[i];
int maxofarray1;
bool changeHappened=false;
bool thereAreTwoSame=false;
for(int i=0;i<n;++i) //changing the two digits to make the highest number if possible
{
maxofarray1=maxofarray(a,i+1,n);
if(a[i]<maxofarray1)
{
int temp=a[a[n]];
a[a[n]]=a[i];
a[i]=temp;
changeHappened = true;
break;
}
}
for(int i=0;i<n;++i) //need to check if there are two of the same digit so I can change
//those two making the number the same instead of making it lower
for(int j=i+1;j<n;++j)
if(a[i]==a[j])
{
thereAreTwoSame=true;
break;
}
if(!changeHappened) //if the change has not been yet made, either leaving the number as is
//(changing two same numbers) or changing the last two to do as little "damage" to the number
{
if(!thereAreTwoSame)
{
int temp=a[n-1];
a[n-1]=a[n-2];
a[n-2]=temp;
}
}
for(int i=0;i<n;++i)
cout << a[i] << " ";
return 0;
maxofarray:
int maxofarray(int a[], int i,int n) //finding the maximum of the array from i to n
{
int max1=0;
int maxind;
for(int j=i;j<n;++j)
{
if(max1<a[j])
{
max1=a[j];
maxind=j;
}
}
a[n]=maxind; //can't return both the index and maximum (without complicating with structs)
//so I add it as the last element
return max1;
}
The problem in your code is complexity. I didn't fully understand your algorithm, but having nested loops is a red flag. Instead of trying to improve bits and pieces of your code you should rather rethink your overall strategy.
Lets start by assuming the digit 9 does appear in the number. Consider the number is
9...9 c ...9...
where 9...9 are the leading digits that are all 9 (possibly there are none of them). We cannot make the number bigger by swapping one of those.
c is the first digits !=9, ie its the place where we can put a 9 to get a bigger number. 9 is the digit that will make the number maximum when put in this place.
Last, ...9... denotes the last appearance of the digit 9 and digits sourrinding that. After that 9 no other 9 appears. While we increase the number by replacing c, the number will get smaller be replacing that 9, hence we have to choose the very last one.
For the general case only a tiny step more is needed. Here is a rough sketch:
std::array<size_t,10> first_non_appearance;
std::array<size_t,10> last_appearance;
size_t n;
std::cin >> n;
std::vector<int> number(n);
for (size_t i=0;i <n;++i) {
std::cin >> a[i];
for (int d=0;d<10;++d) {
// keep track of first and last appearance of each digit
}
}
size_t first = 0;
size_t second = 0;
for (int d=0;d<10;++d) {
// determine biggest digit that appeared and use that
}
std:swap( a[first],a[last] );
It is not complete, perhaps requires handling of special cases (eg number with only one digit), but I hope it helps.
PS: You are using a variable length array (int a[n+1];), this is not standard C++. In C++ you should rather use a std::vector when you know the size only at runtime (and a std::array when the size is known).
VLA (variable length arrays) are not standard. So instead of using this nonstandard feature, you might want to use a STL data type.
Given N is rather big, you also avoid stack overflow, given that VLA are allocated on the stack. And STL containers with variable length allocate on the heap.
Then, as you pointed out yourself, it makes sense to remember the index of the last occurrence of each digit, avoiding to search over and over again for a swap candidate index.
Your implementation idea is basically, to replace the first digit from the left, which has a bigger replacement to the right of it.
This is how I did it:
static void BigSwap(std::string& digits)
{
int64_t fromRight[10];
size_t ndigitsFound = 0;
for (size_t i = 0; i < 10; i++)
fromRight[i] = -1;
size_t i = digits.size() - 1;
while (ndigitsFound < 10 && i > 0)
{
if (-1 == fromRight[digits[i] - '0'])
{
fromRight[digits[i] - '0'] = static_cast<int64_t>(i);
ndigitsFound++;
}
i--;
}
for (size_t j = 0; j < digits.size(); j++)
{
char d = digits[j] - '0';
for (char k = 9; k > d; k--)
{
if (fromRight[k] != -1 && static_cast<size_t>(fromRight[k]) > j)
{
auto temp = digits[j];
digits[j] = k + '0';
digits[fromRight[k]] = temp;
return;
}
}
}
}

How do online judges pass the input data?

I'm trying to solve this problem from an online judge (Codeforces):
One day Deivis came across two Vectors of integers A and B, and wondered, could it be possible to form the number X by adding an element of A to another element of B?
More formally, it is possible to choose two indexes i and j such that Ai + Bj = x?
Input
The first entry line is two integers n and x. The second line contains n numbers, the vector A. The third and last line contains n numbers, vector B.
Output
Print 1 if it is possible to form the number x from a sum of one element of each vector, and 0 otherwise."
My problem is that I can not fill in the second vector, when the program runs on the site it fills the vector with zeros. I am using C ++, here's my code:
#include <bits/stdc++.h>
using namespace std;
#define MAX 10
int main()
{
int n, x, i = 0, j = 0, resp = 0, sum;
vector<int> vetA(MAX), vetB(MAX);
cin >> n >> x;
while (scanf("%d", &vetA[i]) == 1)
i++;
while (scanf("%d", &vetB[j]) == 1)
j++;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
sum = vetA[i] + vetB[j];
if (sum == x)
{
resp = 1;
goto END;
}
}
}
END: printf("%d", resp);
return 0;
}
I try to use getchar() after each while loop, but seems that on the site it does not do data capture like on a keyboard, and so the second vector isn't receiving any data. I've also tried to capture data as a std::string but that doesn't work.
Can someone help me?
Here are some hints/examples to compare your program to:
#include <iostream> //Include each standard library seperately
#include <vector> //#include <bits/stdc++.h> is bad practice
// Only declare variables as they are used.
int n; // Better coding practice is one variable per line.
int x; // Competitions shouldn't care how many lines.
if (!(std::cin >> n >> x)) //This is basically the same as cin.fail()
{
std::cerr << "Error inputting data.\n";
return 1;
}
// Now create the vectors, after the size has read in.
std::vector<int> vetA(n);
std::vector<int> vetB(n);
// The number of elements is known, so use a "for" loop.
for (size_t i = 0; i < n; ++i)
{
std::cin >> vetA[i];
}
for (size_t i = 0; i < x; ++i)
{
std::cin >> vetB[i];
}
You should add in some error handling because your program will be given some invalid inputs.
The inputs and vector sizes are examples since you didn't specify the input format in your Post.