Let a and b be given positive integers . Consider the following C++17 code :
string* first;
first = new string[a];
//some definitions
string* second;
second = new string[b];
//some definitions
By saying a string first[i] is undefined, I mean no definition is ever made to the string first[i] after the creation code given above.
I define first and second to be equal if:
a==b.
first[i] and second[i] are equivalent for every non-negative integer i<a, in the following sense: if first[i] is undefined, then so is second[i]; if first[i] has length l (where l is a non-negative integer), then second[i] has length l and first[i][j] is the same char as second[i][j] for every non-negative integer j<l.
In short, I want the most ordinary string equality with the emphasis on comparing the contents rather than the pointers. What is the most appropriate way to do this in C++17? I tried multiple answers and none of them works.
I'm assuming string is std::string.
The real solution here would be to use std::vector<std::string> rather than managing your own dynamic memory:
std::vector<std::string> first;
//some definitions
std::vector<std::string> second;
//some definitions
bool equal = (first == second); // does what you want
If, for some reason, you cannot use std::vector, the C-style approach would look something like
bool are_equal(std::string* first, std::size_t first_size, std::string* second, std::size_t second_size) {
if (first_size != second_size) return false;
for (std::size_t idx = 0; idx != first_size; ++idx) {
if (first[idx] != second[idx]) return false;
}
return true;
}
int main() {
string* first = new string[a];
//some definitions
string* second = new string[b];
//some definitions
bool equal = are_equal(first, a, second, b);
return 0;
}
With C++20, prefer using std::span here
bool are_equal(std::span<const std::string> first, std::span<const std::string> second) {
if (first.size() != second.size()) return false;
for (std::size_t idx = 0; idx != first.size(); ++idx) {
if (first[idx] != second[idx]) return false;
}
return true;
}
int main() {
string* first = new string[a];
//some definitions
string* second = new string[b];
//some definitions
bool equal = are_equal({first, a}, {second, b});
return 0;
}
Related
It is a leet code problem under the subcategory of string, medium problem.
Query: My program is returning right result for all the test cases at the run time and but when I submit, same test cases are not passing.
I also made a video, click here to watch.
My Code is:
string convert(string s, int numRows) {
int loc_rows = numRows-2;
int i=0;
int a=0,b=0;
int arr[1000][1000];
while(i<s.length())
{
if(a<numRows)
{
arr[a][b] = s[i];
a++;
i++;
}
else if(a>=numRows)
{
if(loc_rows>=1)
{
b++;
arr[loc_rows][b]=s[i];
i++;
loc_rows--;
}
else{
loc_rows=numRows-2;
b++;
a=0;
}
}
}
string result="";
for(int d=0;d<numRows;d++)
{
for(int y=0;y<b+1;y++)
{
char temp = (char)arr[d][y];
if((temp>='a' and temp<='z') or (temp>='A' and temp<='Z') )
result+=temp;
}
}
return result;
}
I believe the issue might be your un-initialised arrays / variables.
Try setting initialising your array: int arr[1000][1000] = {0};
live example failing: https://godbolt.org/z/dxf13P
live example passing: https://godbolt.org/z/8vYEv6
You can't rely on the data that is in these arrays so initialising the values is quite important.
Note: this is because you rely on the empty values in the array to be not a letter ([a-zA-Z]). So that you can re-construct your output with your final loop which attempts to print the characters only. This works the first time around because luckily arr contains 0's in the gaps between your values (or at least not letters). The second time around it contains some junk from the first time around (really - you don't know what this is going to be, but in practise it is probably just the values you left in there from last time). So even though you put in the correct values into arr each time - your final loop finds some of the old non-alpha values in the array - hence your program is incorrect...
Alternatively, we could also use unsigned int to make it just a bit more efficient:
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <vector>
#include <string>
static const struct Solution {
using ValueType = std::uint_fast16_t;
static const std::string convert(
const std::string s,
const int num_rows
) {
if (num_rows == 1) {
return s;
}
std::vector<std::string> res(num_rows);
ValueType row = 0;
ValueType direction = -1;
for (ValueType index = 0; index < std::size(s); ++index) {
if (!(index % (num_rows - 1))) {
direction *= -1;
}
res[row].push_back(s[index]);
row += direction;
}
std::string converted;
for (const auto& str : res) {
converted += str;
}
return converted;
}
};
Description:
My program crash sometimes in std::sort(), I write a minimal program to reproduce this situation, but everything is just alright. Here is the minimal example:
typedef struct st {
int it;
char ch;
char charr[100];
vector<string *> *vs;
} st;
bool function(st *&s1, st *&s2) {
static int i = 1;
cout<<i<<" "<<&s1<<" "<<&s2<<endl;
++i;
return s1->it > s2->it;
}
int main(int argc, char **argv) {
vector<st *> ar;
for (int i = 0; i < 100; ++i) {
st *s = new st;
s->it = urandom32();
ar.push_back(s);
}
ar.clear();
for (int i = 0; i < 100; ++i) {
st *s = new st;
s->it = urandom32();
ar.push_back(s);
}
sort(ar.begin(), ar.end(), function);
return 0;
}
Here is the GDB stack info:
0 0x00007f24244d9602 in article_cmp (cand_article_1=0x7f23fd297010, cand_article_2=0x4015)
at src/recom_frame_worker.h:47
1 0x00007f24244fc41b in std::__unguarded_partition<__gnu_cxx::__normal_iterator > >,
cand_article*, bool ()(cand_article, cand_article*)> (__first=,
__last=, __pivot=#0x7f230412b350: 0x7f23fd297010,
__comp=0x7f24244d95e1 )
at /usr/include/c++/4.8.3/bits/stl_algo.h:2266
2 0x00007f24244f829c in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator > >, bool
()(cand_article, cand_article*)> (__first=, __last=,
__comp=0x7f24244d95e1 )
at /usr/include/c++/4.8.3/bits/stl_algo.h:2296
3 0x00007f24244f1d88 in std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long,
bool ()(cand_article, cand_article*)> (__first=, __last=,
__depth_limit=18,
__comp=0x7f24244d95e1 )
at /usr/include/c++/4.8.3/bits/stl_algo.h:2337
4 0x00007f24244ed6e5 in std::sort<__gnu_cxx::__normal_iterator > >, bool
()(cand_article, cand_article*)> (
__first=, __last=, __comp=0x7f24244d95e1 )
at /usr/include/c++/4.8.3/bits/stl_algo.h:5489
article_cmp is called in sort(article_result->begin(), article_result->end(), article_cmp); and article_result is a vector<cand_article*> *. cand_article is a struct.
Here is the definition of article_cmp:
bool article_cmp(cand_article* cand_article_1, cand_article* cand_article_2) {
return cand_article_1 -> display_time >= cand_article_2 -> display_time;
}
Here is a piece of code where the crash happens:
article_result->clear();
for(vec_iter = _channel_data -> begin(); vec_iter != _channel_data -> end(); vec_iter++) {
cand_article* cand = to_cand_group(*vec_iter);
if(cand == NULL) continue;
// refresh open loadmore
if(m_request.req_type == 1) {
if(cand -> display_time > m_request.start){
article_result->push_back(cand);
}
}else if(m_request.req_type == 2){
if(cand -> display_time < m_request.end){
article_result->push_back(cand);
}
}else{
article_result->push_back(cand);
}
}
sort(article_result->begin(), article_result->end(), article_cmp);
Question:
I don't know how to handle this kind of coredump, cause 0x4015 is a kernel space address? Any suggestions on how to fix this kind of bug? sorry, I can't reproduce this situation with a minimal program. And this happened in a single thread, so you don't need to think about multi-thread situation.
The rule is "if std::sort crashes, you have an invalid comparison function". Your comparison function is:
bool article_cmp(cand_article* lhs, cand_article* rhs) {
return lhs -> display_time >= rhs -> display_time;
}
This is not a strict weak ordering. In particular, if the display times are equal it returns true, which means that if you swap the arguments it will still return true ... and that is not allowed. You need:
bool article_cmp(cand_article* lhs, cand_article* rhs) {
return lhs -> display_time > rhs -> display_time;
}
The reason your simplified example works (congratulations for at least trying to simplify), is that you simplified the comparison function so it is valid. If the return statement was return s1->it >= s2->it;, and you used a smaller range of values, it too would probably crash.
Incidentally, a much more natural C++ declaration of your example structure would look like:
struct st { // No need for that typedef in C++
int it;
char ch;
std::string charr; // ... or *possibly* std::array<char,100>.
std::vector<std::string> vs; // Strings and vectors best held by value
};
Also note that I have actually used the std:: prefix.
Your minimal program is making memory leaks. Because it just removes all the items from the list but did not release the memory used by them. In the case your items are big enough, your program might get crashed after eating up all the memory. That's why your minimal program is still okay, because the items there are very small.
I would change your program to:
typedef struct st {
int it;
char ch;
char charr[100];
vector *vs;
} st;
bool function(st *&s1, st *&s2) {
static int i = 1;
cout<it > s2->it;
}
int main(int argc, char **argv) {
vector ar;
for (int i = 0; i < 100; ++i) {
st *s = new st;
s->it = urandom32();
ar.push_back(s);
}
release all the memory used my ar's items first
for (vector::iterator it = ar.begin(); it != ar.end(); ++it)
delete *it;
ar.clear();
for (int i = 0; i < 100; ++i) {
st *s = new st;
s->it = urandom32();
ar.push_back(s);
}
sort(ar.begin(), ar.end(), function);
return 0;
}
So I'm just a beignner programmer when it comes to C++, and I have to write a function that checks if an int array is sorted using pointers (no index notations allowed), and here's what I have so far:
bool isSorted(const int *ar, int size) {
bool sorted = true;
const int *ptr1, *ptr2, *ptr3;
ptr1 = ar;
ptr2 = ar+1;
ptr3 = ar+size;
for (ptr1; ptr1 < ptr3; ptr1++) {
for (ptr2; ptr2 < ptr3; ptr2++) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
}
return sorted;
}
However, I can't seem to get it to work as it always returns true regardless of whether the array is sorted or not. Any help is appreciated, thanks.
"The more you overthink the plumbing, the easier it is to stop up the
drain" -- Scotty, Star Trek III.
You are making this much more complicated than it has to be.
Ask yourself a basic question: what is a sorted array?
Answer: an array in which each successive element is not less than its preceding element.
Therefore: to check if the array is sorted, just look for an element that's less than its previous element. If you found one, the array is not sorted. If you couldn't find one, the array must be sorted.
bool isSorted(const int *ar, int size) {
if (size == 0)
return true; // Edge case
int previous_value= *ar;
while (size)
{
if (*ar < previous_value)
return false;
previous_value= *ar;
++ar;
--size;
}
return true;
}
No index notations, just a single pointer. No need to do any kind of a nested search, etc... If you want to use only pointers, you could do this:
bool isSorted(const int *ar, int size) {
const int *previous_value=ar;
while (size)
{
if (*ar < *previous_value)
return false;
previous_value= ar;
++ar;
--size;
}
return true;
}
Actually, I like this version even better.
You should keep ptr2 always be ptr+1,so you need to initialize ptr2 in second for() .
And I think only one loop is better.
for(; ptr2 < ptr3; ++ptr1, ++ptr2) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
return sorted;
My general question is how to figure out how to use DFS. It seems to be a weak part of my knowledge. I have vague idea but often get stuck when the problem changes. It caused a lot of confusion for me.
For this question, I got stuck with how to write DFS with recursion.
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[
["aa","b"],
["a","a","b"]
]
My first attempt was stuck in the loop of the helper function. Then from searching on internet, I found that bool palindrome(string s) can be written as a different signature.
bool palindrome(string &s, int start, int end)
This leads to the correct solution.
Here's the code of my initial attempt:
class Solution {
public:
bool palindrome(string s)
{
int len = s.size();
for (int i=0;i<len/2; i++)
{
if (s[i]!=s[len-i])
return false;
}
return true;
}
void helper( int i, string s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (i==slen-1&&flag)
{
ret.push_back(p);
}
for (int k=i; k<slen; k++)
{
if (palindrome(s.substr(0,k)))
{
p.push_back(s.substr(0,k)); //Got stuck
}
}
i++;
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Correct one:
class Solution {
public:
bool palindrome(string &s, int start, int end)
{
while(start<end)
{
if (s[start]!=s[end])
return false;
start++;
end--;
}
return true;
}
void helper( int start, string &s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (start==slen)
{
ret.push_back(p);
return;
}
for (int i=start; i<s.size(); i++)
{
if (palindrome(s, start, i))
{
p.push_back(s.substr(start,i-start+1));
helper(i+1,s,p,ret);
p.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Edit Dec. 4, 2014: I saw some approach using dynamical programming but can't understand the code completely.
esp. isPalin[i][j] = (s[i] == s[j]) && ((j - i < 2) || isPalin[i+1][j-1]);
Why j-I<2 instead of j-I<1?
class Solution {
public:
vector<vector<string>> partition(string s) {
int len = s.size();
vector<vector<string>> subPalins[len+1];
subPalins[0] = vector<vector<string>>();
subPalins[0].push_back(vector<string>());
bool isPalin[len][len];
for (int i=len-1; i>=0; i--)
{
for (int j=i; j<len; j++)
{
isPalin[i][j] = (s[i]==s[j])&&((j-i<2)||isPalin[i+1][j-1]);
}
}
for (int i=1; i<=len;i++)
{
subPalins[i]=vector<vector<string>>();
for (int j=0; j<i; j++)
{
string rightStr=s.substr(j,i-j);
if (isPalin[j][i-1])
{
vector<vector<string>> prepar=subPalins[j];
for (int t=0; t<prepar.size(); t++)
{
prepar[t].push_back(rightStr);
subPalins[i].push_back(prepar[t]);
}
}
}
}
return subPalins[len];
}
};
What exactly are you asking? You have correct working code and your non-working code which is not that different.
I guess I can point out several issues with your code - may be it will be helpful to you:
in the palindrome() function you should compare s[i] to s[len-1-i] rather than to just s[len-i] in the if, since in former case you will compare 1st element (having index 0) to the non-existent element (index len). That might be the reason helper() got stuck.
in the helper() function flag is not initialized. In the for cycle, the end condition should be k<slen-1 instead of k<slen, since in latter case you will omit checking the substring that includes the terminal symbol of the string. Also, incrementing i in the end of helper() is pointless. Finally, indentations are messy in the helper() function.
Not sure why you use DFS - what is the meaning of your graph, what are the vertices and edges here? As to how the recursion works here: in the helper() function you start checking substrings of increased length for being palindrome. If the palindrome is found, you place it into p vector (which represent your current partitioning) and try to break the remainder of the string into palindromes by calling helper() recursively. If you succeed in that (i.e. if the whole string is completely partitioned into palindromes) you place the contents of p vector (current partitioning) into ret (set of all found partitionings), and then clear p to prepare it for the analysis of the next partition (purge of p is achieved by pop_back() call that follows recursive call of helper()). If, on the other hand, you fail to completely break string into palindromes, the p is purged as well, but without transferring its content into ret (this is due to the fact that recursive call for the last piece of string - which is not a palindrome - returns without calling helper() for the final symbol and thus pushing p into ret does not occur). Therefore you end up having all possible palindrome partitionings in the ret.
Hi~ this is my code using DFS + backtracking.
class Solution
{
public:
bool isPalindrome (string s) {
int i = 0, j = s.length() - 1;
while(i <= j && s[i] == s[j]) {
i++;
j--;
}
return (j < i);
}
void my_partition(string s, vector<vector<string> > &final_result, vector<string> &every_result ) {
if (s.length() ==0)
final_result.push_back(every_result);
for (int i =1; i <= s.length();++i) {
string left = s.substr(0,i);
string right = s.substr(i);
if (isPalindrome(left)) {
every_result.push_back(left);
my_partition(right, final_result, every_result);
every_result.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string> > final_result;
vector<string> every_result;
my_partition(s, final_result, every_result);
return final_result;
}
};
I have done Palindrome Partitioning using backtracking. Depth-first search was used here, idea is to split the given string so that the prefix is a palindrome. push prefix in a vector now explore the string leaving that prefix and then finally pop the last inserted element,
Well on spending time on backtracking is of the form, choose the element, explore without it and unchoose it.
enter code here
#include<iostream>
#include<vector>
#include<string>
using namespace std;
bool ispalidrome(string x ,int start ,int end){
while(end>=start){
if(x[end]!=x[start]){
return false;
}
start++;
end--;
}
return true;
}
void sub_palidrome(string A,int size,int start,vector<string>&small, vector < vector < string > >&big ){
if(start==size){
big.push_back(small);
return;
}
for(int i=start;i<size;i++){
if( ispalidrome(A,start,i) ){
small.push_back(A.substr(start,i-start+1));
sub_palidrome(A,size,i+1,small,big);
small.pop_back();
}
}
}
vector<vector<string> > partition(string A) {
int size=A.length();
int start=0;
vector <string>small;
vector < vector < string > >big;
sub_palidrome(A,size,start,small,big);
return big;
}
int main(){
vector<vector<string> > sol= partition("aab");
for(int i=0;i<sol.size();i++){
for(int j=0;j<sol[i].size();j++){
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
}
I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.