Segmentaion fault possible because of map - c++

I wrote a code which has to take two string as input. It has to output number of steps(adjacent letter flips or flipping first and last letter) it takes one word to convert to another. It gives correct values till the size of string is 8. If the size of string is more than 8, it gives segmentation fault. I could not find any mistake. Can anyone please help me out. Thanks in advance. This is the code:
map<string,int>imap;
int easyStrings(string a, string b) {
//cout<<a<<endl;
if(a.compare(b) == 0)
return 0;
map<string,int>::iterator it = imap.find(a);
if(it != imap.end())
return it->second;
imap.insert(pair<string,int>(a,-2));
int min = -2;
string str = a;
str[0] = a[a.length()-1];
str[a.length()-1] = a[0];
it = imap.find(str);
if(it == imap.end() || it->second != -2)
min = 1 + easyStrings(str,b);
for(int i = 0 ; i < a.length()-1; i++)
{
string check = a;
check[i] = a[i+1];
check[i+1] = a[i];
int steps = 0;
it = imap.find(check);
if(it == imap.end() || it->second != -2)
{
steps = 1 + easyStrings(check,b);
if(steps < min || min ==-2)
if(steps > 0)
min = steps;
}
}
imap[a] = min;
return min;
}
I tried using debugger. I shows error in imap.insert(pair(a,-2));. It also gives a huge trace showing problems mainly with malloc.
It does not go into infinite recursion. There are factorial of length of input string at maximum and I only insert a string when it is not found in map.

