Count all possible N-length vowel permutations that can be generated based on the given conditions
Last Updated :
15 Jan, 2024
Given an integer N, the task is to count the number of N-length strings consisting of lowercase vowels that can be generated based the following conditions:
- Each ‘a’ may only be followed by an ‘e’.
- Each ‘e’ may only be followed by an ‘a’ or an ‘i’.
- Each ‘i’ may not be followed by another ‘i’.
- Each ‘o’ may only be followed by an ‘i’ or a ‘u’.
- Each ‘u’ may only be followed by an ‘a’.
Examples:
Input: N = 1
Output: 5
Explanation: All strings that can be formed are: “a”, “e”, “i”, “o” and “u”.
Input: N = 2
Output: 10
Explanation: All strings that can be formed are: “ae”, “ea”, “ei”, “ia”, “ie”, “io”, “iu”, “oi”, “ou” and “ua”.
Approach: The idea to solve this problem is to visualize this as a Graph Problem. From the given rules a directed graph can be constructed, where an edge from u to v means that v can be immediately written after u in the resultant strings. The problem reduces to finding the number of N-length paths in the constructed directed graph. Follow the steps below to solve the problem:
- Let the vowels a, e, i, o, u be numbered as 0, 1, 2, 3, 4 respectively, and using the dependencies shown in the given graph, convert the graph into an adjacency list relation where the index signifies the vowel and the list at that index signifies an edge from that index to the characters given in the list.
- Initialize a 2D array dp[N + 1][5] where dp[N][char] denotes the number of directed paths of length N which end at a particular vertex char.
- Initialize dp[i][char] for all the characters as 1, since a string of length 1 will only consist of one vowel in the string.
- For all possible lengths, say i, traverse over the directed edges using variable u and perform the following steps:
- Update the value of dp[i + 1][u] as 0.
- Traverse the adjacency list of the node u and increment the value of dp[i][u] by dp[i][v], that stores the sum of all the values such that there is a directed edge from node u to node v.
- After completing the above steps, the sum of all the values dp[N][i], where i belongs to the range [0, 5), will give the total number of vowel permutations.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countVowelPermutation( int n)
{
int MOD = ( int )(1e9 + 7);
long dp[n + 1][5];
for ( int i = 0; i < 5; i++)
{
dp[1][i] = 1;
}
vector<vector< int >> relation = {
{ 1 }, { 0, 2 },
{ 0, 1, 3, 4 },
{ 2, 4 }, { 0 }
};
for ( int i = 1; i < n; i++)
{
for ( int u = 0; u < 5; u++)
{
dp[i + 1][u] = 0;
for ( int v : relation[u])
{
dp[i + 1][u] += dp[i][v] % MOD;
}
}
}
long ans = 0;
for ( int i = 0; i < 5; i++)
{
ans = (ans + dp[n][i]) % MOD;
}
return ( int )ans;
}
int main()
{
int N = 2;
cout << countVowelPermutation(N);
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int
countVowelPermutation( int n)
{
int MOD = ( int )(1e9 + 7 );
long [][] dp = new long [n + 1 ][ 5 ];
for ( int i = 0 ; i < 5 ; i++) {
dp[ 1 ][i] = 1 ;
}
int [][] relation = new int [][] {
{ 1 }, { 0 , 2 },
{ 0 , 1 , 3 , 4 },
{ 2 , 4 }, { 0 }
};
for ( int i = 1 ; i < n; i++) {
for ( int u = 0 ; u < 5 ; u++) {
dp[i + 1 ][u] = 0 ;
for ( int v : relation[u]) {
dp[i + 1 ][u] += dp[i][v] % MOD;
}
}
}
long ans = 0 ;
for ( int i = 0 ; i < 5 ; i++) {
ans = (ans + dp[n][i]) % MOD;
}
return ( int )ans;
}
public static void main(String[] args)
{
int N = 2 ;
System.out.println(
countVowelPermutation(N));
}
}
|
Python3
def countVowelPermutation(n):
MOD = 1e9 + 7
dp = [[ 0 for i in range ( 5 )] for j in range (n + 1 )]
for i in range ( 5 ):
dp[ 1 ][i] = 1
relation = [[ 1 ],[ 0 , 2 ], [ 0 , 1 , 3 , 4 ], [ 2 , 4 ],[ 0 ]]
for i in range ( 1 , n, 1 ):
for u in range ( 5 ):
dp[i + 1 ][u] = 0
for v in relation[u]:
dp[i + 1 ][u] + = dp[i][v] % MOD
ans = 0
for i in range ( 5 ):
ans = (ans + dp[n][i]) % MOD
return int (ans)
if __name__ = = '__main__' :
N = 2
print (countVowelPermutation(N))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int countVowelPermutation( int n)
{
int MOD = ( int )(1e9 + 7);
long [,] dp = new long [n + 1, 5];
for ( int i = 0; i < 5; i++) {
dp[1, i] = 1;
}
List<List< int >> relation = new List<List< int >>();
relation.Add( new List< int > { 1 });
relation.Add( new List< int > { 0, 2 });
relation.Add( new List< int > { 0, 1, 3, 4 });
relation.Add( new List< int > { 2, 4 });
relation.Add( new List< int > { 0 });
for ( int i = 1; i < n; i++)
{
for ( int u = 0; u < 5; u++)
{
dp[i + 1, u] = 0;
foreach ( int v in relation[u])
{
dp[i + 1, u] += dp[i, v] % MOD;
}
}
}
long ans = 0;
for ( int i = 0; i < 5; i++)
{
ans = (ans + dp[n, i]) % MOD;
}
return ( int )ans;
}
static void Main() {
int N = 2;
Console.WriteLine(countVowelPermutation(N));
}
}
|
Javascript
<script>
function
countVowelPermutation(n)
{
let MOD = (1e9 + 7);
let dp = new Array(n + 1);
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
for (let i = 0; i < 5; i++) {
dp[1][i] = 1;
}
let relation = [
[ 1 ], [ 0, 2 ],
[ 0, 1, 3, 4 ],
[ 2, 4 ], [ 0 ]
];
for (let i = 1; i < n; i++) {
for (let u = 0; u < 5; u++) {
dp[i + 1][u] = 0;
for (let v in relation[u]) {
dp[i + 1][u] += dp[i][v] % MOD;
}
}
}
let ans = 0;
for (let i = 0; i < 5; i++) {
ans = (ans + dp[n][i]) % MOD;
}
return ans;
}
let N = 2;
document.write(
countVowelPermutation(N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Efficient Approach: As we see that we only need current and previous state of the dp array, We can definitely space optimize the above solution. We can have 5 variables of previous state and 5 variables of current state that we need to compute with the given mapping relations.
Below is the implementation of above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int countVowelPermutation( int n)
{
const int MOD = 1e9 + 7;
long a = 1, e = 1, i = 1, o = 1, u = 1, a_new, e_new, i_new, o_new, u_new;
for ( int j = 2; j <= n; j++) {
a_new = e;
e_new = (a + i) % MOD;
i_new = (a + e + o + u) % MOD;
o_new = (i + u) % MOD;
u_new = a;
a = a_new, e = e_new, i = i_new, o = o_new, u = u_new;
}
return (a + e + i + o + u) % MOD;
}
int main()
{
int N = 2;
cout << countVowelPermutation(N);
}
|
Java
public class VowelPermutation {
static int countVowelPermutation( int n)
{
final int MOD = 1000000007 ;
int a = 1 , e = 1 , i = 1 , o = 1 , u = 1 ;
for ( int j = 2 ; j <= n; j++) {
int aNew = e;
int eNew = (a + i) % MOD;
int iNew = (a + e + o + u) % MOD;
int oNew = (i + u) % MOD;
int uNew = a;
a = aNew;
e = eNew;
i = iNew;
o = oNew;
u = uNew;
}
return (a + e + i + o + u) % MOD;
}
public static void main(String[] args)
{
int N = 2 ;
System.out.println(countVowelPermutation(N));
}
}
|
Python3
def countVowelPermutation(n):
MOD = 10 * * 9 + 7
a = e = i = o = u = 1
for j in range ( 2 , n + 1 ):
a_new = e
e_new = (a + i) % MOD
i_new = (a + e + o + u) % MOD
o_new = (i + u) % MOD
u_new = a
a, e, i, o, u = a_new, e_new, i_new, o_new, u_new
return (a + e + i + o + u) % MOD
N = 2
print (countVowelPermutation(N))
|
C#
using System;
class Program {
static int CountVowelPermutation( int n)
{
const int MOD = 1000000007;
long a = 1, e = 1, i = 1, o = 1, u = 1, a_new,
e_new, i_new, o_new, u_new;
for ( int j = 2; j <= n; j++) {
a_new = e;
e_new = (a + i) % MOD;
i_new = (a + e + o + u) % MOD;
o_new = (i + u) % MOD;
u_new = a;
a = a_new;
e = e_new;
i = i_new;
o = o_new;
u = u_new;
}
return ( int )((a + e + i + o + u) % MOD);
}
static void Main()
{
int N = 2;
Console.WriteLine(CountVowelPermutation(N));
}
}
|
Javascript
function countVowelPermutation(n) {
const MOD = 10 ** 9 + 7;
let a = e = i = o = u = 1;
for (let j = 2; j <= n; j++) {
const a_new = e;
const e_new = (a + i) % MOD;
const i_new = (a + e + o + u) % MOD;
const o_new = (i + u) % MOD;
const u_new = a;
a = a_new;
e = e_new;
i = i_new;
o = o_new;
u = u_new;
}
return (a + e + i + o + u) % MOD;
}
const N = 2;
console.log(countVowelPermutation(N));
|
Time Complexity: O(N)
Space Complexity: O(1)
Share your thoughts in the comments
Please Login to comment...