check how often value of array consecutively appears [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
i have a string "param", say :
param = aaaa;
and i have an array "word" which consists of :
word = [aaaa,aabb,aacc,aaaa,cccc,bbbb,ccdd,ccbb,ddcc,ccee,aaaa];
and i want to check how often another string than param appears on word. from that example above, i expects result to be :
2
6
how do i check that false string consecutively?
i tried to implement some code like this :
bool check(std::string param, std::vector< std::string > word)
{
int sum = 0; //sums of consecutive false string
for (unsigned int limit =0;limit<word.size();limit++)
{
if (word[limit]!=param)
{
sum = sum + 1;
}
else
{
sum = sum - 1;
}
}
if (sum>=10)
{
return true;
}
else
{
return false;
}
}
input
param : "aaaa"
word : ["aaaa",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"bbbb",
"aaaa"]
output ==> false
expected output ==> true

i finally found the answer. thanks to #πάντα ῥεῖ and #Anedar
here is the right code :
bool check(std::string param, std::vector< std::string > word)
{
int sum = 0; //sums of consecutive false string
std:vector<int> sums; //array of sum value
for (unsigned int limit =0;limit<word.size();limit++)
{
if (word[limit]!=param)
{
++sum;
}
else if (sum!=0)
{
sums.push_back(sum);
sum = 0;
}
}
if (sum!=0)
{
sums.push_back(sum); //make sure even if word vector does not end with param, the number still get pushed to counter vector
}
int temp = 0; //variable to store maximum value of consecutive array
for (int iter = 0; iter < sums.size(); iter ++)
{
if (sums[iter]>temp)
temp = sums[iter]; //store maximum value of consecutive array
}
//now the return bool value
if (temp>=10)
{
return true;
}
else
{
return false;
}
}

Ok, first of all, you resetted your sum every loop, so the only two possible results you can get after your for-loop are 1 and -1. What you really want to do when checking consecutives is to reset it only when your current streak has finished, so what you need is something like this:
bool check(std::string param, std::vector< std::string > word)
{
int current=0; //current sum of consecutive false string
std::vector<int> sums; //finished consecutives are stored here
for (unsigned int limit =0;limit<word.size();limit++)
{
if (word[limit]!=param)
{
++current;
}
else if (current != 0)
{
//a consecutive run has just finished
sums.push_back(current);
current=0;
}
}
if (current != 0)
sums.push_back(current);
//deal with sums here
}
I think what it does is pretty straightforward: Count the current strings != param and if it finds a param push the length of the current streak to a vector. You then need to deal with this vector in some way, either by returning it (then bool is the wrong return type) or by doing some other checks with it.
Oh and a small edit: the last if makes sure that even if your vector does not end with a param the number gets pushed to your vector.

expected output ==> true
Just remove the subtraction in the else part inside the for() loop to get the expected output:
bool check(std::string param, std::vector< std::string > word)
{
int sum = 0; //sums of consecutive false string
for (unsigned int limit =0;limit<word.size();limit++)
{
if (word[limit]!=param)
{
sum = sum + 1;
}
// else
// {
// sum = sum - 1;
// }
}
if (sum>=10)
{
return true;
}
else
{
return false;
}
}

Related

How to generate all binary string in order(increasing) upto 2^63 without converting numbers? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Output should be like
0
1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
1111
10000
....etc
Here this should be generated without conversion from number. For example we should not generate 111 by converting 7 to binary.
As the only feature you need is to increment, you could readily write a class:
class BinaryNumber {
public:
uint8_t data[64]; // This is wasted space, see notes.
bool increment();
};
std::ostream & operator<<(std::ostream &, const BinaryNumber &);
It might be that bitset is a better data structure than to waste all that space with 8-bit values when we only care about 1 of the bits, but I wanted to keep this simple.
Incrementing a value isn't bad.
// Returns false once we hit max value
bool BinaryNumber::increment() {
bool retVal = false;
for (int index = 0; index < 64; ++index) {
if (data[index] == 0) {
data[index] = 1;
retVal = true;
break;
}
else {
data[index] = 0;
}
}
return retVal;
}
Think about incrementing the value 0. Look at the code. If the first bit is a 0, we turn it into a one and break the loop (returning true because we broke early).
If it's a 1, we flip it back to zero and recurse, incrementing at index [1]. Loop until we hit a zero so we don't need to carry any further 1s.
I'll leave the write method to you.
This is not the most efficient method, but it's clean and easy to understand.
Since the goal is to generate a string for output, it makes sense to use std::string to hold the current value. Getting the next value just means adding 1 to the current value and handling the carries, just as you’d do by hand. So;
class binary_string {
public:
binary_string() : text(‘0’) {}
const std::string& get() const { return text; }
bool next();
private:
std::string text;
};
bool binary_string::next() {
std::size_t pos;
for (pos = 0; pos < text size(); ++pos) {
if (text[pos] == ‘0’) {
text[pos) = ‘1’:
break;
else
text[pos] = ‘0’;
}
if (pos == 64)
return false;
if (pos == text.size())
text.push_back(‘0’)
return true;
}
To use:
int main() {
binary_string str;
do {
std::cout << str.get();
} while (str.next());
return 0;
}
Be prepared for this to take a long time to finish.

Problem to acces a position in an list c++

I'm implementing a function to insert a set of nodes in a set of routes. This function is described as follows:
void Repair_ChooseARouteAndAPositionRandomly (SOLUTION &sol, vector<int> &NodesPscine, vector<int>&RoutesPscine, DATA data, int max_slot){
while (NodesPscine.size() != 0) {
int aux;
int pairpos;
int pairRoute;
int pairNode;
list<VEHICLE>:: iterator irouteit;
vector<bool> RotaJaFoiSorteada = vector<bool>(sol.SetP.size(),false);
pairpos = rand() % NodesPscine.size();
pairNode = NodesPscine[pairpos];
pairRoute = RoutesPscine[pairpos];
bool sorteaDenovo = true;
while (sorteaDenovo == true) {
bool rotaJafoiSorteada = false;
while (rotaJafoiSorteada == false) {
aux = rand() % sol.SetP.size();
if (RotaJaFoiSorteada[aux] == false) {
irouteit = next(sol.SetP.begin(), aux);
rotaJafoiSorteada = true;
RotaJaFoiSorteada[aux] = true;
}
}
bool NoJaExisteNaRota = false;
list<int>:: iterator ii;
for (ii = irouteit->rotaVehicle.begin(); ii != irouteit->rotaVehicle.end(); ii++) {
if (pairNode == *ii) {
NoJaExisteNaRota = true;
break;
}
}
if (NoJaExisteNaRota == false) {
double melhorDur = 0;
list <int>::iterator melhorPos = irouteit->rotaVehicle.begin();
double NovaDur;
InsereNaPosicaoMaisBarata (irouteit->rotaVehicle, irouteit->type, pairNode, data, melhorDur, melhorPos);
NovaDur = irouteit->duracaoTotal + melhorDur;
if (NovaDur <= max_slot) {
irouteit->rotaVehicle.insert(melhorPos,pairNode);
irouteit->duracaoTotal = NovaDur;
int cont = 0;
list<int>::iterator itprim = irouteit->rotaVehicle.begin();
list<int>::iterator itseg;
irouteit->distanceTotal = 0;
while (cont < irouteit->rotaVehicle.size()-1) {
itseg = next(itprim, 1);
irouteit->distanceTotal += data.dist[*itprim][*itseg];
++itprim;
++cont;
}
sorteaDenovo = false;
NodesPscine.erase(NodesPscine.begin()+pairpos);
RoutesPscine.erase(RoutesPscine.begin()+pairpos);
} // if (NovaDur <= max_slot) {
} // if (NoJaExisteNaRota == false) {
} // while (sorteaDenovo == true) {
} // while (NodesPscine.size() != 0) {
}
I also describe another function and some structs that may be important to identify my mistake.
void InsereNaPosicaoMaisBarata (list<int> Rota, int vehicle, int no, DATA data, double &melhorDur, list <int>::iterator &melhorPos ) {
list <int>:: iterator itprim = Rota.begin();
list <int>:: iterator itseg;
int cont = 0;
melhorDur = 10000000000000000;
while (cont < (Rota.size()-1)) {
itseg = next(itprim, 1);
double aux = data.l[vehicle][*itprim][no] + data.l[vehicle][no][*itseg] - data.l[vehicle][*itprim][*itseg];
if (melhorDur > aux) {
melhorDur = aux;
melhorPos = itseg;
}
++itprim;
++cont;
}
}
struct VEHICLE {
int type;
int idx;
double custo;
double distanceTotal;
double duracaoTotal;
list<int> rotaVehicle;
};
struct SOLUTION {
list<VEHICLE> SetP;
};
Everything goes fine to insert the first pairNode randomly chosen. However, when a second pairNode is chosen, the program runs until the line just after calling the function InsereNaPosicaoMaisBarata. If I put any cout inside this function, it does not appear. I think the problem is in the line "irouteit->rotaVehicle.insert(melhorPos,pairNode);", because when I comment it, the code runs until the end.
If I have, for example, these routes:
route 1 { 4 2 1 3 4 }
route 2 { 3 2 4 3 }
route 3 { 4 2 1 3 4 }
route 4 {4 1 3 4 }
route 5 { 2 4 2 }
route 6 { 3 2 4 3 }
If we have the nodes to be inserted in any of these routes as NodesPscine = {3,2}. If node 3 is randomly chosen to be inserted in route 5, it works well.
After, node 4 is chosen to be inserted in route 4. Then, the program runs until the function InsereNaPosicaoMaisBarata and the error message appears:
*** Error in `./heuristica': malloc(): memory corruption (fast): 0x00000000035d0680 ***
I suppose the way I'm identifying the melhorPos is not okay. But I can't figure out what is wrong.
You did not post all of your code, but one obvious mistake is this:
InsereNaPosicaoMaisBarata (irouteit->rotaVehicle, // <-- This parameter
irouteit->type,
pairNode,
data,
melhorDur,
melhorPos);
Your function is declared as this:
void InsereNaPosicaoMaisBarata (list<int> Rota, // <-- passed by value
int vehicle,
int no,
DATA data,
double &melhorDur,
list <int>::iterator &melhorPos )
Then inside the function, you do this:
list <int>:: iterator itprim = Rota.begin(); // <-- This is a local std::list
list <int>:: iterator itseg;
//...
itseg = next(itprim, 1);
//...
melhorPos = itseg; // <-- This is now referencing a local std::list entry
On return, you then use the last parameter:
irouteit->rotaVehicle.insert(melhorPos,pairNode); // <-- Trouble
The problem with all of this is that the first parameter (Rota) is passed by value. That means the function InsereNaPosicaMaisBarata is working with a temporary std::list.
You then set melhorPos to point to an entry into the temporary list. The problem is that on return, Rota has been destroyed, and you now have an invalid iterator being used on the return.
The solution is to change the function to have the first parameter as a reference:
void InsereNaPosicaoMaisBarata (list<int>& Rota, // <-- passed by reference
int vehicle,
int no,
DATA data,
double &melhorDur,
list <int>::iterator &melhorPos )

How to count duplicates in List<Integer>

Duplicate of Count occurrences of words in ArrayList
i trying to counts duplicates of my JSON response.
Im got values from 1,2 ... to 13,14
First what i do is sort the list:
Collections.sort(calues);
every value can be used 4 times.
So at last i have list with 1,1,1,1,2,2,2,2.....14,14,14,14
I need to count repeated values and when any value like 1,2 etc will be repeated 3 times i need to give message to user.
How i can do this?
Thanks for help :)
Going with tutorial i create this:
public int count(List<Integer> nums) {
boolean inclump = false;
int clumpcnt = 0;
for (int i = 1; i < nums.size(); i++) {
if (Objects.equals(nums.get(i), nums.get(i - 1))) {
if (!inclump) {
inclump = true;
clumpcnt++;
if(clumpcnt ==3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
}
} else {
inclump = false;
}
}
return clumpcnt;
}
but this count the values and when values like 2,2 and 3,3 and 4,4 then this function enter
if(clumpcnt ==3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
I declared a list private List<Integer> cardsValues = new ArrayList<>();
Then i added values here:
first 5 on start application:
#Override
public void onNext(#NonNull Cards cards) {
cardsArray = cards.getArrayCards();
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
}
And the on every click with "Get new Cards"
Im adding new value with this same method
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
And here i call the method
private void checkDuplicateAchievement() {
Collections.sort(cardsValues);
count(cardsValues);
}
Here is my full method
private void getCards(final String deck_id, final int count) {
cardApi.getCards(deck_id, count)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Cards>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Cards cards) {
cardsArray = cards.getArrayCards();
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
cardsRecyclerView.notifyDataSetChanged(); recyclerView.smoothScrollToPosition(cardsRecyclerView.getItemCount());
checkDuplicateAchievement();
}
#Override
public void onError(#NonNull Throwable e) {
}
#Override
public void onComplete() {
}
});
}
You can make use of a HashMap like below.
** Not tested , typing java after a long time!, Just to give you an idea.
public int count(List<Integer> nums) {
Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
for (int i = 1; i < nums.size(); i++) {
if(countMap.get(nums[i]) != null){
countMap.set(i, countMap.get(nums[i]) + 1)
if (countMap.get(i) >=3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
}else{
countMap.set(i, 1)
}
}
}
Try this:
public int count(List<Integer> nums) {
boolean inclump = false; // Not used
int clumpcnt = 0;
int value = nums.get(0);
for (int i = 1; i < nums.size(); i++) {
if (Objects.equals(value, nums.get(i))) {
clumpcnt++;
if (clumpcnt == 3) {
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
Log.d("COUNT", "WOW VALUE " + String.valueOf(value) + " REPEATED 3 TIMES, YOU WIN");
clumpcnt = 0;
}
} else {
clumpcnt = 0;
value = nums.get(i);
}
}
return clumpcnt;
}
FYI, nums list contains 1,1,1,1,2,2,2,2,3,3,3,3
OUTPUT LOG:
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 1 REPEATED 3 TIMES, YOU WIN
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 2 REPEATED 3 TIMES, YOU WIN
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 3 REPEATED 3 TIMES, YOU WIN
You can sort your list and then loop the sorted elements and compare values at adjacent positions.If they match then duplicates are present

push attribute data to trie, add to multiple keys

my knowledge is limited but I have been working (hacking) at this specific data structure for awhile
I use a trie to store ontology strings that are then returned as a stack including the 'gap' proximity when get (string) is called. As an add on the trie stores attributes on the key. The further down the string the greater the detail of the attribute. This is working well for my purposes.
As an additional add on, I use a wildcard to apply an attribute to all child nodes. For example, to add 'paws' to all subnodes of 'mammals.dogs.' I push(mammals.dogs.*.paws). Now, all dogs have paws.
The problem is only the first dog get paws. The function works for push attributes without wild
If you want I can clean this up and give a simplified version, but in the past i've found on stackoverflow it is better to just give the code; I use 'z' as the '*' wild
void Trie::push(ParseT & packet)
{
if (root==NULL) AddFirstNode(); // condition 1: no nodes exist, should this be in wrapper
const string codeSoFar=packet.ID;
AddRecord(root, packet, codeSoFar); //condotion 2: nodes exist
}
void Trie::AddFirstNode(){ // run-once, initial condition of first node
nodeT *tempNode=new nodeT;
tempNode->attributes.planType=0;
tempNode->attributes.begin = 0;
tempNode->attributes.end = 0;
tempNode->attributes.alt_end = 0;
root=tempNode;
}
//add record to trie with mutal recursion through InsertNode
//record is entered to trie one char at a time, char is removed
//from record and function repeats until record is Null
void Trie::AddRecord(nodeT *w, ParseT &packet, string codeSoFar)
{
if (codeSoFar.empty()) {
//copy predecessor vector at level n, overwrites higher level vectors
if (!packet.predecessorTemp.empty())
w->attributes.predecessorTemp = packet.predecessorTemp;
return; //condition 0: record's last char
}
else { //keep parsing down record path
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char || codeSoFar[0] == 'z') {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
InsertNode(w, packet, codeSoFar); //condition 3: no existing char --> mutal recursion
}
}
//AddRecord() helper function
void Trie::InsertNode(nodeT *w, ParseT &packet, string codeSoFar) // add new char to vector array
{
for (unsigned int i=0; i <=w->alpha.size(); i++) { // loop and insert tokens in sorted vector
if (i==w->alpha.size() || codeSoFar[0] < w->alpha[i].token_char) { //look for end of vector or indexical position
//create new TokenT
tokenT *tempChar=new tokenT;
tempChar->next=NULL;
tempChar->token_char=codeSoFar[0];
//create new nodeT
nodeT *tempLeaf=new nodeT;
tempLeaf->attributes.begin = 0;
tempLeaf->attributes.end = 0;
tempLeaf->attributes.planType = 0;
tempLeaf->attributes.alt_end = 0;
//last node
if (codeSoFar.size() == 1){
tempLeaf->attributes.predecessorTemp = packet.predecessorTemp;
}
//link TokenT with its nodeT
tempChar->next=tempLeaf;
AddRecord(tempLeaf, packet, codeSoFar.substr(1)); //mutual recursion --> add next char in record, if last char AddRecord will terminate
w->alpha.insert(w->alpha.begin()+i, *tempChar);
return;
}
}
}
root is global nodeT *w
struct ParseT {
string ID; //XML key
int begin = 0; //planned or actual start date
int end = 0; //planned or actual end date - if end is empty then assumed started but not compelted and flag with 9999 and
int alt_end = 0; //in case of started without completion 9999 case, then this holds expected end
int planType = 0; //actuals == 1, forecast == 2, planned == 3
map<string, string> aux;
vector<string> resourceTemp;
vector<string> predecessorTemp;
};
In this code
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char || codeSoFar[0] == 'z') {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
you are returning as soon as you call AddRecord, even if it is because of a wildcard. It might be easier to have a separate loop when codeSoFar[0] == 'z' that goes through all the alphas and adds the record. Then have an else clause that does your current code.
Edit: Here is what I meant, in code form:
else { //keep parsing down record path
// Handle wildcards
if (codeSoFar[0] == 'z') {
for (unsigned int i = 0; i < w->alpha.size(); i++) {
AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
else {
// Not a wildcard, look for a match
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char) {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
InsertNode(w, packet, codeSoFar); //condition 3: no existing char --> mutal recursion
}
}

How to swaps first and last element of a queue in C++?

I have written a function to swap first and last elements of a queue in C++
void swap(queue Q)
{
queue temp;
createQ (temp);
int x,first,last;
first=dequeue(Q);
while(!isemptyQ(Q))
{
x=dequeue(Q);
last=x;
enqueue(x,temp);
}
enqueue(last,Q);
while(!isemptyQ(temp))
{
x=dequeue(temp);
if(x!=last) enqueue(x,Q); //(if) to avoid adding last element again
}
enqueue(first,Q)
}
note: "just consider (isempty,dequeue,createQ and enqueue) are other functions>>(my first year)"
but if the last element was duplicated in the middle like that
if that are the elements of the queue (5,1,9,3,9)
if we trace that function on these elements it would be (9,1,3,5)
there's a 9 missing !!
so if there's an escape from that or any other idea for the function ?!
No need to check for last if you don't push it.o I would rather do something like:
while(!isemptyQ(Q))
{
x=dequeue(Q);
if (isemptyQ(Q))
{
last=x;
}
else
{
enqueue(x,temp);
}
}
enqueue(last,Q);
while(!isemptyQ(temp))
{
x=dequeue(temp);
enqueue(x,Q);
}
By the way, your code won't work for empty or 1 element queues.
Below is pseudo code that tries to cover all special cases including 1 or zero elements in the queue
swap_first_last(q) {
dequeue(q, x, isEmpty);
initialize(tmp);
first = x;
count = 0;
while(!isEmpty) {
count ++;
last = x;
dequeue(q, x, isEmpty);
if(!isEmpty) {
enqueue(tmp, last);
}
}
if(count == 0) return;
enqueue(q, last);
if(count >= 2) {
dequeue(tmp, x, isEmpty);
while(!isEmpty) {
dequeue(tmp, x, isEmpty);
if(!isEmpty) {
enqueue(q, x);
}
}
enqueue(q, first);
}
}