Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: zadanie z grupowaniem pionków
Forum PHP.pl > Forum > PHP
marcus753
Witam was od tygodnia męczę z piekielnie trudnym zadaniem może ktoś z was mi trochę pomoże...

Zadanie ma taką treść

Jasiu zdenerwowany że przegrał w warcaby wziął n pionków i rzucił nimi na planszę tak że każdy pionek upadł tylko na jedno pole. Jasiu chce teraz pogrupować pionki które leżą obok siebie (czyli ustalić że pionki ułożyły się np. w 5 grup 1 grupa składa się z 3 pionków druga z 2 itd...)

2 pionki zalicza się do tej samej grupy jeśli lezą obok siebie.

mam teraz taki plik wejściowy z współrzędnymi każdego pionka
rząd/kolumna
1:1
2:2
3:3
4:4

czyli pionki ułożyły się na ukos
wynikiem takiego rozłożenia pionków powinno być 1:4 (grupa 1 , składa się z 4 pionków)

gdyby było np
1:1
1:2
2:2
5:5
5:6
wynikiem takiego rozłożenia pionków powinno być 1:3, 2:2 (grupa 1 , składa się z 3 pionków ,grupa 2 , składa się z 2 pionków)

napisałem 2 skyrpty razem z jakies 200 linijek oczywiście nie zadziałały poprawnie dochodzę do momentu w którym zaczynam pisać na nowo ale sam już nie wiem jak to wszystko zrobić ;(

bedę wdzięczny za każdą pomoc sugestie itp. (skrypt nie jest na żaden konkurs gdzie wymagana jest praca indywidualna itp) żeby nie było że wyręczam się tym forum jak chcecie moge zamieścić moje dotychczasowe skrypty ale ja sam już zaczynam się w nich gubić więc nie wiem czy wam by coś dały

POZDRAWIAM sciana.gif sciana.gif

pomysł miałem taki żeby porównać każdy rekord do rekordów leżących obok niego w odległości 1rzedu czyli np. dla danych
1:1
1:2
2:2
5:5
5:6

porównuje 1:1 do 1:2 jeśli leżą obok siebie do nowego pliku zapisuje 1:1:1,1:2:1 (ostatnia cyfra to grupa) następnie porównuje 1:1 do 2:2 w efekcie czego do poprzedniego pliku dopisuje 1:1:1 2:2:1
nastepnie 1:1 do 5:5 jako że 5:5 leży poza najbliższym żędem pobieram kolejną zmienną do porównania czyli 1:2 porownuje do 2:2 i tu już zaczynają się schody teraz przydało by się żeby sprawdzał czy 1:2 ma już jakąś grupe a to oznacza że najpierw musiał bym otworzyć plik aby pobrać dane i na otwartym pliku otwierać go jeszcze raz aby aktualizować nie mam pojecia jak to zrobić albo ominąć...

drugi skrypt miał ignorować takie same rekordy które występują więcej niż jeden raz i zliczać ile rekordów ma tą samą grupe
emtiej
na twoim przykładzie:
1:1
1:2
2:2
5:5
5:6

1:1 = 1+1 = 2
1:2 = 1+2 = 3
2:2 = 2+2 = 4
5:5 = 5+5 = 10
5:6 = 5+6 = 11

Załaduj wszystko do tablicy dla ułatwienia, pomyśl i zrobisz ja ci dałem pomysł, to twoja praca domowa więc się męcz, ale powiem że zadanie nie jest aż tak trudne, wystarczy posiedzieć z 10 minut i ruszyć mózgiem


ps. autor tego zadania chyba nigdy nie grał w warcaby, bo grając w warcaby pionki się stawia na polach tego samego koloru chyba ^^
ADeM
~Emtiej: Twoje rozumowanie sprawdza się dla współrzędnych (1,5);(5,1)?
pozdrawiam
Adem

Ps. Autor pewnie grał w warcaby, ale rzucał także pionkami, które nie zawsze lądują na tych samych kolorach.
thek
Zdefiniuj sąsiedztwo wpierw. Sąsiad to pionek o wartości od 1 do 8 włącznie, który ma wartości współrzędnych na każdej z osi w zakresie -1,+1 do współrzędnych aktualnego.
Algorytm powinien działać łańcuchowo mniej więcej na zasadzie:
1) Weź pierwszy wolny pionek z puli wszystkich i usuń go stamtąd tworząc z niego nową grupę.
2) Wyszukaj jego sąsiadów najbliższych, dodaj do grupy i też usuń z puli wszystkich.
3) Jeśli pula pusta, możesz zakończyć algorytm.
4) Weź kolejny z tej grupy i znajdź jego sąsiadów z puli, usuń je z puli wszystkich i dodaj do grupy.
5) Powtarzaj kroki od 3) aż dojdziesz do ostatniego elementu, który już nie będzie miał sąsiadów.
6) Wróć do kroku 1)
7) Powtarzaj aż brak będzie pionków w grupie tych wolnych.

