Searching for a substring in 2d array in C - c

This is something for searching a substring In a 2d array
int left_to_rigth(char matrix[ROW][COLUNM], char str1[])
{
int i = 0, j, counting = 0, wordcnt;
int length = computeLength(str1); //returns legth of string
int index = -1;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COLUNM; j += 1)
{
if (matrix[i][j] == str1[0])
{
for (wordcnt = 0; wordcnt < length; wordcnt++)
{
if (matrix[i][j + wordcnt] == str1[wordcnt])
{
counting++;
}
}
if (counting == length)
{
index = (i *12) + j;
}
}
}
}
return index;
}
The output:
Enter the string to be searched in the puzzle:
SHOUT
position in the puzzle: 12
PUZZLE(MATRIX)
X T Z M Q Y K C E C F H -->0 1 2 3 4 5 6 7 8 9 10 11
*S H O U T* E X O E A P I -->12 13 14 ------------23
X G T L Q B E L T N F K
A I R I D Z A L L I O D
M E I E T Y S E H R T I
A W B R N E T C W O H X
N O U I R U Z T S C C T
U D T P E C J I E H R U
A L E M C S Y O N I U R
L V *K E R E M* N I P H E
E A N B U R E J O N C Y
A W I I I J N J R U Y F
D W T N T H E N P J Y T
E Q L Z D I L E M M A B
R C I T E N G A M T P C
So the function returns the starting point of SHOUT which is 12 but when I try to search for the word KEREM it should give me 110 but instead it return -1 which says that the word doesnt exist.
It seems like the code only searches for the first 3 lines every input I enter after that returns -1. Could you please help I am a beginner
This is just the first part I need to make it so that it searches in every direction I can either write 4 seperate functions and call them if they dont return -1 but I need to get this working first

