Words of length k generation from a DFA - c++

Good day,
I'm having a serious problem into generating a list with all the words of length k (the generate function is the function intended to generate all the words of length k, the other function is used to find out if a word is accepted or not) from a DFA just by using the DFS algorithm, here's my attempt:
#include<vector>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
vector < pair <int,char> > a[100];
int viz[100], v[100];
char s1[100];
void accepted (int q, char c, char s[100], int x) {
c = s[x];
viz[q] = 1;
cout << q;
for (int i = 0; i < a[q].size(); i++)
if (a[q][i].second == c) {
x++;
accepted (a[q][i].first, a[q][i+1].second, s, x);
}
}
void generate (int q, int k) {
int x = 0;
v[q] = 1;
while (x < k) {
cout << a[q][0].second;
for (int i = 0; i < a[q].size(); i++)
if (v[a[q][i].first] == 0)
{
cout << a[q][i].second;
generate(a[q][i].first, k);
}
x++;
}
}
int main() {
ifstream f ("input.txt");
int n, m, x, y, i, j, k;
char c;
char s[100];
f >> n >> m;
for (i = 0; i < m; i++) {
f >> x >> y;
f >> c;
a[x].push_back (make_pair(y,c));
}
for (i = 0; i < n; i++) {
cout << i << ": ";
for (j = 0; j < a[i].size(); j++)
cout << a[i][j].first << a[i][j].second << " ";
cout << endl;
}
cout << endl << "Fiite states: 2, 3" << endl << endl;
cin.get (s,100);
accepted(0, s[0], s, 0);
if (viz[2] == 1) cout << endl << "Accepted";
cout << endl;
cin >> k;
generate (0, k);
cout << endl;
return 0;
}
Also here's how my input looks like:
4 6
0 0 a
0 1 b
1 2 c
2 2 a
2 3 c
3 3 c
Here's how the DFA and the output would look like:
The serious problem I'm facing is that I can't find a way to ouput properly all the obtained words to the screen by calling the generate function.

I changed your generate function as below. Following that is an explanation as to what I thought and how I changed it.
void generate (int q, int k, string &s) {
if (k > 0) {
for (int i = 0; i < a[q].size(); i++)
{
s += a[q][i].second;
generate(a[q][i].first, k-1, s);
s.pop_back();
}
}
else {
cout << s << endl;
}
}
First and foremost, you were attempting a mixture of recursive and repetitive version of DFS, but you had no structure for keeping the stack if you were, and I doubt, going for a repetitive version using an explicit stack. Basically, your outer while loop was wrong, as the depth should increase as you recursively traverse the graph and not repetitively at a single level of recursion using a while loop as you did. You could also, as I mentioned, have a repetitive approach and use an explicitly defined stack other than the one implicitly used by memory when you implement DFS recursively. But it was easier and more intuitive to get a grasp of DFS with its recursive implementation, so I left out the outer loop.
Secondly, keeping a list of visited nodes is not a good idea as you want to list all k-length strings and your DFA is not a simple graph. (i.e. there may exist edges from node u to node u) So I removed the if statement inside the for loop as you could visit the sane node multiple times. Your approach is exponential based on the branching factor of the DFA, but if your k is small enough, it should work regardless of that. And the approach being exponential is not the problem to the solution of which you are looking with this question.
Thirdly, probably due to your usage of while loop, there was a mixup with printing a single character at each level, which is incorrect. Remember, at every node of depth k, you have to print all the characters you encountered starting from the root of the tree. That is why I added a string as the third parameter to your function. Don't worry, though, it's passed by reference and it will only cause an addition of O(k) space complexity to your algorithm, which should be negligible.
If in your main function you start traversing using the call below, you will find that it works properly.
string S;
generate(0, k, S);

Related

Trying to make a program that automatically sorts an array before using binary searching