Przykład wezmę Twój:
1:1, 1:2, 2:2, 5:5, 5:6
Biorę 1:1 i tworzę grupę usuwając go z puli, mam więc:
Grupa 1 -> 1:1
Pula -> 1:2, 2:2, 5:5, 5:6

Szukam sąsiadów i znajduję 1:2, 2:2, więc dodaję do grupy i usuwam z puli, mam więc:
Grupa 1 -> 1:1, 1:2, 2:2
Pula -> 5:5, 5:6

Biorę element kolejny z grupy 1 -> 1:2 Pula ma coś więc szukam sąsiadów w puli, ale ich brak, więc biorę kolejny 2:2, sprawdza ilość w puli jeszcze coś mającej tyle że tu też brak, więc szukanie się dla grupy kończy. Jeśli coś by doszło z tych szukań to automatycznie miałbym kolejne szukanie, co chyba jest logiczne smile.gif

Biorę następny element z puli i tworzę grupę 2, więc mam:
Grupa 1 -> 1:1, 1:2, 2:2
Grupa 2 -> 5:5
Pula -> 5:6
Szukam sąsiadów, znajduję 5:6, usuwam z puli i dodaję do grupy.

Grupa 1 -> 1:1, 1:2, 2:2
Grupa 2 -> 5:5, 5:6
Pula -> pusta

Pula jest pusta, czyli algorytm się kończy.

Banał... smile.gif

EDIT: W sumie nawet krok 7) nie jest potrzebny, bo krok 3) tak naprawdę zawsze zakończy Ci algorytm winksmiley.jpg Kwestia Twojego przemyślenia to jedynie format zapisu współrzędnych pionów. Implementacja algorytmu już mając strukturę pionów to pryszcz.
marcus753
Wielkie dzięki THEK party.gif
Faktycznie teraz jak tak patrze na to zadanie to wcale nie jest trudne ja poprostu się w nim poplątałem bo postanowiłem zrobić je w biegu i nie rozpisałem sobie krok po kroku co mam robić tylko od razu zacząłem pisać...

w sumie pionek nie musisz porównywać do wszystkich pionków w około a tylko do tych na dole i pobokach bo u góry już zostały porównane przez wcześniejszy pionek czarodziej.gif

Pozdrawiam i jeszcze raz dzięki
thek
Niekoniecznie smile.gif Zależy czy masz je posortowane czy nie. Jeśli tak, to masz rację i olewamy wszystkie mające mniejszą pierwszą współrzędną oraz równą pierwszą i mniejszą drugą na zasadzie:
olej olej olej
olej baza może
może może może
Brak sortowania wymusza na Tobie sprawdzenie wszelkich możliwości.

PS: Posortowana PULA to zawsze szukanie i tak od pierwszego elementu, gdyż nigdy nie trafisz na element mniejszy winksmiley.jpg Stąd posortowanie puli na samym początku według pierwszego elementu, a jeśli jest kilka takich samych to wedle drugiego, może być dobrym pomysłem na optymalizację algorytmu, gdyż przerywasz szukanie po osiągnięciu przez skrypt w puli wolnych określonej wartości współrzędnych większej niż (baza +1, baza+1).