Okay, I've done a few speedups and simplifications.
No need for a separate counting [for left-to-right and right-to-left, at least] as you can use wordidx
Also, once you find a match on the inner loop, there is no need to continue with it. And, you can stop the outer loop early
It's faster to calculate the length of str1 outside of the call and pass length as an argument. Also, strlen should work just fine.
On left-to-right, there is no need for j to go all the way to COLUMN - 1 as the last N slots can not match if there isn't enough room on the matrix line to fulfill the remaining string length.
Also, it's undefined behavior because you'll spill over into the next row. This would be harmless [but wrong result] except for the last row, where you'll go beyond the end of the entire matrix.
So, I added a jmax value of COLUMN - length
The right-to-left is slightly trickier. The jmax trick is critical.
So, here are the two functions [they compile cleanly, but I've not tested them]:
#include <string.h>
#define ROW 10
#define COLUMN 10
int
left_to_right(char matrix[ROW][COLUMN], const char *str1, int length)
{
char *matcur;
int i;
int j;
int wordidx;
int jmax = COLUMN - length;
int index = -1;
jmax += 1;
for (i = 0; i < ROW; ++i) {
for (j = 0; j < jmax; ++j, ++matcur) {
matcur = &matrix[i][0];
if (matcur[0] != str1[0])
continue;
for (wordidx = 1; wordidx < length; ++wordidx) {
if (matcur[wordidx] != str1[wordidx])
break;
}
if (wordidx == length) {
index = (i * COLUMN) + j;
break;
}
}
if (index >= 0)
break;
}
return index;
}
int
right_to_left(char matrix[ROW][COLUMN], const char *str1, int length)
{
const char *matcur;
int i;
int j;
int wordidx;
int jmax = COLUMN - length;
int index = -1;
for (i = 0; i < ROW; ++i) {
matcur = &matrix[i][jmax];
for (j = jmax; j >= 0; --j, --matcur) {
if (matcur[0] != str1[0])
continue;
for (wordidx = 0; wordidx < length; ++wordidx) {
if (matcur[wordidx] != str1[wordidx])
break;
}
if (wordidx == length) {
index = (i * COLUMN) + j;
break;
}
}
if (index >= 0)
break;
}
return index;
}

Related

C program chasing and I can't find the mistake

I just started learning programing and I'm having issues with my C code. The idea is to create a squared array sized [m][m] and fill the lateral and one diagonal spaces with 'n' (the user input determine the value of 'm' and 'n'), and then fill the rest of the spaces with numbers following a pattern. But every time it starts to fill the spaces it just crashes without pointing any warning or error.
Here is the code:
#include<stdlib.h>
#include<stdio.h>
int M[100][100] = {}, l, c;
int ImpMat(int m)
{
int l, c;
for(l = 0; l < m; l++)
{
printf("\n");
for(c = 0; c < m; c++)
printf("%i ", M[l][c]);
}
}
int Matriz(int m, int n)
{
int l, c;
for(l = 0; l < m; l++)
{
for(c = 0; c < m; c++)
{
if(c == 0 || c == m - 1 || c + l == m - 1)
M[l][c] = n;
else
M[l][c] = 0;
}
}
}
int NumMatI(int m)
{
int l, c, p, q;
for(l = 2; l < m; l++)
for(c = m -2; c >= 1; c++)
{
p = l - 1;
q = c + 1;
if(l + c > m - 1)
M[l][c] = M[p][c] + M[p][q];
}
}
int main()
{
int m, n;
printf("Type the value of 'm': ");
scanf("%i", &m);
printf("Type the value of 'n': ");
scanf("%i", &n);
Matriz(m, n);
NumMatI(m);
ImpMat(m);
return 0;
}
The function 'ImpMat' just prints the array, the 'Matriz' creates the array (the size is limited to 100) and 'NumMatI' is where it tries to fill the array.
I already realised the function 'NumMatI' is the one crashing the program, but can't find what is causing it.
I'm using Dev-C++.
In for(c = m -2; m >= 1; c++), the comparison should involve c somehow.

simple program doesn't work with negative array numbers

I just started to learn C language. By now I have very basic knowledge. At the moment I am coding some very simple programs from given exercises by my University.
Current exercise I have is: Write a program that finds two largest elements in n element array (2 ≤ n ≤ 10) and outputs sum of those two elements.
The problem is that my written code works only with positive array numbers and doesn't work with negative numbers.
Current code:
#include <stdio.h>
int main() {
int seka[] = {0,0,0,0,0,0,0,0,0,0}; //array in lithuanian = seka
int k; //variable to determine array size
int m = seka[0];
int n = seka[0];
int y = 0;
scanf ("%d",&k);
for(int i = 0; i < k; ++i){
scanf ("%d",&seka[i]);
}
for(int j = 0; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
for(int o = 0; o < k; ++o){
if (seka[o] == m)
y = y + 1;
}
if(y >= 2){
n = m;
}
else
{
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] > n)
n = seka[l];
}
}
printf ("%d", m + n);
return 0;
}
Input used:
5
4 9 5 6 3
Output got:
15
But if input has negative numbers:
6
-5 -8 -6 -2 -5 -8
Output is:
0
I know that this is not the most efficient approach for given problem, but I am still learning and I hope that you will help me finding the root of the issue.
Fixed my code with your help, now works like it should.
Fixed code:
#include <stdio.h>
int main() {
int seka[] = {0,0,0,0,0,0,0,0,0,0}; //array in lithuanian = seka
int k; //variable to determine array size
int y = 0;
scanf ("%d",&k);
for(int i = 0; i < k; ++i){
scanf ("%d",&seka[i]);
}
int m = seka[0];
for(int j = 1; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
for(int o = 0; o < k; ++o){
if (seka[o] == m)
y = y + 1;
}
int n;
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] < n)
n = seka[l];
}
if(y >= 2){
n = m;
}
else
{
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] > n)
n = seka[l];
}
}
printf ("%d", m + n);
return 0;
}
You update the max value with
for(int j = 0; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
but you initialize it with
m = seka[0];
The problem is that seka[0] has not been set by the user, yet, so its value is 0. That's Why the maximum value cannot be less than 0.
In order to fix it, just initialize the maximum with the first element of the array, but after the user input. Then loop starting from index 1:
m = seka[0];
for(int j = 1; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}

Why isn't my printf() statement in my searchPuzzle function isn't working?

For some reason, my print statement within my searchPuzzle function isn't working. Can you guys explain the reason why? I am trying to find certain words within a crossword puzzle which is 15x15. The word I am trying to find is the states with the US, like NewYork for example. The char ** arr represents the crossword puzzle. while the char** list represents the list of states. My go is for my function is to try to find the states in the crossword puzzle and to print out the states it does find. Int listsize has the value of 50. While n has the value of 15.
This is the cross word puzzle:
W D B M J Q D B C J N Q P T I
I R Z U X U Z E A O I O R T N
M N Z P L R N H L Y L X H M D
M Y E K A I D P I U L Y O W I
A O A B A R K U F V I H L A A
L O N M R X K I O J N A V R N
A E P T A A R A R T O W A I A
S U C Z A U S I N A I A L Z V
K O T A O N R K I S S I A O N
A H X S V K A I A E A I B N E
U D S X N X C C D W G S A A V
O I S D W L E J N J T X M H A
M O X W T N H Q D X O Q A Q D
R U U V G E O R G I A Q V D A
V F L O R I D A L G L W O X N
This is the list of states:
Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
NewHampshire
NewJersey
NewMexico
NewYork
NorthCarolina
NorthDakota
Ohio
Oklahoma
Oregon
Pennsylvania
RhodeIsland
SouthCarolina
SouthDakota
Tennessee
Texas
Utah
Vermont
Virginia
Washington
WestVirginia
Wisconsin
Wyoming
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// DO NOT INCLUDE OTHER LIBRARY!
// Declarations of the two functions you will implement
// Feel free to declare any helper functions
void printPuzzle(char** arr, int n);
void searchPuzzle(char** arr, int n, char** list, int listSize);
// Main function, DO NOT MODIFY!!!
int main(int argc, char **argv) {
int bSize = 15;
if (argc != 2) {
fprintf(stderr, "Usage: %s <puzzle file name>\n", argv[0]);
return 2;
}
int i, j;
FILE *fptr;
char **block = (char**)malloc(bSize * sizeof(char*));
char **words = (char**)malloc(50 * sizeof(char*));
// Open file for reading puzzle
fptr = fopen(argv[1], "r");
if (fptr == NULL) {
printf("Cannot Open Puzzle File!\n");
return 0;
}
// Read puzzle block into 2D arrays
for(i=0; i<bSize; i++){
*(block+i) = (char*)malloc(bSize * sizeof(char));
fscanf(fptr, "%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", *(block+i), *(block+i)+1, *(block+i)+2, *(block+i)+3, *(block+i)+4, *(block+i)+5, *(block+i)+6, *(block+i)+7, *(block+i)+8, *(block+i)+9, *(block+i)+10, *(block+i)+11, *(block+i)+12, *(block+i)+13, *(block+i)+14 );
}
fclose(fptr);
// Open file for reading word list
fptr = fopen("states.txt", "r");
if (fptr == NULL) {
printf("Cannot Open Words File!\n");
return 0;
}
// Save words into arrays
for(i=0; i<50; i++){
*(words+i) = (char*)malloc(20 * sizeof(char));
fgets(*(words+i), 20, fptr);
}
// Remove newline characters from each word (except for the last word)
for(i=0; i<49; i++){
*(*(words+i) + strlen(*(words+i))-2) = '\0';
}
// Print out word list
printf("Printing list of words:\n");
for(i=0; i<50; i++){
printf("%s\n", *(words + i));
}
printf("\n");
// Print out original puzzle grid
printf("Printing puzzle before search:\n");
printPuzzle(block, bSize);
printf("\n");
// Call searchPuzzle to find all words in the puzzle
searchPuzzle(block, bSize, words, 50);
printf("\n");
// Print out final puzzle grid with found words in lower case
printf("Printing puzzle after search:\n");
printPuzzle(block, bSize);
printf("\n");
return 0;
}
void printPuzzle(char** arr, int n){
// This function will print out the complete puzzle grid (arr). It must produce the output in the SAME format as the samples in the instructions.
// Your implementation here
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
printf("%c ", *(*(arr + i) + j));
}
printf("\n");
}
}
void searchPuzzle(char** arr, int n, char** list, int listSize){
// This function checks if arr contains words from list. If a word appears in arr, it will print out that word and then convert that word entry in arr into lower case.
// Your implementation here
for(int e = 0; e < listSize; e++){
for(int f = 0; f < strlen(*(list+e)); f++){
if(*(*(list + e) + f) >= 'a' && *(*(list + e) + f) <= 'z' ){
*(*(list + e) + f) = *(*(list + e) + f) - ('a' - 'A');
}
}
}
int k = 0;
for(int a = 0; a < listSize; a++){
for(int b = 0; b < n; b++){
for(int c = 0; c < n; c++){
if(*(*(list + a) + k) >= 'a' && *(*(list + a) + k) <= 'z' ){
*(*(list + a) + k) = *(*(list + a) + k) - ('a' - 'A');
}
if( *(*(list + a) + k) == *(*(arr + c) + b) ){
k++;
}
if( *(*(list + a) + k) != *(*(arr + c) + b) ){
k = 0;
break;
}
printf("%i ", k);
if ( k == (strlen(*(list+a))-1) ){
printf("Found: ");
for(int l = 0; l < strlen(*(list+a)); l++){
printf("%c", *(*(list + a) + l));
//printf("\n");
}
printf("\n");
k = 0;
break;
}
}
}
}
}
if( *(*(list + a) + k) == *(*(arr + c) + b) ){
k++;
}
if( *(*(list + a) + k) != *(*(arr + c) + b) ){
k = 0;
break;
}
In the first if, you increment k if you find a match. Then, in the next if, we are checking the next character in the word (since we did k++), with the same character *(*(arr + c) + b) from the crossword. For example, in NEWYORK, you match N with N (so far good), then compare E with N which is not equal, so it breaks out of loop. You should use an if .. else here, instead of two separate ifs, since the second condition should only be checked if the first is false.
When you find a non-matching character, you are using break. This will break out of the c loop, meaning that, if any character in a crossword line fails to match the word from list, the remaining characters in that line will not be checked. Here, you don't have to break out of the loop; setting k = 0 should be enough.
In *(*(arr + c) + b) you are incrementing c in the inner loop, so you are only checking for vertical matches in the crossword. If you want to check for horizontal matches also, you should also do the same checks after changing the nesting order of b and c loops. (OR you can check *(*(arr + b) + c)(changed b and c position) in the same loop and use another variable for horizontal in place of k. But note that this does not work if crossword is not square ie. not NxN)
As #bruno mentioned in comments, use arr[c][b] instead of *(*(arr + c) + b) as it is more readable and maintainable. Also use a loop to read characters in the crossword. That will be more maintainable than %c %c %c ...
In my linux machine, the following code is truncating one extra character from the words in list. Most likely because you are on Windows, and Windows uses \r\n line endings and Linux uses \n endings. So this won't work as you expect if your word list file was written in non-windows machine (Mac, Linux). If you want it to work anywhere, you can use strcspn function with \r\n to remove new line characters.
// Remove newline characters from each word (except for the last word)
for(i=0; i<49; i++){
*(*(words+i) + strlen(*(words+i))-2) = '\0';
}
After making changes, you should get this (tell if anything is missing):
Found:ALABAMA
Found:ALASKA
Found:ARIZONA
Found:CALIFORNIA
Found:FLORIDA
Found:GEORGIA
Found:HAWAII
Found:ILLINOIS
Found:INDIANA
Found:NEVADA
Since it is a school work, I will let you make the changes in code.
I modified the print function a bit. I suppose it should work:
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(X) sizeof(X) / sizeof(X[0])
void printPuzzle(const char ** arrP, int size){
for (int i = 0; i < size; i++){
printf(*arrP++);
printf("\n");
}
}
// Main function, DO NOT MODIFY!!!
int main(int argc, char **argv) {
const char * puzzle [] = {"ABC","DEF","GHI"};
printPuzzle(puzzle, ARRAY_SIZE(puzzle));
return 0;
}

