Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 27.09.2012, 10:17
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию Непростая задачка с listbox

Доброго дня. Помогите реализовать алгоритм. Я не буду описывать всю программу, напишу чуть иначе. Есть алгоритм, как реализовать в коде - не хватает ума.
Итак. Имеется массив чисел. Числа положительные и отрицательные. Массив мы представим в виде listbox1 на форме.
Так же на форме будет listbox2 и listbox3 - для запихивания значений из массива. Итак поехали :
Массив представляет собой последовательность чисел в listbox1. В итоге массив должен начинаться с положительного числа, и заканчиваться отрицательным. Числа должны чередоваться, НЕчетные - положительны, четные элементы отрицательны. Это то что должно получиться в итоге. Сразу мы имеем массив чисел, которые идут по нарастающей :
+35
-42
+96
-112
+186
-740
Вот в этом примере массив шикарен и все правильно.
Но бывает такое :
1. Два числа подряд идут отрицательных
2. Два числа идут положительных
3. Массив начинается НЕ с положительного
4. Массив заканчивается НЕ отрицательным
- это вещи с которыми будем бороться
Пример :
-15
+35
-42
+78
-116
-182
+350
-360
+620
+630
-700
+730
В этом массиве имеется все 4 описанных косяка. Что программа должна с ними делать.
1. В первую очередь, обязательно проверить начинается ли и заканчивается ли массив сотв-но положительным и отрицательными. Если нет - в начало listbox сунуть положительное (0) в конец отрицательное (-800).
2. Далее если программа в списке находит два подряд идущих отрицательных (-116,-182) то :
2.1 Если ВТОРОЕ отрицательное отличается от первого отричательно меньше чем на 2 - удалить ил listbox первое отрицательное.
Если второе(otr2) отрицательное отличается от первого(otr1) БОЛЬШЕ чем на два - между этими числами нужно вставить положительное - которое будет равно отрицательному(переведенному в положительное) плюс 2. Получится -116, + 118, -182
3. Если в списке два плюса(+620,+630) - почти то же самое : Если второе положительное отличается от первого положительного менее чем на 2 - второе положительное нужно удалить.
Если второе положительное больше первого более чем на 2 - между ними нужно воткнуть отрицательное число, которое будет равно второму положительному минус два, перевернутое в отрицательное. т.е. мы получим 620,-628,630.
Итак в listbox1 был кривоватый массив который программа исправила.
Было бы идеально, если бы пары чиле которые НЕ исправлялись - ушли в listbox2 а те что исправлены - в listbox3. На нашем примеремы получим исправленный массив :
0
-15
+35
-42
+78
-116
+118
-182

+350
-360
+620
-628

+630
-700
+730
-800
т.е. все числа пойду в листбокс2, кроме : отмечных красным.
Если логика непонятна - поясню боллее развернуто.
Спасибо заранее))

Последний раз редактировалось alexusankov, 27.09.2012 в 10:19.
Ответить с цитированием
  #2  
Старый 27.09.2012, 10:45
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
Если логика непонятна - поясню боллее развернуто.
Логика понятна. Единственно непонятно что не получается?
Ответить с цитированием
  #3  
Старый 27.09.2012, 10:57
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию

Как это в коде реализовывается.
Как искать в массиве сочетания ++, или --.
Если я воткнуть изменения в массив, между ++ один - например.
Ответить с цитированием
  #4  
Старый 27.09.2012, 11:04
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
Как это в коде реализовывается.
Как искать в массиве сочетания ++, или --.
В цикле проверяешь знак текущего элемента со знаком следующего. Так как массив изменяется, то лучше использовать цикл while, а не for.
Цитата:
Сообщение от alexusankov
Если я воткнуть изменения в массив, между ++ один - например.
Так можно "воткнуть" в позицию 7 элемент "-":
Код:
  ListBox1.Items.Insert(7, '-');
Ответить с цитированием
  #5  
Старый 27.09.2012, 12:55
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию

Хоть убиться, не могу представить как это в коде реализовать
Ответить с цитированием
  #6  
Старый 27.09.2012, 12:59
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
Хоть убиться, не могу представить как это в коде реализовать
Тогда покажи ту часть кода которую смог представить и реализовать.
Ответить с цитированием
  #7  
Старый 27.09.2012, 13:08
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию

Да вообще принципиально всю.
Пока написано :
Код:
for x:=1 to (listbox1.Items.Count div 2) + (listbox1.Items.Count mod 2)  do begin
  i1:=strtoint(listbox1.Items[i]);  //  0 1 2 3 5 5
  i2:=strtoint(listbox1.items[i+1]);  // 1 2 3 4 5 7
  edit1.Text := inttostr((listbox1.Items.Count div 2) + (listbox1.Items.Count mod 2));
    if (i1 > 0) and (i2 < 0) then begin
      listbox2.Items.Add(inttostr(i1));
      listbox2.Items.add(inttostr(i2));
      i:=i+2;
    end;


end;
усе. код берет по 2 строки и проверяет что первая положительна, вторая нет.
Думаю..
з.ы. хрень какая то. чувствую не по 2 строки брать нужно....
****
Да, нужно брать по 1 переменной I:=i+1; иначе по 2 плюса или минуса не найти.
попробуем..

Последний раз редактировалось alexusankov, 27.09.2012 в 13:14.
Ответить с цитированием
  #8  
Старый 27.09.2012, 13:15
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
усе. код берет по 2 строки и проверяет что первая положительна, вторая нет.
Думаю..
з.ы. хрень какая то. чувствую не по 2 строки брать нужно....
А где та часть кода которая проверяет чтобы первый элемент был положительный, а последний отрицательный и если это не так то вставляет нужные числа? Вроде эта часть кода не должна представлять никаких сложностей...
Ответить с цитированием
  #9  
Старый 27.09.2012, 13:17
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию

Цитата:
Сообщение от poli-smen
А где та часть кода которая проверяет чтобы первый элемент был положительный, а последний отрицательный и если это не так то вставляет нужные числа? Вроде эта часть кода не должна представлять никаких сложностей...
не представляет. с ней нет проблем
Код:
if Copy(listbox1.Items[0],1,1) = '-' then listbox1.Items.Insert(0,'+1');
if Copy(listbox1.Items[listbox1.Items.count - 1],1,1) = '+' then listbox1.Items.Add('-1440');
что делать с остальным ума не приложу
З.ы. Кажись нужно сувать значение в переменную так, чтобы в а1 оказалось предыдущее значение а2. Мне кажется это правильный путь. И флаг добавить. Точно, буду думать.
Час.

Последний раз редактировалось alexusankov, 27.09.2012 в 13:26.
Ответить с цитированием
  #10  
Старый 27.09.2012, 13:59
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
не представляет. с ней нет проблем
Код:
if Copy(listbox1.Items[0],1,1) = '-' then listbox1.Items.Insert(0,'+1');
if Copy(listbox1.Items[listbox1.Items.count - 1],1,1) = '+' then listbox1.Items.Add('-1440');
Странно, а по условию нужно добавлять числа 0 и -800

Вот, проверяй, вроде работает:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  i, i1, i2: Integer;
begin
  ListBox1.Items.Text := '-15'#13'+35'#13'-42'#13'+78'#13'-116'#13'-182'#13'+350'#13'-360'#13'+620'#13'+630'#13'-700'#13'+730';

  if StrToInt(ListBox1.Items[0]) < 0 then ListBox1.Items.Insert(0, '0');
  if StrToInt(ListBox1.Items[ListBox1.Items.Count - 1]) >= 0 then ListBox1.Items.Add('-800');

  i := 0;
  while i < ListBox1.Items.Count - 1 do
  begin
    i1 := StrToInt(ListBox1.Items[i]);
    i2 := StrToInt(ListBox1.Items[i + 1]);

    if (i1 < 0) and (i2 < 0) then
    begin
      if Abs(i1 - i2) < 2 then
      begin
        ListBox1.Items.Delete(i);
      end else
      begin
        ListBox1.Items.Insert(i + 1, '+' + IntToStr(2 - i1));
        Inc(i);
      end;
    end else
    if (i1 >= 0) and (i2 >= 0) then
    begin
      if Abs(i1 - i2) < 2 then
      begin
        ListBox1.Items.Delete(i);
      end else
      begin
        ListBox1.Items.Insert(i + 1, IntToStr(2 - i2));
        Inc(i);
      end;
    end else
    begin
      Inc(i);
    end;
  end;
end;
Осталось только добавление в ListBox2 и ListBox3 сделать.
Цитата:
Сообщение от alexusankov
что делать с остальным ума не приложу
З.ы. Кажись нужно сувать значение в переменную так, чтобы в а1 оказалось предыдущее значение а2. Мне кажется это правильный путь. И флаг добавить. Точно, буду думать.
Час.
Ок. Потом сравним результаты
Ответить с цитированием
  #11  
