Hitung karakter berbeda dalam sebuah string di Object pascal
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
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;
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).
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;