Getting a sigseg fault when trying to modify an incrementing index in two separate arrays

So I'm trying to separate an array of char into blocks of 4 characters, keep track of whether the current block is even or odd, and rearrange them in increasing odd order and then increasing even order. I have an int variable to keep track of which index I'm at in the array and a for loop to determine if the current block is odd and if it is, put those characters into arrayOne, and if they're even put them into arrayTwo. At the end I would put arrayOne and arrayTwo together. However I think my incrementing idx variable in the loop checking if the current block is even is throwing a sigseg fault and i'm not sure why.
void unzip_file(const std::string& filename) {
ifstream file(filename, ios::in | ios::binary | ios::ate);
streampos sz = file.tellg();
file.seekg(0, ios::beg);
char* input = new char[sz];
file.read(input, sz);
char* arrayOne = new char[sz / 2];
char* arrayTwo = new char[sz / 2];
char* finalArray = new char[sz];
int eo = sz / 4;
int idx = 0;
for (int i = 1; i <= eo; i++) {
if (i % 2 != 0) {
for (int x = 0; x < 4; x++) {
arrayOne[idx] = input[idx];
idx++;
}
}
else {
for (int y = 0; y < 4; y++) {
arrayTwo[idx] = input[idx];
idx++;
}
}
}
}
This is the array that's passed into the function
H W e o l r l l o d , !
You are trying to write to the smaller arrayOne and arrayTwo with the same index as the bigger input array. This will give a SEGV if idx >= (sz / 2) . Try using own indices for the smaller arrays.
// make input length multiple of 4
const char input[] = "H W e o l r l l o d , ! ";
const int sz = sizeof(input)/sizeof(input[0]);
// add one here if we want a c-string afterwarts (\0-terminated)
char* arrayOne = new char[(sz / 2) + 1];
char* arrayTwo = new char[(sz / 2) + 1];
char* finalArray = new char[sz];
int eo = sz / 4;
int idx = 0;
// keep different indices to arrayOne and arrayTwo
int idxOne = 0;
int idxTwo = 0;
for (int i = 1; i <= eo; i++) {
if (i % 2 != 0) {
for (int x = 0; x < 4; x++) {
arrayOne[idxOne] = input[idx];
idx++;
// increment these seperately
idxOne++;
}
}
else
{
for (int y = 0; y < 4; y++) {
arrayTwo[idxTwo] = input[idx];
idx++;
// increment these seperately
idxTwo++;
}
}
}
// terminate to make a valid c-string
arrayOne[idxOne] = '\0';
arrayTwo[idxTwo] = '\0';
printf("%s\n", arrayOne);
printf("%s\n", arrayTwo);
Note If the size of the input size sz is not multiple of 4 you will miss the remaining characters in input (sz / 4 rounds down).
Note 2 If you want to printf the strings, the 0-termination is necessary (and a bigger array, see code comment).

