Sorting string array with numbers C++ [duplicate] - c++

This question already has answers here:
Sorting std::strings with numbers in them?
(4 answers)
Closed 6 years ago.
I have problem solving this problem.
The task is simple at first line I enter how many examples I have.
On second line I need to enter how many numbers im going to read.
and then we enter all the numbers separate by space.
The task itselfs do , sorting the string array wtih numbers from smalles to the biggest one. After that if we have even numbers entered we print the middle number -1, if they are uneven we just print the middle number.
So far if I use the exact same code with long long it works perfectly , but it is limited only to 19 digit number and I want to expand the program so it can use bigger numbers.
Using that way the sort func , when I try to sort 16 elements from 160 to 10 , they all messed it start from 110 then in the midle is 160 and so one , which makes absolutly non sense, using 5 numbers or 8 works perfectly w/o any problem , using more numbers fails.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int examples;
cin >> examples;
for (size_t i = 0; i < examples; i++)
{
long long unsigned int n;
cin >> n;
string * numbers = new string[n];
for (size_t i = 0; i < n; i++)
{
cin >> numbers[i];
}
sort(numbers, numbers + n);
if (n % 2 == 0) {
cout << numbers[n / 2 - 1];
}
else
cout << numbers[n / 2];
}
system("pause");
return 0;
}

First, if you allocate memory with operator new, you must release it with operator delete[].
Second, when you sort strings instead of values, they are sorted just like strings would do, and here is where your problem lies. You see, 100 is alphabetically less than 2 or 20, that's why it would appear earlier.
Here's the output your program gives. Check this rule out, and you'll see that i'm right.
10 100 110 120 130 140 150 160 20 30 40 50 60 70 80 90
Third, using operator new is discouraged for pretty much anything. You have STL, and you seem to be using it extensively - why not vector?
Fourth, you don't check if anything we write into numbers[i] is actually a number. Think on that.
Fifth, for N being long enough(more than 2^sizeof(size_t)) your problem will NEVER stop due to integer overflow.
Sixth, you don't check for n == 0, and you will ultimately get memory access violation if you enter it.
A fast-right-off-the-bat fix for your problem:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main() {
int examples;
cin >> examples;
for (size_t i = 0; i < examples; i++)
{
size_t n;
cin >> n;
if (n <= 0)
break;
vector<string> numbers(n);
for (size_t i = 0; i < n; i++)
cin >> numbers[i];
//here we add a predicate for string checking,
//which evaluates the length of string
//before using the usual operator<.
sort(begin(numbers), end(numbers), [](const string& s1, const string& s2){
if (s1.length() < s2.length())
return true;
if (s2.length() < s1.length())
return false;
else
return (s1 < s2);
});
if (n % 2 == 0) {
cout << numbers[n / 2 - 1];
}
else
cout << numbers[n / 2];
}
system("pause");
return 0;
}
Still, it has a number of problems:
Checking if numbers[i] is actually a number
I'm not sure that
predicate I wrote doesn't have bugs - I'm just trying to give you
the idea of how it should work.

Related

Unable to have 100 factorial with C++ on output screen(displaying 0)

