Wyszukiwanie duplikatów wtablicy 2D FPC

0

Witam, od jakiegoś czasu nie umiem sobie poradzic z problemem jakim jest wyszukiwanie duplikatów w tablicy 2D w FreePascalu tj. wyprowadzam na ekran tablice wypełniona liczbami losowymi z przedziału (-50,30) i chce wyszukac powtarzajace sie elementy i wyprowadzić je na ekran. Czy byłby ktoś w stanie podrzucić jakimś kodem bądz pomysłem? Z góry dzieki :)

0

najprościej można iść po kolei wierszami i przy każdym elemencie sprawdzasz, czy w reszcie tablicy nie ma duplikatu

0

wyprowadzam na ekran tablice wypełniona liczbami losowymi z przedziału (-50,30) i chce wyszukac powtarzajace sie elementy i wyprowadzić je na ekran.

Jeśli macierz ma rozmiar statyczny, to możesz pobawić się w przechodzenie po każdym elemencie tablicy w dwóch pętlach zagnieżdżonych; Jeśli to jest dla Ciebie zbyt trudne - możesz przekopiować zawartość macierzy dwuwymiarowej do tymczasowej tablicy jednowymiarowej za pomocą procedury CopyMemory i w niej szukać duplikatów za pomocą tylko jednej pętli dla każdej komórki macierzy; Przykład:

uses
  SysUtils;
type
  TNumber = ShortInt;
const
  SIZE_X = 3;
  SIZE_Y = 4;
  CELL_COUNT = SIZE_X * SIZE_Y;
type
  T2DArray = array [0 .. SIZE_X - 1, 0 .. SIZE_Y - 1] of TNumber;
  T1DArray = array [0 .. CELL_COUNT - 1] of TNumber;
const
  arr2D: T2DArray = ((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12));
var
  arr1D: T1DArray;
  I: Byte;
begin
  // Windows.ZeroMemory(@arr1D[0], CELL_COUNT * SizeOf(TNumber));
  FillChar(arr1D[0], CELL_COUNT * SizeOf(TNumber), 0);
  // Windows.CopyMemory(@arr1D[0], @arr2D[0, 0], CELL_COUNT * SizeOf(TNumber));
  Move(arr2D[0, 0], arr1D[0], CELL_COUNT * SizeOf(TNumber));

  for I := 0 to CELL_COUNT - 1 do
    WriteLn(Format('arr1D[%d]: %d', [I, arr1D[I]]));

  ReadLn;
end.

Program wyświetli w oknie konsoli poprawne wartości z tablicy arr1D:

arr1D[0]: 1
arr1D[1]: 2
arr1D[2]: 3
arr1D[3]: 4
arr1D[4]: 5
arr1D[5]: 6
arr1D[6]: 7
arr1D[7]: 8
arr1D[8]: 9
arr1D[9]: 10
arr1D[10]: 11
arr1D[11]: 12

Dzięki temu, że statyczna tablica dwuwymiarowa w pamięci jest jednym ciągiem bajtów (ciągiem kolejnych komórek tablicy) można łatwo ją skopiować; Wykorzystałem do przykładu typ ShortInt, ponieważ jest to najmniejszy typ mogący przyjąć wartości z zadanego przedziału (-50, 30) (nie licząc typu o własnym zakresie); Przeszukanie duplikatów zaimplementuj już sam;

Procedura FillChar (lub ZeroMemory) nie jest konieczna - wstawiona po to, by sprawdzić poprawność algorytmu.

0

za pomocą procedury CopyMemory

I widzę że to Delphi się wszystkim do głowy wbiło: Pascal ma move.

Procedura ZeroMemory

Pascal: FillChar

Ale lepiej tworzyć kod pod jedyny słuszny system, bo kogo to obchodzi że używasz WinApi skoro w RTL masz dokładnie to samo? I tak w Delphi moduł windows to wręcz wymóg bo jego programiści nie znają klasycznych funkcji Pascala...

0

Kod kompilowałem i testowałem pod Lazarusem (pod Delphi też);

Problem nie leży w tym. Problem leży w tym, że w Lazarusie mechanicznie dodajesz sobie moduł Windows bo bez niego i bez wrapperów CopyMemory nie działa jako że to WinApi. Natomiast w module system masz sobie takie coś jak move które robi dokładnie to samo, bez polegania na danym systemie operacyjnym i platformie, tak? Tak, tylko po co, skoro ty nie wiesz o istnieniu procedur Pascala, tylko WinApi ci w głowie... Niezłym mózgiem trzeba być żeby dla skopiowania pamięci przywiązywać program do danego systemu operacyjnego. Zapewne odruchy z Delphi, walcz z nimi, bo naprawdę, to jest nieźle rąbnięte gdy będziesz kompilować program pod Linuxa czy inny WTF i problemy będziesz mieć bo nie znasz w miarę podstawowych procedur Pascala.
Dokładnie to samo tyczy się ZeroMemory.

0

