Find the letter that only repeats once in a string of characters and show its position?

0

The objective is to enter the number of characters that the chain will have, and find the letter that only repeats once acum_menor , then show its position. I did it by comparing the string with another one that contains the letters of the alphabet.

But at the moment of showing the position in which the letter that does not repeat is, I can not think of a way to do it, I have to capture the position of the letter whose repetition is less than 2 (I mean 1)

#include <iostream>
#include <string.h>

using namespace std;
int pos_letra= -1;
int main (){

  int lon;
cin>>lon;
 char* palabra = new char[lon];
cin>>palabra;

  int acum, acum_menor=2, i, menor, letra;

  char letras[] = "abcdefghijklmnopqrstuvwxyz";

  for( letra = 0 ; letras[letra] ; letra++){
    for( i = 0 , acum = 0 ; i < lon ; i++){
        if( palabra[i] == letras[letra] )
            acum++;
          if (acum==1 && pos_letra < 0)
            pos_letra=i;
    }
             if( acum != 0 ){
             cout << letras[letra] << " se repite " << acum << endl;
                if ( acum < acum_menor ){
                menor = letra;
                acum_menor = acum;
      }
    }
  }
  cout << endl<< letras[menor] << " es moss. se repite "  << acum_menor << " vez / en los " << lon << " participantes "<< endl;
  cout<<pos_letra<<" moss hallado";
  return 0;
}
  • Entry example: "xvxx" .
  • Example of output:
    • v se repite 1 .
    • x se repite 3 .
asked by Gabriel Balderrama 09.07.2018 в 14:51
source

2 answers

0

Your algorithm is quite inefficient, for each letter (exists or does not exist in the input string) you go through the input string; so you end up doing N × M operations. Operations can be reduced by simply traversing the input string.

Proposal.

I would start by creating an object to store the data we want to process:

struct FrecuenciaLetra
{
    char letra = 0;
    int frecuencia = 0;
    int posicion = std::numeric_limits<int>::max();
};

This object tells us, for each letter, how many times it appears in the text and the position in which it was found for the first time, the next thing would be to create a function that given a text, return a collection of FrecuenciaLetra for each letter different from the text:

std::vector<FrecuenciaLetra> reduce(const std::string &);

As you can see, I follow the advice of eferion in which std::string is used instead of a training 1 of characters. The algorithm to follow is simple:

FrecuenciaLetra items[std::numeric_limits<char>::max()]{};
int indice = 0;

for (int letra : palabra)
{
    auto &item = items[letra];
    item.letra = letra;
    ++item.frecuencia;
    item.posicion = std::min(item.posicion, indice);
    ++indice;
}

We create a FrecuenciaLetra formation that contains all possible characters and we will use the character index to access the corresponding%% instance of%. Once located the one that corresponds we increase its frequency and we are left with the smallest index.

As it is likely that in the training FrecuenciaLetra we find empty positions, we will filter the results before returning them:

std::vector<FrecuenciaLetra> resultado;
std::copy_if(std::begin(items), std::end(items), std::back_inserter(resultado),
    [](auto &i) { return i.letra != 0; });

With the suggested code, trying with the string items :

int main()
{
    std::string s;
    std::getline(std::cin, s);
    for (const auto &fl : reduce("patata"))
        std::cout << '\'' << fl.letra
                  << "' aparece por primera vez en " << fl.posicion
                  << " y aparece " << fl.frecuencia
                  << " veces en el texto.\n";
    return 0;
}

We get the following output:

'a' aparece por primera vez en 1 y aparece 3 veces en el texto.
'p' aparece por primera vez en 0 y aparece 1 veces en el texto.
't' aparece por primera vez en 2 y aparece 2 veces en el texto.

You can see the code working Here .

  • Also known as an array, or in English: array.
  • answered by 10.07.2018 / 13:11
    source
    1

    Your problem has a well-defined name: VLA or V ariable L ength A rray

    cin>>lon;
    char palabra[lon];
    

    palabra is a VLA since, even though it is an array of fixed size, the number of elements is determined at runtime. This feature is not supported by the C ++ standard ... so do not use it.

    Instead, choose to use dynamic memory:

    char* palabra = new char[lon];
    

    Or, better yet, use the std::string class that's what it is for:

    std::string palabra;
    std::cin >> palabra; // y esto funciona independientemente de la longitud de la cadena
    

    What makes your code not work correctly is here:

    int tam = sizeof palabra / sizeof palabra[0];
    

    And why is this a problem?

    Simply because sizeof is evaluated in compile time ... while the size of palabra , as we said before, will be determined in execution time strong> ... the compiler is not a fortune-teller so that's not going to work in life.

    On the other hand ... Why do you have tam if you have already requested the length in lon ? By all means, tam surplus and, additionally, if you use std::string there would also be over lon . For example, to iterate in the (0..longitud) range you could do the following:

    for( i = 0 , acum = 0 ; i < palabra.length(); i++){
    
        
    answered by 09.07.2018 в 15:40