How to implement ordered crossover - artificial-intelligence

So I have two parents
ABCDE
EDCBA
can I just select a subset from both:
From parent one: ACD
From parent two: EDC
Then I copy parent one into offspring one but copy the selected subset with parent twos order so:
Offspring one: DBCAE
Offspring two: CDEBA

To answer the title question:
http://www.eecs.tufts.edu/~jfinke02/jmona/xref/jmona/example/tsp/crossover/OrderedCrossoverFunction.html:
1 /**
2 * OrderedCrossoverFunction.java
3 *
4 * Copyright 2009, 2010 Jeffrey Finkelstein
5 *
6 * This file is part of jmona.
7 *
8 * jmona is free software: you can redistribute it and/or modify it under the
9 * terms of the GNU General Public License as published by the Free Software
10 * Foundation, either version 3 of the License, or (at your option) any later
11 * version.
12 *
13 * jmona is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * jmona. If not, see <http://www.gnu.org/licenses/>.
19 */
20 package jmona.example.tsp.crossover;
21
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Vector;
25
26 import jmona.CrossoverFunction;
27 import jmona.functional.Range;
28 import jmona.random.RandomUtils;
29
30 /**
31 * Ordered crossover (also known as OX) for a tour in the traveling salesman
32 * problem.
33 *
34 * #author Jeffrey Finkelstein
35 * #since 0.1
36 */
37 // TODO references for the original authors of TSP crossover functions
38 public class OrderedCrossoverFunction implements
39 CrossoverFunction<List<Integer>> {
40
41 /**
42 * Perform ordered crossover (also known as OX) on the specified tours.
43 *
44 * Ordered crossover works in two stages. First, a random slice is swapped
45 * between the two tours, as in a two-point crossover. Second, repeated cities
46 * not in the swapped area are removed, and the remaining integers are added
47 * from the other tour, in the order that they appear starting from the end
48 * index of the swapped section.
49 *
50 * #param tour1
51 * A tour.
52 * #param tour2
53 * Another tour.
54 * #see jmona.CrossoverFunction#crossover(Object, Object)
55 */
56 #Override
57 public void crossover(final List<Integer> tour1, final List<Integer> tour2) {
58
59 // get the size of the tours
60 final int size = tour1.size();
61
62 // choose two random numbers for the start and end indices of the slice
63 // (one can be at index "size")
64 final int number1 = RandomUtils.randomData().nextInt(0, size - 1);
65 final int number2 = RandomUtils.randomData().nextInt(0, size);
66
67 // make the smaller the start and the larger the end
68 final int start = Math.min(number1, number2);
69 final int end = Math.max(number1, number2);
70
71 // instantiate two child tours
72 final List<Integer> child1 = new Vector<Integer>();
73 final List<Integer> child2 = new Vector<Integer>();
74
75 // add the sublist in between the start and end points to the children
76 child1.addAll(tour1.subList(start, end));
77 child2.addAll(tour2.subList(start, end));
78
79 // iterate over each city in the parent tours
80 int currentCityIndex = 0;
81 int currentCityInTour1 = 0;
82 int currentCityInTour2 = 0;
83 for (final int i : new Range(size)) {
84
85 // get the index of the current city
86 currentCityIndex = (end + i) % size;
87
88 // get the city at the current index in each of the two parent tours
89 currentCityInTour1 = tour1.get(currentCityIndex);
90 currentCityInTour2 = tour2.get(currentCityIndex);
91
92 // if child 1 does not already contain the current city in tour 2, add it
93 if (!child1.contains(currentCityInTour2)) {
94 child1.add(currentCityInTour2);
95 }
96
97 // if child 2 does not already contain the current city in tour 1, add it
98 if (!child2.contains(currentCityInTour1)) {
99 child2.add(currentCityInTour1);
100 }
101 }
102
103 // rotate the lists so the original slice is in the same place as in the
104 // parent tours
105 Collections.rotate(child1, start);
106 Collections.rotate(child2, start);
107
108 // copy the tours from the children back into the parents, because crossover
109 // functions are in-place!
110 Collections.copy(tour1, child2);
111 Collections.copy(tour2, child1);
112 }
113
114 }
More theory: http://www.dmi.unict.it/mpavone/nc-cs/materiale/moscato89.pdf (mirror: http://www.scribd.com/doc/101866504/1989-On-Genetic-Crossover-Operators-for-Relative-Order-Preservation)
Related: http://www.scribd.com/doc/53306810/35/ORDERED-CROSSOVER:

Here is the code above implemented in C++ with my own random class. I'm not sure if the rotation is correct but the cross overing seems legit. At the end of the day, you won't get any repeats!
#include <array>
#include <random>
#include <iostream>
// I converted this found code into a functional class
// http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
class MyRandom
{
public:
MyRandom() : gen(rd()) {}
int nextInt(const int& max)
{
std::uniform_int_distribution<> dis(0, max);
return dis(gen);
}
private:
std::random_device rd;
std::mt19937_64 gen;
std::uniform_int_distribution<> setdis;
bool disSet = false;
};
void crossover(std::vector<int>& parent1, std::vector<int>& parent2)
{
int size = int(parent1.size());
MyRandom rand;
int number1 = rand.nextInt(7);
int number2 = rand.nextInt(7);
int start = fmin(number1, number2);
int end = fmax(number1, number2);
std::vector<int> child1;
std::vector<int> child2;
for(int i = start; i<end; i++)
{
child1.push_back(parent1[i]);
child2.push_back(parent2[i]);
}
int geneIndex = 0;
int geneInparent1 = 0;
int geneInparent2 = 0;
for (int i = 0; i<size; i++)
{
geneIndex = (end + i) % size;
geneInparent1 = parent1[geneIndex];
geneInparent2 = parent2[geneIndex];
bool is_there = false;
for(int i1 = 0; i1<child1.size(); i1++)
{
if(child1[i1] == geneInparent2)
{
is_there = true;
}
}
if(!is_there)
{
child1.push_back(geneInparent2);
}
bool is_there1 = false;
for(int i1 = 0; i1<child2.size(); i1++)
{
if(child2[i1] == geneInparent1)
{
is_there1 = true;
}
}
if(!is_there1)
{
child2.push_back(geneInparent1);
}
}
std::rotate(child1.begin(), child1.begin()+start, child1.end());
std::rotate(child2.begin(), child2.begin()+start, child2.end());
for(int i = 0; i<size; i++)
{
parent1[i] = child2[i];
parent2[i] = child1[i];
}
}
int main(int argc, const char * argv[]) {
std::vector<int> parent1 = {0, 1, 2, 3, 4, 5, 6, 7};
std::vector<int> parent2 = {7, 6, 5, 4, 3, 2, 1, 0};
for(int i = 0; i<8; i++)
{
std::cout << parent1[i] << " ";
}
std::cout << std::endl;
for(int i = 0; i<8; i++)
{
std::cout << parent2[i] << " ";
}
std::cout << std::endl;
crossover(parent1, parent2);
for(int i = 0; i<8; i++)
{
std::cout << parent1[i] << " ";
}
std::cout << std::endl;
for(int i = 0; i<8; i++)
{
std::cout << parent2[i] << " ";
}
std::cout << std::endl;
return 0;
}

