Lexicographic Order in Multidimensional Array C++ - arrays

I'm having trouble with one final task that my program should do.
Having my output character in a lexicographic order.
For example, if I input bbbaaa it should have an output of
Frequencies:
a 3
b 3
Not
Frequencies:
b 3
a 3
Can anyone help me solve this problem?
Here is my code:
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
void sort(char letters[], int integers[], int size);
void swap_letters(char& first, char& second, int& int1, int& int2);
int index_of_largest(const int integers[], int start_index, int number_used);
int main(){
const int MAX_CHARS = 200;
char letters[MAX_CHARS] = {'\0'};
int integers[MAX_CHARS] = {'\0'};
int index, size = 0;
char character;
cout << "Enter text:" << endl;
cin.get(character);
character = tolower(character);
while (character!= '.' && size < MAX_CHARS){
if(isalpha(character)){
index = 0;
while (index < size){
if(letters[index] == character)
break;
else
index++;
}
if (index < size){
integers[index] = integers[index] + 1;
}
else{
letters[index] = character;
integers[index] = 1;
size++;
}
}
cin.get(character);
character = tolower(character);
}
letters[index] = tolower(letters[index]);
sort(letters, integers, size);
cout << "Frequencies:"<< endl;
for(int i = 0; i < size; i++){
cout << letters[i] << " " << integers[i] << endl;
}
return 0;
}
void sort(char letters[], int integers[], int size){
for (int i = 0; i < size -1; i++){
int j = index_of_largest(integers, i, size);
swap_letters(letters[i], letters[j], integers[i], integers[j]);
}
}
void swap_letters(char& first, char& second, int& int1, int& int2){
char temp_char = first;
first = second;
second = temp_char;
int temp_int = int1;
int1 = int2;
int2 = temp_int;
}
int index_of_largest(const int integers[], int start_index, int number_used){
int max_int = integers[start_index];
int max_int_index = start_index;
for (int index = start_index + 1; index < number_used; index++){
if (integers[index] > max_int){
max_int = integers[index];
max_int_index = index;
}
}
return max_int_index;
}

The problem is in function index_of_largest() where you detect the index of largest checking only integers and ignoring letters.
All goes well when all letters are with different frequencies but doesn't work when a couple two or letter are with the same frequency. In this case you should take in count letters too.
I suppose you can correct the function in this way
int index_of_largest(const int integers[], const char letters[], int start_index, int number_used){
int max_int = integers[start_index];
int max_int_index = start_index;
for (int index = start_index + 1; index < number_used; index++){
if ( (integers[index] > max_int)
|| ( (integers[index] == max_int)
&& (letters[index] < letters[max_int_index]) )){
max_int = integers[index];
max_int_index = index;
}
}
return max_int_index;
}
But I suggest you to follow the Jack's suggestion: use STL container/algorithm when you can / when is possible
p.s.: sorry for my bad English.

Related

How to apply radix sort (uses counting sort) with struct containing multiple strings