Tak, tylko po co, skoro ty nie wiesz o istnieniu procedur Pascala, tylko WinApi ci w głowie... Niezłym mózgiem trzeba być żeby dla skopiowania pamięci przywiązywać program do danego systemu operacyjnego. Zapewne odruchy z Delphi, walcz z nimi, bo naprawdę, to jest nieźle rąbnięte gdy będziesz kompilować program pod Linuxa czy inny WTF i problemy będziesz mieć bo nie znasz w miarę podstawowych procedur Pascala.

Nie, nie będę kompilował programów pod Linuxem - piszę jedynie pod Windows; Pytacz także nie zaznaczył, że kod ma być wieloplatformowy, więc podałem rozwiązanie domyślnie pod Windows; I nie dlatego podałem CopyMemory zamiast Move że tego drugiego nie znam, tylko dlatego, że podałem rozwiązanie dla Windows z domieszką WinAPI, które lubię, choć rzadko stosuję; Tak samo z ZeroMemory i FillChar - tyle że dodatkowo jest różnica w ich działaniu, bo ta pierwsza zeruje blok pamięci, a druga go wypełnia dowolnymi bajtami - mnie potrzebne było zerowanie pamięci ze względu na wartości w tablicy jako stała, więc skorzystałem z WinAPI;

Zapewne odruchy z Delphi, walcz z nimi

Owszem - pięć lat programuję w OP (w IDE Delphi) i stąd przyzwyczajenie do wstawek WinAPI; Pomimo tego nie mam zamiaru "walczyć" z tym - powtarzam, nie poszę kodów wieloplatformowych bo nie jest mi to potrzebne; Jak będę musiał, to skorzystam ze stricte "pascalowych" procedur/funkcji;

Na przyszłość polecam zacząć pomagać odpowiadając na zadane pytania, a nie czepiać się odpowiadających, co z resztą robisz w 95% wątków - "walcz z nimi, bo naprawdę, to jest nieźle rąbnięte".

1

Tak samo z ZeroMemory i FillChar - tyle że dodatkowo jest różnica w ich działaniu, bo ta pierwsza zeruje blok pamięci, a druga go wypełnia dowolnymi bajtami - mnie potrzebne było zerowanie pamięci ze względu na wartości w tablicy jako stała, więc skorzystałem z WinAPI;

Odkrywcze... I niestety nie rozumiem jakim problemem jest podanie w FillChar zera...

Nie, nie będę kompilował programów pod Linuxem - piszę jedynie pod Windows; Pytacz także nie zaznaczył, że kod ma być wieloplatformowy, więc podałem rozwiązanie domyślnie pod Windows; I nie dlatego podałem CopyMemory zamiast Move że tego drugiego nie znam, tylko dlatego, że podałem rozwiązanie dla Windows z domieszką WinAPI, które lubię, choć rzadko stosuję;

Ale to że ktoś czegoś nie zaznaczył, nie znaczy że ma być tak czy siak. Ja po prostu stwierdzam że move jest generalnie lepsze, bo niezależne od OS, tak? I serio, nie musisz pisać pod Linuxa, ale inni mogą i dlatego twój kod powinien być napisany poprawnymi praktykami.

Owszem - pięć lat programuję w OP (w IDE Delphi) i stąd przyzwyczajenie do wstawek WinAPI; Pomimo tego nie mam zamiaru "walczyć" z tym - powtarzam, nie poszę kodów wieloplatformowych bo nie jest mi to potrzebne; Jak będę musiał, to skorzystam ze stricte "pascalowych" procedur/funkcji;

No masz rację, nawet możesz wstawiać sleep w funkcje obsługi plików - bo się bufor przepełni, prawda? :)
Widzisz, to co tobie jest potrzebne nie zawsze jest tym samym co jest dobrymi praktykami - na tej samej zasadzie Patryk odejmował maski bitowe, do czego się również "przyczepiłem". Natomiast tutaj chcemy raczej dobrych praktyk jeżeli tak narzekamy na źle napisany kod. Więc jeżeli dobre praktyki to dotyczy to wszystkich, nie tylko osób które nie stosują wcięć.

Na przyszłość polecam zacząć pomagać odpowiadając na zadane pytania, a nie czepiać się odpowiadających, co z resztą robisz w 95% wątków - "walcz z nimi, bo naprawdę, to jest nieźle rąbnięte".

Nie czepiam się, zauważam fakty. I niestety algorytm wyszukiwania danych w tablicy okazał się dla mnie zbyt niskolotny, natomiast Ty, jako osoba która coś umie - przykułeś uwagę. Jeżeli nie zauważyłeś - zazwyczaj "czepiam się" osób które coś umieją w takim celu żeby wykryć ich głupoty i czegoś ich nauczyć (ohoh, ale o sobie mam wielkie mniemanie).
Więc zamiast reagować na to jakbym się czepiał - zrozum że nie robisz kardynalnych błędów a takie właśnie pomniejsze złe praktyki które staram się wyłapać.

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