I'm trying to make a program that asks the user to input a set of 10 numbers before asking them to select a number from the list. it would first automatically sort the ten numbers before being placed in a binary searching function.
Here's the code I wrote.
#include <iostream>
using namespace std;
int searchbinary(int arr[], int left, int right, int x){
while (left <= right){
int mid = left+(right-left)/2;
if (arr[mid]==x){
return mid;
}
else if (arr[mid]<1){
left = mid + 1;
}
else{
right = mid -1;
}
}
return -1;
}
int main(){
int num;
int darr[10];
int output;
int temp;
cout << "Enter 10 Numbers: " << endl;
for (int i=0; i<10; i++){
cin >> darr[i];
}
for (int i=0;i<10;i++){
for (int j=i+1;j<10;j++){
if (darr[i]>darr[j]){
temp = darr[i];
darr[i] = darr[j];
darr[j] = temp;
}
}
}
cout << "Enter a number from list: ";
cin >> num;
output = searchbinary(darr, 0, 9, num);
if (output ==-1){
cout << "Match not Found";
}
else {
cout << "Match Found in Position " << output;
}
return 0;
}
It works fine when I do it separately, but combining the two seems to cause an issue. Any suggestions?
Well, there seems to be a problem with your Binary Search. In the else if condition you wrote arr[mid] < 1 whereas it should have been arr[mid] < x because you are trying to find x not 1. Bellow is the code that should work:
#include <iostream>
using namespace std;
//binary search
int searchbinary(int arr[], int left, int right, int x){
while (left <= right){
int mid = (right+left)/2;//this formula is better than the one you used, it has the same results though
if (arr[mid] == x){
return mid;
}
else if (arr[mid] < x) {//here was your mistake,it is x not 1
left = mid + 1;
}
else{
right = mid -1;
}
}
return -1;
}
int main(){
int num;
int darr[10];
int output;
int temp;
cout << "Enter 10 Numbers: " << endl;
//input
for (int i=0; i<10; i++){
cin >> darr[i];
}
//sorting
for (int i=0;i<10;i++) {
for (int j=i+1;j<10;j++) {
if (darr[i]>darr[j]) {
temp = darr[i];
darr[i] = darr[j];
darr[j] = temp;
}
}
}
cout << "Enter a number from list: ";
cin >> num;
output = searchbinary(darr, 0, 9, num);//searching
//output
if (output == -1){
cout << "Match not Found";
}
else {
cout << "Match Found in Position " << output;
}
return 0;
}
If you fix that issue then your code should work but I would like to point some things out:
It is better not to hardcode numbers, like when you write 10 as a limit to all for loops. It would be better to save 10 in a variable or use darr.length().
Instead of using your own Sort you could have used the built-in sort that the algorithm library provides like this sort(darr, darr+10). In this case it was only with 10 elements but bear in mind that if you ever find yourself trying to solve the same problem with array sizes up to a million or more, the sort you implemented(it is called Bubble sort), would take up to much time, whereas std::sort would be able to do it faster as it has been optimised.
In this problem first sorting the array and then using Binary Search on top of it takes more time than performing Linear Search on the unsorted array. Generally, when searching once for a value on an unsorted array, first sorting it and then using Binary Search takes up more time than just doing Linear Search no matter the size of the array. However, if you wanted to to use the array in the future multiple times then your approach could prove to be faster.
These are all small improvements that you could make to your code but I am guessing this is done for educational purposes that is why you didn't do some of them.

Party Invitation

The problem that I am working on right now is here, but I am of course not looking for the complete answer to this homework problem. All I am asking for is the steps in the final parts of the question. This is what I have so far:
int main()
{
cout << "Please enter the number of guests attending your party: ";
int k;
cin >> k;
cout << "Please enter the number of rounds of removal you'd like to perform: ";
int m;
cin >> m;
for (int i = 1; i <= m; i++) {
cout << "Please enter the multiple at which you'd like the removal to be at for round " << i << ": ";
int r;
cin >> r;
if (k % r == 0) {
k - r;
}
cout << k << endl;
}
system("pause");
}
This is all so confusing to me, and I truly have no idea where to turn to get answers. It seems like I'd need an array to solve this, but arrays in C++ cannot be variable, and the array length would be k, a variable input. Any help would be very appreciated.
I've read that question. you need a dynamic list like Linked list because you need to put and remove different items from different index so using arrays will be difficult.
Try to use std::vector or std::list, you can add or remove any any of list
#include <list>
std::list<int> mylist;
How can you add and remove values from list, check this link http://en.cppreference.com/w/cpp/container/list
For using your own Linklist, check this link How could i create a list in c++?
According to your question an std::vector will be the best choice because it is a combination of an array & linked list in raw terms or we can simply say it's a dynamic array.
However as you mentioned n your comment that you haven't been taught anything other than basic arrays & want a solution within whatever you have learnt, then you have to take an array. Now the problem is that arrays are static & you cannot delete elements from it. So all you can do is to keep a counter that will take care of the number of elements in it.
// array insert and delete
#include <iostream>
using namespace std;
void see_array (int a[], int f, int b)
{
for (int i=f; i<b; ++i)
cout << a[i] << ' ';
cout << '\n';
}
int get_pos (int a[], int f, int b, int num)
{
for (int i=f; i<b; ++i)
{
if (a[i] == num)
return i;
}
return -1; // if search is unsuccessful
}
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10};
int front = 0, back = 10; // as we have 10 elements
// delete last element
--back;
see_array(a, front, back);
// delete first element
++front;
see_array(a, front, back);
// delete element from middle say 6
int pos = get_pos(a, front, back, 6);
if (pos != -1)
{
for (int i = pos; i<back; ++i) // shift elements towards left
{
a[i] = a[i+1];
}
--back; // decrease size of the array
see_array(a, front, back);
}
return 0;
}
/* Output :-
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
2 3 4 5 7 8 9
*/
I hope the above program is of some help to you !!! Good luck !!!