Well I am stuck on this problem for quite a while:
Question:
You are asked to calculate factorials of some small positive integers.
Input:
An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100.
Output:
For each integer n given at input, display a line with the value of n!
//coded in c++
#include <bits/stdc++.h> //loadind up all the libraries at once.
using namespace std;
int main()
{ int T;
scanf("%d", &T);
//I am not doing "cin<<" cause "scanf" is faster than it
for (int i = 0; i < T; i++)
{
int N;
scanf("%d",&N);
long long int product = 1;
while (N >0){
product = product * N;
N--;
}
printf("%lld\n",product);
}
return 0;
}
I am able to get 10!,20! but unable to get 100! (factorial)
so the extreme case doesn't satisfy. Please help me to get a good data type for my variable as 100! a factorial has over than 100 digits. It is displaying 0 when I input 100 on the terminal.
P.S - This problem is from CodeChef website (FCTRL2).
A 64bit integer will overflow with 23!
Therefore you need to do it with digits and a vector.
This is a rather simple task. We can do it like we would do it on a piece of paper. We use a std::vector of digits to hold the number. Because the result will be already too big for an unsigned long long for 23!.
The answer will be exact.
With such an approach the calculation is simple. I do not even know what to explain further.
Please see the code:
#include <iostream>
#include <vector>
int main()
{
std::cout << "Calculate n! Enter n (max 10000): ";
if (unsigned int input{}; (std::cin >> input) && (input <= 10000)) {
// Here we store the resulting number as single digits
std::vector<unsigned int> result(3000, 0); // Magic number. Is big enough for 100000!
result.back() = 1; // Start calculation with 1 (from right to left)
// Multiply up to the given input value
for (unsigned int count = 2; count <= input; count++)
{
unsigned int sum{}, remainder{};
unsigned int i = result.size() - 1; // Calculate from right to left
while (i > 0)
{
// Simple multiplication like on a piece of paper
sum = result[i] * count + remainder;
result[i--] = sum % 10;
remainder = sum / 10;
}
}
// Show output. Supporess leading zeroes
bool showZeros{ false };
for (const unsigned int i : result) {
if ((i != 0) || showZeros) {
std::cout << i;
showZeros = true;
}
}
}
else std::cerr << "\nError: Wrong input.";
}
Using a bigint library will be much faster.
Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.
Additionally compiled and tested with clang11.0 and gcc10.2
Language: C++17

Convert number in binary and print out as matrix (C++)

