Error with a vector when I did permutation - c++

I am trying to permutate my numbers in the vector.
Below are my codes. This code is very simple. Firstly, the input size of a vector is determined by user-input. And then, all the numbers in the vector are permutated in order to find the maximum integer value and minimum integer value when I concatenated all the numbers into one string.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
string retS(const vector<int>& v)
{
string s = "";
for (int e : v) {
s += to_string(e);
}
return s;
}
int main(void) {
int num = 0;
cin >> num;
vector<int> numbers;
for (int i = 0; i < num; ++i) {
int n;
cin >> n;
numbers.push_back(n);
}
sort(numbers.begin(), numbers.end());
unsigned long long maxVal = 0;
unsigned long long minVal = 987654321;
do {
string s = retS(numbers);
if (stoll(s) > maxVal) {
maxVal = stoi(s);
}
if (stoll(s) < minVal)
minVal = stoi(s);
} while (std::next_permutation(numbers.begin(), numbers.end()));
cout << maxVal+minVal << endl;
}
However, the problem is that the error occurred when I inputted two digit numbers. For example, I inputted 10 20 30 40 50 60 70 80 90 20 into my vectors, then my codes didn't work. I think it is because the range of integer variable because the concatenated string can be a size of 20(~up to 20) if I assume only one or two digit number can be accepted.
Therefore, I changed my integer variable into unsigned long long type from int, which is, i think, the longest range value for storing integer type, but, the program was aborted when I executed.
So, Can you help me to have this code work well?

As Zereges noted the problem here is that you are trying to store a number that exceeds the capacity of the biggest numeric variable type that C++ has built-in. You can solve this problem storing such long numbers as strings. This will solve the problem you have, but it will make your code a bit slower.
If you don't want to fight with strings more than necessary this could help you: https://mattmccutchen.net/bigint/ It's a library to work with big integers.
Hope this helps

Sorry, I have made a mistake in my post.
---The Begining of the Mistake---
Firstly, below statement perhaps may not function as you expect.
sort(numbers.begin(), numbers.end());
According to this, sort() sorts the elements in the range [first,last) into ascending order. In fact, there is the same problem for std::next_permutation().
There indeed is a difference between parentheses and square brackets. [ means >= while ) means <. According to your code, the last element would not be sorted.
---The End of the Mistake---
I have just discovered that end() does not return an iterator referring to the last element in the vector container, but the past-the-end element, which is the theoretical element that would follow the last element in the vector.
Moreover, I see you have declared two unsigned long long to hold the values.
unsigned long long maxVal = 0;
unsigned long long minVal = 987654321;
It seems that 987654321 is the upper limit of the value you would like to store. However, there are few potential problems in your code which may make the value's upper bound fails.
(1) The upper limit is not applied to maxVal.
if (stoll(s) > maxVal) { //may add a upper boundary for maxVal
maxVal = stoi(s);
}
(2) The functions of stoll() and stoi() returns a long long and an int respectively. In case, a number greater than the upper limit of long long and int is caught, the above 2 functions will throw std::out_of_range exception. This is a restriction in using the functions. It seems this was the run-time error you have encountered. In addition, though you have tried to declare unsigned long long to store the values, it does not release the restriction in using the 2 functions.
To fix it, you may try the suggestion from Carlos.
Below is a possible implementation of the suggestion from Carlos.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
string retS(const vector<int>& v)
{
string s = "";
for (int i = 0; i < v.size(); i++) {
s += to_string(v.at(i));
}
return s;
}
//prone to error
bool str1GreaterThanStr2(const string str1, const string str2)
{
if (str1.size() != str2.size())
return (str1.size() > str2.size());
int cursor = 0;
while (cursor < str1.size())
{
if (str1.at(cursor) != str2.at(cursor))
return (str1.at(cursor) > str2.at(cursor));
cursor++;
}
return false; //if both string are the same
}
int main(void) {
int num;
vector<int> numbers;
cin >> num;
for (int i = 0; i < num; ++i) {
int n;
cin >> n;
numbers.push_back(n);
}
sort(numbers.begin(), numbers.end());
string maxStr = retS(numbers);
string minStr = retS(numbers);
while (std::next_permutation(numbers.begin(), numbers.end()))
{
string str = retS(numbers);
maxStr = str1GreaterThanStr2(str, maxStr) ? str : maxStr;
minStr = str1GreaterThanStr2(str, minStr) ? minStr : str;
}
cout << maxStr << endl;
cout << minStr << endl;
}
/*
test case tried:
10
10 20 30 40 50 60 70 80 90 20
*/
Hope this helps.

