Transposition of Columns into a Matrix in c ++

1

Hello, I have a char array initialized as follows:

#include <iostream>  

using namespace std;  

main(){

char matriz[6][5]={
{'F','H','V','D','U'},
{'E','L','Q','U','E'},
{'P','E','R','S','E'},
{'V','E','R','A','A'},
{'L','C','A','N','Z'},
{'A','Z','Z','Z','Z'}};

}

And I need to transpose the columns, alphabetically ordering the first row, that is, the row that contains {'F', 'H', 'V', 'D', 'U'}.

The matrix that I need to obtain is the following:

char matriz[6][5]={
{'D','F','H','U','V'},
{'U','E','L','E','Q'},
{'S','P','E','E','R'},
{'A','V','E','A','R'},
{'N','L','C','Z','A'},
{'Z','A','Z','Z','Z'}};

I have managed to alphabetize the first row only, but I can not manage to move the rest of the column to perform the ordering as a single block.

Update:

Ok I finally manage to transpose it but now at least if the first row of the matrix has the same letters, they are sorted alphabetically but the values of only one of the two columns are transposed. Here is the code I have to transpose them.

    for(int j=0;j<largo;j++){
        for(int i=0;i<largo;i++){
            if(textoB[0][j]==texto[0][i]&&textoB[0][j+1]==texto[0][i]){
                texto[0][i]='*';
                for(int k=1;k<fila;k++){
                    textoB[k][j]=texto[k][i];
                }
            }


            else if(textoB[0][j]==texto[0][i])
                for(int k=1;k<fila;k++){
                    textoB[k][j]=texto[k][i];
                }
        }
    }

Text being the original unordered matrix and textB the original matrix with first row alphabetically arranged (unordered in the other spaces).

    
asked by Pipster 28.03.2016 в 21:24
source

2 answers

1

You have not published your code so we can not know what you're wrong about, it could even be a case of What have you tried? .

  

I do not succeed in being able to move the rest of the column to perform the ordering as a single block

The problem is that you are working with a two-dimensional matrix, which makes it a little more uncomfortable to exchange the information in the columns, you can not treat them as "a single block" because they belong to blocks different In memory it should look similar to ...

fila       |    0    |    1    |    2    |    3    |    4    |    5    |
columna    |0|1|2|3|4|0|1|2|3|4|0|1|2|3|4|0|1|2|3|4|0|1|2|3|4|0|1|2|3|4|
memoria    |F|H|V|D|U|E|L|Q|U|E|P|E|R|S|E|V|E|R|A|A|L|C|A|N|Z|A|Z|Z|Z|Z|

So you must go through the rows one by one and exchange the values of the columns that interest you. The approach I suggest is the following:

for (std::size_t fila = 0u; fila != FILAS; ++fila)
{
    // 'izquierda' y 'derecha' son las columnas que se quieren intercambiar
    std::swap(matriz[fila][izquierda], matriz[fila][derecha]);
}

I have used a template-based solution that allows arrays of two dimensions of arbitrary types and sizes (as long as the type provided has operator < ):

template <typename TIPO, std::size_t FILAS, std::size_t COLUMNAS>
void intercambia_columnas(TIPO (&matriz)[FILAS][COLUMNAS], std::size_t izquierda, std::size_t derecha)
{
    for (std::size_t fila = 0u; fila != FILAS; ++fila)
    {
        std::swap(matriz[fila][izquierda], matriz[fila][derecha]);
    }
}
template <typename TIPO, std::size_t FILAS, std::size_t COLUMNAS>
int compara_columnas(const TIPO (&matriz)[FILAS][COLUMNAS], std::size_t izquierda, std::size_t derecha)
{
    for (std::size_t fila = 0u; fila != FILAS; ++fila)
    {
        const auto i = matriz[fila][izquierda], d = matriz[fila][derecha];

        if (i != d)
        {
            return i < d ? -1 : 1;
        }
    }

    return 0;
}

template <typename TIPO, std::size_t FILAS, std::size_t COLUMNAS>
void ordena_matriz(TIPO (&matriz)[FILAS][COLUMNAS])
{
    for (std::size_t a = 0u; a != COLUMNAS - 1u; ++a)
    {
        for (std::size_t b = a + 1u; b != COLUMNAS; ++b)
        {
            if (compara_columnas(matriz, a, b) > 0)
            {
                intercambia_columnas(matriz, a, b);
            }
        }
    }
}

You can see the code working in Wandbox .

Edited

You still do not publish your complete code; your transposition code lacks context therefore it is difficult to know what it fails.

The code you use to transpose only compares the first row ( texto[0] ) but if you want to sort about columns you must take into account all the rows that make up the column, not just the first one.

On the other hand, it depends on the value of largo , you may be reading out of the matrix in operation textoB[0][j+1] (since the limit of j is largo ); this comparison is also incorrect as you will not always need to compare the column after the column j .

    
answered by 31.03.2016 в 09:20
0

I put below a solution that I explain in the same code. And I can not stop commenting that in C ++ arrays and pointers are the last resort, never the first. Well, anyway, here goes ...

#include <iostream>  
#include <map>

const int f = 6;
const int c = 5;

void obtener_orden(const char* m, int* n)
{
    // en los c caracteres de m está la primera fila
    // F, H, V, D, U
    // la idea es que si su orden actual es
    // 0, 1, 2, 3, 4
    // pase a ser 
    // 3, 0, 1, 4, 2 
    // o sea: 
    // D, F, H, U, V
    // y guardarse ese nuevo orden en n:

    // como soy muy vago, me voy a ayudar con un std::multimap 
    // http://es.cppreference.com/w/cpp/container/multimap
    std::multimap<char, int> posiciones;
    for (int i = 0; i < c; ++i) {
        posiciones.insert(std::make_pair(m[i], i));
    }

    // lleno el array n con el nuevo orden:
    int i = 0;
    std::cout << "nuevo orden = ";
    for (std::multimap<char, int>::iterator it = posiciones.begin(); it != posiciones.end(); ++it) {
        std::cout << (*it).first << " => " << (*it).second << "; ";
        n[i++] = (*it).second;
    }
    std::cout << '\n';
}

void ordenar_matriz(char* m, int* orden)
{
    // acá la idea es aplicar el nuevo orden que figura en el array orden
    // a la matriz nueva, que también va a tener f filas de c columnas,

    char nueva[f][c];

    for (int i = 0; i < f; ++i) {      
        for (int j = 0; j < c; ++j) {  
            nueva[i][j] = m[i*c + orden[j]];
        }
    }

    // y mostramos la nueva matriz con el nuevo orden:
    for (int i = 0; i < f; ++i) {      // recorre cada fila
        for (int j = 0; j < c; ++j) {  // y recorre cada columna
            std::cout << nueva[i][j] << ' ';
        }
        std::cout << '\n';
    }
    std::cout << '\n';
}

int main() {  // main() devuelve int

    char matriz[f][c] = {
        { 'F','H','V','D','U' },
        { 'E','L','Q','U','E' },
        { 'P','E','R','S','E' },
        { 'V','E','R','A','A' },
        { 'L','C','A','N','Z' },
        { 'A','Z','Z','Z','Z' } };

    int orden[c] = {0};

    obtener_orden(&matriz[0][0], orden);

    ordenar_matriz(&matriz[0][0], orden);

}
    
answered by 31.03.2016 в 19:57