C - recursive permutations in lexicographical order - c

I am trying to make permutations of strings with up to 8 characters. The problem is it must be done with recursion and it must be in lexicographical order. I found one solution with the recursion but it only works for 4 characters max. After that, it starts to mess up again.
void swap(char* a, char* b){
char temp = *a;
*a = *b;
*b = temp;
}
void recursion(char* arr, int start, int n){
if (start == (n-1)){
printf("%s\n", arr);
return;
}
for (int i = start; i < n; i++){
recursion(arr, start+1, n);
swap(arr+start+1, arr+n-1);
int j = start+1;
while (j < n && arr[start] > arr[j]){
j++;
}
if (j >= n){
continue;
}
swap(arr+start, arr+j);
}
swap(arr+start+1, arr+n-1);
}
int main(int argc, char *argv[]) {
char arr[9];
char charakter;
int m = 0;
while (scanf("%c", &charakter) != EOF){
if (charakter == '\n'){
break;
}
else if (isalpha(charakter) || isdigit(charakter)){
arr[m] = charakter;
m++;
}
else{
fprintf(stderr, "Error!\n");
return 100;
}
}
arr[m] = '\0';
int n = strlen(arr);
int start = 0;
recursion(arr, start, n);
return 0;
}
Any idea how to fix the recursion function?

Your solution is strange, have a look here and here a fix:
void recursion(char *arr, int start, int n) {
if (start == n) {
printf("%s\n", arr);
return;
}
for (int i = start; i < n; i++) {
swap(arr + start, arr + i);
recursion(arr, start + 1, n);
swap(arr + start, arr + i);
}
}
here a proper solution:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
static void recursion(char *str, size_t n, size_t max) {
if (n < max) {
recursion(str, n + 1, max);
for (size_t i = n + 1; i < max; i++) {
char tmp = str[i];
str[i] = str[n];
str[n] = tmp;
recursion(str, n + 1, max);
str[n] = str[i];
str[i] = tmp;
}
} else {
printf("%s\n", str);
}
}
int main(void) {
char str[42];
errno = 0;
if (scanf("%41s", str) != 1) {
if (errno != 0) {
perror("scanf()");
} else {
fprintf(stderr, "no input");
}
return 1;
}
recursion(str, 0, strlen(str));
}

Related

Allocated Dynamically Array of pointers

i'm really stuck.
I pust a big part of code you can try to run it on in online c compiler. My problem is weird, every time after 2 iteration i lost the data on spliter[0][0] when i mean "lost" is modified, for better understand please look what is printing it.
Inside
Inside the loop that iterates I wanted to see if the characters were well allocated in the present time and this is the case, only afterwards when I want to check it is impossible for me to do anything.
My program boils down to separating one character string according to another and dynamically allocating these character strings in my split. Each separator character counts as separator.
I have already prepared the test in comment. I really need help, too long time im stuck here..
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int is_c(char c, char *cha) {
while (*cha) {
if (*cha == c) {
return (1);
}
cha++;
}
return (0);
}
int ct_str(char *str, char *cha) {
int sw;
int nbr;
char item;
nbr = 0;
while (*str) {
if (!(is_c(*str, cha)) && *str >= 33 && *str <= 127 && sw == 1) {
sw = 0;
nbr+=1;
}
str++;
while (is_c(*str, cha)) {
str++;
sw = 1;
}
}
return (nbr);
}
int no_blk(char *str, int position, char *cha) {
while (!is_c(str[position], cha)) {
if (str[position] >= 33 && str[position] <= 127)
return (1);
position++;
}
return (0);
}
int get_size(char *str, int position, char *cha) {
int item;
item = position;
int j;
j = 0;
while (str[item]) {
if (is_c(str[item], cha))
return (j);
item++;
j++;
}
return (0);
}
void split_this(char **split, char *str, char *cha) {
int i;
int level;
int sw;
int e;
level = 0;
i = 0;
int item = 0;
int element = 0;
while(str[i + 1]) {
e = 0;
while(is_c(str[i], cha)) {
sw = 1;
i++;
}
if(sw == 1 && (!is_c(str[i], cha)) && no_blk(str, i, cha)) {
split[level] = (char*)malloc(sizeof(char) * get_size(str, i, cha) + 1);
e = i;
//printf("%i \n", get_size(str, i, cha));
while(e - i < get_size(str, i, cha)) {
split[level][e - i] = str[e];
//printf("%c", split[level][e - i]);
split[level][(e + 1) - i] = '\0';
e++;
}
printf("%c", split[0][0]);
sw = 0;
level++;
}
i++;
}
free(split);
/*
int it = 0;
int ee;
while(split[it]) {
ee = 0;
while(split[it][ee]) {
printf("%c", split[it][ee]);
ee++;
}
it++;
}
*/
}
void ft_split(char *str, char *cha) {
char **spliter = NULL;
spliter = (char**)malloc(sizeof(char) * ct_str(str, cha) + 1);
split_this(spliter, str, cha);
}
int main(int argc, char **argv) {
//if (argc == 3)
//ft_split(argv[1], argv[2]);
ft_split("%%am%s%s%ss%%s%%%qsdqsd%%%on%vs%lre%" , "%%");
return (0);
}