Related

frequency of a digit in an integer in c++

I have been given some integers and I have to count the frequency of a specific digit in the number.
example input:
5
447474
228
6664
40
81
The first number says number of integers in the list. I am finding frequency of 4 in this case. I tried to change the integer to an array, but it is not working.
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
int main() {
int n;
cin>>n;
for (int i=0; i<n; i++)
{
int x;
cin>>x;
int frequency=0;
int t=log10(x);
int arr[t];
for (i=t; i>0; i--)
{
arr[i]=x%10;
x=x/10;
}
for(int i=0; i<t; i++)
{
if(arr[i]==4)
{
frequency++;
}
}
std::cout << frequency << std::endl;
}
return 0;
}
No need to create an array, or to determine the number of digits. Just loop until the number reaches zero.
int digitCount(int n, int d) {
if(n < 0) n = -n;
int count = 0;
for(; n != 0; n /= 10)
if(n % 10 == d) count++;
return count;
}
Test:
cout << digitCount(447474, 4) << endl;
cout << digitCount(-447474, 4) << endl;
Output:
4
4
Your code uses VLAs which are not standard C++. See Why aren't variable-length arrays part of the C++ standard?.
log10(x) is not the number of digits. For example log10(1234) == 3.09131516 but it is 4 digits. Also you are accessing the array out of bounds in the first iteration of the loop: arr[t]. Valid indices in an array of size t are 0,1,2,...,t-1. Trying to access arr[t] is undefined behavior.
Actually you dont need any array. Instead of storing the digits in an array you can immediately check whether it is a 4 and count.
Even simpler would be to read the user input as a std::string:
#include <string>
#include <algorithm>
#include <iostream>
int main() {
std::string input;
std::cin >> input;
std::cout << std::count(input.begin(),input.end(),'4');
}
Perhaps you should add some checks to verify that the user input is actually a valid number. However, also when reading an int you should validate the input.

