Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Wieże Hanoi, Klasa, PHP 5
dr_bonzo
post
Post #1





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Co to robi? Rozwiazuje "Wieze Hanoi", uzywa minimalnej liczby ruchow i pokazuje je kolejno.

PHP5 REQUIRED

  1. <pre><?php
  2. class HanoiStack
  3. {
  4.     private $arrStack = array();
  5.     
  6.     public function HanoiStack()
  7.     {
  8.     }
  9.     
  10.     public function pushItem( $intItem )
  11.     {
  12.         $intItem = intval( $intItem );
  13.         
  14.         if ( count( $this->arrStack ) === 0 )
  15.         {
  16.             array_push( $this->arrStack, $intItem );
  17.         }
  18.         else
  19.         {
  20.             if ( $intItem > $this->getLastItem() )
  21.             {
  22.                 throw new Exception( 'Cannot put bigger brick on smaller (' . $intItem . ' on ' . $this->getLastItem() . ')' );
  23.             }
  24.             
  25.             array_push( $this->arrStack, $intItem );
  26.         }
  27.     }
  28.     
  29.     public function popItem()
  30.     {
  31.         if ( count( $this->arrStack ) === 0 )
  32.         {
  33.             print_r( $this->arrStack );
  34.             throw new Exception( 'Cannot pop intem from empty stack' );
  35.         }
  36.         
  37.         return array_pop( $this->arrStack );
  38.     }
  39.     
  40.     public function getLastItem()
  41.     {
  42.         if ( count( $this->arrStack ) === 0 )
  43.         {
  44.             return -1;
  45.         }
  46.         
  47.         return $this->arrStack[ count( $this->arrStack ) - 1 ];
  48.     }
  49.     
  50.     public function __toString()
  51.     {
  52.         $s = '[ ';
  53.         
  54.         foreach ( $this->arrStack as $v )
  55.         {
  56.             $s .= $v . ' ';
  57.         }
  58.         
  59.         $s .= &#092;"]n\";
  60.         return $s;
  61.     }
  62. }
  63.  
  64. class Hanoi
  65. {
  66.     private $arrStacks = array();
  67.     
  68.     private $intN;
  69.     
  70.     private $intMoves;
  71.     
  72.     public function Hanoi( $intN )
  73.     {
  74.         $this->intN = intval( $intN );
  75.         
  76.         for ( $i = 0; $i < 3; $i++ )
  77.         {
  78.             $this->arrStacks[ $i ] = new HanoiStack();
  79.         }
  80.         
  81.         for ( $i = $this->intN - 1; $i >= 0; $i-- )
  82.         {
  83.             $this->arrStacks[ 0 ]->pushItem( $i ); 
  84.         }
  85.     }
  86.     
  87.     public function solve()
  88.     {
  89.         $this->printTowers();
  90.         
  91.         // z wiezy 0 na wieze 2
  92.         if ( $this->intN <= 0 )
  93.         {
  94.             throw new Exception( 'Wrong intN' );
  95.         }
  96.         
  97.         $i_max = intval( pow( 2, $this->intN ) - 1 );
  98.         
  99.         $intBrickOnePosition = 0;
  100.         $intMoveDirection = ( $this->intN % 2 === 1 ) ? -: 1;
  101.         
  102.         for ( $i = 0; $i < $i_max; $i++ )
  103.         {
  104.             if ( $i % 2 === 0 )
  105.             {
  106.                 // zdejmij jedynke (tu zero: indeksujemy klocki od zera)
  107.                 $intItem = $this->arrStacks[ $intBrickOnePosition ]->popItem();
  108.                 print( '(' . $intBrickOnePosition . ')--[ ' . $intItem . ' ]-->(' . ( $intBrickOnePosition + $intMoveDirection + 3 ) % 3 . ')' . &#092;"n\" );
  109.                 $intBrickOnePosition = ( $intBrickOnePosition + $intMoveDirection + 3 ) % 3;
  110.                 // i przenies ja w keirunku $intMoveDirection
  111.                 $this->arrStacks[ $intBrickOnePosition ]->pushItem( $intItem );
  112.             }
  113.             else
  114.             {
  115.                 $arrTowerIndices = array();
  116.                 $arrTopItems = array();
  117.                 $x = 0;
  118.                 
  119.                 
  120.                 // znajdz wieze z min i max brickiem !== 1
  121.                 for ( $j = 0; $j < 3; $j++ )
  122.                 {
  123.                     if ( $j !== $intBrickOnePosition )
  124.                     {
  125.                         $arrTowerIndices[ $x ] = $j;
  126.                         $arrTopItems[ $x ] = $this->arrStacks[ $j ]->getLastItem();
  127.                         $x++;
  128.                     }
  129.                 }
  130.                 
  131.                 $intTowerWithSmallerTopItem = ( $arrTopItems[ 0 ] < $arrTopItems[ 1 ] ) ? $arrTowerIndices[ 0 ] : $arrTowerIndices[ 1 ];
  132.                 $intTowerWithBiggerTopItem = ( $arrTopItems[ 0 ] > $arrTopItems[ 1 ] ) ? $arrTowerIndices[ 0 ] : $arrTowerIndices[ 1 ];
  133.                 
  134.                 if ( $this->arrStacks[ $intTowerWithSmallerTopItem ]->getLastItem() === -1 )
  135.                 {
  136.                     // zamien je to ta pierwsza jest pusta
  137.                     $temp = $intTowerWithSmallerTopItem;
  138.                     $intTowerWithSmallerTopItem = $intTowerWithBiggerTopItem;
  139.                     $intTowerWithBiggerTopItem = $temp;
  140.                 }
  141.                 
  142.                 // przenies klocek
  143.                 $intItem = $this->arrStacks[ $intTowerWithSmallerTopItem ]->popItem();
  144.                 print( '(' . $intTowerWithSmallerTopItem . ')--[ ' . $intItem . ' ]-->(' . $intTowerWithBiggerTopItem . ')' . &#092;"n\" );
  145.                 $this->arrStacks[ $intTowerWithBiggerTopItem ]->pushItem( $intItem );
  146.                 
  147.                 
  148.             }
  149.             
  150.             $this->printTowers();
  151.         }
  152.     }
  153.     
  154.     private function printTowers()
  155.     {
  156.         print( '0: ' );
  157.         print( $this->arrStacks[ 0 ] );
  158.         print( '1: ' );
  159.         print( $this->arrStacks[ 1 ] );
  160.         print( '2: ' );
  161.         print( $this->arrStacks[ 2 ] );
  162.         print( &#092;"n\" );
  163.     }
  164. }
  165.  
  166.  
  167. class HanoiTowers
  168. {
  169.     public static function main()
  170.     {
  171.         try
  172.         {
  173.             $objHanoiTower = new Hanoi( 3 );
  174.             $objHanoiTower->solve();
  175.         }
  176.         catch ( Exception $e )
  177.         {
  178.             print( $e );
  179.         }
  180.     }
  181. }
  182.  
  183. HanoiTowers::main();
  184. ?></pre>


Ten post edytował dr_bonzo 2.06.2005, 17:47:06
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
GrayHat
post
Post #2





Grupa: Zarejestrowani
Postów: 566
Pomógł: 18
Dołączył: 23.08.2003
Skąd: Łomża

Ostrzeżenie: (0%)
-----


mozna jakis exampel?
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #3





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Ehhh... a chociarz uruchomiles ten skrypt?
Wystarczy go skopiowac i uruchomic -- wyswietli ci kolejne ruchy i kolejne stany wiez.
Go to the top of the page
+Quote Post
GrayHat
post
Post #4





Grupa: Zarejestrowani
Postów: 566
Pomógł: 18
Dołączył: 23.08.2003
Skąd: Łomża

Ostrzeżenie: (0%)
-----


a wogole co to wierze hanoi??
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


WieZe -- google wiedzialo ale nie powiedzialo?
http://en.wikipedia.org/wiki/Tower_of_Hanoi
Go to the top of the page
+Quote Post
Bielo
post
Post #6





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 21.09.2003
Skąd: Truskaw

Ostrzeżenie: (0%)
-----


Sam algorytm rozwiązywania Hanoi wygląda tak:
  1. <?php
  2.  
  3. function hanoi($dyskow, $z, $na)//hanoi(ilosc dyskow do przelozenia, slupek na ktorym zaczynamy, slupek na ktory pr
    z
  4. nosimy)
  5. {
  6. if($dyskow==1)
  7. {
  8. print(&#092;"Przesun dysk nr \".$dyskow.\" z \".$z.\" na \".$na.\"<br />\");
  9. }
  10. else
  11. {
  12. hanoi($dyskow-1, $z, 3-$z-$na);
  13. print(&#092;"Przesun dysk nr \".$dyskow.\" z \".$z.\" na \".$na.\"<br />\");
  14. hanoi($dyskow-1, 3-$z-$na, $na);
  15. }
  16. }
  17.  
  18. ?>

Przyklad pzepisany z ksiazki Helionu "Algorytmy, struktury danych i techniki programowania", sprawdzalem pieknie dziala.

Nie przygladalem sie za bardzo Twojemu skryptowi, ale mysle ze mozna bylo zrobic to krocej
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #7





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Twoj algorytm jest rekurencyjny, a moj nie. Oba opisane sa w wikipedii:

Cytat
Alternately move disc 1 and one of the larger discs. If two of the larger discs are available, always move the smaller one onto the larger. When you move an odd-numbered disc, always move it one peg clockwise; when you move an even-numbered disc, always move it one peg counterclockwise.

An even easier way to remember this solution is to notice that the smallest disk gets every second move, and always moves in the same direction. In between smallest disk moves, there is only one legal move that does does not involve moving the smallest disk again.

----

Cytat
Nie przygladalem sie za bardzo Twojemu skryptowi, ale mysle ze mozna bylo zrobic to krocej

No pewnie, w ogole porzucic klasy, obsluge bledow, skrocic printTowers(), itd.
Go to the top of the page
+Quote Post
Bielo
post
Post #8





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 21.09.2003
Skąd: Truskaw

Ostrzeżenie: (0%)
-----


to co ja napisalem to jest tylko algorytm, a nie caly skrypt. Po dodaniu do niego obslugi bledow i przerobieniu na wersje obiektowa, bylby chyba krotszy od Twojego, ale rozumiem tez uzycie wersji nerekurencyjnej
Go to the top of the page
+Quote Post
Radarek
post
Post #9





Grupa: Zarejestrowani
Postów: 188
Pomógł: 0
Dołączył: 23.05.2005

Ostrzeżenie: (0%)
-----


A mi nawet nie chce sie czytac i probowac zrozumiec wersje iteracyjna, bo po co? Wersja rekurencyjna jest tak intuicyjna i zrozumiala, ze nie trzeba nic wiecej. To niesamowite, ze te kilka linijek jest poprawnym rozwiazaniem [i najoptymalniejszym] podanego problemu. Ale braw nie bije bo znalem juz wczesniej to rozwiazanie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
M4chu
post
Post #10





Grupa: Zarejestrowani
Postów: 135
Pomógł: 0
Dołączył: 28.09.2003
Skąd: Rzeszów

Ostrzeżenie: (0%)
-----


Najoptymalniejszym? Dla mnie najoptymalniejsze to najszybsze, a rekurencyjne takie napewno nie jest.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #11





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Cytat
Ale braw nie bije bo znalem juz wczesniej to rozwiazanie

Prawda jest taka ze nudzilo mi sie tamtej nocy i napisalem ten algorytm.
A wpadlem na niego (rozwiazujac na papierze dziesiatki razy WH) dawno temu.

Cytat
Wersja rekurencyjna jest tak intuicyjna i zrozumiala

A sprobuj go zastosowac w praktyce w realu...
Go to the top of the page
+Quote Post
Bakus
post
Post #12


Administrator serwera


Grupa: Przyjaciele php.pl
Postów: 909
Pomógł: 0
Dołączył: 12.08.2003
Skąd: /var/www/wroclaw.php

Ostrzeżenie: (0%)
-----


@Bielo: Jeżeli masz pomysł, to go rozwiń, napisz skrypt i umieść w osobnym temacie.
Go to the top of the page
+Quote Post
Radarek
post
Post #13





Grupa: Zarejestrowani
Postów: 188
Pomógł: 0
Dołączył: 23.05.2005

Ostrzeżenie: (0%)
-----


Cytat
Najoptymalniejszym? Dla mnie najoptymalniejsze to najszybsze, a rekurencyjne takie napewno nie jest.


Dlaczego nie?(IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Zapewniam cie ze jest. Powiedz jaki jest powod dla ktorego mialo byc nie byc?

Cytat
Prawda jest taka ze nudzilo mi sie tamtej nocy i napisalem ten algorytm.
A wpadlem na niego (rozwiazujac na papierze dziesiatki razy WH) dawno temu.


Przyznam ci sie, ze ja tez kiedys wpadlem na to rozwiazanie, ale mniejsza z tym.

Cytat
A sprobuj go zastosowac w praktyce w realu...


Hm.. jesli pisze program to po to zeby robil cos za mnie. Np. program sortujacy za pomoca quicksorta lub heapsorta. Sprobuj zrobic to w praktyce. Bez sensu gadanie... (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
bela
post
Post #14


Administrator PHPedia.pl


Grupa: Developerzy
Postów: 1 102
Pomógł: 2
Dołączył: 14.09.2003

Ostrzeżenie: (0%)
-----


Cytat(Radarek @ 2005-05-29 15:38:41)
Cytat

Najoptymalniejszym? Dla mnie najoptymalniejsze to najszybsze, a rekurencyjne takie napewno nie jest.


Dlaczego nie?(IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Zapewniam cie ze jest. Powiedz jaki jest powod dla ktorego mialo byc nie byc?

Udowodnij, że jest najoptymalniejsze (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
Radarek
post
Post #15





Grupa: Zarejestrowani
Postów: 188
Pomógł: 0
Dołączył: 23.05.2005

Ostrzeżenie: (0%)
-----


Cytat(bela_666 @ 2005-05-29 15:12:29)
Cytat(Radarek @ 2005-05-29 15:38:41)
Cytat

Najoptymalniejszym? Dla mnie najoptymalniejsze to najszybsze, a rekurencyjne takie napewno nie jest.


Dlaczego nie?(IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Zapewniam cie ze jest. Powiedz jaki jest powod dla ktorego mialo byc nie byc?

Udowodnij, że jest najoptymalniejsze (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Hm.. ilosc ruchow potrzebnych do przeniesienia N krazkow wynosci 2^(n-1) i taka jest zlozonosc programu. Szybciej sie nie da. Zakladajac, ze wersja iteracyjna wykonuje taka sama ilosc ruchow to i tak jest mniej optymalna. Czemu? Bo zawiera wiecej instrukcji (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) . Przepiszcie obra programy na C/C++, skompilujcie do kodu assemblerowego i porownajcie rozmiary kodu. Stawiam, ze mniejszy bedzie rekurencyjny.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #16





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Ale wez tez pod uwage wielokrotne wywolywanie funkcji, co takze zajmuje zasoby i cpu (trzeba utworzyc zmienne lokalne, odlozyc je na stos, wywolac funkcje, zdjac zmienne z powrotem, itd). Ale nie wiem, ktora z metod bedzie szybsza.
Go to the top of the page
+Quote Post
Radarek
post
Post #17





Grupa: Zarejestrowani
Postów: 188
Pomógł: 0
Dołączył: 23.05.2005

Ostrzeżenie: (0%)
-----


Cytat(dr_bonzo @ 2005-05-29 16:50:27)
Ale wez tez pod uwage wielokrotne wywolywanie funkcji, co takze zajmuje zasoby i cpu (trzeba utworzyc zmienne lokalne, odlozyc je na stos, wywolac funkcje, zdjac zmienne z powrotem, itd). Ale nie wiem, ktora z metod bedzie szybsza.

Tak wzialem to pod uwage. Rekurencyjne wywolanie funkcji to odlozenie na stos zmiennych lokalnych funkcji oraz adresu powrotu. Nie wierzysz chyba zeby wersja rekurencyjna bedzie dluzsza? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
onlyX
post
Post #18





Grupa: Zarejestrowani
Postów: 119
Pomógł: 0
Dołączył: 15.07.2003
Skąd: Grajewo

Ostrzeżenie: (0%)
-----


A mi wyrzuciło taki błąd w tym pierszym skrypcie:
Kod
Parse error: parse error, expecting `T_OLD_FUNCTION' or `T_FUNCTION' or `T_VAR' or `'}'' in D:\usr\test\hanoi.php on line 4
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #19





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Bo musisz miec PHP5.

PS. Uzupelniony 1szy post o to info
Go to the top of the page
+Quote Post
piratt
post
Post #20





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 28.09.2005

Ostrzeżenie: (0%)
-----


A wzial ktos pod uwage fakt ze w wersji rekurencyjnej skonczy sie baaardzo szybko pamiec? (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Rekurencja nie jest zalecana przy duzej liczbie wywolan.
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 12.10.2025 - 08:20