I'm trying to implement the Johnson-Trotter algorithm in C++ for a homework assignment. I was really excited after (I thought) I figured it out, but as it turns out I get a seg fault when I run it. Here's the code for it (sorry it's a little long):
#include <iostream>
#define N 3
#define RIGHT true
#define LEFT false
using namespace std;
// Struct to represent a number with its arrow and its mobility
struct number {
int num;
bool arrow;
};
void printPermutation(number permutation[], int n) {
for (int i = 0; i < n; i++) {
if (permutation[i].arrow == LEFT)
cout << '-';
cout << permutation[i].num << ' ';
}
}
void reverseArrows(number permutation[], int n, int k) {
for (int i = 0; i < n; i++)
if (permutation[i].num > permutation[k].num)
permutation[i].arrow ^= 1;
}
void swapMobile(number permutation[], int k) {
number temp;
temp.num = permutation[k].num;
temp.arrow = permutation[k].arrow;
int swapper;
if (permutation[k].arrow == RIGHT)
swapper = 1;
else // permutation[k].arrow == LEFT
swapper = -1;
permutation[k].num = permutation[k + swapper].num;
permutation[k].arrow = permutation[k + swapper].arrow;
permutation[k + swapper].num = temp.num;
permutation[k + swapper].arrow = temp.arrow;
}
void setNextPermutation(number current[], number next[], int n) {
for (int i = 0; i < n; i++) {
next[i].num = current[i].num;
next[i].arrow = current[i].arrow;
}
}
bool isMobile(number permutation[], int n, int k) {
if ((k == 0) && (permutation[k].arrow == LEFT))
return false;
if ((k == n - 1) && (permutation[k].arrow == RIGHT))
return false;
if ((permutation[k].arrow == LEFT) && (permutation[k - 1].num < permutation[k].num))
return true;
if ((permutation[k].arrow == RIGHT) && (permutation[k].num > permutation[k + 1].num))
return true;
return false;
}
int largestMobile(number permutation[], int n) {
int largest = 0;
cout << "Before isMobile\n";
for (int i = 1; i < n; i++)
if (i > largest && isMobile(permutation, n, i))
largest = i;
return largest;
}
bool hasMobile(number permutation[], int n) {
cout << "Before isMobile\n";
for (int i = 0; i < n; i++)
if (isMobile(permutation, n, i))
return true;
return false;
}
// Simple function to iteratively calculate n!
int factorial(int n) {
int factorial = 1;
for (int i = 1; i <= n; i++)
factorial *= i;
return factorial;
}
void JohnsonTrotter(int n) {
cout << "Before factorial\n";
int nFactorial = factorial(n);
number permutations[nFactorial][n];
// Initialize first permutation.
for (int i = 0; i < n; i++) {
permutations[0][i].num = i + 1;
permutations[0][i].arrow = LEFT;
}
int permutation = 0;
cout << "Before hasMobile\n";
while (hasMobile(permutations[permutation], n)) {
cout << "Before setNextPermutation\n";
setNextPermutation(permutations[permutation], permutations[permutation + 1], n);
permutation++;
cout << "Before largestMobile\n";
int k = largestMobile(permutations[permutation], n);
cout << "Before swapMobile\n";
swapMobile(permutations[permutation], k);
cout << "Before reverseArrows\n";
reverseArrows(permutations[permutation], n, k);
}
cout << "Before printPermutation\n";
for (int i = 0; i < nFactorial; i++) {
printPermutation(permutations[i], n);
cout << ' ';
if (!((i + 1) % n))
cout << '\n';
}
}
int main() {
JohnsonTrotter(N);
return 0;
}
I first ran it without any print statements and it gave me a seg fault. I threw in some print statements and I didn't get a seg fault, but I didn't get my expected results either. I removed the print statements, changed N to 2, and got a seg fault again. I changed N to 1 and got an expected result. I changed N to 4 and got a seg fault with and without print statements.
Also, sorry if this is the wrong way to ask this but I've never asked a question on here before.