I'm trying to figure our how to use the Genetic Algorithm to solve N queens.
Here is the program:
#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[224] = {};
int wpl = 0; //weightProb[] length
float mutProb = 0.2; //higher prob yields faster times. works decently anyways. bug: prob = 0
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;
}
The program runs and compiles properly but doesn't produce the results I'm after. I'm wanting to display the x,y co-ordinates of each queen and simply print them out on output. However instead I'm getting random garbage on output and I cant figure out why.
Current output example:
(0,0) (1,3248234234) (2,0) (3,-3248236736) (4,57435727) (5,234743567) (6, 23498348) (7,23487234)
Desired output example (a solution to the N queen problem):
(3,4) (7,2) (0,3) (4,6) (6,5) (1,7) (5,1) (2,0)
Not sure if this is the cause of your specific issue, but it is a problem:
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;
}
}
The above is the initialisation of the population and the beginning of the loop. On the first time through, the children array contains uninitialised data.
Given the rest of the algorithm, you need to be checking the weight of the elements of population (and printing an element from population) if it is a winner, not children.
Related
I am successful in identifying prime and composite from an array. But my qsort function seem to not have any effect when I print the output. I need the primes to be ascending and composite to be descending. When I run the code, it does not sort the output, though it identifies primes and composites.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return b - a;
}
int main() {
int i = 0, n, x, p, c, z, w, j = 0, k = 0, cmpst, null;
int prm;
int prime[50], composite[50], input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &n);
printf("Enter the numbers.\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &input[i]);;
}
for (i = 0; i < n; i++) {
if (input[i] % 2 != 0) {
prime[p++] = input[i];
prm = p;
} else
if (input[i] >= 2 && input[i] % 2 == 0) {
composite[c++] = input[i];
cmpst = c;
}
}
printf("Prime Numbers:");
qsort(prime, prm, sizeof(int), compare_Asc);
for (i = 0; i < p; i++) {
printf("%d", prime[p]);
}
printf("Composite Numbers:");
qsort(composite, cmpst, sizeof(int), compare_Desc);
for (i = 0; i < c; i++) {
printf("%d", composite[c]);
}
return 0;
}
There are some major issues, in the posted code, worth mentioning.
Variables
Declaring all the variables at the beginning of the scope, instead of just before where they are used, can hide bugs.
Uninitialized variables, are an even worse source of errors, because their values are indeterminated.
int i=0, n, x, p, c, z, w, j=0, k=0, cmpst, null;
// ^ ^ ^^^^ ?
// ... Later, in the code:
prime[p++] = input[i];
// ^^^ What value is incremented?
// Where is [p++]? Is it inside the prime array?
A correct initialization would prevent undefined behavior.
int p = 0, c = 0;
int composite[50], input[50];
for(int i = 0; i < n ; ++i) {
if ( is_prime(input[i]) ) { // <-- More on this, later.
prime[p++] = input[i];
}
else {
composite[c++] = input[i];
}
}
Loops
This happens a couple of times, just because the code itself is duplicated (another code smell):
for(i=0;i<p;i++){
// ^^^^^^^^^^^ We want to iterate over [0, p).
printf("%d",prime[p]);
// ^ But this always prints the element one past the end
}
Even if it's just a simple loop, it could be a good idea to write a (testable and reusable) function
void print_arr(size_t n, int arr[n])
{
for (size_t i = 0; i < n; ++i) {
printf("%d ", arr[i]);
} // ^
putchar('\n');
}
// ... Later, in main:
print_arr(p, prime);
print_arr(c, composite);
Primes or composite
I am successful in identifying prime and composite from an array
Well, no. Not with this code, I'm sorry.
if (input[i]%2 != 0) { // Those are ALL the ODD numbers!
prime[p++]=input[i];
}
else if(input[i]>=2 && input[i]%2==0){ // Those are the EVEN numbers greater than 0
composite[c++]=input[i];
}
// What about 0 and the even numbers less than 0?
Not all the odd numbers are prime number (it's a little more complicated than that) and 2 itself is a prime, not a composite.
It's unclear to me if this is a terminology issue or if the snippet is only a placeholder for a proper algorithm. In any case, there are multiple examples of primality test functions in SE sites (I'm quite confident some are posted almost every day).
Overflow risk
See chux - Reinstate Monica's comment:
return a-b; risks overflow when a, b are large int values.
Consider return (a > b) - (a < b); for a full range solution.
Single letter variables names are to be avoided... except for i, j and k used in for() loops only.
You're not updating the index of the arrays c and p as the numbers are being printed out. The arrays are being sorted fine.
In the code below I also remove redundant variables, and rename n to input_count, c to compo_count and p to prime_count.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return b - a;
}
int main ()
{
int i = 0;
int input_count = 0;
int prime_count = 0;
int compo_count = 0;
int prime[50];
int composite[50];
int input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &input_count);
printf("Enter the %d numbers.\n", input_count);
for (i = 0; i < input_count; i++)
{
scanf("%d", &input[i]);
}
for (i = 0; i < input_count; i++)
{
if (input[i] % 2 != 0)
{
prime[prime_count] = input[i];
prime_count += 1;
}
else if (input[i] >= 2 && input[i] % 2 == 0)
{
composite[compo_count] = input[i];
compo_count += 1;
}
}
printf("Prime Numbers:");
qsort(prime, prime_count, sizeof(int), compare_Asc);
for (i = 0; i < prime_count; i++)
{
printf("%d ", prime[i]); // <<-- HERE, not [p]
}
printf( "\n" );
printf ("Composite Numbers:");
qsort(composite, compo_count, sizeof(int), compare_Desc);
for (i = 0; i < compo_count; i++)
{
printf("%d", composite[i]); // <<-- HERE, not [c]
}
printf( "\n" );
return 0;
}
i need to enter number of points(x,y), and then sort the points,from the closest one to (0,0) to the one that is far.. for example:
Enter number of points: 3
Enter point: 1 6
Enter point: 2 5
Enter point: 4 4
Sorted points:(2,5) (4,4) (1,6)
now i did a function that will find the distance,and i did an array and put the distance between two coordinate x and y,and i want to use merge sort to sort the array, my problem is how to go back and print the actual coordinate x y ... (i hope you would understand the problem),what can i do? i thought of putting the cordinate an array and sort them but that won't work :\
(and i didn't learn struct so i can't use unless if there is no other way ...)
plz anyone can help me i really have no idea have to continue:\
#include <stdio.h>
#include <stdlib.h>
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate);
int distance(int a,int b);
void merge(int a[], int na, int b[], int nb, int c[]);
int merge_sort(int ar[], int n);
int main()
{
int x;
int *z;
int *first_coordinate;
int *second_coordinate;
printf("Enter number of points: ");
scanf("%d",&x);
z=(int*)malloc(x*sizeof(int));
first_coordinate=(int*)malloc(x*sizeof(int));
second_coordinate=(int*)malloc(x*sizeof(int));
Enter_numbers(x,z,first_coordinate,second_coordinate);
free(z);
free(first_coordinate);
free(second_coordinate);
return 0;
}
int distance(int a,int b)
{
int dis;
dis=((a*a)+(b*b));
return dis;
}
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate)
{
int a=0,b=0;
int i=0;
int diss=0;
while(x>0)
{
printf("Enter points: ");
scanf("%d %d",&a,&b);
diss=distance(a,b);
z[i]=diss;
first_coordinate[i]=a;
second_coordinate[i]=b;
++i;
x--;
}
}
and the merge sort function i will use after i figure what to do :
int merge_sort(int ar[], int n)
{
int len;
int *temp_array, *base;
temp_array = (int*)malloc(sizeof(int)*n);
if(temp_array == NULL) {
printf("Dynamic Allocation Error in merge_sort");
return FAILURE;
}
for (len = 1; len < n; len *= 2) {
for (base = ar; base < ar + n; base += 2 * len) {
merge(base, len, base + len, len, temp_array);
memcpy(base, temp_array, 2*len*sizeof(int));
}
}
free(temp_array);
return SUCCESS;
}
and here is merge ...
void merge(int a[], int na, int b[], int nb, int c[])
{
int ia, ib, ic;
for(ia = ib = ic = 0; (ia < na) && (ib < nb); ic++)
{
if(a[ia] < b[ib]) {
c[ic] = a[ia];
ia++;
}
else {
c[ic] = b[ib];
ib++;
}
}
for(;ia < na; ia++, ic++) c[ic] = a[ia];
for(;ib < nb; ib++, ic++) c[ic] = b[ib];
}
I would use a struct for solving this task.
If you haven't learned struct yet, this seems to be a good time to learn it.
Note: If you really can't use stuct, see the last part of the answer.
With struct it could be something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
int squared_distance;
} dpoint;
int squared_dst(int x, int y)
{
return (x*x + y*y);
}
// Compare function used for sorting
int compare_dpoint_dst(const void * e1, const void * e2)
{
dpoint* p1 = (dpoint*)e1;
dpoint* p2 = (dpoint*)e2;
if (p1->squared_distance > p2->squared_distance) return 1;
if (p1->squared_distance < p2->squared_distance) return -1;
return 0;
}
void print_dpoint(dpoint dp)
{
printf("(%d, %d) : sd = %d\n", dp.x, dp.y, dp.squared_distance);
}
#define N 5
int main(void) {
// Array of points (fixed size for simplicity)
dpoint ps[N];
// Dummy input (for simplicity)
int x[N] = {1,5,2,3,4};
int y[N] = {9,3,7,1,3};
for (int i = 0; i < N; ++i)
{
ps[i].x = x[i];
ps[i].y = y[i];
}
// Calculate squared distance for all points
for (int i = 0; i < N; ++i)
{
ps[i].squared_distance = squared_dst(ps[i].x, ps[i].y);
}
printf("unsorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
// Sort the points
qsort (ps, sizeof(ps)/sizeof(*ps), sizeof(*ps), compare_dpoint_dst);
printf("sorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
return 0;
}
Notice that you can do the sorting on the squared distance so that you don't need square root in the program.
The program above will generate:
unsorted:
(1, 9) : sd = 82
(5, 3) : sd = 34
(2, 7) : sd = 53
(3, 1) : sd = 10
(4, 3) : sd = 25
sorted:
(3, 1) : sd = 10
(4, 3) : sd = 25
(5, 3) : sd = 34
(2, 7) : sd = 53
(1, 9) : sd = 82
No use of struct
If you for some reason can't use struct, you can use a shadow array to track the sorting but you'll have to write your own sorting. I don't recommend this approach - learn about structinstead. Anyway, it could be something like:
int x[N];
int y[N];
int sd[N]; // squared distance
int sw[N]; // swap order
// read input and calculate distance
// ...
// Fill sw with 0, 1, 2, ....
for (int i=0; i < N; ++i) sw[i] = i;
mySort(sd, sw, N);
// Now you can use sw for printing
for (int i=0; i < N; ++i)
{
// print element sw[i]
printf("(%d,%d)\n", x[sw[i]], y[sw[i]]);
}
}
void mySort(int sd[], int sw[], int N)
{
// .... code for sorting
// ....
// Assume that you need to swap element i and j here
temp = sd[i];
sd[i] = sd[j];
sd[j] = temp;
// Then do exactly the same for sw
temp = sw[i];
sw[i] = sw[j];
sw[j] = temp;
// ....
// ....
}
I am trying to solve 12503 problem on UVA online judge. I think I have figured out the solution, but it gives me TLE. Here is the problem :
You have a robot standing on the origin of x axis. The robot will be given some instructions.
Your task is to predict its position after executing all the instructions.
• LEFT: move one unit left (decrease p by 1, where p is the position of the robot before moving)
• RIGHT: move one unit right (increase p by 1)
• SAME AS i: perform the same action as in the i-th instruction. It is guaranteed that i is a positive
Input
integer not greater than the number of instructions before this.
The first line contains the number of test cases T (T <= 100). Each test case begins with an integer n (1 <= n <= 100), the number of instructions. Each of the following n lines contains an instruction.
Output
For each test case, print the final position of the robot. Note that after processing each test case, the
robot should be reset to the origin.
Sample Input
2
3
LEFT
RIGHT
SAME AS 2
5
LEFT
SAME AS 1
SAME AS 2
SAME AS 1
SAME AS 4
Sample Output
1
-5
Here is my code in C:
#include <stdio.h>
char com[102][20];
int command(char comd[], int pos);
int main() {
int t;
int pos;
int i, n;
char tmp[20];
scanf("%d", &t);
for(i = 0; i < t; i++) {
scanf("%d", &n);
int j;
pos = 0;
for (j = 0; j < n; j++) {
gets(com[j]);
if (strcmp(com[j], "LEFT") == 0)
pos--;
else if(strcmp(com[j], "RIGHT") == 0)
pos++;
else {
pos = command(com[j], pos);
}
}
printf("%d\n", pos);
}
return 0;
}
int command(char comd[], int pos) {
if (strcmp(comd, "LEFT") == 0) {
pos--;
return pos;
}
else if (strcmp(comd, "RIGHT") == 0) {
pos++;
return pos;
}
else{
int a = atoi(&comd[8]);
return command(com[a-1], pos);
}
}
Is there any suggestion why this code gives TLE ?
In the int command(char comd[], int pos) function, you are using recursive call at the last line. This may lead to TLE.
To solve this problem you can use another array to store the number of steps taken by the robot at a command. You just have to access the index of the array later to get step at a previous command.
Here is how I would do it-
#include <stdio.h>
#include <string.h>
int move[110];
int getMove(char inp[], int);
int main()
{
int t, n;
char inp[50];
scanf(" %d ",&t);
while(t--)
{
scanf(" %d ",&n);
int i, pos = 0;
for(i = 0; i < n; i++)
{
gets(inp);
pos += getMove(inp, i);
}
printf("%d\n",pos);
}
return 0;
}
int getMove(char inp[], int i)
{
if(inp[0]=='S')
{
int j;
sscanf(strrchr(inp,' ')," %d",&j);
move[i] = move[j - 1];
}
else
{
move[i] = (inp[0] == 'L') ? -1 : 1;
}
return move[i];
}
So here is my code . I am trying to find a short way to make this programme work withouth changing any of the arregment.I have been tought the buble way i think its called to arrange a group from highest to lowest but it clearly say in my given orders not to change the entire group.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int randomInRange (unsigned int min, unsigned int max)
{
//srand(time(NULL));
int base_random = rand();
if (RAND_MAX == base_random) return randomInRange(min, max);
int range = max + 1 - min,
remainder = RAND_MAX % range,
bucket = RAND_MAX / range;
if (base_random < RAND_MAX - remainder) {
return min + base_random/bucket;
} else {
return randomInRange (min, max);
}
}
int main()
{
int ari,i,min,max;
printf("Gi'me length of the group")
scanf("%d",&ari);
int pinakas[ari];
printf("Gi'me lowest and highest values");
scanf("%d",&min);
scanf("%d",&max);
for(i = 0; i < ari; i++)
{
pinakas[ari] = randomInRange(min,max);
}
int el,meg,c;
el = max+1;
meg = min-1;
c = 0;
printf("Highest Lowest");
while( c != 4;)
{
for(i = 0; i < ari; i++)
{
if(el > pinakas[ari])
{
el = pinakas[ari];
}
if( meg < pinakas[ari])
{
meg = pinakas[ari];
}
if(i == 4)
{
printf("%d %d",el,meg);
( is there something that i can put here is order to make el,meg to go for the second lowest ,second highest? and so on till i get the 5 highest and 5 lowests.Keep in mind the the lowest length of my group will be pinakas[5].)
}
}
c++;
}
For each item in the array, up to 5 comparisons are done for the min list and 5 for the max list.
Suggest calling a function to do this in a tidy fashion.
#include<assert.h>
// `list` is `const` as OP says "withouth changing any of the arregment".
void sort_ends(const int *list, size_t listlen, int *minlist, int *maxlist,
size_t mlen) {
assert(list);
assert(minlist);
assert(maxlist);
assert(mlen >= 1);
assert(listlen >= mlen);
minlist[0] = list[0];
// For each element after the first ...
for (size_t i = 1; i < listlen; i++) {
int mincandidate = list[i];
size_t mini = i;
if (mini > mlen) mini = mlen;
do {
mini--;
if (mincandidate >= minlist[mini])
break;
// swap mincandidate and minlist[mini]
int t = mincandidate;
mincandidate = minlist[mini];
minlist[mini] = t;
} while (mini > 0);
}
// Do similar for maxlist, left for OP
}
int main() {
int ari;
// ...
int pinakas[ari];
// ...
int mlen = 5;
int minlist[mlen];
int maxlist[mlen];
sort_ends(pinakas, ari, minlist, maxlist, mlen);
return 0;
}
Alternative approach, find min index and then memove().
#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.