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);
Related
Basically, I have this function:
int countFreq(string pat, string txt)
{
int M = pat.length();
int N = txt.length();
int res = 0;
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (txt[i + j] != pat[j])
break;
if (j == M)
{
res++;
}
}
return res;
}
Which basically checks the number of times a pattern appears in a string. Now, the problem is that if the pattern is "121", and the string is "12121212", it will find 3 "121" substrings ("12121212" and the one in the middle), but I don't want it to do that, it shouldn't take in consideration the one in the middle, so it should only find 2 substrings, not 3.
How should I do something like that?
You can just make the index skip the length of the pattern (minus 1, because it automatically increments by 1) to skip the rest of the string and prevent additional matches.
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (txt[i + j] != pat[j])
break;
if (j == M)
{
res++;
i += M - 1; // Skip the rest of the string
}
}
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;
}
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.
Given a string, I want to print all the combinations, picking letters from left to right: Ex. Input: abcd
Output:
abc
acd
abd
bcd
ac
ad
bc
bd
cd
I can do it, but i cannot generalize it, for ex. in the string abcd, i can get all the mentioned combinations by deleting only one letter. Then I can do it also by deleting two letters and so on.
code:
name = "abcdefghi";
//Deleting 2 letters
for(int i = 1; i < name.size(); i++){
for(int k = 2; k < name.size(); k++){
for(int j = 0; j < name.size(); j++){ // PRINT ARRAY
if(j != i && j != k) cout << name[j];
}
cout << endl;
}
}
// Deleting 1 letter:
for(int i = 1; i < name.size(); i++){
for(int j = 0; j < name.size(); j++){ // PRINT ARRAY
if(j != i) cout << name[j];
}
cout << endl;
}
How can I generalize it so that I can first print the combination with 1 letter missing, then 2 letters missing, then 3, and so on...
Because if I keep going like this, to get all the combinations with the number of letters missing from 1 to n, I will need n number of for loops...
You can do it like this for example:
print_combinations(const string& name) {
if(name.size() > 1) {
for(int i = 0; i < name.size(); ++i) {
string name2 = name;
name2.erase(i, 1);
cout << name2;
}
for(int i = 0; i < name.size(); ++i) {
string name2 = name;
name2.erase(i, 1);
print_combinations(name2);
}
}
}
Currently, you can use a counter and use it as flag, something like:
void print_combinations(const std::string& s)
{
if (s.size() >= 32) {
return; // String too long
}
std::uint32_t end = 1u << s.size();
for (std::uint32_t i = 0; i != end; ++i)
{
auto j = i;
for (const auto c : s)
{
if ((j & 1) != 0) {
std::cout << c;
}
j >>= 1;
}
std::cout << std::endl;
}
}
Demo
I am trying to use radix sort to sort file contain social security and date of birth the format looks like this "###-##-####,#######.I have to apply radix sort on each fields according to command line switch. I have a radix sort that is work for int array and i am trying to modify the code for string type array but i am not sure how to accomplish this. I did a quick sort for string type by comparing strings and pivot and that is work fine however for radix sort I am not if I can do this with string type or I have to convert the string to integer. I have tried to use "atoi" to convert to integer but I am not sure how to correctly do this if I have to.
string getMax(string arr[], int n){
string max = arr[0];
for (int i = 1; i < n; i++){
if (arr[i]>max)
max = arr[i];
}
return max;
}
void countSort(string a[], int size, int k){
string *b = NULL; int *c = NULL;
b = new string[size];
c = new int[k];
for (int i = 0; i <k; i++){
c[i] = 0;
//cout << c[i] << "\n";
}
for (int j = 0; j <size; j++){
c[(a[j]/k)%10]++; //a[j] is a string
//cout << c[a[j]] << endl;
}
for (int f = 1; f <10; f++){
c[f] += c[f - 1];
}
for (int r = size - 1; r >= 0; r--){
b[c[(a[r] / k) % 10] - 1] = a[r];
c[(a[r] / k) % 10]--;
}
for (int l = 0; l < size; l++){
a[l] = b[l];
}
}
void radixSort(string b[], int r){
string max = getMax(b, r);
for (int digit = 1; max / digit > 0; digit *= 10){
countSort(b, r, digit);
}
};
I didn't try, but I think you can do radix sort for string.
Calculate the length of the longest string in the array to sort.
Do radix sort just like for integers. Do sorting using each characters in the string.
If a string is shorter than another and there is no character in the "digit", consider its value as -65536 (or a smaller value than any other characters).
UPDATE: I tested my idea and it seems working.
#include <cstdio>
#include <string>
using std::string;
size_t getMax(string arr[], int n){
size_t max = arr[0].size();
for (int i = 1; i < n; i++){
if (arr[i].size()>max)
max = arr[i].size();
}
return max;
}
void countSort(string a[], int size, size_t k){
string *b = NULL; int *c = NULL;
b = new string[size];
c = new int[257];
for (int i = 0; i <257; i++){
c[i] = 0;
//cout << c[i] << "\n";
}
for (int j = 0; j <size; j++){
c[k < a[j].size() ? (int)(unsigned char)a[j][k] + 1 : 0]++; //a[j] is a string
//cout << c[a[j]] << endl;
}
for (int f = 1; f <257; f++){
c[f] += c[f - 1];
}
for (int r = size - 1; r >= 0; r--){
b[c[k < a[r].size() ? (int)(unsigned char)a[r][k] + 1 : 0] - 1] = a[r];
c[k < a[r].size() ? (int)(unsigned char)a[r][k] + 1 : 0]--;
}
for (int l = 0; l < size; l++){
a[l] = b[l];
}
// avold memory leak
delete[] b;
delete[] c;
}
void radixSort(string b[], int r){
size_t max = getMax(b, r);
for (size_t digit = max; digit > 0; digit--){ // size_t is unsigned, so avoid using digit >= 0, which is always true
countSort(b, r, digit - 1);
}
}
int main(void) {
string data[] = {
"aaaba",
"dfjasdlifjai",
"jiifjeogiejogp",
"aabaaaa",
"gsgj",
"gerph",
"aaaaaaa",
"htjltjlrth",
"joasdjfisdjfdo",
"hthe",
"aaaaaba",
"jrykpjl",
"hkoptjltp",
"aaaaaa",
"lprrjt"
};
puts("before sorting:");
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
printf(" %s\n", data[i].c_str());
}
radixSort(data, (int)(sizeof(data) / sizeof(data[0])));
puts("after sorting:");
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
printf(" %s\n", data[i].c_str());
}
return 0;
}