Related

Determining if an array of numbers contains a specific element within 2D character array

Overview
I am currently writing a C program that simulates a bingo checker. In this program, a user enters a 2D Array, a string of numbers, followed another 2D array. All done through standard input.
The first 2D array is the bingo pattern. The 1D array is the numbers called during the game. The second 2D array is the player's actual pattern on their card. The purpose of the program is to determine if their bingo is valid or invalid. A sample input is as follows:
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 1 1 1 1
12 20 15 40 45 32 71 07 56 51 36 55 19 10 43 23 70 11 27 60 67 03 72 33 56 09 02
12 29 39 57 61
15 30 45 60 75
07 23 00 46 68
02 18 37 51 70
10 27 32 55 71
Problem
Since I have to compare the arrays with the strings of numbers, I thought it would be easier to create a third 2D array, named playerPattern, which is also filled with ones and zeros. In the final block of code in the snippet below, the program checks if the value in the current position of the player's actual board, playerBoard, is within the numbersCalled array. If so, it places a 1 in that spot. Then, it will compare the first 2D array, bingoPattern with playerPattern.
However, in the final for-loop, the if condition is causing the program to halt and throw a signal 11 disruption.
if (strcmp(currentArrayElem, currentNumCalled) == 0 { strcpy(&playerPattern[row][col], "1");
}
I can not figure out why the memory allocation is an issue here, as the pointers seem to be set-up correctly.
// necessary import statements
#include <stdio.h>
#include <string.h>
int main() {
char* bingoPattern[5][5]; // array to store initial bingo pattern (1's and 0's)
char* playerBoard[5][5]; // array to store player's actual bingo board
char* playerPattern[5][5]; // array to store player's actual bingo pattern
char inputNumString[225]; // undelimited string of numbers for initial standard input
// read-in bingo pattern
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
fscanf(stdin, "%d", &bingoPattern[i][j]); } }
// read-in numbers called
fgets(inputNumString, 225, stdin); // skip empty line
fgets(inputNumString, 225, stdin); // collect string input
fgets(inputNumString, 225, stdin); // skip empty line
char *numbersCalled[75]; // final array of delimited elements
char singleNumber; // single string of delimited numbers
inputNumString[strlen(inputNumString + 1)] = 32;
singleNumber = strtok(inputNumString, " ");
int numCalledCount = 0; // stores amount of numbers called
while (singleNumber != NULL) {
numbersCalled[numCalledCount] = singleNumber;
numCalledCount = numCalledCount + 1;
singleNumber = strtok(NULL, " ");
}
// read-in player's actual board
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
fscanf(stdin, "%d", &playerBoard[i][j]);
}
}
// populate player pattern with zero's
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
playerPattern[i][j] = 0;
}
}
// create player pattern
char* currentNumCalled;
char* currentArrayElem;
for (int currentNumber = 0; currentNumber < numCalledCount; currentNumber++) {
currentNumCalled = numbersCalled[currentNumber];
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
currentArrayElem = &playerBoard[row][col];
if (strcmp(currentArrayElem, currentNumCalled) == 0) {
strcpy(&playerPattern[row][col], "1");
}
}
}
}
return 0;
}

Euler project problem 58, where's the error

I'm just not able to see where's the error on my code, I am getting 26249 (or 26247 if I go back one spiral level), but it should be 26241.
Obviously, there must be a problem with my logic, but I can't point out where.
Spiral Primes, Project Euler Problem 58
Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.
37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 05 04 03 12 29
40 19 06 01 02 11 28
41 20 07 08 09 10 27
42 21 22 23 24 25 2643 44 45 46 47 48 49
It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that 8 out of the 13 numbers lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.
If one complete new layer is wrapped around the spiral above, a square spiral with side length 9 will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?
#include <stdio.h>
#define print(ref) printf(#ref" = %d\n",ref);
#define printl(ref) printf(#ref" = %ld\n",ref);
#define NUM_OF_PRIMES 5000
int primesOnThisLevel(int);
void generatePrimes();
int isPrime(int);
int canBeExpressedAsPrime(int);
int primes[NUM_OF_PRIMES] = {2,3,5};
int primesFound = 3;
int main(){
int numbersInDiagonal = 1;
int primesInDiagonal = 0;
int level;
generatePrimes();
for (level = 2 ; numbersInDiagonal/10 <= primesInDiagonal ; level++){
primesInDiagonal += primesOnThisLevel(level);
numbersInDiagonal += 4;
}
print(numbersInDiagonal)
print(primesInDiagonal)
int sideLenght = (2*level)-1;
print(sideLenght*sideLenght);
print(sideLenght);
return 0;
}
int primesOnThisLevel(int level){
int primesCount = 0;
int sideLenght = (2*level)-1;
int differenceBetweenCorners = 2*(level-1);
int cornerValue = sideLenght*sideLenght;
for (int i = 0 ; i < 3 ; i++){
cornerValue -= differenceBetweenCorners;
primesCount += isPrime(cornerValue);
}
return primesCount;
}
void generatePrimes(){
for (int i = 7 ; primesFound < NUM_OF_PRIMES ; i +=2 ){
if ( isPrime(i) ){
primes[primesFound++] = i;
}
}
print(primes[primesFound-1]);
}
int isPrime(int prospect){
if ( prospect == 3 || prospect == 5 ) return 1;
if ( !canBeExpressedAsPrime(prospect) ) return 0;
for (int i = 0 ; primes[i]*primes[i] <= prospect ; i++)
if ( prospect%primes[i] == 0 ) return 0;
return 1;
}
int canBeExpressedAsPrime(int prospect){
if ( prospect%6 == 1 ) return 1;
if ( prospect%6 == 5 ) return 1;
return 0;
}
Special Thanks to Roberto Trani whom pointed out the error which was regarding boundaries, the previous limit included 10% which was not supposed to happen, here it is the ammended main function, which is the perfect situation to use a do-while loop.
int main(){
int numbersInDiagonal = 1;
int primesInDiagonal = 0;
int level = 2;
generatePrimes();
do {
primesInDiagonal += primesOnThisLevel(level);
numbersInDiagonal += 4;
level++;
} while ( numbersInDiagonal < primesInDiagonal*10 );
int sideLenght = (2*(--level))-1;
print(sideLenght);
return 0;
}

Delete any number of Columns in 2D dynamic array and resize the matrix size after column deletion