Before you read ahead or try to help, this question is regarding my homework so the requirements to this question will be very specific.
I am writing a code that takes a user input between 0 and 511 and converts it into a binary number. Then the program will replace all the 1's in the binary number with T and all the 0's in the number as H. Afterwards it will print out the results (the binary number with the H and T replacement) as a 3*3 matrix.
This is the desired output (not what I have but what I want):
Enter a number between 0 and 511: 299
The binary number is: 100101011
The matrix is:
THH
THT
HTT
The problem with my code is that I am unsure of how to replace an array that consists of all integers to have certain parts of the index to be either characters or strings. For sure the part with the binary number conversion works but the replacement of the 0's and 1's of the array is where the trouble is at. I am also unsure of how to print out the matrix result. I assume it goes either of 2 ways: 1. The program creates a new array for the previous array's elements stored and prints out the matrix array instead. 2. There is a way to only print the array 3 lines at a time. The only way I can think of is to somehow cut the for loop short and add a line break after every 3 values. I am aware that there are a few pointable errors in my code but I do not know how to fix them.
Although this is in the C++ language, what I have learned is the C style syntax (no std:: kinds of code or stuff like that because I haven't learned it yet and I will not understand it) So far I have learned basic arrays, loops, and functions.
#include <iostream>
using namespace std;
int main(){
int arr[10];
int input, i;
cout<<"Enter a number between 0 and 511: ";
cin>> input;
for(i = 0; input > 0; i++){
arr[i] = (input % 2);
input = input / 2;
}
cout<<"The binary number is: ";
for(i = i - 1; i >= 0; i--){
cout<<arr[i];
}
string newArr[10] = arr[10]; //the error here states that the array initializer must be an initializer list
for(int i = 0; i < sizeof(arr)/sizeof(arr[10]); i++){
if(arr[i] == 1){
arr[i] = "T"; //the error here mentions that a string/ character cannot be assigned with a integer array
}
else{
arr[i] = "H";
}
}
for(int i = 0; i < sizeof(arr)/sizeof(arr[10]); i++){
cout<<arr[i]<< " ";
}
}
This would be sufficient:
#include <iostream>
using namespace std;
int main()
{
// you never actually checked if the input is valid
// so you may or may not want this loop:
int input;
do
{
cout << "Enter a number between 0 and 511: ";
cin >> input;
} while ((input < 0) || (input > 511));
// space for matrix, new lines and null
// to construct a null terminated string
char buffer[3 * (3 + 1) + 1];
int i = 0;
// since the bits are read from left to right
// I will use a mask instead of bit shifting the input
int bit = 1 << 9;// 2^9 == 512
for (int r = 0; r < 3; r++)// rows
{
for (int c = 0; c < 3; c++)// columns
{
// this could come after the check
// and then bit would start at 256
bit >>= 1;
// perform the check and add the corresponding letter
buffer[i++] = (bit & input) ? 'T' : 'H';
}
// add new lines
buffer[i++] = '\n';
}
// if you don't want the last '\n'
// this could be { buffer[--i] = '\0'; }
buffer[i++] = '\0';
cout << buffer;
}

exited, segmentation fault

The input for this problem is a first number that indicates how many cases will be input to be analyzed.
Input:
3
8 12
9 27
259 111
The first number means that there will be 3 cases. The next 3 lines are the cases. The program has to output the GCD (Greatest Common Divisor) of the 3 cases.
4
9
37
The code I wrote looks like the following:
#include <iostream>
#include <vector>
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int main() {
int N;
std::cin >> N;
int i = 0;
std::vector<int> cards;
while (i <= N) {
i++;
int F1, F2;
std::cin >> F1 >> F2;
cards[i] = gcd(F1, F2);
}
for (int j; j <= N; i++) {
i++;
std::cout << cards[i] << "\n";
}
}
It reads the first integer (number of test cases), runs the loop once (reads one test case) and stops running. The terminal outputs exited, segmentation fault. What is the problem?
In your code there are some problem, first of all you haven't setted the size of the vector, that result like it has 0 lenght.
Another error are the loops;
In fact in the firts one you add 1 to i before you do all the other operation, and in this way you'll start to insert from te second component of the vector (vector start his indexing at 0).
Also in the second loop there are some problems, for example you declare a variable j that it is totally usless becouse in the folowing operations you still use i (that is setted at the end value of the previous loop, the while one).
Try to correct this things and understand it and in this way you'll understand also the reason of your error, that is pretty common in c++.
I hope that i've helped you a bit :)

how to store value from decimal to binary in such a way that it save value in 6 places in c++

i have to convert values from 1 to 63(decimal to binary) in such a way that it store in table in 6 place.
for instance, if i enter 2 it convert it into binary: 10 , but i want it to show it in 6-places like 000010. and store it in a table.
i am unable to find a code which convert decimal to binary and show 6 places..what should i do to do this...??
#include <iostream>
using namespace std;
int main()
{
int a[10], n, i;
cout<<"Enter the number to convert: ";
cin>>n;
for(i=0; n>0; i++)
{
a[i]=n%2;
n= n/2;
}
cout<<"Binary of the given number= ";
for(i=i-1 ;i>=0 ;i--)
{
cout<<a[i];
}
}
i tried this but i convert it into the specified bit like convert 2 in 10, and 3 in 11 same as for others, but i want to convert it into 3=000011.
So the one way to solve your problem is: First, initialize the array of 6 elements with zeros...
also you dont have to use an array of 10 as you mentioned clearly that numbers are 1 to 63
int a[6], n, i;
So you can just add this before your input1
for (i = 0; i < 6; i++) {
a[i] = 0;
}
Now the loop you had run doesn't make much sense to me as a programmer, although I know it is correct... because the condition is on n but increment is on i. So I'd change it like this
while (n > 0) {
a[i] = n % 2;
n = n / 2;
i++;
}
And change the i-1 to 5 (OR MAX_CAP - 1; where MAX_CAP is 6)
for(i=5 ;i>=0 ;i--)
{
cout<<a[i];
}
But According to me, you should use vectors instead of arrays to get rid of that initialization
vector<int> a(6,0);

TIME_LIMIT_EXCEEDED at Codeforces 558E

I am beginner in the programming field and I have started to solve problems on Codeforces and this is my first problem on it and when I submit this problem solution A Simple Task with this code
#include <iostream>
#include <string>
using namespace std;
void swapchar(char &x, char &y)
{
char temp;
temp = x;
x = y;
y = temp;
}
void main()
{
string s;
long n, q;
long i, j;
bool k;
cin >> n >> q;
cin >> s;
for (int x = 0; x<q; x++)
{
cin >> i >> j >> k;
if (i<1 || j<1 || i>n || j>n)
break;
if (k == 1)
{
for (int u = i - 1; u < j; u++)
{
for (int v = u + 1; v < j; v++)
{
if (s[u] > s[v])
swapchar(s[u], s[v]);
}
}
}
else if (k == 0)
for (int u = i - 1; u < j; u++)
{
for (int v = u + 1; v < j; v++)
{
if (s[u] < s[v])
swapchar(s[u], s[v]);
}
}
}
cout << s << endl;
}
then the codeforces' output is :-
Time limit exceeded on test 6
and when i searched about what it is the test 6 i found :-
Test: #6, time: 5000 ms., memory: 12 KB, exit code: -1, checker exit code: 0, verdict: TIME_LIMIT_EXCEEDED
Input
2256 44182
kanqevxwgecliptqmdsgnflqyohgtukphlbmjxndbtjqujuafxankfghlseytdwdviamqjscacuyrghriuaihxtyersgnyvigenpflwequgbdusnvlgplxjxkqhjbdvkmufpoirqueufblnnrnbhmcnvewzfdonwjgswuneimtykntwgrlfqlvkdblwjzplhffzqpopbjmvrjcxyzgxqhkjbrgdqnipsipexpoozphfrgzboiiiskawtbhegerhvknrzljclhnpokpazhspsmzeiujddlpfireoyjzriickcuwtbimxjbhunedcdgaabztczkzmahnriarzcmnkjrrfqkodxbpocmxjvutpqbmawcsghwxdidhmwbfxuqegpjtqfvaloycogvoxdtjotlknazaeofaxlomeywwlezlndhpjwbgpxgkvubropxffytucvlbhjugzqgglrezoqsrvwkdrbuehbjxtgobugghqrgbgacqi...
I don't know what does that problem mean and how to solve it
Please explain and help me.
You're using a selection sort (with a few superfluous swaps) that's O(n^2) complexity, try using std::sort instead. You don't have too much to change in your code:
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
string s;
long n, q;
long i, j;
bool k;
cin >> n >> q;
cin >> s;
for (int x = 0; x<q; x++)
{
cin >> i >> j >> k;
if (i<1 || j<1 || i>n || j>n)
break;
if (k == 1)
{
std::sort(s.begin() + i-1, s.begin() + j);
}
else if (k == 0)
std::sort(s.begin() + i-1, s.begin() + j, std::greater<char>());
}
cout << s << endl;
}
std::sort(s.begin() + i-1, s.begin() + j); sorts from s.begin() + i-1 up to but not includings.begin() + j. The second just sorts in reverse order by using > (std::greater) instead of < for comparison. Note the #include <algorithm> for the std::sort and #include <functional> for std::greater.
Note that I got rid of your swapchar function since we don't need it anymore, I also changed the return type of main to int as it's supposed to be.
The above code manages to handle the test 6 that you had problems with but exceeds time limit for test 9 (I even tried some small other changes there).
To complete tests 9+ you're probably supposed to think a bit more about the problem and possible input, take for example the following sort queries:
20 57 1
89 950 1
57 100 0
57 100 1
1 9500 0
Here we'd do tons of useless sorting and I wouldn't be surprised if the 9th problem were to test if you identified this. First we sort the range [20, 57] and [89, 950] in ascending order, then we sort the range [57, 100] in descending order and resorting the same range in ascending order right afterwards overriding the first one completely. Lastly we sort the range [1, 9500] in descending order, overwriting all the previous sorts which we could have completely left out since they're overwritten anyways.
We could make use of the knowledge that later sorts can and likely will override previous ones. We could first save all the "sort queries" we were given and later start with the last one (since that one would override all previous ones anyways) and go in reverse order only sorting the ranges we haven't sorted yet. That way we can get rid of lots of useless sorting that we'd otherwise do even though we'd later overwrite it and speeding it up a lot.