2

Para un ejercicio de programación competitiva debo ordenar ciertos datos, y cuando estos son iguales debo ordenarlos alfabéticamente. El problema es que si los nombres son "iguales" deberían imprimirse de la misma forma en la que fueron impresos. Este es mi código:

#include <bits/stdc++.h>
using namespace std;
bool condicion(pair<string,vector<int>> &x, pair<string,vector<int>> &y ){
    x.second[4]=x.second[0]+x.second[1];
    y.second[4]=y.second[0]+y.second[1];
    if(x.second[0]>y.second[0])return true;
    if(x.second[0]==y.second[0] and x.second[1]>y.second[1])return true;
    string a= x.first, b = y.first;
        for (int j = 0; j <a.size(); j++) a[j]=tolower(a[j]);
        for (int j = 0; j < b.size(); j++)b[j]=tolower(b[j]);
    if(a<b)return true;
    return false;
}


int main(){
    int neq, npar; //numero de equipos y partidas
    while(cin>>neq and neq!=0){
        cin>>npar;
        map<string,vector<int>>mapa;
        for (int i = 0; i < neq; ++i){ //crea equipos
            string equipos;
            vector<int>puntos;
            for (int j = 0; j < 5; ++j)puntos.push_back(0);
            cin>>equipos;
            mapa[equipos]=puntos;
        }
        for (int i = 0; i < npar; ++i){ //analiza las partidas formato equipo1 0 - 0 equipo2
            int puntos1[10]={0},puntos2[10];
            int gol1,gol2;
            string equipo1,equipo2;
            cin>>equipo1>>gol1;
            getchar();
            getchar();
            getchar();
            cin>>gol2>>equipo2;
            if(gol1>gol2)mapa[equipo1][0]+=3;
            else if(gol2>gol1)mapa[equipo2][0]+=3;
            else{mapa[equipo2][0]+=1; mapa[equipo2][0]+=1;}
            //goles dados
            mapa[equipo1][1]+=gol1;
            mapa[equipo2][1]+=gol2;
            //goles recibidos
            mapa[equipo1][2]+=gol2;
            mapa[equipo2][2]+=gol1;
            //partidas
            mapa[equipo1][3]++;
            mapa[equipo2][3]++;
        }
        vector<pair<string,vector<int>>> orden;
        map<string,vector<int>>::iterator it;
        for (it=mapa.begin(); it!=mapa.end(); ++it)orden.push_back(make_pair(it->first,it->second));
        sort(orden.begin(),orden.end(),condicion);
        int pos =1;
        for (int i=0; i<orden.size(); ++i){
           if(i==0)cout<<pos<<".";
           else if(orden[i].second[4]==orden[i-1].second[4])cout<<"  ";
           else cout<<pos<<".";
           pos++;
           int aux = 15 - orden[i].first.size();
           for(int j = 0; j<aux;j++)cout<<" ";
           cout<<orden[i].first<<"  "<<orden[i].second[0]<<"  "<<orden[i].second[3]
                <<"  "<<orden[i].second[1]<<"  "<<orden[i].second[2]<<"  "<<orden[i].second[1]-orden[i].second[2];
            if(orden[i].second[3]==0)cout<<" N/A"<<endl;
            else printf("%6.2f\n", orden[i].second[0] * 100.0 / (3.0 * orden[i].second[3]));
        }
    }
    return 0;
}

El problema es que cuando hay una entrada del tipo

4 0
B
b
a
A

me imprime los datos tal que

1.              A  0  0  0  0  0 N/A
                a  0  0  0  0  0 N/A
                B  0  0  0  0  0 N/A
                b  0  0  0  0  0 N/A

En vez de

1.              a  0  0  0  0  0 N/A
                A  0  0  0  0  0 N/A
                b  0  0  0  0  0 N/A
                B  0  0  0  0  0 N/A

Que seria el orden correcto de la entrada.

Imagino que el problema recae en mi condición del sort:

bool condicion(pair<string,vector<int>> &x, pair<string,vector<int>> &y ){
    x.second[4]=x.second[0]+x.second[1];
    y.second[4]=y.second[0]+y.second[1];
    if(x.second[0]>y.second[0])return true;
    if(x.second[0]==y.second[0] and x.second[1]>y.second[1])return true;
    string a= x.first, b = y.first;
        for (int j = 0; j <a.size(); j++) a[j]=tolower(a[j]);
        for (int j = 0; j < b.size(); j++)b[j]=tolower(b[j]);
    if(a<b)return true;
    return false;
}

Pero genuinamente no logro hacer que funcione, es lo ultimo que me falta para resolver este problema(Y si, me di cuenta muy tarde que era mejor hacer una estructura en vez de usar vectores).

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
Oliver
  • 21
  • 1
  • De [`using namespace std`](https://es.stackoverflow.com/questions/460/por-qu%C3%A9-el-usar-using-namespace-std-se-considera-mala-pr%C3%A1ctica) – y peor, `bits/stdc++.h` es una cabecera exclusiva a GCC y no es intentado para ser usado directamente. Ademas el codigo no es portabil así. – Aconcagua May 16 '22 at 11:51
  • `if(condition) return true; /*else*/ return false;` es estilo malo. Prefiere `return condition;` en su lugar. – Aconcagua May 16 '22 at 11:53
  • *'condicion'* no es un nombre bueno para una función – el nombre debería exprimir su tarea, su intención – mejor son nombres como *'menor'/'menos'* (*'less'* en inglés – no sequro lo cual a preferir – germanohablante yo...). – Aconcagua May 16 '22 at 12:35

1 Answers1

0

Despues de hacer minúsculas de todas letras dos palabras aparecen igual a la mapa. Así solo depende del orden de insertar (y del algoritmo interno como elementos iguales son tratados) cual antecederá.

Para hacer palabras en minúsculas anteceder palabras en majuscules te propongo return a < b || (a == b && x.first > x.second);. Así dos palabras diferente solo en minusculas y majuscules seran ordenado por sus valores ASCII (UTF-8 será mas complicado) – y como A tiene valor menor de a tienes que comparar de mayor en lugar de menor.

Si quieres cumplir la comparación en una sola iteración:

auto ix = x.first.begin();
auto iy = y.first.begin();
auto ue = x.first.end();
for(; ix != x.end() && iy != y.end(); ++ix, ++iy)
{
    auto lx = tolower(*ix);
    auto ly = tolower(*iy);
    if(lx < ly)
        return true;
    if(lx > ly)
        return false;
    // only differing in case!
    // remember first position of pure inequality in case
    if(*ix != *iy && ue == x.end())
        ue = ix;
}

// if getting here:
// if at all up to common length only differing in case

// shorter one (if any) being sorted first

// one iterator *must* be at the end!
if(ix != x.end())
    return false;
if(iy != y.end())
    return true;

// both at the end:
if(ue != x.end())
{
    // differing in case at at least one position
    // compare the first of we remembered before
    iy = y.begin() + (ue - x.begin());
    return *ue > *iy; // small letters come AFTER capitals in ASCII!
}
// now totally equal
return false;
Aconcagua
  • 138
  • 5