#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#include <time.h>
#define ROWS 1000
#define COLUMNS 1000
// Function to check if a string is a palindrome
int is_palindrome(const char *str, int len) {
for (int start = 0, end = len - 1; start < end; ++start, --end) {
if (str[start] != str[end]) {
return 0;
}
}
return 1;
}
int main(int argc, char **argv) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Create and initialize the matrix with random characters
char matrix[ROWS][COLUMNS];
if (rank == 0) {
for (int i = 0; i < ROWS; ++i) {
for (int j = 0; j < COLUMNS; ++j) {
matrix
[i
][j
] = (rand() % 26) + 'A'; }
}
}
// Broadcast the matrix to all processes
MPI_Bcast(matrix, ROWS * COLUMNS, MPI_CHAR, 0, MPI_COMM_WORLD);
// Palindrome lengths to search for
int palindrome_lengths[] = {3, 4, 5, 6};
int total_lengths = sizeof(palindrome_lengths) / sizeof(palindrome_lengths[0]);
if (rank == 0) {
printf("Palindrome search\n\n"); }
for (int num_threads = 1; num_threads <= 8; ++num_threads) {
if (rank == 0) {
printf("***************************************************************************\n"); }
for (int idx = 0; idx < total_lengths; ++idx) {
int length = palindrome_lengths[idx];
int local_count = 0, global_count = 0;
// Divide the rows among processes
int rows_per_process = ROWS / size;
int start_row = rank * rows_per_process;
int end_row = (rank == size - 1) ? ROWS : start_row + rows_per_process;
// Start timer on rank 0
double start_time;
if (rank == 0) {
start_time = MPI_Wtime();
}
// Each process searches for palindromes in its assigned rows
for (int row = start_row; row < end_row; ++row) {
for (int col = 0; col < COLUMNS; ++col) {
// Check horizontal palindromes
if (col + length <= COLUMNS) {
if (is_palindrome(&matrix[row][col], length)) {
local_count++;
}
}
// Check vertical palindromes
if (row + length <= ROWS) {
char temp[length];
for (int k = 0; k < length; ++k) {
temp[k] = matrix[row + k][col];
}
if (is_palindrome(temp, length)) {
local_count++;
}
}
// Check diagonal (down-right) palindromes
if (row + length <= ROWS && col + length <= COLUMNS) {
char temp[length];
for (int k = 0; k < length; ++k) {
temp[k] = matrix[row + k][col + k];
}
if (is_palindrome(temp, length)) {
local_count++;
}
}
// Check diagonal (up-right) palindromes
if (row - length + 1 >= 0 && col + length <= COLUMNS) {
char temp[length];
for (int k = 0; k < length; ++k) {
temp[k] = matrix[row - k][col + k];
}
if (is_palindrome(temp, length)) {
local_count++;
}
}
}
}
// Reduce the local counts to rank 0
MPI_Reduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
// Rank 0 prints the results
if (rank == 0) {
double end_time = MPI_Wtime();
printf("%d palindromes of size %d found in %.6f seconds using %d threads.\n", global_count, length, end_time - start_time, num_threads);
}
MPI_Barrier(MPI_COMM_WORLD);
}
}
MPI_Finalize();
return 0;
}