Find a first pseudopalindrome in the array - c

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;
}

Related

Each function works, but not together

i have string like "1111 1010 101010" and i have two functions
int getFirstNumber(char *a){
char *p = strtok(a," ");
char str[strlen(p)];
for (int i = 0; i < strlen(p); ++i){
str[i] = p[i];
}
return getBin(str);
}
int getThirdNumber(char *a){
char *p = strtok(a," ");
int k = 0;
while (p != NULL){
p = strtok(NULL," ");
if (k == 1){
break;
}
k +=1;
}
char str[strlen(p)-1];
for (int i = 0; i < strlen(p) - 1; ++i){
str[i] = p[i];
}
return getBin(str);
}
getBin
int getBin(char *a){
int k = 1;
int res;
for (int i = strlen(a) - 1; i >= 0;i -=1){
if (a[i] == '1'){
res += k;
}
k *= 2;
}
return res;
}
The problem is if i use getFirstNumber or use getThirdNumber alone, it works, but together i have Segmentation Fault. What is wrong,

Two-Way Insertion Sort not sorting

This is supposed to be a Two-Way insertion sort, but it's not sorting. I'm also supposed to print out the number of assignments for sorting, but right now I just want it to sort.
A separate output array of size 2n+1 is set aside. Initially x[0] is placed into the middle element of the array n.
Continue inserting elements until you need to insert between a pair of elements in the array.
As before you need to make room for the new element by shifting elements. Unlike before,
you can choose to shift all smaller elements one step to the left or all larger elements one step
to the right since there is additional room on both sides of the array. The choice of which
shift to perform depends on which would require shifting the smallest amount of elements.
I can't find much on the internet about this sort except that no one uses it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d ", arr[j]);
printf("\n");
}
int main() {
FILE *in;
int size_arr = 0;
char ch;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Error!");
exit(1);
}
do {
ch = fgetc(in);
if (ch == '\n')
size_arr++;
} while (ch != EOF);
rewind(in);
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
int n = 0;
while (!feof(in)) {
fscanf(in, "%d", &arr[n]);
n++;
}
fclose(in);
for (n = 0; n < 2 * size_arr; n++) {
sort_arr[n] = 0;
}
sort_arr[size_arr] = arr[0];
for (n = 1; n < size_arr; n++) {
int index = size_arr;
if (arr[n] <= sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index >= 0) {
index--;
}
}
if (arr[n] > sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index < 2 * size_arr) {
index++;
}
}
if (sort_arr[index] == 0) {
sort_arr[index] = arr[n];
} else {
int next_R, next_L = index;
while (sort_arr[next_R] != 0 && next_R <= 2 * size_arr) {
next_R++;
}
while (sort_arr[next_L] != 0 && next_L >= 0) {
next_L--;
}
int R_move = next_R - index;
int L_move = index - next_L;
if (R_move > L_move) {
while (L_move <= index) {
sort_arr[L_move] = sort_arr[L_move + 1];
L_move++;
}
sort_arr[index] = arr[n];
} else {
while (R_move >= index) {
sort_arr[R_move] = sort_arr[R_move - 1];
R_move--;
}
sort_arr[index] = arr[n];
}
}
}
printArray(arr, size_arr);
return 0;
}
I'm not sure this solves all problems but it is a problem you must fix.
This code
int next_R, next_L = index;
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
has undefined behavior as next_R is uninitialized.
Maybe you want:
int next_R = index, next_L = index;
^^^^^
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
In any case you have to initialize next_R before using it.
I also find this line strange:
printArray(arr, size_arr);
^^^
Seems you are printing the original array instead of the sorted array.
May be you want:
printArray(sort_arr, size_arr);
^^^^^
There are some problems in your code:
when you scan the file in the first pass, you should count the number of integers instead of the number of characters.
when inserting, your loops are off by one: the tests should read while (L_move < index) and while (R_move >= index)
while (!feof(in)) is always wrong, you should instead write while (fscanf(in, "%d", &arr[n]) == 1) {...
you should probably allocate the arrays arr and sort_arr instead of defining them as VLAs with automatic storage to prevent undefined behavior on large input files.
you should use binary search into the sorted portion, otherwise your algorithm has a basic complexity of O(N2) that dwarfs the small gain obtained from the minimisation of the insertion phase.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void print_array(const int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d%c", arr[j], " \n"[j == len - 1]);
}
int main(void) {
FILE *in;
int size_arr, n, start;
int value;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Cannot open input file %s\n", "data_a5.txt");
exit(1);
}
for (size_arr = 0; fscanf(in, "%d", &value) == 1; size_arr++)
continue;
rewind(in);
int *arr = calloc(2 * size_arr + 1, sizeof(*arr));
if (arr == NULL) {
printf("Cannot allocate memory for %d entries\n", size_arr);
exit(1);
}
start = size_arr;
for (n = 0; n < size_arr && fscanf(in, "%d", &value) == 1; n++) {
/* insert value into the sorted array */
int a, b;
for (a = start, b = start + n; a < b;) {
int mid = a + (b - a) / 2;
if (arr[mid] < value) {
a = mid + 1;
} else {
b = mid;
}
}
/* insert value at offset b */
if (b - start < start + n - b) {
/* shift left portion to the left */
for (int i = start--; i < b; i++) {
arr[i - 1] = arr[i];
}
b--;
} else {
/* shift right portion to the right */
for (int i = start + n + 1; --i > b;) {
arr[i] = arr[i - 1];
}
}
arr[b] = value;
}
fclose(in);
print_array(arr + start, n);
free(arr);
return 0;
}
like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len){
while(len--)
printf("%d ", *arr++);
printf("\n");
}
int main(void){
int size_arr = 10;
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
for(int i = 0; i < size_arr; ++i)
arr[i] = -50 + rand() % (100 + 1);
puts("before:");
printArray(arr, size_arr);
int left, right;
sort_arr[left = right = size_arr] = arr[0];
for (int n = 1; n < size_arr; ++n){
int v = arr[n];
if(v <= sort_arr[left]){
sort_arr[--left] = v;
} else if(v >= sort_arr[right]){
sort_arr[++right] = v;
} else {
int L = left, R = right, M, MV;
while(L <= R){
M = L + (R-L)/2;
MV = sort_arr[M];
if(MV < v)
L = M + 1;
else if(v < MV)
R = M - 1;
else
break;
}
//M: insert position
enum { LEFT, RIGHT } CHOICE;
if(v == MV){
int ML = M, MR = M;
while(sort_arr[ML-1] == sort_arr[ML])
--ML;
while(sort_arr[MR] == sort_arr[MR+1])
++MR;
if( ML-left >= right-MR){
M = MR+1;
CHOICE = RIGHT;
} else {
M = ML;
CHOICE = LEFT;
}
} else if(v > MV){
++M;
CHOICE = M-left+1 > right-M;// ? RIGHT : LEFT;
} else {
CHOICE = M-left-1 > right-M;// ? RIGHT : LEFT;
}
if(CHOICE == RIGHT){
memmove(sort_arr + M+1, sort_arr + M, (right-M+1)*sizeof(v));
sort_arr[M] = v;
++right;
} else {
memmove(sort_arr + left-1, sort_arr + left, (M-left)*sizeof(v));
sort_arr[M-1] = v;
--left;
}
}
}
puts("after:");
printArray(sort_arr + left, size_arr);
return 0;
}

