for loop stops when if statement is satisfied - if-statement

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..

Related

Remove adjacent duplicates

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

problem in using list in game maker studio

I am new to the game maker. I created a list and I want to compare all the data in the list with a specific value. I used the following code:
for(var i=0;i<ds_list_size(lst);i++;)
{
if ds_list_find_value(lst,i)>tmp
ds_list_replace(lst,i,ds_list_find_value(lst,i)-1);
}
and I face the following error:
Push :: Execution Error - Variable Get -1.lst(100001, -1)
at
gml_Object_object0_RightButtonPressed_1 (line 21) - for(var i=0;i
where is my problem?
Thanks all.
if your first for loop i = 0; and when the first entry in the list is smaller than tmp it tries to replace the first place in the list with a not existing one. so you could either check if its the first entry of the list with
if ( i == 0 ) { }
or your could start the for loop from the second entry with
for(var i=1;i<ds_list_size(lst);i++;)
I think the ; at the end of i++; is unnecessary, you only need to use ; in a for-loop as seperator.
GML gives more freedom to common C# rules though (like how there are no brackets needed around an if-condition), so perhaps that's allowed.
Another possibility might be that the index is out of range at ds_list_replace()

How to convert one string to another by successive substitutions of characters?

I'm currently trying to design an algorithm that doing such thing:
I got two strings A and B which consist of lowercase characters 'a'-'z'
and I can modify string A using the following operations:
1. Select two characters 'c1' and 'c2' from the character set ['a'-'z'].
2. Replace all characters 'c1' in string A with character 'c2'.
I need to find the minimum number of operations needed to convert string A to string B when possible.
I have 2 ideas that didn't work
1. Simple range-based for cycle that changes string B and compares it with A.
2. Idea with map<char, int> that does the same.
Right now I'm stuck on unit-testing with such situation : 'ab' is transferable to 'ba' in 3 iterations and 'abc' to 'bca' in 4 iterations.
My algorithm is wrong and I need some fresh ideas or working solution.
Can anyone help with this?
Here is some code that shows minimal RepEx:
int Transform(string& A, string& B)
{
int count = 0;
if(A.size() != B.size()){
return -1;
}
for(int i = A.size() - 1; i >= 0; i--){
if(A[i]!=B[i]){
char rep_elem = A[i];
++count;
replace(A.begin(),A.end(),rep_elem,B[i]);
}
}
if(A != B){
return -1;
}
return count;
}
How can I improve this or I should find another ideas?
First of all, don't worry about string operations. Your problem is algorithmic, not textual. You should somehow analyze your data, and only afterwards print your solution.
Start with building a data structure which tells, for each letter, which letter it should be replaced with. Use an array (or std::map<char, char> — it should conceptually be similar, but have different syntax).
If you discover that you should convert a letter to two different letters — error, conversion impossible. Otherwise, count the number of non-trivial cycles in the conversion graph.
The length of your solution will be the number of letters which shouldn't be replaced by themselves plus the number of cycles.
I think the code to implement this would be too long to be helpful.

loop until a certain condition is met

From this site https://www.geeksforgeeks.org/lca-for-general-or-n-ary-trees-sparse-matrix-dp-approach-onlogn-ologn/
I have a problem with this while loop part:
// runs till path 1 & path 2 mathches
int i = 0;
while (path[1][i] == path[2][i])
i++;
I want to increment i until two array elements are equal and I expected this loop to be like:
// runs till path 1 & path 2 mathches
int i = 0;
while (path[1][i] != path[2][i])
i++;
because I want to increment "i" when values are not equal but it does not seem so. Why equality is checked instead of inequality? This while loop confuses my mind. (Note: I run the whole code and it is working.)
By the line which follows (in your reference) where the last matching is returned, I see it that the error is in the comment. It should say something like "runs as long as the paths match" not "till".

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.