Сколько разных букв в строке - PullRequest
8 голосов
/ 05 марта 2011

Мне нужно написать программу, которая подсчитывает, сколько разных букв в строке.Например, «abc» даст 3;и "abcabc" тоже даст 3, потому что есть только 3 разные буквы.

Мне нужно использовать паскаль, но если вы можете помочь с кодом на разных языках, это тоже будет очень хорошо.1004 * Вот мой код, который не работает:

var s:string;
    i,j,x,count:integer;
    c:char;
begin
  clrscr;

  Readln(s);
  c:=s[1];
  x:=1;

  Repeat
  For i:=1 to (length(s)) do
  begin
    If (c=s[i]) then
    begin
      delete(s,i,1);
      writeln(s);
    end;
  end;
  c:=s[1];
  x:=x+1;
  Until length(s)=1;

  Writeln(x);

x - счетчик другой буквы;Может, мой алгоритм очень плохой ... есть идеи?Спасибо.

Ответы [ 9 ]

11 голосов
/ 06 марта 2011

У вас есть ответы о том, как это сделать, вот почему ваш путь не работает.

Прежде всего, у вас была хорошая идея: начните с первого символа в строке, посчитайте его(вы забыли включить код счета), удалите все вхождения одного и того же символа в строке.Идея неэффективна, но она будет работать.У вас возникли проблемы с этим битом кода:

For i:=1 to (length(s)) do
begin
  If (c=s[i]) then
  begin
    delete(s,i,1);
  end;
end;

Проблема в том, что Паскаль примет значение Length(s) при настройке цикла, но ваш код изменяет длину строки, удаляя символы(используя delete(s,i,1)).Вы в конечном итоге посмотрите на плохую память.Вторичная проблема заключается в том, что i будет продвигаться вперед, не имеет значения, соответствует ли он и удаляет ли символ или нет.Вот почему это плохо.

Index:  12345
String: aabbb

Вы собираетесь проверить i = 1,2,3,4,5, ища a.Когда i равно 1, вы найдете совпадение, удалите первый символ, и ваша строка будет выглядеть следующим образом:

Index:  1234
String: abbb

Вы сейчас тестируете с i = 2, и это несовпадение, потому что s [2] = b.Вы только что пропустили один a, и данный a собирается остаться в массиве в другом раунде и заставить ваш алгоритм считать его дважды.«Фиксированный» алгоритм будет выглядеть следующим образом:

i := 1;
while i <= Length(s) do
  if (c=s[i]) then
    Delete(s,i,1)
  else
    Inc(i);

Это отличается: в данном примере, если я нашел совпадение в 1, курсор не перемещается, поэтому он видит второеa.Кроме того, поскольку я использую цикл while, а не цикл for, я не могу столкнуться с возможными деталями реализации цикла for.

У вашего алгоритма есть другая проблема.После цикла, который удаляет все вхождения первого символа в строке, вы подготавливаете следующий цикл, используя этот код:

c: = s [1];

Проблема в том, что если выпередать этому алгоритму строку вида aa (длина = 2, два одинаковых символа), он собирается войти в цикл, удалить или вхождения a (те, которые превращают s в пустую строку), а затем попытаться прочитатьпервый символ ПУСТОЙ строки.

Последнее слово: ваш алгоритм должен обрабатывать пустую строку на входе, возвращая счет = 0.Вот фиксированный алгоритм:

var s:string;
    i,count:integer;
    c:char;
begin
  Readln(s);
  count:=0;

  while Length(s) > 0 do
  begin
    Inc(Count);
    c := s[1];
    i := 1;
    while i <= Length(s) do
    begin
      If (c=s[i]) then
        delete(s,i,1)
      else
        Inc(i);
    end;
  end;

  Writeln(Count);

  Readln;
end.
4 голосов
/ 05 марта 2011

Вот моя версия.Я не говорю, что вы получите большую оценку в своем задании, если сдадите это.

function NumberOfUniqueChars(s: string): Integer;
var
  i, j: Integer;
  c: char;
begin
  for i := 1 to Length(s) do
    for j := i+1 to Length(s) do
      if s[i]<s[j] then
      begin
        c := s[i];
        s[i] := s[j];
        s[j] := c;
      end;
  Result := 0;
  for i := 1 to Length(s) do begin
    if (i=1) or (s[i]<>c) then
      inc(Result);
    c := s[i];
  end;
