Hitung karakter berbeda dalam sebuah string di Object pascal

Sep 11 2020

Selamat siang, saya telah membuat kode ini yang seharusnya menghitung karakter berbeda dalam sebuah string, kode saya diuji oleh beberapa input tetapi gagal menghitung karakter dalam input ini:

zcinitufxoldnokacdvtmdohsfdjepyfioyvclhmujiqwvmudbfjzxjfqqxjmoiyxrfsbvseawwoyynn 

ini memiliki hampir 80 karakter dan string maksimum yang dapat dibaca Pascal memiliki panjang 256 karakter. Saya tidak dapat menemukan algoritme yang lebih baik untuk menyelesaikan ini, jadi saya mencari bantuan dari para ahli di bidang ini, atau siapa pun yang terbuka untuk berbagi pengetahuan.

Saya rasa kode saya melompati karakter di setiap loop.

Ini kode saya:

function freq(char: char; username : String): Integer;
var 
   i, auxfreq: Integer;
begin
    auxfreq:= 0;
    for i:= 1 to length(username) do
        if char = username[i] then
            auxfreq:= auxfreq + 1;
            //writeln(freq);    
    freq:= auxfreq;         
end; 

function OddUserName(username : String): Boolean;
var
    usernameaux : String;
    length_usernameaux, i : Integer;
    Result : Boolean;

begin
    Result:= false;
    usernameaux:= username;
    i:= 0;
    repeat
        i +=1; 
        length_usernameaux:= length(usernameaux);
        if freq(usernameaux[i], usernameaux) <> 1 then 
            delete(usernameaux, i, 1);
    until i = length_usernameaux;
    // length(usernameaux) is supposed to be the number of the distinct characters.
    
    {if length(usernameaux) mod 2 <> 0 then // you will have to ignore this.
        Result:= true; // odd}

    //writeln(usernameaux); 
    //writeln(length(usernameaux));
    OddUserName:= Result; // ignore this too    
end; 

Saya sangat menghargai bantuan Anda.

Jawaban

1 RemyLebeau Sep 11 2020 at 02:56

Anda tidak memperhitungkan dengan benar panjang string yang berubah saat Anda delete()memasukkan karakter darinya.

Jika usernamekosong, Anda akhirnya mengakses karakter yang tidak valid karena repeatloop Anda mencoba mengakses karakter di indeks 1, yang tidak ada. Sebenarnya, Anda berakhir di loop tanpa akhir karena i = length_usernameauxakan selalu False karena idimulai pada 1 dan naik ke atas tetapi length_usernameauxselalu 0 (yah, setidaknya, loop berjalan hingga imeluap ke nilai negatif dan akhirnya naik kembali ke 0, tetapi dengan waktu itu Anda mungkin telah merusak kode Anda sebelum itu terjadi).

Jika usernametidak kosong, Anda kenaikan ipada setiap iterasi loop, yang akan melewatkan berikutnya karakter ketika delete()'ing karakter di i. iharus tetap berada di indeks yang sama setiap kali karakter adalah delete()'d, karena karakter berikutnya akan meluncur ke bawah untuk menempati indeks karakter yang baru saja delete' d '. Kenaikan ihanya jika BUKAN delete()karakter.

Coba ini sebagai gantinya:

function freq(charToFind: char; username : String): Integer;
var 
  i, auxfreq: Integer;
begin
  auxfreq := 0;
  for i := 1 to Length(username) do
  begin
    if charToFind = username[i] then
      auxfreq := auxfreq + 1;
  end;
  //writeln(freq);    
  freq := auxfreq;         
end; 

function OddUserName(username : String): Boolean;
var
  usernameaux : String;
  length_usernameaux, i : Integer;
  Result : Boolean;
begin
  Result := false;
  usernameaux := username;
  length_usernameaux := Length(usernameaux);
  i := 1;
  while i <= length_usernameaux do
  begin
    if freq(usernameaux[i], usernameaux) > 1 then
    begin
      Delete(usernameaux, i, 1);
      length_usernameaux := length_usernameaux - 1;
    end else
    begin
      i = i + 1;
    end;
  end;
  // length_usernameaux is supposed to be the number of the distinct characters.
    
  {if length_usernameaux mod 2 <> 0 then // you will have to ignore this.
    Result := true; // odd}

  //writeln(usernameaux); 
  //writeln(length_usernameaux);
  OddUserName := Result; // ignore this too    
end;
2 SilverWarior Sep 11 2020 at 04:03

Jika Anda hanya perlu mendapatkan jumlah karakter yang berbeda dalam beberapa string, Anda dapat menggunakan sesuatu yang sederhana seperti ini:

function CountDistinctCharacters(InputString: string): Integer;
var I: Integer;
    //String for storing all distinct characters
    DistinctChars: string;
begin
  //Loop trough every character in input string
  for I := 1 to Length(InputString) do
  begin
    //Use Pos function to find position of specific character in DistinctChars string
    //Function returns 0 if character is not found
    if Pos(InputString[I], DistinctChars) = 0 then
    begin
      //If character isn't found in DistinctChars string add it to it
      DistinctChars := DistinctChars+InputString[I];
    end;
  end;
  //Finaly check the lenght of DistinctChars string to get the number of distinct character
  //found and return it as function result
  Result := Length(DistinctChars);
end;

Jika Anda juga memerlukan informasi tentang karakter mana yang ada dalam string input Anda, alih-alih menggunakan DistinctCharsvariabel string lokal meneruskan string sebagai var pamaeter ke fungsi Anda seperti:

//Pass external string as var parameter to your function in order to allow function to
//fill it with all distinct characters
function CountDistinctCharacters(InputString: string; var DistinctChars: string): Integer;
var I: Integer;
begin
  //Loop trough every character in input string
  for I := 1 to Length(InputString) do
  begin
    //Use Pos function to find position of specific character in DistinctChars string
    //Function returns 0 if character is not found
    if Pos(InputString[I], DistinctChars) = 0 then
    begin
      //If character isn't found in DistinctChars string add it to it
      DistinctChars := DistinctChars+InputString[I];
    end;
  end;
  //Finaly check the lenght of DistinctChars string to get the number of distinct character
  //found and return it as function result
  Result := Length(DistinctChars);
end;

Tetapi jika Anda juga menginginkan informasi tentang berapa banyak dari setiap karakter yang ada dalam string input Anda, maka Anda harus menggunakan beberapa struktur data untuk hasil Anda yang memungkinkan penyimpanan pasangan data seperti TDictionary atau mungkin array record di mana setiap record menyimpan pasangan informasi (karakter dan jumlah kemunculan).

1 CouldnoTB-Zone Sep 11 2020 at 04:59

Saya telah berhasil memperbaikinya dengan cara saya, dengan cara ini yang berkat bantuan Anda. Yang saya lakukan adalah mengurangi indeks satu per satu setelah menghapus karakter yang digandakan. Seperti ini :

function OddUserName(username : String): Boolean;
var
    usernameaux : String;
    length_usernameaux, i : Integer;
    //Result : Boolean;

begin
    Result:= false;
    usernameaux:= username;
    i:= 0;
    repeat
        i +=1; 
        length_usernameaux:= length(usernameaux);
        if freq(usernameaux[i], usernameaux) <> 1 then 
        begin   
            delete(usernameaux, i, 1);
            i-=1; // <----- added 
        end;    
    until i = length_usernameaux;
    
    if length(usernameaux) mod 2 <> 0 then
        Result:= true; // odd

    //writeln(usernameaux); 
    //writeln(length(usernameaux));
    OddUserName:= Result;   
end;