The check with the module in the loop doesn`t work

There is a task. It is necessary in a one-dimensional array of N real numbers to calculate the number of the maximum modulo element among unpaired numbers.
I wrote the code, but it does not work. I can’t understand what’s wrong with him.
#include <iostream>
#include <math.h>
using namespace std;
int main() {
setlocale(0, "");
const int KolEl = 5;
int mas[KolEl];
int max = abs(mas[0]);
int result;
for (int i = 0; i < KolEl; i++)
{
cout << " Введите елемент[" << i << "] = ";
cin >> mas[i];
if (mas[i] % 2 == 1) {
if (abs(mas[i]) > max) {
result = i;
cout << result << endl;
}
}
}
system("pause");
}
You initialize max as:
int mas[KolEl];
int max = abs(mas[0]);
However, the values in mas[] are garbage values (read: undefined behavior). So now the value in max is also UB.
You then go on to use that value to compare to the input you take:
if (abs(mas[i]) > max) {
So the result of that comparison is undefined.
You probably meant to declare max as something like:
int max = INT_MIN;
So that the first comparison will always be true (every int except INT_MIN will be greater than it).

Printing an array in reverse

Task
You'll be given an array of N integers and you have to print the integers in the reverse order.
Constraints
1<=N<=1000
1<=A_i<=10000, where A_i is the ith integer in the array.
Input
4
1 2 3 4
Output
4 3 2 1
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int N, y; //declaring N as the length of array
cin >> N; //intakes the length as an input
if (N>=1 && N<=1000){ //checks whether the length satisfies the rules
int a[N]; // makes an array containing N elements
for (int x =1; x<N; x++){ //starts transcription on the array
cin>>y; //temporarily assigns the input on a variable
if (y>=1&&y<=10000){ //checks if the input meets rules
a[x]=y; //copies the variable on the array
}
}
for (int z = N; z>1; z--){ //runs a loop to print in reverse
cout<<a[z]<<endl;
}
}
return 0;
}
Problem
Obtained output is
-1249504352
3
2
Indicating an error in transcription.
Question
Can somebody please tell me where I am making a mistake? Secondly, is it possible to directly check whether an input is meeting requirement rather than temporarily declaring a variable for it?
Here is a solution in idiomatic c++11, using std::vector, which is a dynamically resizable container useful for applications like this.
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
int size;
std::cin >> size; // take in the length as an input
// check that the input satisfies the requirements,
// use the return code to indicate a problem
if (size < 1 || size > 1000) return 1;
std::vector<int> numbers; // initialise a vector to hold the 'array'
numbers.reserve(size); // reserve space for all the inputs
for (int i = 0; i < size; i++) {
int num;
std::cin >> num; // take in the next number as an input
if (num < 1 || num > 10000) return 1;
numbers.push_back(num);
}
std::reverse(numbers.begin(), numbers.end()); // reverse the vector
// print each number in the vector
for (auto &num : numbers) {
std::cout << num << "\n";
}
return 0;
}
A few things to note:
using namespace std is considered bad practice most of the time. Use (e.g.) std::cin instead for things which come from the std namespace.
numbers.reserve(size) is not necessary for correctness, but will make the program faster by reserving space in advance.
for ( auto &num : numbers ) uses a range-based for loop, available in c++11 and later versions.
You could make your for loop indices go from high to low:
for (int i = N-1; i > 0; --i)
{
std::cout << a[i] << "\n"; // Replace '\n' with space for horizontal printing.
}
std::cout << "\n";
This would apply with std::vector as well.
With std::vector, you can use a reverse iterator. There are other techniques available (as in other answers).

Having Trouble With A Simple C++ Program

I'm creating this very simple C++ program.
the program asks the user to enter a few integers and stores them in an array.but when a specific integer(for example 50)is entered,the input is ended and then,all of the integers are displayed on the screen except for 50.
for example:
input:
1
2
88
50
output:
1
2
88
the error i'm getting is when i use cout to print the array,all of numbers are shown,including 50 and numbers i did'nt even entered.
this is my code so far:
#include<iostream>
int main() {
int num[100];
for(int i=0;i<=100;i++) {
cin >> num[i];
if (num[i]!=50) break;
}
for(int j=0;j<=100;j++) {
cout << num[j] << endl;
}
return 0;
}
Change the program the following way
#include<iostream>
int main()
{
const size_t N = 100;
int num[N];
size_t n = 0;
int value;
while ( n < N && std::cin >> value && value != 50 ) num[n++] = value;
for ( size_t i = 0; i < n; i++ ) std::cout << num[i] << std::endl;
return 0;
}
Here in the first loop variable n is used to count the actual number of entered values. And then this variable is used as the upper bound for the second loop.
As for your program then the valid range of indices for the first loop is 0-99 and you have to output only whose elements of the array that were inputed.
A do while loop is more suitable for your problem. The stop condition will check if the number fit inside the array (if k is not bigger than 100) and if number entered is 50.
#include<iostream>
using namespace std;
int main() {
int num[100];
int k = 0;
// A do while loop will be more suitable
do{
cin >> num[k++];
}while(k<100&&num[k-1]!=50);
for (int j = 0; j < k-1; j++) {
cout << num[j] << endl;
}
return 0;
}
Also, a better solution to get rid of 100 limitation is to use std::vector data structure that automatically adjust it's size, like this:
vector<int> num;
int temp;
do {
cin >> temp;
num.push_back(temp);
} while (temp != 50);
Note, you can use temp.size() to get the number of items stored.
You read up to 101 numbers, but if you enter 50 you break the loop and go for printing it. In the printing loop you go through all 101 numbers, but you actually may have not set all of them.
In the first loop count in a count variable the numbers you read until you meet 50 and in the printing loop just iterate count-1 times.
You have allocated an array of 100 integers on the stack. The values are not initialized to zero by default, so you end up having whatever was on the stack previously appear in your array.
You have also off-by-one in both of your loops, you allocated array of 100 integers so that means index range of 0-99.
As the question is tagged as C++, I would suggest that you leave the C-style array and instead use a std::vector to store the values. This makes it more flexible as you don't have to specify a fixed size (or manage memory) and you don't end up with uninitialized values.
Little example code (requires C++11 compiler):
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers; // Store the numbers here
for(int i = 0; i < 100; ++i) // Ask a number 100 times
{
int n;
std::cin >> n;
if( n == 50 ) // Stop if user enters 50
break;
numbers.push_back(n); // Add the number to the numbers vector
}
for (auto n : numbers) // Print all the values in the numbers vector
std::cout << n << std::endl;
return 0;
}
There are just 2 changes in your code check it out :
int main()
{
int num[100],i; //initialize i outside scope to count number of inputs
for(i=0;i<100;i++) {
cin >> num[i];
if (num[i]==50) break; //break if the entered number is 50
}
for(int j=0;j<=i-1;j++)
{
cout << num[j] << endl;
}
return 0;
}
Okay, others already pointed out the two mistakes. You should use i < 100 in the loop conditions instead of i <= 100 and you have to keep track of how many elements you entered.
Now let me add an answer how I think it would be better.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; // a temp variable in the for loop.
numbers.size() < 100 && // check that we have less than 100 elements.
std::cin >> temp && // read in the temp variable,
// and check if the read was a success.
temp != 50) // lastly check that the value we read isn't 50.
{
numbers.push_back(temp); // Now we just add it to the vector.
}
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i]; // Now we just print all the elements of
// the vector. We only added correct items.
}
The above code doesn't even read anymore numbers after it found 50. And if you want to be able to enter any number of elements you just have to remove the check that we have less than 100 elements.
Now I commented the above code a bit much, if you compress it it'll reduce to just:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i];
}
If you can use the C++11 standard it reduces to:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int element : numbers)
std::cout << element;
}
for (auto element : numbers) is new, it basically means for every int 'element' in 'numbers'.

Project euler #8 in C++ getting wrong answer that is somewhat maximum uint_64 value

Here's a link to the problem I'm trying to solve: https://projecteuler.net/problem=8.
I've written a code that seems to work well while I'm calculating a product of anything from 1 to 12 (included) consecutive digits. For example the biggest product of 12 adjacent digits I get is 1792336896, which seems logical as it's less than 9^12.
However, when I put 13 instead of 12 in my code, the answer I get is 18446744073195294960 which is way out of proportion. I've been looking at this a couple of days now, and I just can't see where I went wrong. I would really appreciate if anyone could look into it.
Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
int numbers[1000];
string line;
string numb;
uint64_t product=0;
void convert(){
for (int i = 0 ; i < numb.length() ; i++)
{
numbers[i] = numb[i] - '0';
}
}
void calculate_lines(){
int digits = 13;
for (int i=0;i<numb.length()-digits;i++){
int temp=1;
for (int j=i;j<digits+i;j++){
if (numbers[j] == 0){
i+=digits;
break;
}
temp=temp*numbers[j];
}
if (temp>=product){
product=temp;
}
}
}
void read_lines(){
ifstream infile;
infile.open("numbers.txt");
if (infile.is_open())
{
while (getline(infile,line))
{
numb+=line;
}
infile.close();
}
}
int main()
{
read_lines();
convert();
calculate_lines();
cout << product << endl;
return 0;
}
You calculate the product with the variable int temp. This isn't large enough to contain a product of 13 digits, so it overflows. It becomes a negative value, which later becomes a very large positive value when converted to uint64_t.
While the variable that holds the final result product is a uint64_t, you need to make sure that intermediate values are stored in large enough variables. You need temp to be uint64_t as well.