Optymalizacja kodu

0

Na lekcję informatyki miałem napisać program, który nie wyświetla w polu memo liczby jeśli jest ona: podzielna przez 7, posiada 7 w swojej liczbie albo jeśli suma wszystkich cyfr liczby wynosi 7. Kod programu jest następujący:


var i,e,z,h:integer;
      podzielna,dostepna,qs:boolean;
begin
  for i:=1 to 999 do
     begin
        podzielna:=i mod 7=0;
        e:=i mod 10;
        z:=(i mod 100) div 10;
        h:=i mod 100;
        qs:=e+z+h=7;
        dostepna:=(e=7) or (z=7) or (h=7);
        if podzielna or dostepna or qs
            then memo1.Lines.add('x')
            else memo1.Lines.add(IntToStr(i));
     end;
end;

A pytanie jest takie... czy da się ten kod zoptymalizować, pisząc go krótszym...? Dać się da na pewno ale jak? Sam próbowałem coś wymyślić no ale jak na razie nic specjalnego. Jak na razie mam 2 tyg styczności z Delphi więc wszystkiego jeszcze nie łapie ;)

Pozdro

0

for s:=0 to 9 do for d:=0 to 9 do for j:=0 to 9 do... :-)

0

EEEEeeee o_O nie czaje... 3 pętle?

0

czy da się ten kod zoptymalizować, pisząc go krótszym...?

Usuń wszystkie entery. Skróć nazwy zmiennych. Tylko że to nie jet nazywane optymalizacją, tylko obfuskacją.

Jeżeli chodzi o optymalizację poprzez przyśpieszenie, to wywal debug, daj -O3 . Jak nie starczy, to wywal powtarzające się instrukcje, użyj dodatkowych zmiennych do przechowywania wyników pośrednich. Użyj opcji przechowywania zmiennych w rejestrach. Jak nie starczy to użyj assemblera... Jak nie starczy to zmodernizuj sprzęt.

0
-oho123 napisał(a):

Usuń wszystkie entery. Skróć nazwy zmiennych. Tylko że to nie jet nazywane optymalizacją, tylko obfuskacją.

No to niech będzie obfuskacją... dodam wyraz do swojego słowniczka ;)
Ehm zmienne to jedno ale tu raczej chodzi o cały kod od begin do end...

Czyli nie o usunięcie zbędnych rzeczy etc. tylko o skrócenie kodu, napisanie go w 2 czy 3 linijkach a nie tak długo jak ja.

0

Czyli nie o usunięcie zbędnych rzeczy etc. tylko o skrócenie kodu, napisanie go w 2 czy 3 linijkach a nie tak długo jak ja.

Jeżeli sądzisz że prędkość programu zależy od ilości linijek, to genialny jesteś.

Zobacz to i policz o ile szybsze jest.

var i,e,z,h:integer;podzielna,dostepna,qs:boolean;begin for i:=1 to 999 do begin podzielna:=i mod 7=0;e:=i mod 10;z:=(i mod 100) div 10;h:=i mod 100;qs:=e+z+h=7;dostepna:=(e=7) or (z=7) or (h=7);if podzielna or dostepna or qs then memo1.Lines.add('x') else memo1.Lines.add(IntToStr(i));end;end;

Jak chodzi o obfuskację, to poczytaj co to jest, bo to była ironia... Żebyś nie dopisał źle...

Jak chcesz żeby program działał szybciej, to zazwyczaj robi się to poprzez napisanie inaczej, nie krócej... I już ci opisałem co zrobić. A najlepiej to poszukaj w google, tam będziesz miał to opisane jak dla debili...

0

Jak kulą w płot...

Mówiłem, że nie chodzi tu o napisanie kodu tak jak ty to zrobiłeś ale o skrócenie goo. Wykorzystując do tego bo ja wiem "case of" czy jakieś Bóg wie inne "instrukcje".
Weźmy to do czego ja jak na razie doszedłem

 function qs(n: Integer): Integer;
begin
  if n = 0 then
    Result := 0
  else
    Result := (n mod 10) + qs(n div 10);
end;

Porównaj kod z tym na górze to może ci się światełko zapali ;]
Czyli zmiana kodu na krótszy a nie usuń to usuń tamto...

napisane w gogle jak dla debili

no to gratuluje wypowiedzi

Czyli reasumując "napisać inaczej, lepiej, krócej"...

0

Ja bym na początku przed próbą optymalizacji zrobił ten kod poprawny. Ogólnie to pojęcie optymalizacji można rozszerzyć nie tylko na szybkość działania, ale także np. na czytelność kodu, łatwości utrzymania, czy możliwość jego ponownego użycia (w przypadku tak prostych funkcji to akurat nie ma znaczenia). Ogólnie to bym zrobił funkcję przyjmującą listę (tablicę) cyfr w kolejności jak występują w liczbie, która by zwracała prawdę, jak dana liczba spełnia warunki, a w głównej funkcji bym po kolei generował cyfry i jeżeli warunek dla danych cyfr jest spełniony, to konstruuje z nich stringa. Uniknie się tutaj w ten sposób np. błędów w wyłuskiwaniu kolejnych cyfr (np. użycie mod zamiast div), w przypadku liczb od 1 do 999 nie ma co mówić o wydajności. Taki sposób da się też łatwo dostosować do innych warunków lub większego zakresu liczb.

Edit: samo w sobie skrócenie kodu może być dobrą rzeczą, ale tylko jak zwiększa to czytelność.

0

Mówiłem, że nie chodzi tu o napisanie kodu tak jak ty to zrobiłeś ale o skrócenie goo.