C++ code malfunctioning

I wrote a basic linear search C++ code. Whenever I run this, the result I get is always the opposite of the expected result.
For instance, I want to search 4. In an array where it is present, it will say the number is not found, but upon searching an absent element, it will say the element is found at position 0.
Even after an hour or so of constantly looking at the code I have not found any solution.
#include <iostream>
using namespace std;
//scanning program
int linearsearch (int A[] , int z, int n, int srchElement) {
for (int z = 0; z < n; z++) {
if (A[z] == srchElement) {
return z;
}
}
return -1;
}
//main program
int main () {
int i, n, A[1000], z;
//asking for size of array
cout << "give size of the array needed to be scanned: ";
cin >> n;
cout << endl;
if (n > 999) {
cout << "invalid value";
return -1;
}
//making sure of the size of the array
cout << "enter " << n << " integers: ";
//asking for the array
for (i = 0; i < n; i++) {
cin >> A[i];
}
int srchElement, index;
do {
cout << endl << "enter element to search (-1 to exit ): ";
//srchElement is defined here
cin >> srchElement;
if (srchElement == -1) break;
index = linearsearch(A, n, srchElement, z);
//calling thscanning function
if (index == -1) {
cout << srchElement << " not present" << endl;
}
//outputting the results of the scan
else {
cout << srchElement << " present " << index << endl;
}
} while (true);
return 0;
}
Your parameters to linearsearch are not in the correct order - you are passing n into the unused z parameter. With your current function you should call it like:
index=linearsearch(A, 8675309, n, srchElement);
I recommend you get rid of z as a parameter, then you won't need to pass a value to it.
Also please note: Spaces and indentation do not make your program run slower, but they do make it a lot easier to read.
The order of arguments in the function definition is not the same as in the function call.
It should be like (Line no 4):
int linearsearch (int A[] , int n, int srchElement, int z)
This is your search function correctly formatted:
int linearsearch (int A[] , int z, int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement, z);
You pass a value z in with the call. It is unitialised and does nothing, in main() or in the function.
You pass the arguments into the function in the wrong order. You are:
passing n (from main()) into the unused z value
searching for the uninitialised z (from main())
passing in the element you are looking for as n (array size). (This will quite likely result in out of bounds error, e.g. if searching for -1)
Try this:
int linearsearch (int A[], int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement);
You immediate problem: as The Dark spotted, this call:
index=linearsearch(A, n, srchElement, z);
doesn't match the declaration
int linearsearch (int A[] , int z, int n, int srchElement)
Function arguments in C++ are positional: just because the last call argument and the second declaration parameter are both called z doesn't mean anything.
Now, there are several local issues of style:
this kind of function is risky in the first place
int linearsearch (int[],int,int,int)
because it relies on you remembering the correct order for the last three integer parameters. If you must do this, you should be extra careful to give them all distinctive names, be very clear about which is which, and keep the order consistent across families of functions.
It's better, where possible, to help the compiler help you out, by either giving the arguments distinct types (or enumerations, or whatever), or grouping them into a structure.
For example, using a std::vector<int> instead of your array effectively groups int A[] and int n together in an object, so they can't get out of sync and n can't get confused with the other integers floating around
You shouldn't be passing z in the first place. You immediately hide it with a local int z in the loop, so it can't be doing anything. Remove it from both the declaration and the call. This simplification is sufficient to fix your bug.
Your secondary problem is that the code is ugly. It's poorly formatted and hard to read, and and that makes it more difficult to spot mistakes. Try to make your code simple and readable: there's less opportunity for things to go wrong, and its easier to see the problems when they occur.
Your tertiary problem is that the code is bad. Most of this can be done using standard library facilities (making your code simpler), which are themselves well-tested and generally have carefully-designed interfaces. Use them first, and replace if necessary.