end;
4 голосов
/ 05 марта 2011

Я эксперт по Delphi, поэтому я не совсем понимаю, насколько ограничен простой Паскаль.Тем не менее, это Delphi:

// Returns the number of *distinct* "ANSI" characters in Str
function NumChrs(const Str: AnsiString): integer;
var
  counts: array[0..255] of boolean;
  i: Integer;
begin
  ZeroMemory(@counts[0], sizeof(boolean) * length(counts));
  for i := 1 to length(Str) do
    counts[ord(Str[i])] := true;
  result := 0;
  for i := 0 to high(counts) do
    if counts[i] then
      inc(result);
end;

Первая строка может быть написана

  for i := 0 to high(counts) do
    counts[i] := false;

, если вы не можете использовать Windows API (или функцию Delphi FillChar).

Если вы хотите иметь поддержку Unicode (как в Delphi 2009+), вы можете сделать

// Returns the number of *distinct* Unicode characters in Str
function NumChrs(const Str: string): integer;
const
  AllocBy = 1024;
var
  FoundCodepoints: array of integer;
  i: Integer;

  procedure Push(Codepoint: integer);
  var
    i: Integer;
  begin
    for i := 0 to result - 1 do
      if FoundCodepoints[i] = Codepoint then
        Exit;
    if length(FoundCodepoints) = result then
      SetLength(FoundCodepoints, length(FoundCodepoints) + AllocBy);
    FoundCodepoints[result] := Codepoint;
    inc(result);
  end;  

begin

  result := 0;
  for i := 1 to length(Str) do
    Push(ord(Str[i]));

end;
3 голосов
/ 06 марта 2011

И использование конструкции Delphi (неэффективно, но чисто)

function returncount(basestring: String): Integer;
var charstrings: TStringList;
    I:Integer;
begin
Result := 0;
charstrings := TStringlist.create;
try    
  charstrings.CaseSensitive := False;
  charstrings.Duplicates := DupIgnore;
  for I := 1 to length(basestring) do 
    charstrings.Add(basestring[i];
  Result := charstrings.Count;
finally
  charstrings.free;
end;
end;
2 голосов
/ 06 марта 2011

Просто бросаем в set -альтернативу ...

program CountUniqueChars;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  InputStr: String;
  CountedChr: Set of Char;
  TotalCount: Integer;
  I: Integer;
begin
  Write('Text: ');
  ReadLn(InputStr);

  CountedChr := [];
  TotalCount := 0;

  for I := 1 to Length(InputStr) do
  begin
    Write('Checking: ' + InputStr[i]);
    if (InputStr[i] in CountedChr)
    then WriteLn('  --')
    else begin
      Include(CountedChr, InputStr[i]);
      Inc(TotalCount);
      WriteLn('  +1')
    end;
  end;


  WriteLn('Unique chars: ' + IntToStr(TotalCount));
  ReadLn;
end.
2 голосов
/ 06 марта 2011

версия Delphi. Та же идея, что и в версии "The Communist Duck Python".

function GetNumChars(Str: string): Integer;
var
    s: string;
    c: Char;
begin
    s := '';
    for c in Str do
    begin
        if Pos(c, s) = 0 then
        begin
            s := s + c;
        end;
    end;
    Result := Length(s);
end;
2 голосов
/ 05 марта 2011

Разные языки в порядке?

RUBY:

s = "abcabc"
 => "abcabc"
m = s.split(//)
 => ["a", "b", "c", "a", "b", "c"]
p = m & m
 => ["a", "b", "c"]
p.count
 => 3
1 голос
/ 05 марта 2011

В Python, с объяснением, если вы хотите его для любого другого языка: (Так как вы хотели разные языки)

s = 'aahdhdfrhr' #s is the string
l = [] #l is an empty list of some kind.
for i in s: #Iterate through the string
    if i not in l: #If the list does not contain the character
        l.append(i) #Add the character to the list
print len(l) #Print the number of characters in the list
0 голосов
/ 06 марта 2011
function CountChars(const S:AnsiString):Integer;
var C:AnsiChar; CS:Set of AnsiChar;
begin
  Result := 0;
  CS := [];
  for C in S do
    if not (C in CS) then
    begin
      CS :=  CS + [C];
      Inc(Result);
    end;
end;
...