Print all combination of a string using recursion in C

I have an assignment to write code that printing all combinations of N char. For example, if the input is 3, the expected output must be "aaa aab aac aba ... ccc". But my code looping over and over again. Here's my code.
#include <stdio.h>
#ifndef MAX
#define MAX 5
#endif
void comb(char kar[], int size, int index) {
// string = aaa
// lim = 'd'
char lim = 'a' + size;
while (index != -1) {
if (kar[size-1] != lim) { // != c
for (int i = 0; i < size; i++) {
printf("%s ", kar);
kar[size-1]+=1;
}
return comb(kar, size, index);
} else {
while (kar[index-1] == lim && index != -1) {
kar[index-1]='a';
index--;
}
kar[index-1] += 1;
return comb(kar, size, size);
}
}
}
int main(int argc, char const *argv[]) {
int n;
char kar[MAX];
printf("Input N char : ");
scanf(" %d", &n);
for (int j = 0; j < n; j++) {
kar[j] = 'a';
}
comb(kar, n, n);
return 0;
}
I'm a little bit confused and I have no idea where is the mistake. Thank you.
The problem has been solved. I changed some elements in the comb() and added the pow() function to define the recursion limit.
int comb(char kar[], int size, int index, int limit) {
char lim = 97 + size;
int limit_value = pow(size,size);
if(limit == limit_value){
return 1;
} else {
if (index < size-1) {
printf("%s ", kar);
kar[size-1]+=1;
return comb(kar, size, index+1, limit+1);
} else {
int cek = index;
printf("%s ", kar);
while (kar[cek] == lim-1 ) {
kar[cek]=97;
cek-=1;
}
kar[cek] += 1;
return comb(kar, size, 0, limit+1);
}
}
}

can't able to return pointer value of function to main

link of program question https://www.hackerrank.com/challenges/cut-the-sticks/problem
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readline();
char** split_string(char*);
int* cutTheSticks(int arr_count, int* arr, int* result_count) {
int c=arr_count,min;
int result[c];
for (int k=0;k<arr_count;k++){
min = *arr;
for (int i = 0; i < c; i++) {
if (*(arr + i) < min)
min = *(arr + i);
}
int count=0;
for (int i=0; i < c; i++) {
if(min==*(arr+i))count++;
}
for (int i=0; i < c; i++) {
*(arr+i)=*(arr+i)-min;
}
int temp=0;
for(int i=0;i<c;i++){
for(int x=i;x<c;x++){
if(*(arr+i)<*(arr+x)){
temp=*(arr+i);
*(arr+i)=*(arr+x);
*(arr+x)=temp;
}
}
}
result[k]= c;
*(result_count)=*(result_count)+1;
c = c - count;
if(c==0)break;
}
return result;
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* n_endptr;
char* n_str = readline();
int n = strtol(n_str, &n_endptr, 10);
if (n_endptr == n_str || *n_endptr != '\0') { exit(EXIT_FAILURE); }
char** arr_temp = split_string(readline());
int* arr = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
char* arr_item_endptr;
char* arr_item_str = *(arr_temp + i);
int arr_item = strtol(arr_item_str, &arr_item_endptr, 10);
if (arr_item_endptr == arr_item_str || *arr_item_endptr != '\0') {
exit(EXIT_FAILURE); }
*(arr + i) = arr_item;
}
int arr_count = n;
int result_count;
int* result = cutTheSticks(arr_count, arr, &result_count);
for (int i = 0; i < result_count; i++) {
fprintf(fptr, "%d", *(result + i));
if (i != result_count - 1) {
fprintf(fptr, "\n");
}
}
fprintf(fptr, "\n");
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) { break; }
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') {
break; }
size_t new_length = alloc_length << 1;
data = realloc(data, new_length);
if (!data) { break; }
alloc_length = new_length;
}
if (data[data_length - 1] == '\n') {
data[data_length - 1] = '\0';
}
data = realloc(data, data_length);
return data;
}
char** split_string(char* str) {
char** splits = NULL;
char* token = strtok(str, " ");
int spaces = 0;
while (token) {
splits = realloc(splits, sizeof(char*) * ++spaces);
if (!splits) {
return splits;
}
splits[spaces - 1] = token;
token = strtok(NULL, " ");
}
return splits;
}
This above code is my full code from harkerrank, below is main fuction.
i can't able to return my pointer value from cutTheStricks to main function.
// Please store the size of the integer array to be returned in
result_count
pointer. For example,
// int a[3] = {1, 2, 3};
//
// *result_count = 3;
//
// return a;
int* cutTheSticks(int arr_count, int* arr, int* result_count) {
int c=arr_count,min;
int result[c];
for (int k=0;k<arr_count;k++){
min = *arr;
for (int i = 0; i < c; i++) {
if (*(arr + i) < min)
min = *(arr + i);
}
int count=0;
for (int i=0; i < c; i++) {
if(min==*(arr+i))count++;
}
for (int i=0; i < c; i++) {
*(arr+i)=*(arr+i)-min;
}
int temp=0;
for(int i=0;i<c;i++){
for(int x=i;x<c;x++){
if(*(arr+i)<*(arr+x)){
temp=*(arr+i);
*(arr+i)=*(arr+x);
*(arr+x)=temp;
}
}
}
result[k]= c;
*(result_count)=*(result_count)+1;
c = c - count;
if(c==0)break;
}
return result;
}
I am not getting any output but my logic is correct.
I know there is there is something missing therefore i can't able to return my output;
I can't figure out which pointer value(*result or *result_count ) is not passing
or what is happening i can't able to figure out.
You are returning the address of a local array whose life time ends with the function, change
int result[c];
to
int *result = malloc(sizeof(*result) * c);
You are also using the address of an uninitialized value here:
*(result_count)=*(result_count)+1;
change
int result_count;
to
int result_count = 0;