I am trying to delete first 20 columns from each of the slices of my 3D dynamic array. I guessed trying to write a function for 2D dynamic array would solve the problem which I would iterate over each of the levels of 3D array. I got an example in stackoverflow which I am trying to make work.
But the problem is the function can not delete the whole column. Instead it only delete one element. Can anyone give me idea how to delete whole column from a 2D dynamic array?
void removeColumn(int** matrix, int col){
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
while(col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][col]=matrix[i][col+1];
col++;
} matrix[i] = realloc(matrix[i], sizeof(double)*MATRIX_WIDHT); }
My expected ouput is like
Sample input:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
sample output:
1 3 4
5 7 8
9 11 12
13 15 16
Update: here is the code which delete the column completely after using #frslm advice
but matrix is not resizing.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int** fill(size_t rows, size_t cols, int input[][cols])
{
int i,j,count=1;
int** result;
result = malloc((rows)*sizeof(int*));
for(i=0;i<rows;i++)
{
result[i]=malloc(cols*sizeof(int));
for(j=0;j<cols;j++)
{
result[i][j]=count++;
}
}
return result;
}
void printArray2D(size_t rows, size_t cols,int** input)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
printf(" %4d",input[i][j]);
}
printf("\n");
}
}
void removeColumn(int** matrix, int col2del , int rows, int cols){
int MATRIX_WIDTH = cols;
int MATRIX_HEIGHT = rows;
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
int curr_col = col2del;
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
//matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
matrix[i] = realloc(matrix[i], sizeof (matrix[i][0])*MATRIX_WIDTH);
}
}
int main()
{
int arRow,arCol;
arRow =8;
arCol = 9;
int ar[arRow][arCol];
int **filled;
filled = fill(arRow, arCol, ar);
printArray2D(arRow,arCol,filled);
removeColumn(filled, 3,arRow,arCol);
printf("After 3rd Column Delete.......\n");
printArray2D(arRow,arCol,filled);
return(0);
}
Output: last column duplicates
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71 72
After 3rd Column Delete.......
1 2 3 5 6 7 8 9 9
10 11 12 14 15 16 17 18 18
19 20 21 23 24 25 26 27 27
28 29 30 32 33 34 35 36 36
37 38 39 41 42 43 44 45 45
46 47 48 50 51 52 53 54 54
55 56 57 59 60 61 62 63 63
64 65 66 68 69 70 71 72 72
You increment col until it reaches the end of the first row, but you never reset it for subsequent rows, which is why you end up removing only the first row's column.
Make sure you reset col at the start of each iteration:
void removeColumn(int** matrix, int col){
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
int curr_col = col; // <- use a temporary `col` variable for each row
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
}
}
Edit (in response to OP's edit):
Ensure that removeColumn() updates the number of columns (cols) after resizing the matrix; one way to do that is by using a pointer: int *cols as a parameter instead of int cols (don't forget to pass in an address, &arCol, when calling this function). Also, I suggest getting rid of the unnecessary MATRIX_HEIGHT variable:
void removeColumn(int** matrix, int col2del, int rows, int *cols){
int MATRIX_WIDTH = --(*cols);
for(int i=0;i<rows; i++) {
int curr_col = col2del;
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
matrix[i] = realloc(matrix[i], sizeof(matrix[i][0])*MATRIX_WIDTH);
}
}
It's easier if you pass the width and height, and update the width:
void removeColumn(int** matrix, int col, int* width, int height)
{
int j, i;
for (j = 0; j < height; ++j) {
if (col == *width-1) {
continue;
}
for (i = col; i < *width; ++i) {
matrix[j][i] = matrix[j][i+1];
}
// this is not necessary, but I'm adding as requested
matrix[j] = realloc(
matrix[j],
sizeof(int) * (*width - 1)
);
}
--(*width);
}
You could also avoid dynamic memory allocations, avoiding memory defragmentation:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int max_width, max_height;
int width, height;
int* values;
} matrix;
void removeColumn(matrix* matrix, int col)
{
int y, i;
for (y = 0; y < matrix->height; ++y) {
if (col == matrix->width-1) {
continue;
}
i = col + matrix->height * y;
while (i < matrix->width) {
matrix->values[i] = matrix->values[++i];
}
}
--matrix->width;
}
void printMatrix(matrix* matrix)
{
int y, x;
for (y = 0; y < matrix->height; ++y) {
for (x = 0; x < matrix->width; ++x) {
printf("%d ", matrix->values[x + matrix->width * y]);
}
printf("\n");
}
}
int main ()
{
int y, x = 0;
matrix matrix;
matrix.max_width = 4;
matrix.max_height = 4;
matrix.width = 4;
matrix.height = 4;
int values[4][4];
matrix.values = &values;
for (y = 0; y < matrix.height; ++y) {
for (x = 0; x < matrix.width; ++x) {
int i = x + matrix.width * y;
matrix.values[i] = i % 10;
}
}
printMatrix(&matrix);
removeColumn(&matrix, 1);
printf("===\n");
printMatrix(&matrix);
}
Tested using: https://www.tutorialspoint.com/compile_c_online.php
ADDED
But when the array size is too big then do we have any other option
but using dynamic array
If you want to make a resizable array, you could use a single malloc when allocating the array and use a realloc when the width will be greater than max_width or the height will be greater than max_height.
Nevertheless, I believe we should try to avoid lots of dynamic allocations using malloc or realloc, because they're slow (though most of the time you won't notice), they can severely defragment memory and the way you did it generates lots of unnecessary cache misses.
You should also grow them more than required, for instance, exponentially, if you don't know that you will need to resize the array several times. That's how hashes and dynamic arrays are usually implemented (properly).
You may find, for instance, several JSON, XML and HTML C libraries without dynamic memory to avoid its pitfalls, and in many professional video games, a huge malloc might be used to avoid lots of them and simple arrays are used liberally.
Why is realloc eating tons of memory?
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
http://gameprogrammingpatterns.com/data-locality.html
https://codefreakr.com/how-is-c-stl-implemented-internally/
http://gamesfromwithin.com/start-pre-allocating-and-stop-worrying
CppCon 2014: Mike Acton "Data-Oriented Design and C++"
Of course, you can use dynamic memory, but it's better to understand its pitfalls for better decisions.

Sorting 2d array (matrix) in C