Старый 27.09.2012, 16:16
Аватар для alexusankov
alexusankov alexusankov вне форума
Новичок
 
Регистрация: 27.08.2012
Сообщения: 78
Версия Delphi: C++/Delphi 2010
Репутация: 10
По умолчанию

Внезапно.....
Какой маленький кусок, а почти все делает. буду до вечера пытаться понять, почему у меня другой код, и почему этот работает.
А что значит if Abs и Inc(i); ?
Если в списке будет три минуса, в принципе, все пройдет гладко я так понимаю?
Я так понимаю, что я сам себе вынес мозг на столько, что голова не понимает. Завтра попытаюсь понять, зачем я все в своем коде так сложно навернул

Последний раз редактировалось alexusankov, 27.09.2012 в 16:21.
Ответить с цитированием
  #12  
Старый 27.09.2012, 16:32
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от alexusankov
Внезапно.....
Какой маленький кусок, а почти все делает. буду до вечера пытаться понять, почему у меня другой код, и почему этот работает.
А что значит if Abs и Inc(i); ?
Функция Abs делает числа положительными. Функция Inc(i) увеличивает значение переменной на единицу.
Цитата:
Сообщение от alexusankov
Если в списке будет три минуса, в принципе, все пройдет гладко я так понимаю?
Думаю будет работать
Ответить с цитированием
  #13  
Старый 27.09.2012, 21:13
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,090
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну, в принципе, можно и так изгаляться.
Но есть вариант попроще.
1. Создаем 2 служебных списка.
2. В один список кладем все положительные числа.
3. Во второй - все отрицательные.
4. Сортируем списки, если надо.
5. Делаем проверку, что нужную последовательность вообще можно составить (число элементов в обоих списках должно быть одинаковым)
6. Составляем новый список, поочередно беря элементы из служебных.
Код:
var
  I : Integer;
  P, N : Array Of Integer;
  D : Integer;
begin
  // Prepare
  SetLength(P,0);
  SetLength(N,0);

  // Split source list
  For I := 0 To ListBox1.Items.Count-1 Do
    Begin
      D := StrToInt(ListBox1.Items[i]);
      If D > 0 
        Then Begin SetLength(P,Length(P)+1); P[High(P)] := D; End
        Else Begin SetLength(N,Length(N)+1); N[High(N)] := D; End;
    End;

  // Check lengths
  If Length(P) <> Length(N) Then
    Raise Exception.Create('ERROR!!!');

  // Sort - if needed
  ...

  // Build new list
  ListBox1.Items.Clear;
  For I := Low(P) To High(P) Do
    Begin
      ListBox1.Items.Add(IntToStr(P[i]));
      ListBox1.Items.Add(IntToStr(N[i]));
    End;
end;
Ответить с цитированием
  #14  
Старый 28.09.2012, 00:23
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от lmikle
Ну, в принципе, можно и так изгаляться.
Но есть вариант попроще.
1. Создаем 2 служебных списка.
2. В один список кладем все положительные числа.
3. Во второй - все отрицательные.
4. Сортируем списки, если надо.
5. Делаем проверку, что нужную последовательность вообще можно составить (число элементов в обоих списках должно быть одинаковым)
6. Составляем новый список, поочередно беря элементы из служебных.
Такой вариант не сработает. Дело в том, что из условия задачи не следует, что в первоначальном списке количество отрицательных и положительных элементов непременно должно совпадать, даже более того, первоначальный список может состоять из одних только положительных, либо одних только отрицательных чисел, а смысл алгоритма состоит в том, чтобы привести этот список к "нормализованному" виду, в котором положительные и отрицательные числа чередуются.
Ответить с цитированием
  #15  
Старый 28.09.2012, 00:49
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,090
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну дык о том и речь. Если кол-во положительных и отрицательных чисел не равно, то требуемвй список построить нельзя. Да, напрямую это в задании не сказано. Но как ты построишь список, начинающийся с положительного числа, заканчивающийся отрицательным и в котором пол. и отр. числа чередуются, если у тебя 5 пол. и 3 отр. числа? Это просто невозможно.

ЗЫ. Может я не очень внимательно читал задание, но мне показалось что условие именно такого, как я описал.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 21:11.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025