Find a first pseudopalindrome in the array

I have a array of strings and I want to find the first pseudopalindrome in the array for every string (if there is any). So I decided to sort my array at first, then reverse the word and do a binary search for a reversed word. So here it is what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char len(char *x){
char len = 0;
while (*x != '\0'){
x++;
len++;
}
return len;
}
char compare(char *x, char *y){
char x0 = &x;
char y0 = &y;
while (*x != '\0'){
if (tolower(*x) < tolower(*y)) return -1;
if (tolower(*x) > tolower(*y)) return 1;
x++;
y++;
}
// if we are here it means that strings are equal (case insensitive)
x = &x0;
y = &y0;
while (*x != '\0'){
if (*x > *y) return -1;
if (*x < *y) return 1;
x++;
y++;
}
// strings are equal (case sensitive)
return 0;
}
char *reverse(char *x){
int i, j;
char temp, *rev = NULL;
rev = malloc(sizeof(char)*(len(x)+1));
rev = strcpy(rev,x);
i = 0;
j = len(x) - 1;
while (i < j){
temp = rev[i];
rev[i] = x[j];
rev[j] = temp;
i++;
j--;
}
return rev;
}
int binsearch(char *x, char *A, int len){
int l, r, m, index;
l = 0;
r = len - 1;
index = -1;
while (l <= r){
m = (l + r) / 2;
if (compare(x, A[m]) == 0){
index = m;
r = m - 1;
}
else if (compare(x, A[m]) == -1) r = m - 1;
else l = m + 1;
}
return index;
}
int main()
{
int n, i, j, k, fnd;
char T[10000][101], temp[101];
scanf("%d", &n);
for (i = 0; i < n; i++){
scanf("%s", &T[i]);
}
for (i = 1; i < n; i++){
strcpy(temp, T[i]);
j = i - 1;
while (j >= 0 && compare(T[j], temp) == 1){
strcpy(T[j+1], T[j]);
j--;
}
strcpy(T[j+1], temp);
}
for (i = 0; i < n; i++){
fnd = binsearch(reverse(T[i]), T, n);
printf("%d", fnd);
}
return 0;
}
This program stops executing. The problem is probably with binary search as every function before executes well. But what's wrong with this binary search? Or what else can break the code?
Does the return type causing the problem .. for binary search no return type is mentioned
Edit 1. But you have not mentioned return type for function in its declaration
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char len(char *x){
char len = 0;
while (*x != '\0'){
x++;
len++;
}
return len;
}
char compare(char *x, char *y){
char* x0 = x;
char* y0 = y;
while (*x != '\0'){
int a0 = tolower(*x);
int b0 = tolower(*y);
if ( a0 < b0)
return -1;
if ( a0 > b0)
return 1;
x++;
y++;
}
// if we are here it means that strings are equal (case insensitive)
x = x0;
y = y0;
while (*x != '\0'){
if (*x > *y) return -1;
if (*x < *y) return 1;
x++;
y++;
}
// strings are equal (case sensitive)
return 0;
}
char *reverse(char *x){
int i, j;
char temp, *rev = NULL;
rev = malloc(sizeof(char)*(len(x)+1));
rev = strcpy(rev,x);
i = 0;
j = len(x) - 1;
while (i < j){
temp = rev[i];
rev[i] = x[j];
rev[j] = temp;
i++;
j--;
}
return rev;
}
int binarysearch(char *x,char A[][101], int len){
int l, r, m, index;
l = 0;
r = len - 1;
index = -1;
while (l <= r){
m = (l + r) / 2;
if (compare(x, A[m]) == 0){
index = m;
r = m - 1;
}
else if (compare(x, A[m]) == -1) r = m - 1;
else l = m + 1;
}
return index;
}
int main()
{
int n, i, j, k, fnd;
char T[10000][101], temp[101];
scanf("%d", &n);
for (i = 0; i < n; i++){
scanf("%s", &T[i]);
}
for (i = 1; i < n; i++){
strcpy(temp, T[i]);
j = i - 1;
while (j >= 0 && compare(T[j], temp) == 1){
strcpy(T[j+1], T[j]);
j--;
}
strcpy(T[j+1], temp);
}
for (i = 0; i < n; i++){
fnd = binarysearch(reverse(T[i]), T, n);
printf("%d", fnd);
}
return 0;
}
Not really an answer, but code in comments is painful to read.
You may also try to simplify your code; it's quite astonishing to have some much code for just a palindrome; some functions you are reimplementing are part of standard c (strlen, strcasecmp, strdup)
The function for telling if a word is palindrome is expected to really simple; here a sample of what it could be
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool isspeudopalindrom(const char *x){
for (int i = 0; i < strlen(x) / 2; ++i) {
if (tolower(x[i]) != tolower(x[strlen(x) - 1 - i]))
return false;
}
return true;
}
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; i++){
if (isspeudopalindrom(argv[i]))
printf("palindrom\n");
else
printf("not palindrom\n");
}
return 0;
}

