Moore Machines implementation in C++

Moore Machines: A Moore Machine is basically a DFA with an output associated with every state. These machines can be used for a wide variety of tasks such as counting occurrences of a particular substring in a given string, finding 2’s complement of a binary number, etc.

Working of Moore Machine:

  • It has an output associated with each state.
  • On taking input, it goes to the next state.
  • On reaching the next state, it prints the output of the next state.
  • This continues until the end of input is reached.

Some Applications of Moore Machine

Application 1:
Given a string S consisting of a and b, and a substring “abb”, the task is to count the occurrence of the given substring str in the given string S using Moore Machines.

Examples:

Input: S = “babbbbabb”
Output:
00010001
occurences: 2
Explanation:
The substring “abb” occurs two times in the given string.
Hence, for every substring “abb” a ‘1’ is produced.
The number of 1s is 2.



Input: S = “ab”
Output:
000
occurences: 0
Explanation:
There is no occurrence of substring “abb” in the given string.
Hence, the number of 1s is 0.

Approach:

The required Moore Machine for this problem is given by:

The Transition table for the machine is given below:

To implement this, create a structure for mapping input to its next state:

struct item
{
     int value;
     State* next;
};

Then, include this struct as a data member to our class State. The class has three data members:

  • Input_1: This is a variable of type item defined above. It maps the first type of input ‘a’ to its next State.
  • Input_2: This is also a variable of type item. It maps the second type of input ‘b’ to its next State.
  • m_out: This is the output associated with each state of the Moore Machine.

Each object of the class behaves as a state. It takes input and goes to the appropriate next state. To go to the next state, an object pointer can be used. Every object also has an input associated with it.

The following member functions will be used to work on this data:



  • Initialize(): This intializes the class object(state) with inputs and corresponding next state(s).
  • Transition(): This acts as a transition table for machine. It takes a character from the input string and passes it to the current state which then goes into appropriate next state after producing an output.
  • Traverse(): This function takes an input string and character by character passes it into the transition function and return the output string.
  • mooreOut(): This function defines the required states(objects) and initializes them to required values. Then passes the input string to the traverse function and recieves output string.
  • countStr(): This function counts the occurences of 1 in the output string and returns it.

The next step is to store the current state of the machine while passing string inputs to it. This can be done by using a static Object pointer as a class data member: 

Below is the implementation of the above approach:

C++14

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Define a class named State
class State {
private:
    // Item
    struct item {
        char value;
        State* next;
    };
  
    // Three states
    item Input1;
    item Input2;
    char m_out;
  
public:
    // Constructor
    State()
        : Input1{ ' ', nullptr },
          Input2{ ' ', nullptr },
          m_out{ ' ' }
    {
    }
  
    // Member functions
    static State* m_ptr;
    void Initialize(item input1,
                    item input2,
                    char out);
    static char Transition(char x);
    static string Traverse(string& str,
                           int n);
};
  
// Global object pointer points to
// current state
State* State::m_ptr{ nullptr };
  
// Function that initializes the states
// with appropriate values
void State::Initialize(item input1,
                       item input2,
                       char out)
{
    Input1 = input1;
    Input2 = input2;
    m_out = out;
}
  
// Transition function that takes each
// character of string
char State::Transition(char x)
{
    char ch{};
  
    // Prints the output
    if ((*m_ptr).Input1.value == x) {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input1.next;
    }
    else {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input2.next;
    }
  
    // Return ch
    return ch;
}
  
// Takes the whole string and pass
// it through machine
string State::Traverse(string& str,
                       int n)
{
    string str1{};
  
    // Add all the transition state to
    // the string str1
    for (int i = 0; i < n; i++)
        str1 += Transition(str[i]);
  
    // Append output
    str1 += (*m_ptr).m_out;
    cout << (*m_ptr).m_out << endl;
  
    // Return str1
    return str1;
}
  
// Function that create states and
// produce output
string mooreOut(string str, int n)
{
    State q1, q2, q3, q4;
  
    // Initializing the states
    q1.Initialize({ 'a', &q2 },
                  { 'b', &q1 }, '0');
    q2.Initialize({ 'a', &q2 },
                  { 'b', &q3 }, '0');
    q3.Initialize({ 'a', &q2 },
                  { 'b', &q4 }, '0');
    q4.Initialize({ 'a', &q2 },
                  { 'b', &q1 }, '1');
    State::m_ptr = &q1;
  
    // Traverse the string str1
    string str1{ State::Traverse(str, n) };
    return str1;
}
  
// Function that counts the occurences
// of 1 in the output string
int countStr(string& str, int n)
{
    int count{};
  
    // Count the 1s in str
    for (int i = 0; i < n; i++) {
        if (str[i] == '1')
            count++;
    }
  
    // Return count
    return count;
}
  