I want to alphabetically sort the struct strings with radix sort, however I am struggling to apply radix sort to check each digit of the strings. I checked other posts but I couldn't find a structure similar to mine.
The problem is that my code checks for each ENTRY of the struct not EACH digit of the string in that entry. (By entry I mean; table[0], table[1] etc.) So basically it sorts the string in itself of each entry. I couldn't build the logic, can someone help me please?
EDIT: the length of the strings are not the same
Here is my code:
typedef struct FUNCTIONS_STRUCT
{
char *fncName;
void (*fnc)(char *);
char *description;
} FUNCTIONS_STRUCT_t;
FUNCTIONS_STRUCT_t FUNC_TABLE[] =
{
{ "ABCD", ABCD, "" },
{ "abcD", abcD, "" },
{ "EaBB", EaBB ,""}
//it goes on ..
};
// Function to find the Largest Number
int getMax(int array[], int n) {
int max = array[0];
int i;
for (i = 1; i < n; i++)
if (array[i] > max)
max = array[i];
return max;
}
// Function for Count sort
void countSort(int array[], int n, int dig) {
int output[n];
int i, count[10] = {0};
for (i = 0; i < n; i++)
count[(array[i] / dig) % 10]++;
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
for (i = n - 1; i >= 0; i--){
output[count[(array[i] / dig) % 10] - 1] = array[i];
count[(array[i] / dig) % 10]--;
}
for (i = 0; i < n; i++)
array[i] = output[i];
}
void radixsort(int array[], int n) {
//Get the largest number to know the maximum number of digits
int m = getMax(array, n);
int dig;
//Counting sort is performed for every digit
for (dig = 1; m / dig > 0; dig *= 10)
countSort(array, n, dig);
}
int main()
{
int functionTableUnitSize = sizeof(FUNC_TABLE) / sizeof(FUNC_TABLE[0]);
radixsort(&FUNC_TABLE, functionTableUnitSize);
return 0;
}
I assume that the function names in your question have a uniform length of 4 alphanumeric characters. In C, identifiers can use 63 different alphanumeric characters from these groups:
lower case (abcdefghijklmnopqrstuvwxyz)
upper case letters (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
digits (0123456789)
and the underscore (_)
Different encodings have a different order (e.g. EBCDIC lower case letters are sorted before upper case letters, while the reverse is true for ASCII). For a portable C programm we can therefore define our own lexical sorting order.
We can do this for example in a function called build_lexical_sorting_index.
Details
I have minimally adjusted the naming from the code you provide in your question
your functions must work with FUNCTION arrays and not with int arrays
radix_sort first creates the lexical sorting index
count_sort must then be called for each of the 4 alphanumeric characters of a function name
words are usually sorted from the leftmost character, that's why we do it this way
count_sort is then called for each of the 4 characters
this determines the index from the lexical_sorting index of the corresponding character from the function name
then the count sorting algorithm as shown in your question is applied
at the end the result is printed
If one slightly modifies your code according to the above mentioned points, it looks like this:
#include <stdio.h>
#define UNIFORM_FUNCNAME_LENGTH 4
typedef struct {
char *fnc_name;
void (*fnc)(char *);
char *description;
} FUNCTION;
void ABCD(char *a) {};
void abcD(char *a) {};
void EaBB(char *a) {};
void A012(char *a) {};
void _ABC(char *a) {};
FUNCTION func_table[] = {
{"ABCD", ABCD, ""},
{"abcD", abcD, ""},
{"EaBB", EaBB, ""},
{"A012", A012, ""},
{"_ABC", _ABC, ""}
//it goes on ..
};
int lexical_sorting_index[256] = {0};
int lexical_index(int ch) {
return lexical_sorting_index[ch];
}
void count_sort(FUNCTION *array, int n, int char_position) {
FUNCTION output[n];
int count[256] = {0};
for (int i = 0; i < n; i++) {
int ch = array[i].fnc_name[char_position];
int index = lexical_index(ch);
count[index]++;
}
for (int i = 1; i < 256; i++)
count[i] += count[i - 1];
for (int i = n - 1; i >= 0; i--) {
int ch = array[i].fnc_name[char_position];
int index = lexical_index(ch);
output[count[index] - 1] = array[i];
count[index]--;
}
for (int i = 0; i < n; i++)
array[i] = output[i];
}
void build_lexical_sorting_index() {
int nr = 0;
for (int i = 'a'; i <= 'z'; i++)
lexical_sorting_index[i] = nr++;
for (int i = 'A'; i <= 'Z'; i++)
lexical_sorting_index[i] = nr++;
for (int i = '0'; i <= '9'; i++)
lexical_sorting_index[i] = nr++;
lexical_sorting_index['_'] = nr;
}
void radix_sort(FUNCTION *array, int n) {
build_lexical_sorting_index();
for(int char_position = UNIFORM_FUNCNAME_LENGTH - 1; char_position >= 0; char_position--)
count_sort(array, n, char_position);
}
int main() {
int table_size = sizeof(func_table) / sizeof(func_table[0]);
radix_sort(func_table, table_size);
for (int i = 0; i < table_size; i++)
printf("%s ", func_table[i].fnc_name);
return 0;
}
When the program is executed, the following is displayed in the debug console:
abcD ABCD A012 EaBB _ABC

C: Best way to index the digits in an integer

If I have an
int i = 11110001
How would I be able to convert this int into an int array where
int array[8] = {1, 1, 1, 1, 0, 0, 0, 1}
Using a little different approach and snprintf:
#include <stdio.h>
int main (void) {
int i = 11110001;
char arr[9]; //8 digits + \0
int array[8];
if ((snprintf(arr,9,"%d", i) == 8) { //return the 8 characters that were printed
int c;
for(c = 0; c < 8; c++)
array[c] = arr[c] - '0';
}
return 0;
}
P.S: I'm assuming positive values only
You may try like this:
#include <math.h>
char * convertNumber(unsigned int i) {
/* unsigned int length = (int)(log10((float)i)) + 1; */
/* char * arr = (char *) malloc(length * sizeof(char)), * x = arr; */
char * arr = malloc(8);
char * x = arr;
do
{
*x++ = i% 10;
i/= 10;
} while (i != 0);
return arr;
}
Try this :
#include<stdio.h>
void convert_int_to_array(unsigned int);
int main()
{
unsigned int a = 12345678;
convert_int_to_array(a);
return 0;
}
void convert_int_to_array(unsigned int a)
{
int array[25]; // array large enough for an integer
int i = 0, count = 0;
unsigned int num = a;
memset(array, '\0', 20); // I've not included the header file for this.
// gives a warning on compilation.
while(num > 0)
{
array[i] = num % 10;
num = num / 10;
++i;
++count;
}
for(i = count; i>=0;--i)
{
printf("array[%d] = %d\n",i, array[i]);
// or
printf("%d", array[i]);
// dont use both the printf statements, else you will see a
// messed up output.
}
}
BINARY REPRESENTATION :
#include<stdio.h>
struct bit
{
int a : 1;
};
int main()
{
struct bit b;
int d ,f,i;
d=f=256; // take any number of your choice
printf("binary representation of 256:\n");
for(i = 15; i>=0 ; i--) //assuming that the number wont have more than
// 15 DIGITS
{
f=f>>i;
b.a = f;
//d= d>>1;
f=d;
printf("%d",b.a);
}
return 0;
}

Converting 4 bytes to unsigned int

If one has a character array such as
char bytes[256] = "10000011011110110010001101000011";
I want to unsigned value of this which would be : 2205885251
I'm trying to do something along these lines
unsigned int arr[256];
for(int i = 0, k=0; i<256; i++, k++)
{
arr[k] = bytes[i]|bytes[i+1]<<8|bytes[i+2]<<16|bytes[i+3]<<24;
}
I am obtaining the wrong value: 3220856520, can anyone point out what I am doing wrong?
#include <stdio.h>
char bytes[256] = "10000011011110110010001101000011";
int main(void)
{
unsigned int out;
int i;
for (out = 0, i = 0; i < 32; ++i)
if (bytes[31 - i] == '1')
out |= (1u << i);
printf("%u\n", out);
return 0;
}
Output is:
2205885251
#include <stdio.h>
int main()
{
char bytes[256] = "10000011011110110010001101000011";
unsigned int value = 0;
for(int i = 0; i< 32; i++)
{
value = value *2 + (bytes[i]-'0');
}
printf("%u\n",value);
}
it outputs: 2205885251
char bytes[] = "10000011011110110010001101000011";
unsigned int k;
k = strtoul(bytes, NULL, 2);
printf("%u \n", k);
valter

Merge sort of characters in string C

I have this working merge-sort algorithm in C. But it works only for integers. When I tried to change int to char, i'm getting segfault.
Can you please help me, what should I change in this code, so I could use MergeSort like this:
char*str = "test_string";
MergeSort(str, 0, strlen(str)-1);
void Merge(int *array, int left, int mid, int right){
int tempArray[right-left+1];
int pos=0,lpos = left,rpos = mid + 1;
while(lpos <= mid && rpos <= right){
if(array[lpos] <= array[rpos]){
tempArray[pos++] = array[lpos++];
}
else{
tempArray[pos++] = array[rpos++];
}
}
while(lpos <= mid) tempArray[pos++] = array[lpos++];
while(rpos <= right)tempArray[pos++] = array[rpos++];
int iter;
for(iter = 0;iter < pos; iter++){
array[iter+left] = tempArray[iter];
}
return;
}
void MergeSort(int *array, int left, int right){
int mid = (left+right)/2;
if(left<right){
MergeSort(array,left,mid);
MergeSort(array,mid+1,right);
Merge(array,left,mid,right);
}
return;
}
I'm lost. Thanks!
Change your declaration of array from int * to char * in both functions. Make tempArray a char[] instead of an int[]. You are trying to read memory that is 4x (or 8x) out of bounds at the end of the array, hence the seg-fault. Put another way, char is 1 byte (usually) while int is 4 or 8, so you are looking at items of a different size stacked next to each other. Also, do not pass in a const * for your string. Declaring a string as char*str = "test_string"; implies read-only memory on some systems. Use char str[] = "test_string"; instead. If you are not using strictly C, you can use C++ templates to make a function that works for int and char: http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part-1
#include <stdio.h>
#include<ctype.h>
#include<string.h>
int Run_count=-1;
int main ( int argc , char *argv[] )
{
/* if you dont want to use argv, put the elements in A yourself,
size being the number of string*/
/*L --> left side, R --> right side*/
int i = 0;
int size = argc-1;
char *A[argc-1];
for(i=1;i<=argc;i++){*(A+i-1) = argv[i];}
Caller(A,size);
for(i=0;i<size;i++){
printf("%s\n", A[i]);
}
printf("%d",Run_count);
}
int Caller(char* A[] , int n){
Run_count++;
int sizeL, sizeR ,i;
char *L[n/2+1] , *R[n-n/2+1];
if (n < 2){return 1;}
sizeL = n/2;
sizeR = n - sizeL;
for(i=0;i<sizeL;i++) {L[i] = *(A+i);}
for(i=0;i<n - n/2;i++) {R[i] = *(A+i+n/2);}
Caller( L, sizeL);
Caller( R, sizeR);
merger( L,sizeL, R,sizeR, A);
}
void merger(char* L[], int lengthL , char* R[] , int lengthR , char *A[]){
int i, j, k ,t =0 ;
for(k = 0 , j = 0; k < lengthL && j < lengthR ;t++){
if(compare(*(L+k),*(R+j))){
*(A+t) = *(L+k);
k++;}
else{*(A+t) = *(R+j);j++;}
}
while(k < lengthL ){
*(A+t) = *(L+k);
k++;t++;
}
while(j < lengthR ){
*(A+t) = *(R+j);
j++;t++;}
}
int compare(char *line1 , char *line2 )
{
int i;
for(i = 0;*(line1 + i) != '\0' && *(line2 + i) != '\0' ;){
if(isdigit(*(line1+i)) && isalpha(*(line2+i))){return 0;}
else if(isdigit(*(line2+i)) && isalpha(*(line1+i))){return 1;}
else if(*(line1 + i) > *(line2 + i)){return 0;}
else if(*(line1 + i) == *(line2 + i)){i++;}
else{return 1;}
}
}

Strange occurence in genetic algorithm implementation

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 8
#define POP 8
int answers[SIZE] = {5,3,1,7,4,6,0,2};
int getRand(int mod){
if (mod==0) return 0;
else return random()%mod;
}
void printArray(int array[]){
int i;
for(i=0; i<SIZE-1; i++) printf("(%i,%i),",i,array[i]);
printf("(%i,%i)",SIZE-1,array[SIZE-1]);
printf("\n");
}
int getWeight(int array[]){
int weight = 28;
int queen;
for(queen=0;queen<SIZE;queen++){ //for each queen
int nextqueen;
for(nextqueen=queen+1;nextqueen<SIZE;nextqueen++){ //for each of the other queens (nextqueen = queen to avoid counting pairs twice)
if(array[queen] == array[nextqueen] || abs(queen-nextqueen)==abs(array[queen]-array[nextqueen])){ //if conflict
weight--;
}
}
}
return weight;
}
void geneticAlgorithm(){
int population[POP][SIZE];
int children[POP][SIZE];
int weightProb[] = {};
int wpl = 0; //weightProb[] length
float mutProb = 0.05;
int done = 0;
int i;
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = getRand(SIZE);
while(done == 0){
for(i=0;i<POP;i++){
if(getWeight(children[i]) == 28){
printf("solution: ");
printArray(children[i]);
done = 1;
}
}
for(i=0;i<wpl;i++) weightProb[i] = (int)NULL; //clear weightprob
wpl=0;
//weighted probability distribution
for(i=0;i<POP;i++){
int w = getWeight(population[i]);
for(int j=0;j<w;j++){
weightProb[wpl] = i; //fill array with member number w times
wpl++;
}
}
//reproduce
for(i=0;i<POP;i+=2){
int par1 = weightProb[getRand(wpl)];
int par2 = weightProb[getRand(wpl)];
int split = getRand(SIZE);
//crossover
for(int j=0;j<split;j++){
children[i][j] = population[par1][j];
children[i+1][j] = population[par2][j];
}
for(int j=split;j<SIZE;j++){
children[i][j] = population[par2][j];
children[i+1][j] = population[par1][j];
}
//mutation
if(getRand(1000000)<=mutProb*1000000){
int child=getRand(2);
if(child == 0) children[i][getRand(SIZE)] = getRand(SIZE);
else children[i+1][getRand(SIZE)] = getRand(SIZE);
}
}
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = children[i][j];
wpl = 0;
}
}
int main(int argc, const char * argv[]){
srandom((unsigned int)time(NULL)); //seed random
geneticAlgorithm();
return 0;
}
when filling weightProb[], the population randomly changes.
i've debugged using print statements and it stops when wpl++ is commented out, but that is required
(wpl is the length of the weightProb array).
how is this happening?
This declaration:
int weightProb[] = {};
declares an empty array. This means each time you write to an element you write out of bounds of the array, and bad things will happen.

Resources