I was solving a problem of the array in which I have to do a left rotation of an array. wrote the code and submit successfully some test cases passed in some it showing abort called I don't know whats the problem. I googled it shows it's due to storage becomes full. what if I declare my temp array in heap. would it make any difference? forgive me for my indentation.
#include <bits/stdc++.h>
using namespace std;
string ltrim(const string &);
string rtrim(const string &);
vector<string> split(const string &);
vector<int> rotateLeft(int d, vector<int> arr) {
vector<int> temp(d);
for (int i = 0; i < d; i++) {
temp[i] = arr[i];
}
for (int i = 0; i < arr.size(); i++) {
arr[i] = arr[d + i];
}
for (int i = 0; i < arr.size(); i++) {
arr[arr.size() - d + i] = temp[i];
}
return arr;
}
int main() {
ofstream fout(getenv("OUTPUT_PATH"));
string first_multiple_input_temp;
getline(cin, first_multiple_input_temp);
vector<string> first_multiple_input = split(rtrim(first_multiple_input_temp));
int n = stoi(first_multiple_input[0]);
int d = stoi(first_multiple_input[1]);
string arr_temp_temp;
getline(cin, arr_temp_temp);
vector<string> arr_temp = split(rtrim(arr_temp_temp));
vector<int> arr(n);
for (int i = 0; i < n; i++) {
int arr_item = stoi(arr_temp[i]);
arr[i] = arr_item;
}
vector<int> result = rotateLeft(d, arr);
for (int i = 0; i < result.size(); i++) {
fout << result[i];
if (i != result.size() - 1) {
fout << " ";
}
}
fout << "\n";
fout.close();
return 0;
}
string ltrim(const string & str) {
string s(str);
s.erase(s.begin(), find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace))));
return s;
}
string rtrim(const string & str) {
string s(str);
s.erase(find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(), s.end());
return s;
}
vector<string> split(const string & str) {
vector<string> tokens;
string::size_type start = 0;
string::size_type end = 0;
while ((end = str.find(" ", start)) != string::npos) {
tokens.push_back(str.substr(start, end - start));
start = end + 1;
}
tokens.push_back(str.substr(start));
return tokens;
}
The problem is in your 3 loops:
for (int i = 0; i < d; i++) {
temp[i] = arr[i];
}
for (int i = 0; i < arr.size(); i++) {
arr[i] = arr[d + i];
}
for (int i = 0; i < arr.size(); i++) {
arr[arr.size() - d + i] = temp[i];
}
first loop will crash if d > n. It can be the case that your task may have d > n sometimes.
Second loop should crash always when d > 0, because arr[d + i] is out of bounds if d + i >= arr.size() which will always happen because loop is until i < arr.size().
Third loop will also always crash because out of bounds. For example if d == 1 and i == arr.size() - 1 then you get arr[arr.size() - 1 + arr.size() - 1] which is out of bounds.
Also you have to watch if d > n in some tests, then you have to make d %= n;.
Also just a notice - inputs of most HackerRank problems can be read using just things like int i = 0; std::cin >> i; and loops. No need for strings operations like stoi/ltrim/rtrim/split. For example to read array of n numbers,
provided as one or several lines of input, you can do:
std::vector<int> nums;
for (size_t i = 0; i < n; ++i) {
int i = 0;
std::cin >> i;
nums.push_back(i);
}
You can use just standard std::rotate to rotate array left.
One interesting way to solve the problem in O(N) time and O(1) extra memory without std::rotate and std::reverse functions and without temporary storage is to reverse order of first d elements, then reverse order of last n - d elements, then reverse whole array. Of cause usually you just use std helpers, but sometimes you want to implement algorithms from scratch. I.e. something like following:
void reverse(int * begin, int * end) {
--end;
while (begin < end)
std::swap(*begin++, *end--);
}
void rotate(int * begin, int * end, int d) {
d %= (end - begin);
reverse(begin, begin + d);
reverse(begin + d, end);
reverse(begin, end);
}
The shortest way to fix your algorithm (it takes O(N) time and O(N) extra memory) to make it work is:
vector<int> rotateLeft(int d, vector<int> arr) {
d %= arr.size();
vector<int> temp(d);
for (int i = 0; i < d; i++) {
temp[i] = arr[i];
}
for (int i = 0; i < arr.size() - d; i++) {
arr[i] = arr[d + i];
}
for (int i = 0; i < d; i++) {
arr[arr.size() - d + i] = temp[i];
}
return arr;
}
Related
I am trying to print all substring of string but this function not printing all substring can you explain whats wrong?
require o/p= >
a
ab
abc
b
bc
c
curr o/p=>
a
ab
abc
b
void subString(string s, int n)
{
for (int i = 0; i < n; i++) {
for (int len = 1; len <= n - i; len++) {
string str;
for (int k = i; k < len; k++) {
str += s[k];
}
if (str != "")
cout << str << endl;
}
}
}
k is initialized with i (trying to use index in overall string), but the loop condition is compared to len (trying to use index in current substring). This is contradiction. Use either one index.
Use index in overall string:
for (int k = i; k < i + len; k++) {
str += s[k];
}
Use index in current substring:
for (int k = 0; k < len; k++) {
str += s[i + k];
}
Another way is to use the standard substr() (assuming string here is std::string):
str = s.substr(i, len);
i have a file that each line of it have a row of matrix and in each row, double numbers placed with space between them, this file include a lot of these matrices with a empty line between them
now i have two different versions of code:
1- single thread read from file with getline(file, readLine) and directly process readLine, split it and use stod to make double numbers and make matrix
#include <fstream>
#include <string>
using namespace std;
void decomposeSerial(double *A, long n)
{
long i, j, k;
for (k = 0; k < n; k++) {
for (j = k + 1; j < n; j++)
A[k*n + j] = A[k*n + j] / A[k*n + k];
for (i = k + 1; i < n; i++)
for (j = k + 1; j < n; j++)
A[i*n + j] = A[i*n + j] - A[i*n + k] * A[k*n + j];
}
}
void main() {
const string inFilePath = ".\\data_in\\file.txt";
const string outFilePath = ".\\data_out\\file.txt";
ifstream inFile(inFilePath);
ofstream outFile(outFilePath);
int n;
int matrixLine = 0;
double * matrix = NULL;
string readLine;
while (getline(inFile, readLine)) {
if (!readLine.empty()) {
if (matrixLine == 0) {
n = 0;
string temp = readLine;
size_t pos = 0;
while ((pos = temp.find(" ")) != string::npos) {
temp.erase(0, pos + 1);
n++;
}
matrix = (double *)malloc(sizeof(double) * n * n);
}
size_t pos = 0;
string token;
int i = 0;
while ((pos = readLine.find(" ")) != string::npos) {
token = readLine.substr(0, pos);
matrix[matrixLine * n + i] = stod(token);
readLine.erase(0, pos + 1);
i++;
}
matrixLine++;
if (matrixLine == n) {
decomposeSerial(matrix, n);
double det = 1;
for (long o = 0; o < n; o++) {
det *= matrix[o * n + o];
}
outFile << det << "\n";
}
}
else {
matrixLine = 0;
}
}
inFile.close();
outFile.close();
}
http://codeshare.io/5enk9x
2- single thread read from file with getline(file, readLine) and append readLine to an element of a string array dedicated for this matrix, and after this, in parallel, each thread get one of these elements and go through the same process to make matrix
#include <fstream>
#include <string>
#include <omp.h>
using namespace std;
double det[1000];
string input[1000];
int ns[1000];
void computation(double* src, int n, int l)
{
long i, j, k;
for (k = 0; k < n; k++) {
for (j = k + 1; j < n; j++)
src[k*n + j] = src[k*n + j] / src[k*n + k];
for (i = k + 1; i < n; i++)
for (j = k + 1; j < n; j++)
src[i*n + j] = src[i*n + j] - src[i*n + k] * src[k*n + j];
}
double res = 1;
for (int j = 0; j < n; j++) {
res *= src[j*n + j];
}
det[l] = res;
}
void main() {
const string inFilePath = ".\\data_in\\file.txt";
const string outFilePath = ".\\data_out\\file.txt";
ifstream inFile(inFilePath);
int matrixCount = 0;
bool inMatrix = false;
string readLine;
int dim = 0;
while (getline(inFile, readLine)) {
dim++;
if (readLine.empty()) {
ns[matrixCount] = dim - 1;
dim = 0;
inMatrix = false;
matrixCount++;
}
else {
if (inMatrix == false) {
inMatrix = true;
input[matrixCount] = readLine;
}
else {
input[matrixCount] += readLine;
}
}
}
ns[matrixCount] = dim;
matrixCount++;
inFile.close();
#pragma omp parallel
{
#pragma omp for schedule(dynamic)
for (int i = 0; i < matrixCount; i++) {
string matrixStr = input[i];
int n = ns[i];
double * matrix = (double *)malloc(sizeof(double) * n * n);
size_t pos = 0;
string token;
int k = 0;
while ((pos = matrixStr.find(" ")) != string::npos) {
token = matrixStr.substr(0, pos);
matrix[k] = stod(token);
matrixStr.erase(0, pos + 1);
k++;
}
computation(matrix, n, i);
free(matrix);
}
}
ofstream outFile(outFilePath);
for (int i = 0; i < matrixCount; i++) {
outFile << det[i] << "\n";
}
outFile.close();
}
http://codeshare.io/ad83Yy
but incredibly, second code work much much slower to make matrices
when i print readLine what comes from getline func with printf("%s", readLine) it prints weird chars, anyway i got that when i append readLine to string array element, these weired chars change on the console and i guess that's why i get slower performance as functions line str.find(" ") or stod(str) work better with first weird ones comparing to second ones
if you think the same, you may suggest a way to prevent char changing in appending
These kinds of performance issues can't be reasoned. You need to use a profiler and measure which parts of the code take up how much time.
To start with I would make both codes more similar. There are a lot of differences that could confuse the issue (for once version 1 has a giant memory leak).
I'm currently trying to read from a .txt file into a string array and then use a bubble sort to sort them alphabetically though when I actually run my code it gives the reverse of my array as seen below:
bool swapped = true;
int j = 0;
string tmp;
while (swapped)
{
swapped = false;
j++;
for (int i = 0; i < n - j; i++)
{
if (arr[i].compare(arr[i + 1]));
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
for (int i = 0; i < n; i++)
{
cout <<arr[i + 1];
}
This is the code for the bubble sort.
ifstream file("titles.txt");
string myArray[6];
for (int i = 0; i < 6; i++)
{
file >> myArray[i];
//cout << myArray[i];
}
sortStrings(myArray, 6);
and this is the code for the reading of the .txt file.
the file contains the letters b c a d e f in this order
though the output i receive is edabc.
Any help would be appreciated.
I fixed a few problems and this should work:
bool swapped = true;
string tmp;
int j = 0;
while (swapped)
{
swapped = false;
++j;
for (int i = 0; i < n - j; i++)
{
// 1. Your original code has a comma in the following line which terminates the if statement
// 2. compare function returns signed integer indicating the relationship
// between two strings, and > 0 value indicates previous string is greater:
// http://www.cplusplus.com/reference/string/string/compare/
if (arr[i].compare(arr[i + 1]) > 0)
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
for (int i = 0; i < n; i++)
{
cout <<arr[i] << endl;
}
Semicolon at the end of an if statement works as if the condition is always true.
The following snippets are identical
if (cond);
{
// ...
}
if (cond) { }
// ...
Take a look std::string's compare method:
Return value
negative value if *this appears before the character sequence specified by the arguments, in lexicographical order
zero if both character sequences compare equivalent
positive value if *this appears after the character sequence specified by the arguments, in lexicographical order
Thus, you should rather check if the value greater than zero in order to sort in ascending order. There is also operator > for std::string, that wouldn't result in the error you encountered.
Summary (formatting applied):
#include <fstream>
#include <iostream>
using namespace std;
void sortStrings(string* arr, int n) {
bool swapped = true;
int j = 0;
string tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < n - j; i++) {
if (arr[i].compare(arr[i + 1]) > 0) {
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
}
int main() {
ifstream file("titles.txt");
string myArray[6];
for (int i = 0; i < 6; i++) {
file >> myArray[i];
}
sortStrings(myArray, 6);
for (int i = 0; i < 6; i++) {
cout << myArray[i] << ' ';
}
}
We can define the term 'value of a name' as the average position of
the letters in the name, calculating 'A' as 1, 'B' as 2, 'C' as 3, and
so on. The value of "BOB" would be (2 + 15 + 2)/ 3 = 6. According to
this value, the names will be arranged from the smallest towards the
biggest in the output. When two or more names have the same value,
the name which is in the first position in the original list (the
first one the user inputs) should show up first in the sorted list
(the output).
Input In the first line we have an integer N (1 <= N <= 100), which is
the number of names. In every of the N lines we have one name ([A-Z],
no empty spaces). Names contain 1 - 200 letters.
Output Print out the sorted list (one name in a line).
Test-case
Input: 3 BOB AAAAAAA TOM Output: AAAAAAA BOB TOM
I tried something, and the code seemed to work, I just had a problem with the output. I couldn't find a way to arrange the names with the same value, according to their position in the original list. Here's the other test-case I tried, but didn't figure out:
Input:
10
COSOPYILSPKNKZSTUZVMEERQDL
RRPPNG
PQUPOGTJETGXDQDEMGPNMJEBI
TQJZMOLQ
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
YNWEPZKNBOOXNZVWKIUS
LV
CJDFYDMYZVOEW
TMHEJLIDEHT
KGTGFIFWYTKPWTYQQPGKRRYFXN
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
My output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
CJDFYDMYZVOEW // these two
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM // should be arranged with their places switched
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
#include <iostream>
#include <string>
using namespace std;
int main() {
int N;
cin >> N;
string words[N];
int res[N];
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> words[i];
word = words[i];
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res[i] = value;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
for (int i = 0; i < N; i++) {
cout << words[i] << endl;
}
return 0;
}
string words[N];
int res[N];
This here is not valid C++, you can not size a stack array using a runtime variable, although some compilers might support such a feature. You might use say std::vector instead, which behaves much like an array.
vector<string> words;
vector<int> res;
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> word;
words.push_back(word);
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res.push_back(value);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
The ordering is because your sorting algorithm is not stable. Stable means that items with equal values will maintain the same order relative to each other.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
What you have is very close to bubble sort, which is stable.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N - i - 1; j++) { // i elements sorted so far
if (res[j] > res[j + 1]) {
swap(res[j], res[j + 1]);
swap(words[j], words[j + 1]);
}
}
}
C++ also provides a stable sort in <algorithm>, but it can't function directly on two arrays like this unfortunately, one option is to compute the value on the fly, another could be to make a class holding both items and sort that, or another to sort the indices.
std::stable_sort(words.begin(), words.end(), [&](auto &a, auto &b)
{
int suma = 0, sumb = 0; // better yet, make a "int value(const string &str)" function.
for (int j = 0; j < a.length(); j++) {
suma += (int)a[j] - 64;
}
for (int j = 0; j < b.length(); j++) {
sumb += (int)b[j] - 64;
}
int valuea = suma / a.length();
int valueb = sumb / b.length();
return valuea < valueb;
});
A class containing both items is pretty straight forward, for indices, make a 3rd array and sort that.
vector<size_t> indices;
...
string word;
cin >> word;
indices.push_back(words.size());
words.push_back(word);
...
std::stable_sort(indices.begin(), indices.end(), [&](auto a, auto b){ return res[a] < res[n]; });
for (int i = 0; i < N; i++) {
cout << words[indices[i]] << endl;
}
A possible solution could be order the result array during construction.
When you add the words in the result array, use the result obtained to add the word in the right place. In this way you can check if exist already the same value and add the new word after the previous with the same value.
After reading the next word use insertion sort (wiki) which is stable
read word
calculate value
insert in a right place in the array
go to 1 until i < N otherwise print out
Doesn't require additional sorting procedure.
in python:
def sort_list(list1, list2):
zipped_pairs = zip(list2, list1)
z = [x for _, x in sorted(zipped_pairs)]
return z
times = int(input())
entries = []
ordered = []
for x in range(times):
entries.append(input())
for x in entries:
chars = []
for y in x:
chars.append(ord(y) - 96)
ordered.append(sum(chars))
print(sort_list(entries,ordered))
If you use a std::multimap<int, std::string>, there would be no need to sort, as the key would already serve as the sorting criteria.
Here is a solution using std::multimap:
#include <string>
#include <numeric>
#include <iostream>
#include <sstream>
#include <map>
// Test data
std::string test = "10\n"
"COSOPYILSPKNKZSTUZVMEERQDL\n"
"RRPPNG\n"
"PQUPOGTJETGXDQDEMGPNMJEBI\n"
"TQJZMOLQ\n"
"BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM\n"
"YNWEPZKNBOOXNZVWKIUS\n"
"LV\n"
"CJDFYDMYZVOEW\n"
"TMHEJLIDEHT\n"
"KGTGFIFWYTKPWTYQQPGKRRYFXN\n";
int main()
{
std::istringstream strm(test);
// Read in the data
std::multimap<int, std::string> strmap;
int N;
strm >> N;
std::string word;
for (int i = 0; i < N; ++i)
{
strm >> word;
// get the average using std::accumulate and divide by the length of the word
int avg = std::accumulate(word.begin(), word.end(), 0,
[&](int total, char val) { return total + val - 'A' + 1; }) / word.length();
// insert this value in the map
strmap.insert({ avg, word });
}
// output results
for (auto& w : strmap)
std::cout << w.second << "\n";
}
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
The std::accumulate is used to add up the values to get the average.
Or just order them in the end (You won't need the 2nd array):
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int sumA = 0, sumB = 0;
for (int k = 0; k < words[i].size(); k++)
sumA += words[i][k] - 'A' + 1;
for (int k = 0; k < words[j].size(); k++)
sumB += words[j][k] - 'A' + 1;
if (sumA / words[i].size() > sumB / words[j].size())
swap(words[i], words[j]);
}
}
As they shown above, it's way better to use a vector to store your data.
I want to create a function that returns a structure, then run a loop for that function. The idea is basically to calculate the maximum sum, start point and end point of a set of n numbers (1000 in this case) and this for 10 lines in a text file
struct triple
{
float Max;
int sp;
int ep;
};
triple Max_line(string linename, int n)
{
int k, i, stp, enp, j;
triple Result;
float Maxi;
float T[n];
string s;
stringstream ss(linename);
j = 0;
Maxi = 0;
stp = 0;
enp = 0;
while (getline(ss, s, ',')and k < n)
{
T[j] = atof(s.c_str());
j++;
}
for (i = 0; i < n - 1; i++)
{
int k;
float S;
S = T[i];
k = i;
while (k < n - 1)
{
S = S + T[k + 1];
if (S > Maxi)
{
Maxi = S;
stp = i + 1;
enp = k + 2;
}
k++;
}
}
Result = { Maxi, stp, enp }
return Result;
}
int main(int argc, char *argv[]) {
int i, j;
triple fin;
fstream myfile("1000.txt"); //extract data from a file containing 10 lines each has 1000 different numbers
string a, b;
getline(myfile, a); //skip the first line
for (i = 0; i < 10; i++)
{
getline(myfile, b);
fin = Max_line(b, 1000);
cout << fin.Max << ";" << fin.sp << ";" << fin.ep << endl;
}
return 0;
}
When I printed the results inside the Max_line function it gave me the right values, I don't understand why it's not working inside the for loop.
Can anyone help me with that please?