Remove adjacent duplicates - c++

Expected output is "ca" but I'm getting "aca". I have dry ran it, but do not understood why it is doing so. Please, can anyone help me in solving this?
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a = "abbaca";
int i = 0;
while(i < a.size()){
if(a[i] == a[i+1]){
a.erase(i, i+1);
i = 0;
}
else{
i++;
}
}
cout << a;
return 0;
}

a.erase(i, i+1) is wrong.
The string::erase() method takes a starting index and a count, not a pair of indexes denoting a range, as you are thinking.
When removing the duplicate bs, i is 1, and you erase i+1=2 chars, thus "abbaca" becomes "aaca", which is correct. But then, the loop starts over, and when removing the duplicate as, i is 0, so you erase i+1=1 char, thus "aaca" becomes "aca", which is wrong.
You want to remove exact 2 chars each time, so use a.erase(i, 2) instead.
Online Demo

The function 'erase()' erases a part of the string content, shortening the length of the string.The second parameter in the erase function is the count, it means how many characters you want it to remove. If you want 'ca' as expected output you should mention 2 as count of characters to be removed. In the first case it becomes 2 so bb is removed but for 'aa' the count becomes as 1 so 'aca' is the output.
Below is the code for output 'ca', change this erase statement as shown:
if(a[i]==a[i+1]){
a.erase(i,2);
i=0;
}
keep the rest as same

Related

Doing a scenario problem in C++ and am unsure of how to proceed with boolean and if-loops