I have a task to sort a 2d array but it is really hard for me. I can't figure out where I'm making a mistake.
It will be good to use while loop instead of for loop
Here is the task:
Enter a square matrix of dimensions n.
Elements below main diagonal sort in ascending order.
Elements above main diagonal sort in descending order.
Elements on main diagonal sort:
first even numbers in ascending order.
then odd numbers in descending order.
Matrix before sorting:
1 5 4 7 2
4 8 5 9 0
2 7 6 5 3
3 1 7 4 9
2 5 1 7 3
Matrix after sorting :
4 9 9 7 5
1 6 5 5 4
1 2 8 3 2
2 3 4 3 0
5 7 7 7 1
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main () {
int n, i, j, a, k, l, o;
int m[50][50];
printf ("Enter n of square matrix : \n");
scanf ("%d", &n);
printf ("Enter rows and columns numbers n :\n");
i = 0;
while (i < n) {
j = 0;
while (j < n) {
scanf ("%d", &m[i][j]);
j++;
}
i++;
}
printf ("Matrix before sorting \n");
i = 0;
while (i < n) {
j = 0;
while (j < n) {
printf ("%d ", m[i][j]);
j++;
}
printf ("\n");
i++;
}
printf ("Matrix after sorting \n");
i = 0;
while (i < n) {
j = 0;
while (j < n) {
if (i < j) {
k = j + 1;
while (k < (n - 1)) {
if (m[i][k] < m[i][k + 1]) {
a = m[i][k];
m[i][k] = m[i][k + 1];
m[i][k + 1] = a;
}
k++;
}
}
else if (i > j) {
l = i + 1;
while (l < (n - 1)) {
if (m[l][j] > m[l + 1][j]) {
a = m[l][j];
m[l][j] = m[l + 1][j];
m[l + 1][j] = a;
}
l++;
}
}
else {
if (m[i][j] % 2 == 0 && m[i + 1][j + 1] % 2 == 0) {
if (m[i][j] > m[i + 1][j + 1]) {
a = m[i][j];
m[i][j] = m[i + 1][j + 1];
m[i + 1][j + 1] = a;
}
}
if (m[i][j] % 2 != 0 && m[i + 1][j + 1] % 2 != 0) {
if (m[i][j] < m[i + 1][j + 1]) {
a = m[i][j];
m[i][j] = m[i + 1][j + 1];
m[i + 1][j + 1] = a;
}
}
}
j++;
}
i++;
}
i = 0;
while (i < n) {
j = 0;
while (j < n) {
printf ("%d ", m[i][j]);
j++;
}
printf ("\n");
i++;
}
return 0;
}
CHANGES MADE ON 02/02/2018
I need to make simple code , without things like size_t,buffer and pointers etc...
I made some code but when i use odd n number of matrix it wont work properly (for example 5x5) I don't know where i m making mistake .
#include <stdio.h>
#include <stdlib.h>
int main()
{
static int a[500][500];
int i,j,l,k,m,b,n,t,d,c;
printf("Unesite n kvadratne matrice : \n");
scanf("%d" , &n);
printf("Matrica pre sortiranja \n \n");
for ( i = 0; i < n; i++)
{
for ( j = 0; j < n ; j++)
{
scanf("%d",&a[ i ][ j ]);
}
}
for ( i = 0; i < n; i++)
{
for ( j = 0; j < n; j++)
{
if ( i > j ) // ispod dijagonale
{
for ( l = i ; l < n ; l++)
{
for ( k = j ; k < l ; k++ )
{
if ( a[ i ][ j ] > a[ l ][ k ] && k < l )
{
t = a[ i ][ j ];
a[ i ][ j ] = a[ l ][ k ];
a[ l ][ k ] = t ;
}
}
}
}
if ( i < j ) // iznad dijagonale
{
for ( m = i ; m < n ; m++)
{
for ( b = j ; b < n ; b++)
{
if ( a[ i ][ j ] < a[ m ][ b ] && m < b )
{
t = a[ i ][ j ];
a[ i ][ j ] = a[ m ][ b ];
a[ m ][ b ] = t ;
}
}
}
}
if ( i == j ) // dijagonala
{
for (d = i ; d < n ; d++)
{
for ( c = d + 1 ; c < n ; c++)
{
if ( a[ d ] [ d ] % 2 != 0 && a[ c ] [ c]%2 == 0 )
{
t = a[ d ] [ d ] ;
a[ d ] [ d ] = a[ c ] [ c] ;
a[ c ] [ c] = t ;
}
}
}
for (d = i ; d < n ; d++)
{
for ( c = d + 1 ; c < n ; c++)
{
if ( a[ d ][ d ] %2 == 0 && a[ c ][ c ] %2 ==0
&& a[ d ][ d ] > a [ c ][ c ])
{
t = a[ d ] [ d ] ;
a[ d ] [ d ] = a[ c ] [ c] ;
a[ c ] [ c] = t ;
}
else if ( a[ d ][ d ] %2 != 0 && a[ c ][ c ] %2
!=0 && a[ d ][ d ] < a [ c ][ c ])
{
t = a[ d ] [ d ] ;
a[ d ] [ d ] = a[ c ] [ c] ;
a[ c ] [ c] = t ;
}
}
}
}
}
}
printf("Posle sortiranja : \n");
for ( i = 0; i < n; i++)
{
for ( j = 0; j < n;j++)
{
printf(" %d ",a[i][j]);
}
printf("\n \n");
}
return 0;
}
It's an intriguing problem. As I outlined in a comment, I think the solution has to be tackled in three separate sorting operations:
Sorting the diagonal
Sorting the upper triangle
Sorting the lower triangle
The sequence in which those operations occur is immaterial. Indeed, if you want to run the three sorts in parallel with threads, you could do that.
The trick to sorting the diagonal is to write a comparison function that ensures that all even numbers come before all odd numbers (so every even number is deemed smaller than any odd number), but when two even numbers are compared, they're sorted in ascending order whereas when two odd numbers are compared, they're sorted in descending order. The cmp_aeod() function (ascending even odd descending) function achieves this.
It would be possible to work with just one of the cmp_asc() and cmp_dsc() functions, but it is more straight-forward to have both. The (x > y) - (x < y) idiom does two comparison always, but if x is bigger than y, the first term is 1, the second 0, and the result is 1. If x is smaller than y, the first term is 0, the second is 1, and the result is -1. If x is equal to y, of course, both terms are 0 and the result is also 0.
The key to sorting the triangles is to note that sorting algorithms work on contiguous arrays, but the data in the triangles is not contiguous. The solution shown is to number the elements in the triangle from 0 to m, where m = (n * (n - 1)) / 2, given that the square matrix is an n by n one. The code then needs to be able to identify which indexes in the matrix should be accessed for the corresponding element number, and this mapping is done by the ut or lt matrix in the triangle-sorting functions. I couldn't work out a non-iterative formula to convert the sequence number in the triangle into a row/col pair, so I created the map matrix. This gives an auxilliary storage requirement of size O(N2).
The sort algorithm used is a simple quadratic sort; you can change it for a more sophisticated algorithm (quicksort or whatever) as you wish.
/*
** + Enter a square matrix of dimensions n .
** + Elements below main diagonal sort in ascending order.
** + Elements above main diagonal sort in descending order.
** + Elements on main diagonal sort :
** - first even numbers in ascending order.
** - then odd numbers in descending order.
*/
static inline int cmp_asc(int x, int y) { return (x > y) - (x < y); }
static inline int cmp_dsc(int x, int y) { return (x < y) - (x > y); }
static inline int cmp_eaod(int x, int y)
{
int px = x & 1;
int py = y & 1;
if (px != py)
return px - py;
if (px == 1)
return cmp_dsc(x, y);
return cmp_asc(x, y);
}
#include <stdio.h>
static void print_matrix(const char *tag, size_t r, size_t c, int matrix[r][c])
{
printf("%s:\n", tag);
for (size_t i = 0; i < r; i++)
{
for (size_t j = 0; j < c; j++)
printf("%3d", matrix[i][j]);
putchar('\n');
}
}
static void sort_diagonal(size_t n, int matrix[n][n])
{
for (size_t i = 0; i < n; i++)
{
for (size_t j = i + 1; j < n; j++)
{
if (cmp_eaod(matrix[i][i], matrix[j][j]) > 0)
{
int t = matrix[i][i];
matrix[i][i] = matrix[j][j];
matrix[j][j] = t;
}
}
}
}
/*
** D0 U0 U1 U2 U3
** L0 D1 U4 U5 U6
** L1 L2 D3 U7 U8
** L3 L4 L5 D4 U9
** L6 L7 L8 L9 D5
**
** D0 = (0, 0); U0 = (0, 1); U1 = (0, 2); U2 = (0, 3); U3 = (0, 4);
** L0 = (1, 0); D1 = (1, 1); U4 = (1, 2); U5 = (1, 3); U6 = (1, 4);
** L1 = (2, 0); L2 = (2, 1); D2 = (2, 2); U7 = (2, 3); U8 = (2, 4);
** L3 = (3, 0); L4 = (3, 1); L5 = (3, 2); D3 = (3, 3); U9 = (3, 4);
** L6 = (4, 0); L7 = (4, 1); L8 = (4, 2); L9 = (4, 3); D4 = (4, 4);
*/
/*
** It is probably best to create an array that does the mapping from an
** index to the row/column, with one such mapping for the lower
** triangle; one for the upper triangle.
*/
static void sort_lt(size_t n, int matrix[n][n])
{
size_t m = (n * (n - 1)) / 2;
int lt[m][2];
size_t r = 1;
size_t c = 0;
for (size_t i = 0; i < m; i++)
{
lt[i][0] = r;
lt[i][1] = c++;
if (c == r)
{
r++;
c = 0;
}
}
//print_matrix("LT map", m, 2, lt);
for (size_t i = 0; i < m; i++)
{
size_t xi = lt[i][0];
size_t yi = lt[i][1];
for (size_t j = i + 1; j < m; j++)
{
size_t xj = lt[j][0];
size_t yj = lt[j][1];
if (cmp_asc(matrix[xi][yi], matrix[xj][yj]) > 0)
{
int t = matrix[xi][yi];
matrix[xi][yi] = matrix[xj][yj];
matrix[xj][yj] = t;
}
}
}
}
static void sort_ut(size_t n, int matrix[n][n])
{
size_t m = (n * (n - 1)) / 2;
int ut[m][2];
size_t r = 0;
size_t c = 0;
for (size_t i = 0; i < m; i++)
{
ut[i][0] = r;
ut[i][1] = ++c;
if (c == n - 1)
{
r++;
c = r;
}
}
//print_matrix("UT map", m, 2, ut);
for (size_t i = 0; i < m; i++)
{
size_t xi = ut[i][0];
size_t yi = ut[i][1];
for (size_t j = i + 1; j < m; j++)
{
size_t xj = ut[j][0];
size_t yj = ut[j][1];
if (cmp_dsc(matrix[xi][yi], matrix[xj][yj]) > 0)
{
int t = matrix[xi][yi];
matrix[xi][yi] = matrix[xj][yj];
matrix[xj][yj] = t;
}
}
}
}
static void test_matrix(const char *tag, size_t n, int matrix[n][n])
{
char buffer[64];
snprintf(buffer, sizeof(buffer), "Matrix %s (%zux%zu) - before", tag, n, n);
print_matrix(buffer, n, n, matrix);
//print_matrix("Before sorting diagonal", n, n, matrix);
sort_diagonal(n, matrix);
//print_matrix("After sorting diagonal", n, n, matrix);
sort_lt(n, matrix);
//print_matrix("After sorting lower triangle", n, n, matrix);
sort_ut(n, matrix);
//print_matrix("After sorting upper triangle", n, n, matrix);
snprintf(buffer, sizeof(buffer), "Matrix %s (%zux%zu) - after", tag, n, n);
print_matrix(buffer, n, n, matrix);
}
int main(void)
{
int matrix1[5][5] =
{
{ 1, 5, 4, 7, 2 },
{ 4, 8, 5, 9, 0 },
{ 2, 7, 6, 5, 3 },
{ 3, 1, 7, 4, 9 },
{ 2, 5, 1, 7, 3 },
};
test_matrix("SAMPLE1", 5, matrix1);
// gen_matrix -i -n matrix2 -r 10 -c 10 -L 10 -H 99
int matrix2[10][10] =
{
{ 87, 32, 98, 58, 60, 71, 46, 81, 70, 14, },
{ 22, 92, 15, 98, 51, 26, 94, 67, 46, 56, },
{ 71, 89, 86, 16, 20, 89, 97, 89, 45, 92, },
{ 63, 13, 76, 19, 75, 19, 66, 89, 58, 41, },
{ 82, 68, 75, 26, 58, 20, 89, 87, 65, 66, },
{ 74, 83, 68, 92, 10, 98, 90, 21, 39, 63, },
{ 24, 65, 23, 68, 62, 44, 48, 22, 27, 59, },
{ 26, 27, 71, 71, 51, 31, 43, 69, 92, 10, },
{ 54, 19, 41, 50, 10, 89, 42, 52, 94, 54, },
{ 42, 50, 79, 48, 77, 18, 29, 40, 61, 63, },
};
test_matrix("SAMPLE 2", 10, matrix2);
return 0;
}
When run, the output is:
Matrix SAMPLE1 (5x5) - before:
1 5 4 7 2
4 8 5 9 0
2 7 6 5 3
3 1 7 4 9
2 5 1 7 3
Matrix SAMPLE1 (5x5) - after:
4 9 9 7 5
1 6 5 5 4
1 2 8 3 2
2 3 4 3 0
5 7 7 7 1
Matrix SAMPLE 2 (10x10) - before:
87 32 98 58 60 71 46 81 70 14
22 92 15 98 51 26 94 67 46 56
71 89 86 16 20 89 97 89 45 92
63 13 76 19 75 19 66 89 58 41
82 68 75 26 58 20 89 87 65 66
74 83 68 92 10 98 90 21 39 63
24 65 23 68 62 44 48 22 27 59
26 27 71 71 51 31 43 69 92 10
54 19 41 50 10 89 42 52 94 54
42 50 79 48 77 18 29 40 61 63
Matrix SAMPLE 2 (10x10) - after:
48 98 98 97 94 92 92 90 89 89
10 58 89 89 87 81 75 71 70 67
10 13 86 66 66 65 63 60 59 58
18 19 22 92 58 56 54 51 46 46
23 24 26 26 94 45 41 39 32 27
27 29 31 40 41 98 26 22 21 20
42 42 43 44 48 50 87 20 19 16
50 51 52 54 61 62 63 69 15 14
65 68 68 68 71 71 71 74 63 10
75 76 77 79 82 83 89 89 92 19
The 'SAMPLE1 - before' data corresponds to the input in the question, and the 'SAMPLE 1 - after' output corresponds to the desired output. The bigger matrix result seems to match the requirements too.
I developed the diagonal sort first because it is by far the easiest; the even ascending, odd descending order is a problem I'd solved before. I then developed one of the triangle sorts, and debugged that. Getting the second triangle sorted was then very straight-forward. Making sure that I had a good flexible matrix printing function also helped. The commented out calls were all used at some point during the development.
Timing tests
The 'sort in place' code shown becomes very slow as the matrix grows. There's an alternative method — copy the data out of the matrix into a 1D vector; sort the vector; copy the data back into the matrix. I did some timing tests. With a matrix size of 10x10, the times were comparable (15µs for the basic sort code shown above; 12µs for code using extract, quicksort, insert). When the matrix size was 20x20, the performance was firmly in favour of the extract, quicksort, insert: 172µs vs 32µs in favour of quicksort, and by 900x900, the basic sort was taking 285s vs 0.054s for quicksort. The discrepancy is growing faster than a quadratic sort can account for. The trouble is the very complex access path to get to the elements being sorted. The code for creating the lt and ut matrices remains useful. The lt and ut matrices tell you which cells to collect the data from for sorting the triangle (order doesn't much matter while extracting the data since it is about to be sorted anyway), but also (crucially) tells you where to place each element in the sorted data.
You can find my code on GitHub in my SOQ (Stack
Overflow Questions) repository in the
src/so-4829-1562
sub-directory. (Note that at the moment, the code uses VLAs for intermediate matrices; it crashes at around 1000x1000 on a Mac. I need to change it to use dynamic memory allocation in the sort code as well as in the data generation code. It may get fixed, sooner or later. Also, I'm not convinced there's enough time between refreshes of hardware to use the basic sort on 10000x10000 size matrices, though I think the quick sort code would still be usable.)
Another interesting test would be to adapt the 'basic sort' to use extract, quadratic sort, insert when sorting the triangles. I'm pretty sure it would vastly outpace the 'basic sort' code, though it would still lose out to the O(NlogN) quick sort code as the arrays got bigger. The copying time becomes negligible compared to the sorting time.
Using qsort() etc
/* SO 4829-1562 */
#include "time.sort2d-31.h"
#include "emalloc.h"
/*
** + Enter a square matrix of dimensions n .
** + Elements below main diagonal sort in ascending order.
** + Elements above main diagonal sort in descending order.
** + Elements on main diagonal sort :
** - first even numbers in ascending order.
** - then odd numbers in descending order.
*/
/* Variation 4: Use system qsort() and common code to coordinate sorting of triangles */
/* Avoids two matrices lt and ut, thereby reducing the extra data space needed. */
static inline int cmp_asc(int x, int y) { return (x > y) - (x < y); }
static inline int cmp_dsc(int x, int y) { return (x < y) - (x > y); }
static inline int cmp_eaod(int x, int y)
{
int px = x & 1;
int py = y & 1;
if (px != py)
return px - py;
if (px == 1)
return cmp_dsc(x, y);
return cmp_asc(x, y);
}
static int qs_cmp_int_asc(const void *v1, const void *v2)
{
int i1 = *(const int *)v1;
int i2 = *(const int *)v2;
return cmp_asc(i1, i2);
}
static int qs_cmp_int_dsc(const void *v1, const void *v2)
{
int i1 = *(const int *)v1;
int i2 = *(const int *)v2;
return cmp_dsc(i1, i2);
}
static int qs_cmp_int_eaod(const void *v1, const void *v2)
{
int i1 = *(const int *)v1;
int i2 = *(const int *)v2;
return cmp_eaod(i1, i2);
}
static void sort_diagonal(size_t n, int matrix[n][n])
{
int data[n];
for (size_t i = 0; i < n; i++)
data[i] = matrix[i][i];
qsort(data, n, sizeof(data[0]), qs_cmp_int_eaod);
for (size_t i = 0; i < n; i++)
matrix[i][i] = data[i];
}
/*
** D0 U0 U1 U2 U3
** L0 D1 U4 U5 U6
** L1 L2 D3 U7 U8
** L3 L4 L5 D4 U9
** L6 L7 L8 L9 D5
**
** D0 = (0, 0); U0 = (0, 1); U1 = (0, 2); U2 = (0, 3); U3 = (0, 4);
** L0 = (1, 0); D1 = (1, 1); U4 = (1, 2); U5 = (1, 3); U6 = (1, 4);
** L1 = (2, 0); L2 = (2, 1); D2 = (2, 2); U7 = (2, 3); U8 = (2, 4);
** L3 = (3, 0); L4 = (3, 1); L5 = (3, 2); D3 = (3, 3); U9 = (3, 4);
** L6 = (4, 0); L7 = (4, 1); L8 = (4, 2); L9 = (4, 3); D4 = (4, 4);
*/
typedef void (*Copier)(int *val1, int *val2);
static void copy_a_to_b(int *val1, int *val2) { *val2 = *val1; }
static void copy_b_to_a(int *val1, int *val2) { *val1 = *val2; }
static void copy_lt_data(size_t n, int matrix[n][n], int vector[], Copier copy)
{
size_t m = (n * (n - 1)) / 2;
size_t r = 1;
size_t c = 0;
for (size_t i = 0; i < m; i++)
{
(*copy)(&matrix[r][c++], &vector[i]);
if (c == r)
{
r++;
c = 0;
}
}
}
static void copy_ut_data(size_t n, int matrix[n][n], int vector[], Copier copy)
{
size_t m = (n * (n - 1)) / 2;
size_t r = 0;
size_t c = 0;
for (size_t i = 0; i < m; i++)
{
(*copy)(&matrix[r][++c], &vector[i]);
if (c == n - 1)
{
r++;
c = r;
}
}
}
typedef void (*Mapper)(size_t n, int matrix[n][n], int vector[], Copier copy);
typedef int (*Comparator)(const void *v1, const void *v2);
static void sort_triangle(size_t n, int matrix[n][n], Mapper mapper, Comparator cmp)
{
size_t m = (n * (n - 1)) / 2;
int *data = MALLOC(m * sizeof(*data));
(*mapper)(n, matrix, data, copy_a_to_b);
qsort(data, m, sizeof(data[0]), cmp);
(*mapper)(n, matrix, data, copy_b_to_a);
FREE(data);
}
void quick_sort(size_t n, int matrix[n][n])
{
sort_diagonal(n, matrix);
sort_triangle(n, matrix, copy_lt_data, qs_cmp_int_asc);
sort_triangle(n, matrix, copy_ut_data, qs_cmp_int_dsc);
}
I also put a timing test together — see GitHub for the source code. The results were:
Basic sort (10x10) - elapsed: 0.000010
Clean sort (10x10) - elapsed: 0.000008
Quick sort (10x10) - elapsed: 0.000015
Basic sort (20x20) - elapsed: 0.000153
Clean sort (20x20) - elapsed: 0.000112
Quick sort (20x20) - elapsed: 0.000026
Basic sort (30x30) - elapsed: 0.000800
Clean sort (30x30) - elapsed: 0.000645
Quick sort (30x30) - elapsed: 0.000060
Basic sort (40x40) - elapsed: 0.002661
Clean sort (40x40) - elapsed: 0.002057
Quick sort (40x40) - elapsed: 0.000106
Basic sort (50x50) - elapsed: 0.006347
Clean sort (50x50) - elapsed: 0.005038
Quick sort (50x50) - elapsed: 0.000175
Basic sort (60x60) - elapsed: 0.014120
Clean sort (60x60) - elapsed: 0.009732
Quick sort (60x60) - elapsed: 0.000258
Basic sort (70x70) - elapsed: 0.023101
Clean sort (70x70) - elapsed: 0.016593
Quick sort (70x70) - elapsed: 0.000360
Basic sort (80x80) - elapsed: 0.035169
Clean sort (80x80) - elapsed: 0.027466
Quick sort (80x80) - elapsed: 0.000445
Basic sort (90x90) - elapsed: 0.053590
Clean sort (90x90) - elapsed: 0.039012
Quick sort (90x90) - elapsed: 0.000665
Basic sort (100x100) - elapsed: 0.074192
Clean sort (100x100) - elapsed: 0.053694
Quick sort (100x100) - elapsed: 0.000797
Basic sort (200x200) - elapsed: 0.656721
Clean sort (200x200) - elapsed: 0.478688
Quick sort (200x200) - elapsed: 0.002313
Basic sort (300x300) - elapsed: 2.826153
Clean sort (300x300) - elapsed: 2.126663
Quick sort (300x300) - elapsed: 0.004871
Basic sort (400x400) - elapsed: 8.384908
Clean sort (400x400) - elapsed: 6.374244
Quick sort (400x400) - elapsed: 0.008324
Basic sort (500x500) - elapsed: 22.083337
Clean sort (500x500) - elapsed: 16.124325
Quick sort (500x500) - elapsed: 0.014953
Basic sort (600x600) - elapsed: 43.233985
Clean sort (600x600) - elapsed: 31.362548
Quick sort (600x600) - elapsed: 0.019563
Basic sort (700x700) - elapsed: 85.463261
Clean sort (700x700) - elapsed: 60.488744
Quick sort (700x700) - elapsed: 0.027003
Basic sort (800x800) - elapsed: 148.358024
Clean sort (800x800) - elapsed: 102.991679
Quick sort (800x800) - elapsed: 0.038143
Basic sort (900x900) - elapsed: 253.434539
Clean sort (900x900) - elapsed: 150.658682
Quick sort (900x900) - elapsed: 0.045815
Quick sort (10x10) - elapsed: 0.000007
Quick sort (20x20) - elapsed: 0.000025
Quick sort (30x30) - elapsed: 0.000057
Quick sort (40x40) - elapsed: 0.000104
Quick sort (50x50) - elapsed: 0.000196
Quick sort (60x60) - elapsed: 0.000245
Quick sort (70x70) - elapsed: 0.000397
Quick sort (80x80) - elapsed: 0.000435
Quick sort (90x90) - elapsed: 0.000538
Quick sort (100x100) - elapsed: 0.000676
Quick sort (200x200) - elapsed: 0.002780
Quick sort (300x300) - elapsed: 0.005868
Quick sort (400x400) - elapsed: 0.009393
Quick sort (500x500) - elapsed: 0.016258
Quick sort (600x600) - elapsed: 0.024982
Quick sort (700x700) - elapsed: 0.031137
Quick sort (800x800) - elapsed: 0.042561
Quick sort (900x900) - elapsed: 0.052450
Quick sort (1000x1000) - elapsed: 0.061720
Quick sort (2000x2000) - elapsed: 0.229984
Quick sort (3000x3000) - elapsed: 0.480724
Quick sort (4000x4000) - elapsed: 0.826916
Quick sort (5000x5000) - elapsed: 1.308370
Quick sort (6000x6000) - elapsed: 1.890218
Quick sort (7000x7000) - elapsed: 2.559171
Quick sort (8000x8000) - elapsed: 3.346258
Quick sort (9000x9000) - elapsed: 4.359553
Quick sort (10000x10000) - elapsed: 5.345243
Quick sort (20000x20000) - elapsed: 22.189061
Quick sort (30000x30000) - elapsed: 51.385711
Quick sort (40000x40000) - elapsed: 97.543689
Quick sort (50000x50000) - elapsed: 177.373366
Quick sort (60000x60000) - elapsed: 315.083561
Quick sort (70000x70000) - elapsed: 476.135379
Quick sort (80000x80000) - elapsed: 756.888114
Quick sort (90000x90000) - elapsed: 1002.540185
At the very smallest sizes (10x10 or less), it is possible that the qsort() code is slower than the others — the difference is tiny (a few microseconds) but fairly consistent. By the time you've reached 20x20, the qsort() code is persistently faster, and the discrepancy grows. Note that the size, N, used for O(NlogN) or O(N2), corresponds to the square of the size of the matrix — so the amount of data to be sorted in a 20x20 matrix is four times the amount of data to be sorted in a 10x10 matrix. The performance of the basic sort or 'clean sort' is so bad that a 90k x 90k matrix doesn't bear thinking about, but the qsort() code sorts it in a time comparable to the time taken by the others to sort a 900 x 900 matrix (1/10,000th the size).
Fixing the code added 2018-02-02
The code added to the question on 2018-02-02 is a good attempt at solving the problem in a different way.
As noted by the OP, it sometimes fails to sort the data correctly.
The problem is that the code in the lower triangle
Here's the code fixed so it produces the correct output on the two sample matrices used previously.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
static int a[500][500];
int i, j, l, k, m, b, n, t, d, c;
printf("Unesite n kvadratne matrice:\n");
scanf("%d", &n);
printf("Matrica pre sortiranja\n\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &a[i][j]);
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
printf("%3d", a[i][j]);
printf("\n");
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i > j) // ispod dijagonale (LT)
{
int s = j + 1; // JL
for (l = i; l < n; l++)
{
//for (k = j; k < l; k++) // OP
for (k = s; k < l; k++) // JL
{
//printf("a[%d][%d] = %d <=> a[%d][%d] %d\n", // JL
// i, j, a[i][j], l, k, a[l][k]); // JL
//if (a[i][j] > a[l][k] && k < l) // OP
if (a[i][j] > a[l][k]) // JL
{
t = a[i][j];
a[i][j] = a[l][k];
a[l][k] = t;
}
}
s = 0; // JL
}
}
if (i < j) // iznad dijagonale (UT)
{
int s = j + 1; // JL
for (m = i; m < n; m++)
{
//for (b = j; b < n; b++) // OP
for (b = s; b < n; b++) // JL
{
//printf("a[%d][%d] = %d <=> a[%d][%d] %d\n", // JL
// i, j, a[i][j], m, b, a[m][b]); // JL
//if (a[i][j] < a[m][b] && m < b) // OP
if (a[i][j] < a[m][b]) // JL
{
t = a[i][j];
a[i][j] = a[m][b];
a[m][b] = t;
}
}
s = m + 2; // JL
}
}
if (i == j) // dijagonala
{
for (d = i; d < n; d++)
{
for (c = d + 1; c < n; c++)
{
if (a[d][d] % 2 != 0 && a[c][c] % 2 == 0)
{
t = a[d][d];
a[d][d] = a[c][c];
a[c][c] = t;
}
}
}
for (d = i; d < n; d++)
{
for (c = d + 1; c < n; c++)
{
if (a[d][d] % 2 == 0 && a[c][c] % 2 == 0
&& a[d][d] > a[c][c])
{
t = a[d][d];
a[d][d] = a[c][c];
a[c][c] = t;
}
else if (a[d][d] % 2 != 0 && a[c][c] % 2
!= 0 && a[d][d] < a[c][c])
{
t = a[d][d];
a[d][d] = a[c][c];
a[c][c] = t;
}
}
}
}
}
}
printf("Posle sortiranja:\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
printf("%3d", a[i][j]);
printf("\n");
}
return 0;
}
The commented out printing operations were crucial to seeing what the trouble was.
Sample output
This program was sort2d-mk2-73.
$ sort2d-mk2-73 < example-2.in
Unesite n kvadratne matrice:
Matrica pre sortiranja
87 32 98 58 60 71 46 81 70 14
22 92 15 98 51 26 94 67 46 56
71 89 86 16 20 89 97 89 45 92
63 13 76 19 75 19 66 89 58 41
82 68 75 26 58 20 89 87 65 66
74 83 68 92 10 98 90 21 39 63
24 65 23 68 62 44 48 22 27 59
26 27 71 71 51 31 43 69 92 10
54 19 41 50 10 89 42 52 94 54
42 50 79 48 77 18 29 40 61 63
Posle sortiranja:
48 98 98 97 94 92 92 90 89 89
10 58 89 89 87 81 75 71 70 67
10 13 86 66 66 65 63 60 59 58
18 19 22 92 58 56 54 51 46 46
23 24 26 26 94 45 41 39 32 27
27 29 31 40 41 98 26 22 21 20
42 42 43 44 48 50 87 20 19 16
50 51 52 54 61 62 63 69 15 14
65 68 68 68 71 71 71 74 63 10
75 76 77 79 82 83 89 89 92 19
$ sort2d-mk2-73 < example-1.in
Unesite n kvadratne matrice:
Matrica pre sortiranja
1 5 4 7 2
4 8 5 9 0
2 7 6 5 3
3 1 7 4 9
2 5 1 7 3
Posle sortiranja:
4 9 9 7 5
1 6 5 5 4
1 2 8 3 2
2 3 4 3 0
5 7 7 7 1
$
For comparison, the code posted in the question (sort2d-mk2-67) generated:
$ sort2d-mk2-67 < example-2.in
Unesite n kvadratne matrice :
Matrica pre sortiranja
Posle sortiranja :
48 98 98 97 94 92 92 90 89 66
10 58 89 89 89 87 81 75 70 63
10 13 86 71 67 66 65 60 59 56
18 19 22 92 58 58 54 51 46 46
23 24 26 29 94 45 41 39 32 27
26 27 31 40 41 98 26 22 21 20
42 42 43 44 48 50 87 20 19 16
50 51 52 54 61 62 63 69 15 14
65 68 68 68 71 71 71 76 63 10
74 75 77 79 82 83 89 89 92 19
$ sort2d-mk2-67 < example-1.in
Unesite n kvadratne matrice :
Matrica pre sortiranja
Posle sortiranja :
4 9 9 7 5
1 6 5 5 3
1 2 8 4 2
2 3 5 3 0
4 7 7 7 1
$
One of the changes between sort2d-mk2-67.c and sort2d-mk2-73.c was compressing the printing; another change was to print the matrix before and after the sorting operation.
In the smaller matrix, you can see that the 3 in row 1 column 4 (counting from 0) should be the 4 in row 2 column 3.
Similarly, the 5 in row 3 column 2 should be the 4 in row 4 column 1.
The fixed code is OK.
I've not benchmarked this code (yet).