// Driver Code
int main()
{
  
    // Given string
    string str{ "babbabbabbb" };
  
    int n{ static_cast<int>(str.length()) };
  
    // Function Call
    string str1{ mooreOut(str, n) };
    int n1{ static_cast<int>(str.length()) };
  
    // Print the count of substring
    cout << "abb occurs " << countStr(str1, n1)
         << " times\n";
    return 0;
}

chevron_right


Output:

000010010010
abb occurs 3 times


Time Complexity: O(N)
Auxiliary Space: O(N)

Application 2:
Given a binary string str, the task is to find the 2s complement of the given string str.

Input: str = “111010000”
Output: 000110000

Input: str = “111”
Output: 001

Approach: The idea is to start from the rightmost bit and pass it into the machine giving the output. Pass the whole string like this, going from right to left. The following observations can be observed:

For Example: The given string is “111010000”. Now, 2s compliment is given by 1s complement of(str) + 1. Therefore,

str =           "111010000"
1s compliment = "000101111"
                +        1
---------------------------
2s compleemnt =  000110000

Here we can observe that from the rightmost bit the bits are copied the same way untill 1 appears. After that all the bits are reversed.



Therefore, the idea is to define a Moore Machine to start to take input from the rightmost side. As long as the bit is 0 it gives the same output(0). When 1 is encountered then it gives 1 for that. After this, for any bit taken as input its inverse is given as output.

The Moore Machine for this problem is given below:

To implement this first, map the transition table for this machine. Three states are needed i.e. three objects of class State defined at the beginning:

  • State1 => Initailize( {‘0’, &State1}, {‘1’, &State2}, ‘0’)
  • State2 => Initialize( {‘0’, &State2}, {‘1’, &State3}, ‘1’)
  • State3 => Initialize( {‘0’, &State2}, {‘1’, &State3}, ‘0’)

After initialization, a Transition function is needed like the one defined above. It takes an input and for that prints output of the current state and goes to the next state by mapping input to the next state using the transition table defined above. Then to traverse the string, the transition begins from the rightmost bit and goes till the leftmost bit.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Define a class named State
class State {
private:
    struct item {
        char value;
        State* next;
    };
    item Input1;
    item Input2;
    char m_out;
  
public:
    // Constructors
    State()
        : Input1{ ' ', nullptr },
          Input2{ ' ', nullptr },
          m_out{ ' ' }
    {
    }
    static State* m_ptr;
  
    // Member Functions
    void Initialize(item input1,
                    item input2,
                    char out);
    static char Transition(char x);
    static string Traverse(string& str,
                           int n);
};
  
// Global object pointer points to
// current state
State* State::m_ptr{ nullptr };
  
// Function that initializes the states
// with appropriate values
void State::Initialize(item input1,
                       item input2,
                       char out)
{
    Input1 = input1;
    Input2 = input2;
    m_out = out;
}
  
// Transition function takes each
// character of string
char State::Transition(char x)
{
    char ch{};
  
    // Prints the output
    if ((*m_ptr).Input1.value == x) {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input1.next;
    }
    else {
  
        // Output the current state
        cout << (*m_ptr).m_out;
        ch = (*m_ptr).m_out;
  
        // Next input state
        m_ptr = (*m_ptr).Input2.next;
    }
  
    // Return ch
    return ch;
}
  
// Takes the whole string and passes
// through machine
string State::Traverse(string& str, int n)
{
    string str1{};
  
    // Add all the transition state to
    // the string str1
    for (int i = n - 1; i >= 0; i--) {
        str1 += Transition(str[i]);
    }
  
    // To read the characters from end
    // therefore we need to reverse
    reverse(str1.begin(), str1.end());
  
    return str1;
}
  
// Function to create states and
// produce output
string mooreOut(string str, int n)
{
    State q1, q2, q3;
  
    // Initializing the states
    q1.Initialize({ '0', &q1 },
                  { '1', &q2 }, '0');
    q2.Initialize({ '0', &q2 },
                  { '1', &q3 }, '1');
    q3.Initialize({ '0', &q2 },
                  { '1', &q3 }, '0');
    State::m_ptr = &q1;
    return State::Traverse(str, n);
}
  
// Driver Code
int main()
{
    // Given string
    string str{ "111010000" };
    int n{ static_cast<int>(str.length()) };
  
    // Function Call
    string str1{ mooreOut(str, n) };
  
    // Print the output
    cout << "2's complement: " << str1;
    return 0;
}

chevron_right


Output:

2's complement: 000110000


Time Complexity: O(N), where N is the length of the given binary string.
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important CS Theory concepts for SDE interviews with the CS Theory Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.