Thread: simple singleton pattern

  1. #1
    Registered User
    Join Date
    Aug 2016
    Location
    Canada
    Posts
    8

    simple singleton pattern

    I've been struggling with this. Let's define a SINGLETON to be a data element that is not repeated immediately before or after itself in the sequence.
    I pass most tests. But I'm failing in this one:
    a b c c b b b d a
    It should return 4 but its returning 3.
    I think I'm not granting a point for the first a
    I think that my code is a bit of a cheat too ie: going below 0 sometimes.
    Wondering if someone can offer advice to steer me in the right algorithm.?

    Code:
    #include<iostream>
    using namespace std;
    
    
    int main(){
    
    
    string previous_word = ""; 
    string word;
    int n = 0;
    
    
    cout << "Please enter a sequence of words terminated by xxxxx" << endl;
    //a b c c b b b d a
    
    
    cin >> word;
    
    
    while (word != "xxxxx"){
        previous_word = word;
        cin >> word;
        if (word != previous_word)
            n++;
        else
            n--;
    };
    
    
    if (n < 0)
        n=0;
    
    
    cout << "There were " << n << " singletons found." << endl;
    }

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Should NOT the correct answer be 6 instead of 4?

    Edit: If yes, think about whether you really need the subtraction.

    Tim S.
    Last edited by stahta01; 08-21-2016 at 07:57 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    No, he's right, the answer should really be 4.

    The program actually has lots of problems. If I take his code and insert some output statements, we see what's really going on. Not only is there the problem Tim S. pointed out, but you can easily get in the middle of a sequence like c, c, b and count it when it shouldn't.
    Code:
    // OP's output:
    b versus a
    It counts! singletons=1
    c versus b
    It counts! singletons=2
    c versus c
    It doesn't count! singletons=1
    b versus c
    It counts! singletons=2
    b versus b
    It doesn't count! singletons=1
    b versus b
    It doesn't count! singletons=0
    d versus b
    It counts! singletons=1
    a versus d
    It counts! singletons=2
    xxxxx versus a
    It counts! singletons=3
    There were 3 singletons found.
    Obviously wrong for lots of reasons.

    The correct algorithm for the output OP wants is a little more clever. You have to be able to look 1 back and 1 forward from a word in the middle of the sequence. Perhaps use a stack to maintain the order of the sequence, pushing each word. In the very beginning when the stack is empty, just push the word. When the stack has two elements, compare them and count a singleton if you can. Once the stack has 3 words in it, compare the middle one with the others, counting it as a singleton if you can. Then you have to recreate the stack with 1 element in it: the most recent word at the top. Now keep going until you are out of words.

    There are obviously more convenient implementations than using a stack, but I think that explains it best. I'd like OP to try coding this method.

    In my test program, it also gives me 4 singletons in "a b c c b b b d a".
    Last edited by whiteflags; 08-21-2016 at 08:49 PM.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Just to add, this method is for longer sequences. If the sequence is actually short, it's not a big deal, but it is handled different.

    Basically you have the following word (result) pairs: a (1); a, b (2); a, a (0). That's the only headache I've really found, and you can just treat it as a special case again.

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    a b *c *c *b *b *b d a

    The ones with the "*" if front are the ones I think now needs removed.

    Which leaves a b d a with a count of 4.

    Is this correct?

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    yeah

  7. #7
    Registered User
    Join Date
    Aug 2016
    Location
    Canada
    Posts
    8
    I wrote a stack implementation yes, but it still comes down to an algorithm.
    My stack main alg. has too much conditional logic. Instead I have crafted this simple loop.
    It is close I think. It fails on the last test. It is counting 9-7-2 twice for some reason.
    I will continue the stack solution after if this current try is not possible.


    Code:
    #include <iostream>
    using namespace std;
    
    
    int main(){
    
    
    int start = 0;
    int array_size = 9;
    int end = array_size - 1;
    
    
    //int array[array_size] = {7,7,2}; //pass 1
    //int array[array_size] = {2,7,7}; //pass 1
    //int array[array_size] = {2}; //pass 1
    //int array[array_size] = {2,7}; //pass 2 
    //int array[array_size] = {2,7,4}; //pass 3
    //int array[array_size] = {2,1,2,1}; //pass 4
    //int array[array_size] = {2,1,2,1,2}; //pass 5
    //int array[array_size] = {2,1,2,1,2,1}; //pass 6
    //int array[array_size] = {2,2,2}; //pass 0
    //int array[array_size] = {5,1,5}; //pass 3
    int array[array_size] = {2,7,5,5,7,7,7,9,2}; //fail 5
    
    
    int singleton_count = 0;
    
    
    for (int i=0; i<=end; i++){
    
    
    	for (int j=i; j>=start && array[j-1] !=array[j] && array[j+1] !=array[j]; j--){
    		
    		cout << array[j] << " " << array[j-1] << " " << array[j+1] << endl;
    		
    		singleton_count += 1;
    		start += 1;
    				
    	}
    }
    cout << "there are "<< singleton_count << " singletons" << endl;
    return 0;
    }

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I wrote a stack implementation yes, but it still comes down to an algorithm.
    Yes, the reason I suggested a stack was because you were initially reading the input directly from a stream, so you needed some way to store at least 3 old elements to do the algorithm right.

    It is close I think. It fails on the last test. It is counting 9-7-2 twice for some reason.
    Well, now your program is exhibiting undefined behavior. I mean, the algorithm starts off with j=0, then eventually array[-1] is accessed. It could have nothing to do with it, just saying. Either way, the implementation is slightly different from what I would expect. I can't say I see a point in nesting the loop.

    This code does all the sequences you've shown here.
    Code:
    template<typename T>
    unsigned long CountSingletons(const vector<T>& seq)
    {
        // Special cases
        if (seq.size() == 1)
            return 1;
        if (seq.size() == 2)
            return seq.front() != seq.back() ? 2 : 0;
        
        unsigned long singletons = 0;
        
        // Count first element if not paired
        if (seq[0] != seq[1])
            singletons++;
        // Count last element if not paired
        if (seq.back() != seq[seq.size() - 2])
            singletons++;
        
        // the rest
        for (typename vector<T>::size_type i = 1; i < seq.size() - 1; i++) {
            if (seq[i - 1] != seq[i] && seq[i] != seq[i + 1])
                singletons++;
        }
        return singletons;
    }
    The template is so you can do numbers or words...
    Last edited by whiteflags; 09-03-2016 at 11:29 PM.

  9. #9
    Registered User
    Join Date
    Aug 2016
    Location
    Canada
    Posts
    8
    Thanks, I will study this that you sent me. My stack is below for posterity. It is missing on aab, counting 2 instead of 1.
    I've tried and am close to re-writing it. Would you suggest a total re-write even though the stack is working?
    Or am I missing something simple that I can still do this with the stack idea.
    Code:
    #include<iostream>
    #include<stdlib.h>
    using namespace std;
    
    
    struct wordNode{
       string word;
       struct wordNode *next;
    };
    
    
    struct wordNode *wordCollection = NULL;
    struct wordNode *prev, *cur;
    struct wordNode * insert(struct wordNode *p);
    void print(wordNode*p);
    void delete_list(struct wordNode *list);
    int count_nodes(struct wordNode *p);
    int count_singletons(struct wordNode *p, int count_of_nodes);
    
    
    int main(){
    
    
    char code;
    int count_of_nodes;
    int singletons;
    
    
    for (;;) {
    
    
        cout << "Enter list command(+-flx): ";
        cin >> code;
    
    
        switch (code) {
          case '+':
              wordCollection = insert(wordCollection);
              break;
          case 'f':
              count_of_nodes = count_nodes(wordCollection);
              cout << count_of_nodes << " nodes in list." << endl;
              singletons = count_singletons(wordCollection,count_of_nodes);
              cout << "There are " << singletons << " singletons in the list." << endl;
              break;
          case '-':
              delete_list(wordCollection);
              break;
          case 'l':
              print(wordCollection);
              break;
          case 'x':
              cout << "Goodbye." << endl;
              return 0;
          default:
              cout << "Illegal code" << endl;
        }
        cout << endl;
      }
    }
    
    
    struct wordNode * insert(struct wordNode *p){
    
    
        struct wordNode *newNode;
    
    
        string string_to_store;
        cout << endl;
        cout << "What string to store?" << endl;
        cin >> string_to_store;
        newNode = new wordNode;
        newNode->word = string_to_store;
        newNode->next = p;
        return newNode;
    }
    
    
    
    
    void print(struct wordNode *p){
    while (p != NULL)
      {
        cout << p->word;
        p=p->next;
      }
    }
    
    
    
    
    int count_nodes(struct wordNode *p){
    int count=0;
    while (p != NULL)
      {
        count++;
        p=p->next;
      }
    return count;
    }
    
    
    
    
    void delete_list(wordNode *head){
    
    
    if (head != NULL)
       {
       struct wordNode *cur;
       cur = head->next;
       while(cur!=NULL)
          {
             head->next = cur->next;
             cur->next = NULL;
             free(cur);
             cur = head->next;
          }
       }
    }
    
    
    
    
    int count_singletons(struct wordNode *p, int count_of_nodes){
    
    
    struct wordNode *cur, *prev;
    //int counter=0;
    string prev_cur = "";
    string prev_prev = "";
    int singletons=0;
    bool real_point;
    
    
       if (count_of_nodes == 0)
          return 0;
    
    
       if (count_of_nodes == 1)
          return 1;
    
    
       if (count_of_nodes == 2){
          cur=p;
          prev=cur;
          cur=cur->next;
          if (prev->word != cur->word)
            return 2;
          else
            return 0;}
    
    
    
    
       for (cur=p; cur!=NULL; ){
    
    
         prev=cur;
         cur=cur->next;
    
    
         //if we are at the end and the last two match then don't count else count
         if ((cur==NULL) && (prev_prev.length()> 0 ) && (prev->word!=prev_prev)&& (real_point == true))
           singletons += 1;
         else
         real_point = false;
         if ((cur!=NULL)&&(prev->word != cur->word)){
           singletons += 1;
           real_point = true;
           prev_prev = prev->word;
           }
    
    
       }
       return singletons;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Adapt a singleton class to lose it`s singleton feature
    By heatblazer in forum C++ Programming
    Replies: 4
    Last Post: 04-08-2016, 05:54 PM
  2. Singleton Pattern Question
    By nickman in forum C++ Programming
    Replies: 3
    Last Post: 07-09-2014, 10:45 PM
  3. Replies: 0
    Last Post: 11-19-2008, 01:16 AM
  4. Simple Pattern Recognition
    By SMurf in forum Tech Board
    Replies: 1
    Last Post: 01-17-2007, 11:14 AM
  5. Singleton
    By Smallz in forum C++ Programming
    Replies: 5
    Last Post: 09-12-2006, 11:57 PM

Tags for this Thread