Strange output formed by testing a combinations of sums or products in c

I have a problem with a simple code. i want to have all products and sums of a specific number for EX 4 -> 0+4 1+3 2+2 3+1 4+0. for the sum so I made this code to do it:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
unsigned int x;
unsigned int y;
}str;
const int MAX = 200000;
int main(int argc,char *argv[]){
int s=atoi(argv[1]);
if(s<0 || s>MAX){
printf("errore nummero incompatibile!\n");
exit(-1);
}
str sum;
int n=MAX;
for (sum.x=0;sum.x<n;sum.x++){
for (sum.y=0;sum.y<n;sum.y++){
if(strcmp(argv[2],"+")==0){
if(sum.x+sum.y==s){
printf("%d + %d = %d\n",sum.x,sum.y,s);
}
}else{
if(sum.x*sum.y==s){
printf("%d * %d = %d\n",sum.x,sum.y,s);
}
}
}
}
exit(-1);
}
the argv[1] is the number to testand the argv[2] is the mode (Sum or product)
here is the product output of 44 *:
1 * 44 = 44
2 * 22 = 44
4 * 11 = 44
11 * 4 = 44
22 * 2 = 44
44 * 1 = 44
25266 * 169990 = 44
33998 * 126330 = 44
42110 * 101994 = 44
50532 * 84995 = 44
50997 * 84220 = 44
63165 * 67996 = 44
67996 * 63165 = 44
84220 * 50997 = 44
84995 * 50532 = 44
101994 * 42110 = 44
126330 * 33998 = 44
167378 * 179622 = 44
169990 * 25266 = 44
179622 * 167378 = 44`
it gives the correct output but then it starts giving more numbers. these are the same each time i run it. what is this and how can i stop this?
You're iterating through every number until MAX, causing you overflows along the way (See vitaut's answer for the explaination of your issue and how to prevent overflow in your case, he explained that very well.). That's not necessary. When you try to find each combinaisons of multiplication of 2 integer, you just have to iterate until said number, or MAX if the number is too large.
Try to change
int n=MAX;
by :
int n = s;
if (s > MAX)
int n=MAX;
This is caused by integer overflow:
25266 * 169990 == 4294967340
4294967340 is too large to be represented as unsigned int which is 32-bit on your platform. So the most significant bits that don't fit get discarded, effectively giving you the result modulo 2 to the power of 32:
4294967340 mod 2**32 == 44
You can detect overflow in sum.x + sum.y by checking if sum.x > UINT_MAX - sum.y and either leave the inner loop or do something else. Similar check can be done for multiplication.

Resources