DFA based division in C++?

C++Server Side ProgrammingProgramming

The Deterministic Finite Automaton(DFA) is used for checking if a number is divisible by another number k or not. The algorithm is useful because it can also find the remainder if the number isn’t divisible.

In DFA based division we build a DFA table with k states. We consider binary representation of the number so there is only 0 and 1 in each state in DFA.

The createTransTable(int k, int transTable[][2]) function is used for creating the transTable and storing the states in it. It takes the number k by which the number is to be divisible and transTable[][2] which is an array with 2 columns. We then declare two variables trans_0 that stores bit 0 next state and trans_1 which stores bit 1 next state.

void createTransTable(int k, int transTable[][2]){
   int trans_0, trans_1;

The for loop inside runs till state is less than k. If the trans_0 is less than the number k then transTable[state][0] equals to trans_0 else k is subtracted from trans_0.

For trans_1 If the trans_1 is less than the number k then transTable[state][1] equals to trans_1 else k is subtracted from trans_1.

for (int state = 0; state < k; state++){
   trans_0 = state << 1;
   transTable[state][0] = (trans_0 < k) ? trans_0 : trans_0 - k;
   trans_1 = (state << 1) + 1;
   transTable[state][1] = (trans_1 < k) ? trans_1 : trans_1 - k;
}

The checkDivisible(int num, int &state, int transTable[][2]) function takes the number which is to be divided , the state variable by reference and the transTable[][2] array. It checks if the number is not equal to 0 then it basically shifts number from left to right using bitwise right shift by 1 untill the number becomes 0 by recursively calling itself. By right shifting the number is divided by 2 untill it becomes 0. The transtable[state][num&1] is then assigned to state variable.

void checkDivisible(int num, int &state, int transTable[][2]){
   if (num != 0){
      checkDivisible(num >> 1, state, transTable);
      state = transTable[state][num&1];
   }
}

The isDivisible (int num, int k) function takes the dividend num and dividend k. The transition table with 2 columns and k number of rows transTable[k][2] is declared. The createTransTable(k, transTable) and checkDivisible(num, state, transTable) are called which modify the state variable. The state variable is then returned which represents our remainder left our dividing.

int isDivisible (int num, int k){
   int transTable[k][2];
   createTransTable(k, transTable);
   int state = 0;
   checkDivisible(num, state, transTable);
   return state;
}

Example

Let us look at the following implementation for DFA based division.

 Live Demo

#include <bits/stdc++.h>
using namespace std;
void createTransTable(int k, int transTable[][2]){
   int trans_0, trans_1;
   for (int state = 0; state < k; state++){
      trans_0 = state << 1;
      transTable[state][0] = (trans_0 < k) ? trans_0 : trans_0 - k;
      trans_1 = (state << 1) + 1;
      transTable[state][1] = (trans_1 < k) ? trans_1 : trans_1 - k;
   }
}
void checkDivisible(int num, int &state, int transTable[][2]){
   if (num != 0){
      checkDivisible(num >> 1, state, transTable);
      state = transTable[state][num&1];
   }
}
int isDivisible (int num, int k){
   int transTable[k][2];
   createTransTable(k, transTable);
   int state = 0;
   checkDivisible(num, state, transTable);
   return state;
}
int main(){
   int num = 67;
   int k = 5;
   int remainder = isDivisible (num, k);
   if (remainder == 0)
      cout <<num<< " is divisible by "<<k;
   else
      cout <<num<< " is not divisible by "<<k<<" and lefts remainder "<<remainder;
   return 0;
}

Output

The above code will produce the following output.

67 is not divisible by 5 and lefts remainder 2
raja
Published on 16-Jan-2021 10:06:41
Advertisements