**This is a translation, very hastily written. If you need any clarification, just comment.
The question given is:
We live in a world with too much garbage. We have found a way to compress the garbage, but it can only be done in a specific way, or else the garbage will explode. The garbage has to be laid out in a line, and it can only be compressed with its neighbor, and only if its neighbor has the same value as it.
The first input is int N, and it represents the amount of garbage in the row. The second input is t, and it must have an input of as many characters as the value in N. If the whole thing is able to be compressed until there's only 1 garbage (t) left, then the output will be "YES".
We've figured out that as long as either N == 1, or all inputs in t (all the characters) are the same, the output will be YES.
Example inputs/outputs:
Input:
2
1 1
Output:
YES
Or
Input:
3
1 2 1
Output:
NO
Or
Input:
1
5
Output:
YES
Here's what we've got so far:
#include <iostream>
#include <string>
using namespace std;
int N;
string t;
bool allCharactersSame(string s)
{
int n = s.length();
for (int i = 1; i < n; i++) {
if (s[i] != s[0])
return false;
}
return true;
}
int main()
{
cin>>N;
cin >> t;
if (N == 1)
{
cout << "YES";
}
else if (allCharactersSame(t))
{
cout <<"YES";
}
else
{
cout<<"NO";
}
}
The problem with this is that it outputs YES no matter what, and we think it's because it takes the whitespace of the input into consideration. If we don't include spaces, it works fine. BUT the question dictates that we Have To have spaces separating our inputs. So, we're stumped. Any suggestions?
(I can't comment, therefore I write this as an answer.)
There is some other problem than you think, because the code in the question works as it should. When I gave it input "5 11111" it said "YES" when I gave it "5 12345" it said "NO".
Kai's first comment is slightly weird, when determining whether all characters in a string are the same it is sufficient to compare each of them to the first one, just as you do it in your allCharactersSame() method.
I'd suggest you add some checks on the provided input; the program should probably notice if given N doesn't match given strings' length and it should probably notice when the given string doesn't consist of numbers. As it is now, e.g. input "3 a" says "YES".

String not modified by loop

I'm solving the following problem:
The assignment is to create and return a string object that consists of digits in an int that is sent in through the function's parameter; so the expected output of the function call string pattern(int n) would be "1\n22\n..n\n".
In case you're interested, here is the URL (You need to be signed in to view) to the full assignment, a CodeWars Kata
This is one of the tests (with my return included):
Test-case input: pattern(2)
Expected:
1
22
Actual: "OUTPUT"
//string header file and namespace are already included for you
string pattern(int n){
string out = "OUTPUT";
for (int i = 1; i <= n; ++i){
string temp = "";
temp.insert(0, i, i);
out += temp;
}
return out;
}
The code is self-explanatory and I'm sure there are multiple ways of making it run quicker and more efficiently.
My question is two-fold. Why doesn't my loop start (even though my expression should hold true (1 <= 2) for above case)?
And how does my code hold in the grand scheme of things? Am I breaking any best-practices?
The overload of std::string::insert() that you are using takes three arguments:
index
count
character
You are using i as both count and character. However, the function expects the character to be of char type. In your case, your i is interpreted as a character with the code of 1 and 2, which are basically spaces (well, not really, but whatever). So your output really looks like OUTPUT___ where ___ are three spaces.
If you look at the ascii table, you will notice that digits 0123...9 have indexes from 48 to 57, so to get an index of a particular number, you can do i + 48, or i + '0' (where '0' is the index of 0, which is 48). Finally, you can do it all in the constructor:
string temp(i, i + '0');
The loop works - but does nothing visible. You insert the character-code 1 - not the character '1'; use:
temp.insert(0, i, '0'+i);
the insert method is not called right:
temp.insert(0, i, i); --->
temp.insert(0, i, i+'0');

Beginner difficulty with vectors and while-loops in C++

Update:
So it turns out there were two issues:
The first is that I checked the [k-1] index before I checked k == 0. This was a crash, although mostly fixable, and not the primary issue I posted about.
The primary issue is that the code seems to execute only after I press ctrl+z. Not sure why that would be.
Original:
So, learning from Stroustrup's text in C++ programming, I got to an example on vectors and tried implementing it myself. The gist is that the program user enters a bunch of words, and the program alphabetizes them, and then prints them without repeats. I managed to get working code using a for statement, but one of my initial attempts confuses me as to why this one doesn't work.
To be clear, I'm not asking to improve this code. I already have better, working code. I'm wondering here why the code below doesn't work.
The "error" I get is that the code compiles and runs fine, but when I input words, nothing happens and I'm prompted to input more.
I'm certain there's an obvious mistake, but I've been looking everywhere for the last 8 hours (no exaggeration) just devoted to finding the error on my own. But I can't.
int main() {
vector<string> warray; string wentry; int k = 0;
cout << "Enter words and I'll alphabetize and delete repeats:\n\n";
while (cin >> wentry) warray.push_back(wentry);
sort(warray.begin(), warray.end());
while (k < warray.size()) {
if (warray[k - 1] != warray[k] || k == 0) cout << warray[k] << "\n";
++k;
}
}
My reasoning for why this should work is this: I initialize my array of words, my word entry per input, and a variable to index word output.
Then I have a while statement so that every input is stacked at the end of the array.
Then I sort my array.
Then I use my index which starts at 0 to output the 0th item of the array.
Then so long as there are words in the array not yet reached by the index, the index will check that the word is not a repeat of the prior index position, and then print if not.
No matter what whappens, the index is incremented by one, and the check begins again.
Words are printed until the index runs through and checks all the words in the array.
Then we wait for new entries, although this gets kind of screwy with the above code, since the sorting is done before the checking. This is explicitly not my concern, however. I only intend for this to work once.
To end the cycle of input you need to insert EOF character which is ctrl+d. However, there are other problems in your code. You have k = 0 to start with so the moment you will try warray[k - 1] your code will crash.
At the point where you take
warray[k - 1]
for the first time, k is zero, so you want to get the warray value at index -1, which is not necessarily defined in memory (and even if, I wouldn't do this anyway). So as it compiles, I guess the address is defined in your case by accident.
I would try simply reversing the OR combination in your if-condition:
if (k == 0 || warray[k - 1] != warray[k])
thus for the first iteration (k == 0) it won't check the second condition because the first condition is then already fulfilled.
Does it work then?
You're stuck in the while loop because you don't have a way of breaking out of it. That being said, you can use Ctrl + d (or use Ctrl + z if executing on windows in the command prompt) to break out of the loop and continue executing the code.
As for while loop at the bottom which prints out the sorted vector of values, your program is going to crash as user902384 suggested because your program will first check for warray[k - 1].
Ideally, you want to change the last part of your program to:
while (k < warray.size())
{
if (k == 0 || warray[k - 1] != warray[k])
cout << warray[k] << "\n";
++k;
}
This way, the k == 0 check passes and your program will skip checking warray[k - 1] != warray[k] (which would equal warray[-1] != warray[0] when k=0).
You just needed to reverse:
if (warray[k - 1] != warray[k] || k == 0)
to
if (k == 0 || warray[k - 1] != warray[k] )
for terminating this condition if k = 0.
An alternative.
Although it can termed as a bit off topic, considering you want to work with std::vector<>, but std::set<> is an excellent container which satisfies your current two conditions:
Sort the strings in alphabetical order.
Delete all the repetitions.
Include <set> in your .cpp file, and create a set object, insert all the std::string and iterate through the set to get your ordered, duplicate-free strings!
The code:
int main() {
//Define a set container.
set<string> s;
//A temporary string variable.
string temp;
//Inserting strings into the set.
while (cin >> temp) s.insert(temp);
//Create a set<int> iterator.
set<string>::iterator it;
//Scanning the set
for(it = s.begin(); it != s.end(); ++it)
{
//To access the element pointed by the iterator,
//use *it.
cout<<*it<<endl;
}
return 0;
}
I just recommended this container, because you will study set in Stroustrup's text, and it is very easy and convenient instead of laboring over a vector.

for loop stops when if statement is satisfied

I am trying to count how many times the unique words in a LinkedList appear using this code:
for(int i2 = 0; i2 < a.size(); i2++)
{
word2 = a.get(i2);
for(int j2 = 0; j2 < a.size(); j2++)
{
if(word2 == a.get(j2))
{
counter++;
}
}
System.out.println(word2 + " : " + counter);
counter = 0;
}
But the counter prints out:
Alphabet : 1
Alright : 1
Apple : 1
Alphabet : 1
Alright : 1
Apple : 1
Alphabet : 1
Alright : 1
Apple : 1
There is obviously more than one of the words, but the counter never gets higher then one. I think that the inner for loop is stopping when the if statement is satisfied, but I don't want it to. Any suggestions?
You should use
word2.equals(a.get(j2))
Using "==" you compare the references to those String which are not equal.
And by the way you will print the counter multiple times for the same word if you have repetitions. Let's say you have the word Apple on 2 positions in your list. When you will reach these 2 positions the counter will go up to 2 and you will print (Apple: 2) 2 times
This seems like java to me. You can't compare string with (==) operator.
if(word2.equals(a.get(j2)))
Just a new addition!!!
As suggested by #user3412998 its better to use Sets so that you can avoid duplication.
Now if you need to use ArrayList only then you need to take one element and check if there are multiple copies of that element using loop.The condition can be checked by .equals method if you are using string or my contains method incase you are inserting objects(dont forget to override your equals method in the corresponding class). This is a very tedious process and I do not recommend it.
I believe that the easiest way will to not to add duplicate elements in your array list. to accomplish that look at the code below..
if(!a.contains(word)){
a.add(word);
}
Note word is a String object.
Here I am checking weather the string is already contained in the ArrayList, before insertion.
make a bit of modifications so that you can use it, for arrays, or for directly inputting data etc..
I hope this helps..

Solving "Welcome to Code Jam" from Google Code Jam 2009

I am trying to solve the following code jam question,ive made some progress but for few cases my code give wrong outputs..
Welcome to Code jam
So i stumbled on a solution by dev "rem" from russia.
I've no idea how his/her solution is working correctly.. the code...
const string target = "welcome to code jam";
char buf[1<<20];
int main() {
freopen("input.txt", "rt", stdin);
freopen("output.txt", "wt", stdout);
gets(buf);
FOR(test, 1, atoi(buf)) {
gets(buf);
string s(buf);
int n = size(s);
int k = size(target);
vector<vector<int> > dp(n+1, vector<int>(k+1));
dp[0][0] = 1;
const int mod = 10000;
assert(k == 19);
REP(i, n) REP(j, k+1) {// Whats happening here
dp[i+1][j] = (dp[i+1][j]+dp[i][j])%mod;
if (j < k && s[i] == target[j])
dp[i+1][j+1] = (dp[i+1][j+1]+dp[i][j])%mod;
}
printf("Case #%d: %04d\n", test, dp[n][k]);
}
exit(0);
}//credit rem
Can somebody explain whats happening in the two loops?
Thanks.
What he is doing: dynamic programming, this far you can see too.
He has 2D array and you need to understand what is its semantics.
The fact is that dp[i][j] counts the number of ways he can get a subsequence of the first j letters of welcome to code jam using all the letters in the input string upto the ith index. Both indexes are 1 -based to allow for the case of not taking any letters from the strings.
For example if the input is:
welcome to code jjam
The values of dp in different situations are going to be:
dp[1][1] = 1; // first letter is w. perfect just the goal
dp[1][2] = 0; // no way to have two letters in just one-letter string
dp[2][2] = 1; // again: perfect
dp[1][2] = 1; // here we ignore the e. We just need the w.
dp[7][2] = 2; // two ways to construct we: [we]lcome and [w]elcom[e].
The loop you are specifically asking about calculates new dynamic values based on the already calculated ones.
Whoa, I was practicing this problem few days ago and and stumbled across this question.
I suspect that saying "he's doing dynamic programming" won't not explain too much if you did not study DP.
I can give clearer implementation and easier explanation:
string phrase = "welcome to code jam"; // S
string text; getline(cin, text); // T
vector<int> ob(text.size(), 1);
int ans = 0;
for (int p = 0; p < phrase.size(); ++p) {
ans = 0;
for (int i = 0; i < text.size(); ++i) {
if (text[i] == phrase[p]) ans = (ans + ob[i]) % 10000;
ob[i] = ans;
}
}
cout << setfill('0') << setw(4) << ans << endl;
To solve the problem if S had only one character S[0] we could just count number of its occurrences.
If it had only two characters S[0..1] we see that each occurrence T[i]==S[1] increases answer by the number of occurrences of S[0] before index i.
For three characters S[0..2] each occurrence T[i]==S[2] similarly increases answer by number of occurrences of S[0..1] before index i. This number is the same as the answer value at the moment the previous paragraph had processed T[i].
If there were four characters, the answer would be increasing by number of occurrences of the previous three before each index at which fourth character is found, and so on.
As every other step uses values from the previous ones, this can be solved incrementally. On each step p we need to know number of occurrences of previous substring S[0..p-1] before any index i, which can be kept in array of integers ob of the same length as T. Then the answer goes up by ob[i] whenever we encounter S[p] at i. And to prepare ob for the next step, we also update each ob[i] to be the number of occurrences of S[0..p] instead — i.e. to the current answer value.
By the end the latest answer value (and the last element of ob) contain the number of occurrences of whole S in whole T, and that is the final answer.
Notice that it starts with ob filled with ones. The first step is different from the rest; but counting number of occurrences of S[0] means increasing answer by 1 on each occurrence, which is what all other steps do, except that they increase by ob[i]. So when every ob[i] is initially 1, the first step will run just like all others, using the same code.