C - recursive permutations in lexicographical order

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));
}

C program palindrome game

I'm new in c programming and i'm trying to make a palindrome game. I've given the code below but there is some mistake I'm making and doesn't run can you please give me a hand. Thank you.
The point of the game is to give number to an array, then change with the keys a,d,x,w and try to make it palindrome.
If there is any error can u please give me some advice ?
This is pal.c
#include <stdio.h>
#include "visible.h"
//--------------------------------------------------
// is_pal
//--------------------------------------------------
void print_status(int a[], int* p, int num_mov);
int is_pal(int a[])
{
int b[6];
int i, j;
j = 0;
for (i = 5; i >= 0; i--)
{
b[j] = a[i];
j++;
}
for (i = 0; i <= 5; i++)
{
if (a[i] != b[i]) {
return 0;
}
}
return 1;
}
//--------------------------------------------------
// process_movement
//--------------------------------------------------
void process_movement(int a[], int* p, int num_mov, char c)
{
char d;
d=c;
if(d == 'd')
{
p = a+1;
num_mov++;
print_status(a,p,num_mov);
}
else if(d == 'a')
{
p = a-1;
num_mov++;
print_status(a,p,num_mov);
}
else if(d == 'x')
{
p = malloc(6*sizeof(int));
a = p-1;
num_mov++;
}
else if(d == 'w')
{
p = malloc(6*sizeof(int));
a = p+1;
num_mov++;
}
}
//--------------------------------------------------
// print_status
//--------------------------------------------------
void print_status(int a[], int* p, int num_mov)
{
printf("Number = ");
int i;
for( i = 0; i < 6; i++)
{
printf("%d ", a[i]);
}
printf("\n Number moves = ");
printf("%d", num_mov);
//printf("\n ","%s%", "Pointer is at position ");
printf("%d", *p);
printf("\n");
}
void user_game_palindrome(int pal_num)
{
int a[5];
int i,num_mov;
num_mov = 0;
i = 5;
while (pal_num != 0) {
a[i] = pal_num % 10;
pal_num = pal_num / 10;
i--;
}
int *p = a;
while (is_pal(a) == 1)
{
char c;
print_status(a,p,num_mov);
c = ask_for_command();
process_movement(a,p,num_mov,c);
}
}
This is ex1.c
#include "pal.h"
int main() {
int pal_num = 123342;
user_game_palindrome(pal_num);
return 0;
}
visible.c
#include "visible.h"
#include "conio.h"
//--------------------------------------------------
// gen_num
//--------------------------------------------------
int gen_num(int lb, int ub) {
int num = (rand() % (ub - lb)) + lb;
return num;
}
/* Note: Do not forget to include the following instruction at the beginning of your main() method:
srand(time(NULL));
*/
//--------------------------------------------------
// my_getchar
//--------------------------------------------------
char my_get_char() {
char my_char;
int b = 0;
char dummy_char;
my_char = getchar();
while (b == 0) {
dummy_char = getchar();
if (dummy_char == '\n')
b = 1;
}
return my_char;
}
this is the visible.c ( my teacher told me to include it)
Your conversion from int to array is wrong
for (i = 0; i < 4; i++) {
a[i] = pal_num%10;
pal_num = pal_num % 10;
}
Here, why would this loop end when i is 4. It should go till pal_num is 0. And pal_num = pal_num % 10; should be pal_num = pal_num / 10;
Try something like
i = 0;
while (pal_num != 0) {
a[i] = pal_num % 10;
pal_num = pal_num / 10;
i++;
}
NOTE: Be aware, that this would essentially reverse your int and store in the array.
There's a lot going wrong in your code and you still haven't fixed many things which have been pointed out by others.
as to remove the unnecessary creating of the array b, is_pal can be defined as:
int is_pal(int a[])
{
int i;
for (i = 0; i < 3; ++i)
{
if (a[5-i] != a[i])
return 0;
}
return 1;
}
process_movement doesn't have a case where d == 'w'
user_game_palindrome should have the while loop checking (is_pal(a) == 0)
And you should apply the changes that were suggested by #Haris

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