EDIT: Ciekawostką jest fakt, że takie rozwiązanie problemu pozwala na uznanie za grupę także pionków stojących na tym samym polu w wyniku rzucenia. Kto powiedział, że na jednym polu może stać tylko jeden? W wyniku rzutu może się okazać normą, że na jedno pole spadnie więcej niż jeden pion.
A na przyszłość zanim zaczniesz robić coś "z biegu" zastanów się nad założeniami bazowymi bo jak widzisz dobre przemyślenie sprawy ułatwia proces ze stopnia "nie wiem co dalej" do "to trywialne". Tutaj jednak najlepsze wyniki mają osoby myślące bardzo abstrakcyjnie i praktycy, bo to oni najszybciej wynajdują algorytm. Ja zacząłem od definicji "sąsiada". Gdy to już miałem reszta poszła gładko.
marcus753
mam dosyć napisałem taki skrypcik i oczywiście nie działa...
sam już nie wiem co robie zle sciana.gif

  1. <?
  2. $a=0;
  3. $c=0;
  4. $baza= 'baza.txt';
  5. $wiersz = file($baza);
  6.  
  7.  
  8.  
  9. while (!empty($wiersz[$a])){
  10. //bierzemy pierwszy pionek
  11. $baza= 'baza.txt';
  12. $wiersz = file($baza);
  13.  
  14. $tuser = explode('|',$wiersz[$a]);
  15. $rzad = $tuser[0];
  16. $kolumna = $tuser[1];
  17. $grupa = $tuser[2];
  18.  
  19. $b=0;
  20.  
  21.  
  22. while (!empty($wiersz[$b])){
  23. //bierzemy drugi pioten (na poczatku bedzie to ten sam )
  24. $baza= 'baza.txt';
  25. $wiersz1 = file($baza);
  26.  
  27. $tuser = explode('|',$wiersz1[$b]);
  28. $rzadn = $tuser[0];
  29. $kolumnan = $tuser[1];
  30. $grupan = $tuser[2];
  31.  
  32.  
  33. $wartosc=0;
  34.  
  35. $rzad1 = $rzad;
  36. $rzad2 = $rzad+1;
  37. $kolumna1 = $kolumna-1;
  38. $kolumna2 = $kolumna;
  39. $kolumna3 = $kolumna+1;
  40.  
  41. //porownujemy wpolrzedne pionka 1 i 2
  42.  
  43. if (($rzad1==$rzadn) AND ($kolumna1==$kolumnan)){$wartosc=1;}
  44. if (($rzad1==$rzadn) AND ($kolumna2==$kolumnan)){$wartosc=1;}
  45. if (($rzad1==$rzadn) AND ($kolumna3==$kolumnan)){$wartosc=1;}
  46. if (($rzad2==$rzadn) AND ($kolumna1==$kolumnan)){$wartosc=1;}
  47. if (($rzad2==$rzadn) AND ($kolumna2==$kolumnan)){$wartosc=1;}
  48. if (($rzad2==$rzadn) AND ($kolumna3==$kolumnan)){$wartosc=1;}
  49.  
  50. if ($wartosc==1){
  51.  
  52. if ($grupa==0){$grupa=$c+1;}
  53. //zapisujemy w transfer zawartosc pliku baza przy ()czym pionkowi 2 zmieniamy grupe )
  54. $plik_transferu = fopen('transfer.txt','a');
  55. flock($plik_transferu, LOCK_EX);
  56. $d=0;
  57.  
  58. while (!empty($wiersz1[$d])){
  59. $baza= 'baza.txt';
  60. $wiersz2 = file($baza);
  61.  
  62. $tuser = explode('|',$wiersz[$d]);
  63. $rzad5 = $tuser[0];
  64. $kolumna5 = $tuser[1];
  65. $grupa5 = $tuser[2];
  66.  
  67. if(($rzad5==$rzadn) AND ($kolumna5==kolumnan)){$grupa5=$grupa;}
  68.  
  69.  
  70. $dane=$rzad5."|".$kolumna5."|".$grupa5."\n";
  71. $d=$d+1;
  72. }
  73.  
  74. fwrite($plik_transferu, $dane);
  75.  
  76. flock($plik_transferu, LOCK_UN);
  77.  
  78. fclose($plik_transferu);
  79.  
  80. //przekopiowanie danych z transferu do bazy
  81.  
  82. $file = "baza.txt";
  83. $fp = fopen($file, "w");
  84. flock($fp, 2);
  85.  
  86. $lista1 = file('transfer.txt');
  87.  
  88. foreach ($lista1 as $userek1){
  89.  
  90. $tuser = explode('|',$userek1);
  91. $rzad10 = $tuser[0];
  92. $kolumna10 = $tuser[1];
  93. $grupa10 = $tuser[2];
  94.  
  95. $dane=$rzad10."|".$kolumna10."|".$grupa10."\n";
  96. fwrite($fp, $dane);
  97.  
  98.  
  99. }
  100. flock($fp, 3);
  101. fclose($fp);
  102.  
  103.  
  104. }}}
  105.  
  106.  
  107. echo "zakonczono dzialanie skryptu "
  108.  
  109.  
  110.  
  111. ?>
thek
Na początek radzę sobie sensownie wszystkie pionki do tablicy wrzucić. Przykładowo bierzesz plik z danymi w którym masz jakąś strukturę opisującą rzucone piony i musisz utworzyć taką, która będzie tablicą z współrzędnymi pionów choćby w postaci:
  1. $pula = array( [0] => array([x] => 2, [y] => 5), [1] => array([x] => 2, [y] => 7), [2] => array([x] => 4, [y] => 8) )
i tak dalej kolejne. Dopiero na tym bazując powinieneś wykonywać grupowanie.

W tej chwili skaczesz z pobieraniem danych z pliku tak, że gubisz się z aktualnym położeniem wskaźnika i nawet nie wiesz gdzie oraz kiedy się znajdujesz w określonym miejscu skryptu. Masz po prostu chaos, którego nie ogarniasz. Uporządkuj go wpierw.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.