C - Segmentation Fault when allocating space for strings

This code must naturally sort an array of strings and it gives a segfault. Unfortunately, I don't know what input it gives segfault on, but I suppose that segfault occurs when allocating memory for strings. Maximum string length is 9000000.
Here it is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
strsort(char **string, int left, int right) {
char *comp, *temp;
int i, j, p;
while(left < right) {
i = left;
j = right;
p = (left + right) / 2;
comp = string[p];
while(1) {
while(i <= j && strcmp(string[i], comp) <= 0)
i++;
while(i <= j && strcmp(string[j], comp) > 0)
j--;
if(i > j)
break;
temp = string[i];
string[i] = string[j];
string[j] = temp;
if(j == p)
p = i;
i++; j--;
}
string[p] = string[j];
string[j] = comp;
j--;
if((j - left) < (right - i)) {
strsort(string, left, j);
left = i;
} else {
strsort(string, i, right);
right = j;
}
}
}
void
ignore_line(void) {
char c;
while((c = getchar()) != '\n');
}
int
main(void) {
enum
{
L = 9000001
};
int n, i, j, len;
char offset = 'a' - 'A';
scanf("%d", &n); ignore_line();
char **string = (char **)malloc(n * sizeof(char *));
for(i = 0; i < n; ++i) {
string[i] = (char *)malloc(L * sizeof(char));
len = -1;
while((string[i][++len] = getchar()) != '\n') {
if(string[i][len] >= 'a')
string[i][len] -= offset;
else
string[i][len] += offset;
}
string[i] = (char *)realloc(string[i], len + 1);
string[i][len] = '\0';
}
strsort(string, 0, n - 1);
for(i = 0; i < n; ++i) {
j = 0;
while(string[i][j] != '\0') {
if(string[i][j] >= 'a')
printf("%c", string[i][j] - offset);
else
printf("%c", string[i][j] + offset);
++j;
}
printf("\n");
}
return 0;
}
The first seg fault is thrown at:
while(i <= j && strcmp(string[i], comp) <= 0)
Consider simply sending a char* to strsort, instead of char**, and comparing instances of char. Much of your code is overcomplicated.
void
strsort(char* string, int left, int right) {
char comp, temp;
See my quicksort implementation.

Resources