I'm really new and bad at programming in C as I just started learning. Please be patient with me. I am currently trying to solve this puzzle: https://www.codingame.com/ide/puzzle/hidden-word. In the website, you can click on the three lines with three dots symbol on a box labeled "test cases" to view the test cases, then click on each test case to see the grid of letters and numbers in the left box, and then the expected output in the right box.
I know what I have to do which is to search through the grid of letters horizontally, vertically, diagonally, and the reverse of them, remove the numbers, don't print the repeated letters and combine the rest of the letters, print it out as the expected output.
I know how to write some of the other parts except for the one most important part, which is described in the title. I don't know how to check the letters horizontally, vertically, diagonally, and the reverse of them as the test cases have different numbers of column and rows. I figured I should use array but I am really bad at writing array codes.
Again, I am new and not a native English speaker so most of the stuff I just referenced on the internet and modified them. I probably shouldn't manually put the input in an array myself as the code is already written in the background (I don't know how to call it) and I don't know how to do this better.
Here is my current code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_STR_LEN 41
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
char aWord[41];
scanf("%s", aWord);
}
int h;
int w;
scanf("%d%d", &h, &w);
for (int i = 0; i < h; i++) {
char line[41];
scanf("%s", line);
}
int i;
int F[7][3] = {
{'2', '\0', '\0'},
{'B', 'A', 'C'},
{'B', 'O', 'B'},
{'3', '\0', '3'},
{'B', 'A', 'C'},
{'B', 'O', 'B'},
{'R', 'E', 'D'}
};
for (i = 0; i < n; i++) {
int string;
scanf("%d", &F);
// remove numbers
// don't print repeated elements
// combine the rest of the elements
strcpy(string, F);
// print the combined elements
}
return 0;
}
As you can see, I have attempted but failed miserably. Can someone guide me through it? You don't really have to help me write the code, you could just tell me where and what to learn to write this type of code or teach me how to write them please. Thanks in advance.
You don't really have to help me write the code, you could just tell me where and what to learn to write this type of code or teach me how to write them please
Note: This is an abstract idea on how to solve the problem using a trie, combine them together to your own implementation
I have an idea on how to solve this. First, you need to know and be able to implement Trie datastructure in C. as you read the n number of words you have to build (append the words to) the trie.
For the grid, you have to create a 2d array of GridEntry as defined below
typedef struct {
char c;
bool crossed; //< #include <stdbool.h>
} GridEntry;
GridEntry grid[rows][columns]; //< don't just copy this, won't work
now you have to iterate each entry in the grid. if it's already crossed skip and go to the next entry, else try to match a word starting at that entry horizontally, vertically and diagonally using the trie. (how to match trie is given below)
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
if (grid[r][c].crossed) continue;
try_match_word(trie, grid, r, c);
}
}
How to match a word with trie? try_match_word function
first, check if any word in the trie start with the current entry character
if not, no matches found return (from try_match_word) otherwise
iteratively pick a direction (horizontally, vertically and diagonally) move towards that direction (here is how to pick a direction)
// your direction is (x, y) = {(1, 1), (1, 0), (0, -1), ...}
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if (x == 0 && y == 0) continue;
// now (x, y) is the direction
int r_end = -1, c_end = -1; // end coordinate of the word
}
}
now you have to move through that direction until you find the grid edge or you match
The longest word when it doesn't match a word anymore. (here is how you move through a grid)
int i = 0;
while (true) {
int cx = c + i*x;
int cy = r + i*y; // (cx, cy) is the current position in the grid
// check boundary conditions here and break the loop;
i++;
}
now before you pick the direction you have to keep a current trie pointer to track the current character of the word as you move through the grid you have to update the trie pointer to the next character's trie.
Trie* curr = trie->chars[grid[r][c].c]; //< current trie
if (curr == NULL) return; //< no matching word
// and inside the move loop (where we've declared cx, cy)
Trie* next = curr->chars[grid[cy][cx].c];
if (next == NULL) {
if (curr->is_end) {
r_end = cy, c_end = cx; // word ends here
}
break;
}
curr = next;
once you match a word you'll know it if a r_end, c_end are != -1. and you have to cross those characters from (c, r) to (c_end, r_end). move through the coordinate and mark crossed grid[cy][cx].crossed = true;
once you matching words from each cell, you have to re iterate through the entries and collect the characters which are not crossed make a string, and return it.
char answer[256]; int i = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
if (grid[r][c].crossed) continue;
answer[i++] = grid[r][c].c;
}
}
answer[i] = '\0';
return answer;
Related
My goal here is to perform MergeSort on a dynamic array-like data structure I called a dictionary used to store strings and their relative weights. Sorry if the implementation is dumb, I'm a student and still learning.
Anyway, based on the segfaults I'm getting, I'm incorrectly allocating memory for my structs of type item to be copied over into the temporary lists I'm making. Not sure how to fix this. Code for mergesort and data structure setup is below, any help is appreciated.
/////// DICTIONARY METHODS ////////
typedef struct {
char *item;
int weight;
} item;
typedef struct {
item **wordlist;
//track size of dictionary
int size;
} dict;
//dict constructor
dict* Dict(int count){
//allocate space for dictionary
dict* D = malloc(sizeof(dict));
//allocate space for words
D->wordlist = malloc(sizeof(item*) * count);
//initial size
D->size = 0;
return D;
}
//word constructor
item* Item(char str[]){
//allocate memory for struct
item* W = malloc(sizeof(item));
//allocate memory for string
W->item = malloc(sizeof(char) * strlen(str));
W->weight = 0;
return W;
}
void merge(dict* D, int start, int middle, int stop){
//create ints to track lengths of left and right of array
int leftlen = middle - start + 1;
int rightlen = stop - middle;
//create new temporary dicts to store the two sides of the array
dict* L = Dict(leftlen);
dict* R = Dict(rightlen);
int i, j, k;
//copy elements start through middle into left dict- this gives a segfault
for (int i = 0; i < leftlen; i++){
L->wordlist[i] = malloc(sizeof(item*));
L->wordlist[i] = D->wordlist[start + i];
}
//copy elements middle through end into right dict- this gives a segfault
for (int j = 0; j < rightlen; j++){
R->wordlist[j] = malloc(sizeof(item*));
R->wordlist[j]= D->wordlist[middle + 1 + k];
}
i = 0;
j = 0;
k = leftlen;
while ((i < leftlen) && (j < rightlen)){
if (strcmp(L->wordlist[i]->item, R->wordlist[j]->item) <= 0) {
D->wordlist[k] = L->wordlist[i];
i++;
k++;
}
else{
D->wordlist[k] = R->wordlist[j];
j++;
k++;
}
}
while (i < leftlen){
D->wordlist[k] = L->wordlist[i];
i++;
k++;
}
while (j < rightlen){
D->wordlist[k] = L->wordlist[j];
j++;
k++;
}
}
void mergeSort(dict* D, int start, int stop){
if (start < stop) {
int middle = start + (stop - start) / 2;
mergeSort(D, start, middle);
mergeSort(D, middle + 1, stop);
merge(D, start, middle, stop);
}
I put print statements everywhere and narrowed it down to the mallocs in the section where I copy the dictionary to be sorted into 2 separate dictionaries. Also tried writing that malloc as malloc(sizeof(D->wordlist[start + i])). Is there something else I need to do to be able to copy the item struct into the wordlist of the new struct?
Again, I'm new to this, so cut me some slack :)
There are numerous errors in the code:
In merge() when copying elements to the R list, the wrong (and uninitialized) index variable k is being used instead of j. R->wordlist[j]= D->wordlist[middle + 1 + k]; should be R->wordlist[j]= D->wordlist[middle + 1 + j];.
In merge() before merging the L and R lists back to D, the index variable k for the D list is being initialized to the wrong value. k = leftLen; should be k = start;.
In merge() in the loop that should copy the remaining elements of the "right" list to D, the elements are being copied from the "left" list instead of the "right" list. D->wordlist[k] = L->wordlist[j]; should be D->wordlist[k] = R->wordlist[j];.
In Item(), the malloc() call is not reserving space for the null terminator at the end of the string. W->item = malloc(sizeof(char) * strlen(str)); should be W->item = malloc(sizeof(char) * (strlen(str) + 1)); (and since sizeof(char) is 1 by definition it can be simplified to W->item = malloc(strlen(str) + 1);).
Item() is not copying the string to the allocated memory. Add strcpy(W->item, str);.
There are memory leaks in merge():
L->wordlist[i] = malloc(sizeof(item*)); is not required and can be removed since L->wordlist[i] is changed on the very next line: L->wordlist[i] = D->wordlist[start + i];.
Similarly, R->wordlist[j] = malloc(sizeof(item*)); is not required and can be removed since R->wordlist[j] is changed on the very next line.
L and R memory is created but never destroyed. Add these lines to the end of merge() to free them:
free(L->wordlist);
free(L);
free(R->wordlist);
free(R);
None of the malloc() calls are checked for success.
Allocate it all at once, before the merge sort even starts.
#include <stdlib.h>
#include <string.h>
// Weighted Word --------------------------------------------------------------
//
typedef struct {
char *word;
int weight;
} weighted_word;
// Create a weighted word
//
weighted_word* CreateWeightedWord(const char *str, int weight){
weighted_word* W = malloc(sizeof(weighted_word));
if (W){
W->word = malloc(strlen(str) + 1); // string length + nul terminator
if (W->word)
strcpy( W->word, str);
W->weight = weight;
}
return W;
}
// Free a weighted word
//
weighted_word *FreeWeightedWord(weighted_word *W){
if (W){
if (W->word)
free(W->word);
free(W);
}
return NULL;
}
// Dictionary (of Weighted Words) ---------------------------------------------
//
typedef struct {
weighted_word **wordlist; // this is a pointer to an array of (weighted_word *)s
int size; // current number of elements in use
int capacity; // maximum number of elements available to use
} dict;
// Create a dictionary with a fixed capacity
//
dict* CreateDict(int capacity){
dict* D = malloc(sizeof(dict));
if (D){
D->wordlist = malloc(sizeof(weighted_word*) * capacity);
D->size = 0;
D->capacity = capacity;
}
return D;
}
// Free a dictionary (and all weighted words)
//
dict *FreeDict(dict *D){
if (D){
for (int n = 0; n < D->size; n++)
FreeWeightedWord(D->wordlist[n]);
free(D->wordlist);
free(D);
}
return NULL;
}
// Add a new weighted word to the end of our dictionary
//
void DictAddWord(dict *D, const char *str, int weight){
if (!D) return;
if (D->size == D->capacity) return;
D->wordlist[D->size] = CreateWeightedWord(str, weight);
if (D->wordlist[D->size])
D->size += 1;
}
// Merge Sort the Dictionary --------------------------------------------------
// Merge two partitions of sorted words
// words • the partitioned weighted word list
// start • beginning of left partition
// middle • end of left partition, beginning of right partition
// stop • end of right partition
// buffer • temporary work buffer, at least as big as (middle-start)
//
void MergeWeightedWords(weighted_word **words, int start, int middle, int stop, weighted_word **buffer){
int Lstart = start; int Rstart = middle; // Left partition
int Lstop = middle; int Rstop = stop; // Right partition
int Bindex = 0; // temporary work buffer output index
// while (left partition has elements) AND (right partition has elements)
while ((Lstart < Lstop) && (Rstart < Rstop)){
if (strcmp( words[Rstart]->word, words[Lstart]->word ) < 0)
buffer[Bindex++] = words[Rstart++];
else
buffer[Bindex++] = words[Lstart++];
}
// if (left partition has any remaining elements)
while (Lstart < Lstop)
buffer[Bindex++] = words[Lstart++];
// We don't actually need this. Think about it. Why not?
// // if (right partition has any remaining elements)
// while (Rstart < Rstop)
// buffer[Bindex++] = words[Rstart++];
// Copy merged data from temporary buffer back into source word list
for (int n = 0; n < Bindex; n++)
words[start++] = buffer[n];
}
// Merge Sort an array of weighted words
// words • the array of (weighted_word*)s to sort
// start • index of first element to sort
// stop • index ONE PAST the last element to sort
// buffer • the temporary merge buffer, at least as big as (stop-start+1)/2
//
void MergeSortWeightedWords(weighted_word **words, int start, int stop, weighted_word **buffer){
if (start < stop-1){ // -1 because a singleton array is by definition sorted
int middle = start + (stop - start) / 2;
MergeSortWeightedWords(words, start, middle, buffer);
MergeSortWeightedWords(words, middle, stop, buffer);
MergeWeightedWords(words, start, middle, stop, buffer);
}
}
// Merge Sort a Dictionary
//
void MergeSortDict(dict *D){
if (D){
// We only need to allocate a single temporary work buffer, just once, right here.
dict * Temp = CreateDict(D->size);
if (Temp){
MergeSortWeightedWords(D->wordlist, 0, D->size, Temp->wordlist);
}
FreeDict(Temp);
}
}
// Main program ---------------------------------------------------------------
#include <stdio.h>
int main(int argc, char **argv){
// Command-line arguments --> dictionary
dict *a_dict = CreateDict(argc-1);
for (int n = 1; n < argc; n++)
DictAddWord(a_dict, argv[n], 0);
// Sort the dictionary
MergeSortDict(a_dict);
// Print the weighted words
for (int n = 0; n < a_dict->size; n++)
printf( "%d %s\n", a_dict->wordlist[n]->weight, a_dict->wordlist[n]->word );
// Clean up
FreeDict(a_dict);
}
Notes for you:
Be consistent. You were inconsistent with capitalization and * placement and, oddly, vertical spacing. (You are waaay better than most beginners, though.) I personally hate the Egyptian brace style, but to each his own.
I personally think there are far too many levels of malloc()s in this code too, but I will leave it at this one comment. It works as is.
Strings must be nul-terminated — that is, each string takes strlen() characters plus one for a '\0' character. There is a convenient library function that can copy a string for you too, called strdup(), which AFAIK exists on every system.
Always check that malloc() and friends succeed.
Don’t forget to free everything you allocate. Functions help.
“Item” was a terribly non-descript name, and it overlapped with the meaning of two different things in your code. I renamed them to separate things.
Your dictionary object should be expected to keep track of how many elements it can support. The above code simply refuses to add words after the capacity is filled, but you could easily make it realloc() a larger capacity if the need arises. The point is to prevent invalid array accesses by adding too many elements to a fixed-size array.
Printing the array could probably go in a function.
Notice how I set start as inclusive and stop as exclusive. This is a very C (and C++) way of looking at things, and it is a good one. It will help you with all kinds of algorithms.
Notice also how I split the Merge Sort up into two functions: one that takes a dictionary as argument, and a lower-level one that takes an array of the weighted words as argument that does all the work.
The higher-level merge sort a dictionary allocates all the temporary buffer the merge algorithm needs, just once.
The lower-level merge sort an array of (weighted_word*)s expects that temporary buffer to exist and doesn’t care (or know anything) about the dictionary object.
The merge algorithm likewise doesn't know much. It is simply given all the information it needs.
Right now the merge condition simply compares the weighted-word’s string value. But it doesn’t have to be so simple. For example, you could sort equal elements by weight. Create a function:
int CompareWeightedWords(const weighted_word *a, const weighted_word *b){
int rel = strcmp( a->word, b->word );
if (rel < 0) return -1;
if (rel > 0) return 1;
return a->weight < b->weight ? -1 : a->weight > b->weight;
}
And put it to use in the merge function:
if (CompareWeightedWords( words[Rstart], words[Lstart] ) < 0)
buffer[Bindex++] = words[Rstart++];
else
buffer[Bindex++] = words[Lstart++];
I don’t think I forgot anything.
I've been given this sentence and I need to shuffle the words of it:
char array[] = "today it is going to be a beautiful day.";
A correct output would be: "going it beautiful day is a be to today"
I've tried many things like turning it into a 2D array and shuffling the rows, but I can't get it to work.
Your instinct of creating a 2D array is solid. However in C that's more involved than you might expect:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int main()
{
char array[] = "today it is going to be a beautiful day.";
char out_array[sizeof(array)];
char words[sizeof(array)][46];
int word_count = 0;
int letter_count = 0;
int on_word = 0;
int count = 0;
int i = 0;
int j = 0;
srand(time(NULL));
// parse words into 2D array
for (i = 0; i < sizeof(array); i++) {
if (array[i] == ' ') {
if (on_word) {
words[word_count++][letter_count] = '\0';
letter_count = 0;
on_word = 0;
}
} else if (array[i] == '\0' || array[i] == '.') {
break;
} else {
on_word = 1;
words[word_count][letter_count++] = array[i];
}
}
words[word_count++][letter_count] = '\0';
// randomly swap around words
for (i = 0; i < word_count; i++) {
char temp[46];
int idx = rand() % word_count;
if (idx != i) {
strcpy(temp, words[idx]);
strcpy(words[idx], words[i]);
strcpy(words[i], temp);
}
}
// output words into out_array
for (i = 0; i < word_count; i++) {
for (j = 0; words[i][j] != '\0'; j++) {
out_array[count++] = words[i][j];
}
out_array[count++] = ' ';
}
out_array[count - 1] = '\0';
printf("%s", out_array);
return 0;
}
You need two basic algorithms to solve this problem.
Split the input string into a list of words.
Randomly sample your list of words until there are no more.
1. Split the input string into a list of words.
This is much simpler than you may think. You don’t need to actually copy any words, just find where each one begins in your input string.
today it is going to be a beautiful day.
^---- ^- ^- ^---- ^- ^- ^ ^-------- ^--
There are all kinds of ways you can store that information, but the two most useful would be either an array of integer indices or an array of pointers.
For your example sentence, the following would be a list of indices:
0, 6, 9, 12, 18, 21, 24, 26, 36
To do this, just create an array with a reasonable upper limit on words:
int words[100]; // I wanna use a list of index values
int nwords = 0;
char * words[100]; // I wanna use a list of pointers
int nwords = 0;
If you do it yourself either structure is just as easy.
If you use strtok life is much easier with a list of pointers.
All you need at this point is a loop over your input to find the words and populate your list. Remember, a words is any alphabetic or numeric value (and maybe hyphens, if you want to go that far). Everything else is not a word. If you #include <ctype.h> you get a very handy function for classifying a character is “word” or “not-word”:
if (isalnum( input[n] )) its_a_word_character;
else its_not_a_word_character_meaning_we_have_found_the_end_of_the_word;
Now that you have a list of words, you can:
2. Randomly sample your list of words until there are no more.
There are, again, a number of ways you could do this. Already suggested above is to randomly shuffle the list of words (array of indices or array of pointers), and then simply rebuild the sentence by taking the words in order.
→ Beware, Etian’s example is not a correct shuffle, though it would probably go unnoticed or ignored by everyone at your level of instruction as it will appear to work just fine. Google around “coding horror fisher yates” for more.
The other way would be to just select and remove a random word from your array until there are no words left.
The random sampling is not difficult, but it does require some precise thinking, making this the actually most difficult part of your project.
To start you first need to get a proper random number. There is a trick to this that people are generally not taught. Here you go:
int random( int N ) // Return an UNBIASED pseudorandom value in [0, N-1].
{
int max_value = (RAND_MAX / N) * N;
int result;
do result = rand(); while (result >= max_value);
return result % N;
}
And in main() the very first thing you should do is initialize the random number generator:
#include <stdlib.h>
#include <time.h>
int main()
{
srand( (unsigned)time( NULL ) );
Now you can sample / shuffle your array properly. You can google "Fisher-Yates Shuffle" (or follow the link in the comment below your question). Or you can just select the next word:
while (nwords)
{
int index = random( nwords );
// do something with word[index] here //
// Remove the word we just printed from our list of words
// • Do you see what trick we use to remove the word?
// • Do you also know why this does not affect our random selection?
words[index] = words[--nwords];
}
Hopefully you can see that both of these methods are essentially the same thing. Whichever you choose is up to you. I personally would use the latter because of the following consideration:
Output
You can create a new string and then print it, or you can just print each word directly. As the homework (as you presented it) does not require generation of a new string, I would just print the output directly. This makes life simpler in the sense that you do not have to mess with another string array.
As you print each word (or append it to a new string), remember how you separated them to begin with. If you use strtok you can just use something like:
printf( "%s", words[index] ); // print word directly to stdout
strcat( output, words[index] ); // append word to output string
If you found the beginnings of each word yourself, you will have to again loop until you find the end of the word:
// Print word, character by character, directly to stdout
for (int n = index; isalnum( words[index+n] ); n++)
{
putchar( words[index+n] );
}
// Append word, character by character, to output string
for (int n = index; isalnum( words[index+n] ); n++)
{
char * p = strchr( output, '\0' ); // (Find end of output[])
*p++ = words[index+n]; // (Add char)
*p = '\0'; // (Add null terminator)
}
All that’s left is to pay attention to spaces and periods in your output.
Hopefully this should be enough to get you started.
I'm stuck at my first more complex coding task in C: developing a program that solves the knight's tour (chess, knight has to visit every field on the board only once) and it also should have a live display, showing which move the program is taking in real time.
The solution I came up with doesn't support live display though, as it is iterating through a for loop until the maximum number of moves has been reached, then prints the moves. How could I change this code to create real time output?
The displayBoard function is only printing a chessboard in the console output, with the current position of the knight as well as the field's name (e.g. A-1). Plan is to change this to a stream output for console, after my initial problem is solved.
(In conjunction to this question: how exactly does the function calling as if condition work? I stumbled upon this in the webs but sadly there was no explanation to it.)
int knight(int line, int row, int moveNumber)
{
int newLine, newRow, i;
//char cells[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
//mark visited cell
board[line][row] = moveNumber;
//for-loop for every possible move
for(i = 0; i < 8; i++)
{
//new position
newLine = line + moves[i][0];
newRow = row + moves[i][1];
//is the move on the board?
if(newLine >= 1 && newLine <= N && newRow >= 1 && newRow <= N)
{
//has the cell been visited yet?
if(!board[newLine][newRow])
{
//recursion until 63th move
if(moveNumber == max_moves || knight(newLine, newRow, moveNumber+1))
{
printf("Move %d: from %c-%d to %c-%d ", moveNumber, cells[row-1], line, cells[newRow-1], newLine);
boardDisplay(newLine, newRow);
return 1;
}
}
}
}
// free last visited cell, if there's no move possible anymore
board[line][row] = 0;
return 0;
}
Im stuck on this one part and I was hoping to get some help. I have a project that is basically a word search. The program reads in a file that contains the Rows and columns followed by the word search puzzle itself. You are required to create possible combinations of strings from the word search and check those combinations with a dictionary that is provided as another text document.
Here's an example of the file read in 1st is Rows and 2nd is Cols followed by the word search puzzle:
4 4
syrt
gtrp
faaq
pmrc
So I have been able to get most of the code to work except for the function that creates strings for the above file. Basically It needs to search the wordsearch and create strings, each created string gets passed on to another function to check if it's in the dictionary. However my code keeps going out of bounds when creating the strings, and it's continuing to cause Seg faults which is really frustrating.
Theses are the constants that are declared, its every possible direction to go while searching the word search puzzle for possible string combinations
const int DX_SIZE = 8;
const int DX[] = {-1,-1,-1,0,0,1,1,1};
const int DY[] = {-1,0,1,-1,1,-1,0,1};
This is the function I have to create the strings:
int strCreate(char** puzzle, char** dictionary, int n, int rows, int col){
int x, y;
int nextX, nextY, i;
char str[20] = {0};
int length = 1;
for(x = 0; x < rows; x++)
{
for(y = 0; y < col; y++)
{
//Grabs the base letter
str[0] = puzzle[x][y];
length = 1;
for(i = 0; i < DX_SIZE; i++)
{
while(length < MAX_WORD_SIZE)
{
nextX = x + DX[i]*length;
nextY = y + DY[i]*length;
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
if((y + nextY) < 0 || (nextY + y) > (rows-1)){
printf("Out of bounds\n");
break;
}
str[length] = puzzle[nextX][nextY];
//search for str in dictionary
checkStr(str, dictionary, n);
length++;
}
memset(&str[1], '\0', 19);
}
}
}
return 0;
}
I know i'm not checking the bounds properly I just can't figure out how to. When X = 1 and nextX = -1, that passes the bounds check, however say the array is at puzzle[0][0] nextX would put puzzle[-1][0] which is out of bounds causing the seg fault.
Thank you for taking the time to read, and I appreciate any help at all.
nextX and nextY are the indices used to access the array puzzle. Then the array bound check should also include the same. But the array bound check includes for example x+nextX.
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
Example:
if( nextX < 0)
printf("Out of bounds...\n");
I am trying to obtain two cluster from the strings via bubble sort algorithm. Main logic is putting the character strings to left side and the numbers to right side, and the positions can not be changed according to the right to left reading, also i need to use bubble sort for this implementation(!)
For example;
If the string is '503692EC12FATMA' i need to put it FIRSTLY as 'ECFATMA50369212' but the thing i didn't get it how i can use bubble sort to implement this mechanism besides a single if statement ?
I tried somethings but i always sort the character array via bubble sort i can not store the old positions, i need to use just one array and it needs to be implementation of C.
My code example :
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
char st[25],temp;
int l,i,j;
// clrscr();
printf("enter Any Sting\n");
gets(st);
l=strlen(st);
/*Logic Bubble Sort */
for(i=1;i<l;i++)
for(j=0;j<l-i;j++)
if(st[j]>st[j+1])
{
temp=st[j];
st[j]=st[j+1];
st[j+1] =temp;
}
printf("sorted string \n");
printf("%s",st);
getch();
}
But this gives me : '01223569AACEFMT' (!)
After i made the string 'ECFATMA50369212', i will use this string to arrange a cluster left to right A < B and 0 < 1.
to : 'AACEFMT01223569'
Like two functions, first function, use bubble sort to divide numbers and characters, then use this functions returned array to compare it right to left for sorting to create sorted character array.
Any help would be appreciated.
I think that the problem with your code is that you are bubble-sorting the array according to the ASCII values of the characters, in which upper-case letters (as well as lower-case letters) appear after number characters.
What you could do to make you program work is define you own comparison function, in which you would treat number characters (48 <= ASCII code <= 57) and upper-case letter characters (65 <= ASCII code <= 90) differently.
To do this in a single pass requires a differentiation of digits and non-digits. Once you have that, the algorithm can be summed up as:
Always swap if you have digit in the first slot and a non-digit in the second.
Else, only swap if their both digits or both non-digits and then, only if they're out of order (the higher slot is "less than" the lower slot).
Following that, you can do this in a single bubble-run. Its all about proper comparison:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
char st[25] = "503692EC12FATMA", temp;
size_t len, i;
int swapped = 1;
puts(st);
len = strlen(st);
while (swapped && len--)
{
swapped = 0;
for (i=0; i<len; ++i)
{
int swap = !isdigit((unsigned char)st[i+1]);
if (isdigit((unsigned char)st[i]))
swap = swap || (st[i+1] < st[i]);
else
swap = swap && (st[i+1] < st[i]);
if (swap)
{
temp = st[i];
st[i] = st[i+1];
st[i+1] = temp;
swapped = 1;
}
}
}
puts(st);
}
Output
503692EC12FATMA
AACEFMT01223569
There are other ways to do this obviously. You can even combine all that madness into a single if expression if you're a masochist, (i didn't for clarity). But to accomplish both clustering and cluster-sorting, this is one way to achieve it.
I suppose it is your homework and you actually need some kind of buble-type sort to do clustering first, without actually sorting, here is sample version which "bubbles" letter to the beginning of the string, preserving their relative positions:
l = strlen(st);
for (i = 1; i < l; i++)
if (isAlpha(st[i])) // bubble this letter to the beginning of the string
for (j = (i - 1); (j >= 0) && !isAlpha(st[j]); j--)
swap(&st[j + 1], &st[j]);
printf("sorted string\n%s\n", st);
NOTE: you need following 2 functions before your main:
char isAlpha(char a) {
return (a >= 'A') && (a <= 'Z');
}
void swap(char* a, char *b) {
char t = *a; *a = *b; *b = t;
}
This is not a bubble sort algorithm. What you're trying to do is just a string manipulation that can be done like that:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
char st[25],temp;
int l,i,j;
// clrscr();
printf("enter Any Sting\n");
gets(st);
int i;
char sorted_st[25];
int str_index = 0;
for (i = 0; i < strlen(l); ++i) {
if((l[i] >= 'a' && l[i] <= 'z') ||
(l[i] >= 'A' && l[i] <= 'Z')) {
sorted_st[str_index++] = l[i];
}
}
for (i = 0; i < strlen(l); ++i) {
if(l[i] >= '0' && l[i] <= '9') {
sorted_st[str_index++] = l[i];
}
}
// add the terminating zero
sorted_st[str_index++] = '\0';
printf("sorted string \n");
printf("%s",st);
getch();
}
ADVICE: It's better your main function to return int. On successful execution should return '0', in other cases error code.
int main() {
/* code */
return 0;
}