Vector equilibrium point(s) function in C++

So I wanted to clean the rust off my C++ skills and thought I'd start with something fairly simple. An equilibrium point in a vector A of size N is a point K, such that: A[0] + A[1] + ... + A[K−1] = A[K+1] + ... + A[N−2] + A[N−1]. The rationale behind the function algorithm is simple: Check each consecutive element of the vector and compare the sum of the elements before said element with the sum of the elements after it and if they are equal, output the index of that element. While it sounds simple (and I imagine that it is) it turned out to be harder to implement in reality. Here's what the code looks like:
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
void EquilibriumPoint(std::vector<int> &A);
void VectorPrint(std::vector<int> &V);
void main()
{
int input;
std::vector<int> Vect1;
cout << "Input the vector elements" << endl;
while (cin >> input)
Vect1.push_back(input);
VectorPrint(Vect1);
EquilibriumPoint(Vect1);
}
void EquilibriumPoint(std::vector<int> &A)
{
for (int it = 0; it != A.size(); ++it)
{
int lowersum = 0;
int uppersum = 0;
for (int beg = 0; beg != it; ++beg) lowersum += A[beg];
for (int end = it + 1; end != A.size(); ++end) uppersum += A[end];
if (uppersum == lowersum) cout << it;
}
}
void VectorPrint(std::vector<int> &V)
{
for (int i = 0; i != V.size(); ++i)
cout << V[i] << endl;
}
As you can see I threw in a print function also for good measure. The problem is that the program doesn't seem to execute the EquilibriumPoint function. There must be a problem with the logic of the implementation but I can't find it. Do you guys have any suggestions?
cin >> input
always returns true for you - so IMHO you have an endless loop. You need to stop collecting elements at some point, for instance
int input = 1
while (input)
{
cin >> input;
Vect1.push_back(input);
}
Will accept all elements that are not zero, when zero arrives, it will end the vector and run your function.
Or you can first input the number of elements (if you want to include zeros), example:
int count;
cin >> count
for (int i = 0; i < count; ++i)
{
cin >> input;
Vect1.push_back(input);
}
I didn't check the rest of the code, though. One problem at a time.

Program to calculate the sum of terms? c++

So im trying to write a program that will calculate the sum of terms but each term is 3 times the previous term minus the second previous term so it looks like this 0, 1, 3, 8, 21, 55 and so on. For example if the user wants 4 terms then the program should output 21. The part im having problems with is setting up the variables to store the previous number and the second previous number. This is what i have so far.
#include <iostream>
using namespace std;
int main(){
int num;
int last;
int last2;
int current;
cout << "Number of terms to be shown: ";
cin >> num;
for(int i = 0; i < num; i++){
for(int term; term <= i; i++){
//THIS IS WHERE IM STUCK
}
}
}
The way i see it is the first for loop will tell the nested for loop how many times to run. In the nested for loop i think is where the math should go (current = (last * 3) - last2) while updating the last and last2 variables to keep the term list going. And then outside the loop i would cout << current so it would display the term. Like always, any help is appreciated!
There is an Undefined Behavior in your code in:
for(int i = 0; i < num; i++){
for(int term; term <= i; i++){ // term not initiaized. and the loop is infinte
//THIS IS WHERE IM STUCK
}
}
You are using term without being intialized. Also you are stuck in the inner loop because you should increment term not i in the inner loop.
So you can make it this way:
for(int i = 0; i < num; ++i){
for(int term = 0; term <= i; ++term){
// now rock here
}
}
You would typically remember the last two values, and simply go on computing the next one:
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Number of terms to be shown: ";
cin >> num;
int p1 = 1;
int p2 = 0;
cout << p2 << " " << p1 << " ";
num -= 2;
while (num > 0)
{
int current = 3 * p1 - p2;
cout << current << " ";
p2 = p1;
p1 = current;
num--;
}
}
This is the algorithm as I see it in my head when I read your question:
unsigned term(unsigned num) {
// the previous term*3 minus the second previous term
if(num > 1) return term(num - 1) * 3 - term(num - 2);
return num; // 0 or 1
}
It uses recursion to call itself, which is a great way to visualize what needs to be done for problems like this. The function works as-is but only for small nums, or else you'll get a stack overflow. It's also rather time consuming since it's doing function calls and calculates all terms many, many times.