Can anyone explain the solution of this memoization/dynamic programming prob/puzzle?

This is the problem statement:
This is a two player game. Initially there are n integer numbers in an array and players A and B get chance to take them alternatively. Each player can take one or more numbers from the left or right end of the array but cannot take from both ends at a time. He can take as many consecutive numbers as he wants during his time. The game ends when all numbers are taken from the array by the players. The point of each player is calculated by the summation of the numbers, which he has taken. Each player tries to achieve more points from other. If both players play optimally and player A starts the game then how much more point can player A get than player B?
Input
The input consists of a number of cases. Each case starts with a line specifying the integer n (0 < n ≤100), the number of elements in the array. After that, n numbers are given for the game. Input is terminated by a line where n=0.
Output
For each test case, print a number, which represents the maximum difference that the first player obtained after playing this game optimally.
Sample Input Output for Sample Input
4
4 -10 -20 7 7
4
1 2 3 4 10
5
4 -10 -20 7 19 12
0
This is the solution of this problem.
#include<stdio.h>
#include<stdlib.h>
#define maxn 103
//typedef long long bg;
typedef long bg;
bg Table[maxn][maxn];
bg Seq[maxn];
bool Flag[maxn][maxn];
bg N;
bg Sum(int l, int r) {
int i, sum = 0;
for (i = l; i <= r; i++)
sum += Seq[i];
return sum;
}
bg Recur(int L, int R) {
bg max, i, d, k;
if (L == R)
return Seq[L];
if (Flag[L][R])
return Table[L][R];
max = Sum(L, R);
d = Seq[L];
for (i = L + 1; i <= R; i++) {
k = Recur(i, R);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
d = Seq[R];
for (i = R - 1; i >= L; i--) {
k = Recur(L, i);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
Flag[L][R] = true;
Table[L][R] = max;
return max;
}
void Cal() {
bg max, i, d, k;
max = Sum(1, N);
d = Seq[1];
for (i = 2; i <= N; i++) {
k = Recur(i, N);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
d = Seq[N];
for (i = N - 1; i >= 1; i--) {
k = Recur(1, i);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
printf("%ld\n", max);
}
void Reset() {
for (int i = 1; i <= 100; i++) {
for (int j = 1; j <= 100; j++)
Flag[i][j] = false;
}
}
int main() {
//freopen("in.txt", "r", stdin);
int i;
while (scanf("%ld", &N) && N) {
for (i = 1; i <= N; i++)
scanf("%ld", &Seq[i]);
Cal();
Reset();
}
return 0;
}
I did debug it but found it difficult to understand the solution.
Can anyone explain the code or the solution of this problem. Or can anyone post code to solve this problem with dynamic programming not recursion?
The state here is Table[left][right] which represents the best solution if you have a sequence that includes the elements from left to right inclusive. At each step every possible move is tried - take N elements from the left or N elements from the right, where N is between 1 and right - left.
Example:
4 -10 -20 7
Take from the left:
Table[1][4] = max(sum(1, 1) - Table[2][4], sum(1, 2) - Table[3][4],
sum(1, 3) - Table[4][4], sum(1, 4)).
Take from the right:
Table[1][4] = max(sum(4, 4) - Table[1][3], sum(3, 4) - Table[1][2],
sum(2, 4) - Table[1][1], sum(1, 4)).
sum(L, R) is the sum of array numbers between L and R. I am subtracting because of the next opponent turn.

Resources