A cursory glance at this function with gdb reveals that this function is recursive, and that strings over a certain length trigger it to enter infinite-depth recursion (or at least a depth that 4 gigs of RAM can't handle). I would look at your recursion conditionals and double check that there is an exit case that will be met for all of them.

Related

stoi() terminate after throwing and instance of 'std::invalid argument in c++-- What am I doing wrong?

Fairly new to coding. Trying some of the easy projects at LeetCode, and failing... Ha! I am trying to take an integer and convert it to a string so I can reverse it, then re-convert the reversed string back into a integer.
This code is throwing the "terminate after throwing and instance of 'std::invalid argument' what(): stoi" error. I've spent an hour searching google and other questions here on SO, but can't figure out why it's not working.
bool isPalindrome(int x) {
std::string backwards ="";
std::string NumString = std::to_string(x);
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
int check = std::stoi(backwards);
if (check == x) {
return true;
}
else {
return false;
}
}
EDIT: I think I figured it out. It was adding the null character to the end of the string upon first conversion, then adding it to the beginning of the string when I reversed it. Spaces can't be converted to integers.
So... I changed this line and it works:
for (int i = NumString.size() - 1; i >= 0 ; i--)
you can also reverse number without using string.
bool isPalindrome(int x) {
long long rev = 0;
int cur = x;
while( cur > 0) {
rev *= 10;
rev += cur % 10;
cur /=10;
}
return rev == x;
}
Its simpler than your answer that you edited in. YOu have
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
Imagine that Numstring has length 3 (no matter what spaces, digits,....)
So now you are efectively doing
for (int i = 3; i >= 0 ; i--) {
backwards += NumString[i];
}
So first loop goes
backwards += NumString[3];
well the indexes of things in an array of length 3 in c++ are 0,1,2. YOu are going one off the end
This is why you see loops doing
for(int i = 0; i < len; i++){}
Note the i < len not i <= len

What is wrong with this loop-based function that returns the position of an element?

This function looks for an integer 'key' in a given vector from a position 'start'. It returns the position of key if it finds it. But if it does not find key, it should return -1.
However, it is only returning -1 as the output. The function works fine if the else statement is removed, but obviously I need it.
So what is wrong in this function? Please explain in simple terms, I am new to C++. Thank you for all your help.
int Sequential_Search(const vector<int>&v, int key, int start){
int result = 0;
int i;
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
return result;
}
This is pretty easy to understand:
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
Let's say your vector contains [1, 2, 3, 4] and you search 2 starting at index 0: here is what your code is doing:
i = 0: (v[i] : 1) == 2 -> false: result = -1
i = 1: (v[i] : 2) == 2 -> true: result = 1
i = 2: (v[i] : 3) == 2 -> false: result = -1
i = 3: (v[i] : 4) == 2 -> false: result = -1
When you've found your value, you still continue to read other value whereas you should stop.
Either using break or directly returning (return i) in the v[i] == key condition;
Either by checking result in the for condition (result == -1 && i < v.size())
Per comment remark: the case with break and return (the last one is not so hard):
int Sequential_Search(const vector<int>&v, int key, int start){
int result = -1; // important for 'break'
for(int i = start; i < v.size(); i++){
if(v[i] == key){
result = i; break;
}
}
return result;
}
int Sequential_Search(const vector<int>&v, int key, int start){
for(int i = start; i < v.size(); i++){
if(v[i] == key){
return i;
}
}
return -1;
}
When the loop finds the key, it sets result = i - but it doesn't stop looping. On the next iteration, v[i] is likely not equal to key, and the loop resets result to -1. The function returns -1 unless key just happens to match the last element.
The reason this is failing with the else statement is because there are many scenarios that the key would not be the last item in the vector.
If the key is 3 and the vector of ints if <1,3,4>, the for loop will loop through 3 times total. On the first iteration, it will go into the else statement since we did not find the key at the 0th index. Result is -1. On the second iteration, we found the key! Set result to i = 1. The third iteration will go into the else statement again, and set the result back to -1.
To fix this, you can use 'break' to leave the for loop as soon as you find result. Set result to I and then follow that with break; This will ensure that if the result is found, you will not go into the else statement again and reset it to -1.

C++ Program abruptly ends after cin

I am writing code to get the last digit of very large fibonacci numbers such as fib(239), etc.. I am using strings to store the numbers, grabbing the individual chars from end to beginning and then converting them to int and than storing the values back into another string. I have not been able to test what I have written because my program keeps abruptly closing after the std::cin >> n; line.
Here is what I have so far.
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using namespace std;
char get_fibonacci_last_digit_naive(int n) {
cout << "in func";
if (n <= 1)
return (char)n;
string previous= "0";
string current= "1";
for (int i = 0; i < n - 1; ++i) {
//long long tmp_previous = previous;
string tmp_previous= previous;
previous = current;
//current = tmp_previous + current; // could also use previous instead of current
// for with the current length of the longest of the two strings
//iterates from the end of the string to the front
for (int j=current.length(); j>=0; --j) {
// grab consectutive positions in the strings & convert them to integers
int t;
if (tmp_previous.at(j) == '\0')
// tmp_previous is empty use 0 instead
t=0;
else
t = stoi((string&)(tmp_previous.at(j)));
int c = stoi((string&)(current.at(j)));
// add the integers together
int valueAtJ= t+c;
// store the value into the equivalent position in current
current.at(j) = (char)(valueAtJ);
}
cout << current << ":current value";
}
return current[current.length()-1];
}
int main() {
int n;
std::cin >> n;
//char& c = get_fibonacci_last_digit_naive(n); // reference to a local variable returned WARNING
// http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable
cout << "before call";
char c = get_fibonacci_last_digit_naive(n);
std::cout << c << '\n';
return 0;
}
The output is consistently the same. No matter what I enter for n, the output is always the same. This is the line I used to run the code and its output.
$ g++ -pipe -O2 -std=c++14 fibonacci_last_digit.cpp -lm
$ ./a.exe
10
There is a newline after the 10 and the 10 is what I input for n.
I appreciate any help. And happy holidays!
I'm posting this because your understanding of the problem seems to be taking a backseat to the choice of solution you're attempting to deploy. This is an example of an XY Problem, a problem where the choice of solution method and problems or roadblocks with its implementation obfuscates the actual problem you're trying to solve.
You are trying to calculate the final digit of the Nth Fibonacci number, where N could be gregarious. The basic understanding of the fibonacci sequence tells you that
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2), for all n larger than 1.
The iterative solution to solving fib(N) for its value would be:
unsigned fib(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value;
}
return current;
}
which is all well and good, but will obviously overflow once N causes an overflow of the storage capabilities of our chosen data type (in the above case, unsigned on most 32bit platforms will overflow after a mere 47 iterations).
But we don't need the actual fib values for each iteration. We only need the last digit of each iteration. Well, the base-10 last-digit is easy enough to get from any unsigned value. For our example, simply replace this:
current = value;
with this:
current = value % 10;
giving us a near-identical algorithm, but one that only "remembers" the last digit on each iteration:
unsigned fib_last_digit(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value % 10; // HERE
}
return current;
}
Now current always holds the single last digit of the prior sum, whether that prior sum exceeded 10 or not really isn't relevant to us. Once we have that the next iteration can use it to calculate the sum of two single positive digits, which cannot exceed 18, and again, we only need the last digit from that for the next iteration, etc.. This continues until we iterate however many times requested, and when finished, the final answer will present itself.
Validation
We know the first 20 or so fibonacci numbers look like this, run through fib:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
11:89
12:144
13:233
14:377
15:610
16:987
17:1597
18:2584
19:4181
20:6765
Here's what we get when we run the algorithm through fib_last_digit instead:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:3
8:1
9:4
10:5
11:9
12:4
13:3
14:7
15:0
16:7
17:7
18:4
19:1
20:5
That should give you a budding sense of confidence this is likely the algorithm you seek, and you can forego the string manipulations entirely.
Running this code on a Mac I get:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string before callin funcAbort trap: 6
The most obvious problem with the code itself is in the following line:
for (int j=current.length(); j>=0; --j) {
Reasons:
If you are doing things like current.at(j), this will crash immediately. For example, the string "blah" has length 4, but there is no character at position 4.
The length of tmp_previous may be different from current. Calling tmp_previous.at(j) will crash when you go from 8 to 13 for example.
Additionally, as others have pointed out, if the the only thing you're interested in is the last digit, you do not need to go through the trouble of looping through every digit of every number. The trick here is to only remember the last digit of previous and current, so large numbers are never a problem and you don't have to do things like stoi.
As an alternative to a previous answer would be the string addition.
I tested it with the fibonacci number of 100000 and it works fine in just a few seconds. Working only with the last digit solves your problem for even larger numbers for sure. for all of you requiring the fibonacci number as well, here an algorithm:
std::string str_add(std::string a, std::string b)
{
// http://ideone.com/o7wLTt
size_t n = max(a.size(), b.size());
if (n > a.size()) {
a = string(n-a.size(), '0') + a;
}
if (n > b.size()) {
b = string(n-b.size(), '0') + b;
}
string result(n + 1, '0');
char carry = 0;
std::transform(a.rbegin(), a.rend(), b.rbegin(), result.rbegin(), [&carry](char x, char y)
{
char z = (x - '0') + (y - '0') + carry;
if (z > 9) {
carry = 1;
z -= 10;
} else {
carry = 0;
}
return z + '0';
});
result[0] = carry + '0';
n = result.find_first_not_of("0");
if (n != string::npos) {
result = result.substr(n);
}
return result;
}
std::string str_fib(size_t i)
{
std::string n1 = "0";
std::string n2 = "1";
for (size_t idx = 0; idx < i; ++idx) {
const std::string f = str_add(n1, n2);
n1 = n2;
n2 = f;
}
return n1;
}
int main() {
const size_t i = 100000;
const std::string f = str_fib(i);
if (!f.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << f[f.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Try it with first calculating the fibonacci number and then converting the int to a std::string using std::to_string(). in the following you can extract the last digit using the [] operator on the last index.
int fib(int i)
{
int number = 1;
if (i > 2) {
number = fib(i - 1) + fib(i - 2);
}
return number;
}
int main() {
const int i = 10;
const int f = fib(i);
const std::string s = std::to_string(f);
if (!s.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << s[s.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Avoid duplicates of the using keyword using.
Also consider switching from int to long or long long when your numbers get bigger. Since the fibonacci numbers are positive, also use unsigned.

bug in c++ program count no of 1's in vector

A question was asked to me during an online interview.
They provided a piece of code and we have to find out a possible bug in the code.
The code is provided below as it is.
The function is provided with a non empty zero indexed vector of integers (which contains only 1 and 0).
The function will return the start position of longest sequence of 1's.
for example if the input values {0,0,0,1,1,1,1,1,0,0,1,1,1,0,1,1} it will return 3 because the longest sequence of 1's is from position 3 to 7 total five consecutive 1's.
if the input values are {0,0,1} then it will return 2 because there is only one 1 and length of longest sequence of 1 is one.
If there are no 1's then it will return -1.
The input vector can be changed so we can't change the signature of the vector to const.
I tested this function with variable no of inputs and I found out that it is working fine.
I am not able to find out any bug in the code. But the instruction says that there is a bug in the code and we can change maximum 2 lines of code to solve the bug.
int solution(vector<int>& A) {
int n = A.size();
int i = n - 1;
int result = -1;
int k = 0;
int maximal = 0;
while (i > 0) {
if (A[i] == 1) {
k = k + 1;
if (k >= maximal) {
maximal = k;
result = i;
}
} else {
k = 0;
}
i = i - 1;
}
if (A[i] == 1 && k + 1 > maximal)
result = 0;
return result;
}
To fix UB for empty case, I add check for !A.empty(),
and I profit of that to replace i by 0 (at that point i == 0)
and to replace the check with maximal value to have a coherent result for tie:
if (!A.empty() && A[0] == 1 && k + 1 >= maximal)
And as I may change an other line, I would fix the prototype as A is not modified.
int solution(const std::vector<int>& A) {
problem specifications are that
1.vector is immutable and
2.Input vector is not empty
I tried same problem in Java but different approach to see what is missing because i cant find any bug in above code.
package javaapplication7;
/**
*
* #author Owner
*/
public class JavaApplication7 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] A={0,1,0,1,1,1,1};
System.out.println(solution(A));
}
static int solution(int A[]){
int i=0,count=0,max=0,pos=-1;
while(i<=A.length-1)
{
if(A[i]==1)
{
count++;
i=i+1;
}
else
{
i=i+1;
count=0;
}
if(count>max)
{
pos=i-count;
max=count;
}
}
if(count==0)
return pos;
else
return pos;
}
}
the given code will favor a sequence closer to the left side if two sequences are of equal length. that doesn't happen for the checking of index 0
if (A[i] == 1 && k + 1 > maximal)
should be
if (A[i] == 1 && k + 1 >= maximal)

BFS maze help c++

I am attempting to make a maze-solver using a Breadth-first search, and mark the shortest path using a character '*'
The maze is actually just a bunch of text. The maze consists of an n x n grid, consisting of "#" symbols that are walls, and periods "." representing the walkable area/paths. An 'S' denotes start, 'F' is finish. Right now, this function does not seem to be finding the solution (it thinks it has the solution even when one is impossible). I am checking the four neighbors, and if they are 'unfound' (-1) they are added to the queue to be processed.
The maze works on several mazes, but not on this one:
...###.#....
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
What could be missing in my logic?
int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
if (maze[i] == 'S') { start=i; }
if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }
char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;
int delta[] = {-cols,-1,cols,+1}; // North, West, South, East neighbors
while(tail>head) {
int front = bfsq[head];
head++;
for (int i=0; i<4; i++) {
int neighbor = front+delta[i];
if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
continue;
}
if (prd[neighbor] == -1 && maze[neighbor]!='#') {
prd[neighbor] = front;
bfsq[tail] = neighbor;
tail++;
if (maze[neighbor] == 'F') { solved = true; }
}
}
}
if (solved == true) {
int previous = finish;
while (previous != start) {
maze[previous] = '*';
previous = prd[previous];
}
maze[finish] = 'F';
return 1;
}
else { return 0; }
delete [] prd;
delete [] bfsq;
}
Iterating through neighbours can be significantly simplified(I know this is somewhat similar to what kobra suggests but it can be improved further). I use a moves array defining the x and y delta of the given move like so:
int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
Please note that not only tis lists all the possible moves from a given cell but it also lists them in clockwise direction which is useful for some problems.
Now to traverse the array I use a std::queue<pair<int,int> > This way the current position is defined by the pair of coordinates corresponding to it. Here is how I cycle through the neighbours of a gien cell c:
pair<int,int> c;
for (int l = 0;l < 4/*size of moves*/;++l){
int ti = c.first + moves[l][0];
int tj = c.second + moves[l][1];
if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
// This move goes out of the field
continue;
}
// Do something.
}
I know this code is not really related to your code, but as I am teaching this kind of problems trust me a lot of students were really thankful when I showed them this approach.
Now back to your question - you need to start from the end position and use prd array to find its parent, then find its parent's parent and so on until you reach a cell with negative parent. What you do instead considers all the visited cells and some of them are not on the shortest path from S to F.
You can break once you set solved = true this will optimize the algorithm a bit.
I personally think you always find a solution because you have no checks for falling off the field. (the if (ti < 0 || ti >= n || tj < 0 || tj >= m) bit in my code).
Hope this helps you and gives you some tips how to improve your coding.
A few comments:
You can use queue container in c++, its much more easier in use
In this task you can write something like that:
int delta[] = {-1, cols, 1 -cols};
And then you simple can iterate through all four sides, you shouldn't copy-paste the same code.
You will have problems with boundaries of your array. Because you are not checking it.
When you have founded finish you should break from cycle
And in last cycle you have an error. It will print * in all cells in which you have been (not only in the optimal way). It should look:
while (finish != start)
{
maze[finish] = '*';
finish = prd[finish];
}
maze[start] = '*';
And of course this cycle should in the last if, because you don't know at that moment have you reach end or not
PS And its better to clear memory which you have allocate in function