#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <unordered_map>
unordered_map<int, int> count_letters(string & s) {
unordered_map<int, int> counter;
for (auto & letter : s) {
counter[letter] += 1;
}
return counter;
}
int get_cnt_even(unordered_map<int, int> & counter) {
int cnt_even = 0;
for (auto it = counter.begin(); it != counter.end(); ++it) {
cout << "letter " << it->first << " " << it->second << " " << it->second % 2 << endl;
if (it->second % 2 == 1) {
cnt_even += 1;
}
}
return cnt_even;
}
string get_all_possible_letters(unordered_map<int, int> & counter) {
char even_char = '\0';
string letters;
for (auto it = counter.begin(); it != counter.end(); ++it) {
for (int i = 0; i < it->second / 2; ++i) {
letters += it->first;
}
if (it->second % 2 == 1) {
even_char = it->first;
}
}
if (even_char != '\0') {
letters.push_back(even_char);
}
return letters;
}
void generate_permutations(string & cur_string, string & letters_to_add, vector<string> & answers) {
if (letters_to_add.empty()) {
answers.push_back(cur_string);
}
int value = '\0'; // to don't coinside with nums[0]
for (int i = 0; i < letters_to_add.size(); ++i) {
if (value == letters_to_add[i]) {
continue;
}
cur_string.push_back(letters_to_add[i]);
// delete from i-th position
value = letters_to_add[i];
letters_to_add.erase(letters_to_add.begin() + i);
generate_permutations(cur_string, letters_to_add, answers);
// insert (return) to i-th position
letters_to_add.insert(letters_to_add.begin() + i, cur_string.back());
cur_string.pop_back();
}
}
void mirror_strings(vector<string> & answers, char even_char = '\0') {
for (auto & str : answers) {
auto reversed_tail = str;
reverse(reversed_tail.begin(), reversed_tail.end());
if (even_char != '\0') {
str += even_char;
}
str += reversed_tail;
}
}
vector<string> generatePalindromes(string s) {
if (s.size() == 1) {
return {s};
}
auto counter = count_letters(s);
int cnt_even = get_cnt_even(counter);
if (s.empty() || cnt_even > 1) {
return {};
}
cout << "cnt_even = " << cnt_even << endl;
string start_letters = get_all_possible_letters(counter);
char even_char = '\0';
if (cnt_even == 1) {
even_char = start_letters[start_letters.size() - 1];
start_letters.pop_back();
if (start_letters.empty()) {
return {string(1, even_char)};
}
}
cout << "start_letters : " << start_letters << endl;
vector<string> answers;
string cur_string;
generate_permutations(cur_string, start_letters, answers);
mirror_strings(answers, even_char);
return answers;
}
int main() {
for (auto v : generatePalindromes("abc")) {
cout << v << endl;
}
return 0;
}