Tłum: Nie chodzi o skrócenie kodu ale o skrócenie go(o?).

Czyli zmiana kodu na krótszy a nie usuń to usuń tamto...

A jak coś usunę to kod się nie zmieni na krótszy?

no to gratuluje wypowiedzi

No ja tobie gratuluję wypowiedzi bo skoro mam problem żeby ciebie zrozumieć to nieźle namieszałeś.

Nie chodzi tobie o skrócenie kodu, tylko o inny algorytm, tylko nie wiem czy szybszy czy krótszy w implementacji.

Weźmy to do czego ja jak na razie doszedłem

Doszedłeś do obfuskacji kodu bo normalny człowiek zastosowałby jakąś pętle. Poza tym to jest wolniejsze bo jeszcze ramkę zapisujesz etc etc

Masz niewydajny, śmieszny algorytm, który działa dla liczb max. 3 cyfrowych. Nie jest on jakiś strasznie zły. Nawet wydajność nie ma znaczenia, bo to tak małe liczby że nawet pentium III to szybko policzy. I nagle chcesz żebyśmy coś z nim zrobili, tylko nie mówisz co. pleciesz głupoty. Może wytłumacz co chcesz osiągnąć, to zrozumiemy jaki masz problem. Bo nie znasz pojęć i błądzisz z tekstami w stylu 'krótszy kod'... Zależy tobie na jego kompaktowości, szybkości, obsłudze większych liczb czy CZYM?!

0

tak jak napisał Xitami:

var i, j, k : integer;
begin
  for i := 0 to 9 do for j := 0 to 9 do for k := 0 to 9 do
    if ((i*100 + j*10 + k) mod 7 = 0) or (i = 7) or (j = 7) or (k = 7) or (i + j + k mod 7 = 0) then
      memo1.Lines.add(IntToStr(i) + IntToStr(j) + IntToStr(k));
end.

w takim algorytmie możliwe jest sprawdzenie podzielności przez 7 bez dzielenia (suma kolejnych cyfr w zapisie dziesiętnym pomnożona przez kolejne potęgi trójki musi być podzielna przez 7 - i tak rekurencyjnie aż do uzyskania 7 lub 0).

chcesz mieć większy zakres, to dodaj sobie kolejne zmienne oznaczające kolejne, większe miejsca dziesiętne.

0

<s>w zadaniu nie jest powiedziane, że liczby nie mogę się powtarzać, więc...

var
  i, j, k : integer;
begin
  i := 0;
  while (i < 999) do // podzielne przez 7
  begin
    writeln(i);
    i := i + 7;
  end;

  for i := 0 to 9 do
  for j := 0 to 9 do
  begin
    writeln(i, j, 7);
    writeln(i, 7, j);
    writeln(7, i, j);
  end;

  for i := 0 to 9 do
  for j := 0 to 9 do
  for k := 0 to 9 do
  if i + j + k = 7 then
    writeln(i, j, k);

end.

writeln trza zmienić na dopisywanie do jakiegoś bufora i na koniec wrzucenie zawartości bufora przed oczy użytkownikowi.</s>

0

ŁF, owszem twój pierwszy kod można poprawić z wyświetlać na NIE wyświetlać oraz można nieco przyspieszyć przenosząc parę warunków nieco wyżej, oraz przenosząc jedno obliczenie wyżej poprawiając wyświetlenie liczby np 001 na 1, ale znacznie to nie poprawi sytuacji:

var i, j, k, n : integer;
begin
  for i := 0 to 9 do
  begin
    if i=7 then continue;
    for j := 0 to 9 do
    begin
      if j=7 then continue;
      for k := 0 to 9 do
      begin
        if (k <> 7) and (i + j + k <> 7) then
        begin
           n:=i*100 + j*10 + k;
           if n mod 7 <> 0 then memo1.Lines.add(IntToStr(n));
        end;
     end;
  end;
end.

Przełomowego przyspieszenia tu chyba nie da się zrobić.

Właśnie wymyśliłem jak to zrobić bez dzielenia :D

var i,j,k,n,q:Integer;

  n:=0;
  q:=0;
  for i:=0 to 9 do
  begin
    for j:=0 to 9 do
    begin
      for k:=0 to 9 do
      begin
        if q<>0 then
        begin
          if (i<>7)and(j<>7)and(k<>7) then
          begin
            if i+j+k<>7 then
            begin
              WriteLn(n);
            end;
          end;
        end;
        Inc(n);
        Inc(q);
        if q>=7 then q:=0;
      end;
    end;
  end;

Na pomysł wpadłem dzięki komentarzowi od @Zjarek.

0

Dzięki za pomoc... czegoś nowego się nauczyłem dzięki wam :)
Przekształciłem ten kod od Dragona na to aby liczby, które odpowiadają dzieleniu czy sumie =7 były wyświetlane w "memo field" za pomocą wybranego znaku. Tylko jest jeden mały mankament to, że nie które liczby wcale się nie pojawiają. Typowo mamy 6 a następnie 8 brakuje liczby 7. Problem występował przed zmianą oraz występuje teraz.

Ps. Tam "begin" Ci się po drodze zapodziało ^^

0

var i,e,z,h:integer;
podzielna,dostepna,qs:boolean;
begin
for i:=1 to 999 do
begin
podzielna:=i mod 7=0;
qs:=e+z+h=7;
dostepna := Pos('7', IntToStr(i)) > 0
if podzielna or dostepna or qs
then memo1.Lines.add('x')
else memo1.Lines.add(IntToStr(i));
end;
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1