Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP] Permutacja ze zbioru bez powtórzeń, gdzie błąd?
Aztech
post 15.05.2008, 13:49:25
Post #1





Grupa: Zarejestrowani
Postów: 276
Pomógł: 3
Dołączył: 22.10.2003
Skąd: Wrocław

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


Witam serdecznie. Chciałem stworzyć sobie klasę, która będzie mi generowała losową próbkę spośród zestawu liter.
Następnie dla tak wygenerowanej próbki znajduje wszystkie wariacje (permutacje) bez powtórzeń.
Np dla wylosowanego zbioru licz:
A,B,C
ma zwrócić:
A,B,C
A,C,B
B,A,C
B,C,A
C,A,B
C,B,A
ale dla zbioru: A,B,A
ma już zwrócić
A,A,B
A,B,A
B,A,A
Poniżej znajdziecie klasę, która działa "prawie" dobrze. Niestety jak to bywa, prawie robi różnicę smile.gif
Zwraca mianowicie dla zestawu A,B,C
A,B,C
B,A,C
C,A,B
czyli zwraca pierwszą znalezioną kombinację, zaczynającą się kolejno od litery:A, następnie od B, a następnie od C
Poniżej klasa i jej wywołanie:
wywołanie
  1. <?php
  2. $lvs=new LswVarSet();
  3. $lvs->buildWordSetNoRepeat($lvs->draw(3),3)
  4. ?>


klasa
  1. <?php
  2. class LswVarSet
  3. {
  4.  
  5. private static $SCR_LETTER_SET = array (
  6. 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'Ą',
  7. 'B', 'B', 'C', 'C', 'C', 'Ć', 'D', 'D', 'D', 'E',
  8. 'E', 'E', 'E', 'E', 'E', 'E', 'Ę', 'F', 'G', 'G',
  9. 'H', 'H', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I',
  10. 'J', 'J', 'K', 'K', 'K', 'L', 'L', 'L', 'Ł', 'Ł',
  11. 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'N', 'Ń', 'O',
  12. 'O', 'O', 'O', 'O', 'O', 'Ó', 'P', 'P', 'P', 'R',
  13. 'R', 'R', 'R', 'S', 'S', 'S', 'S', 'Ś', 'T', 'T', 
  14. 'T', 'U', 'U', 'W', 'W', 'W', 'W', 'Y', 'Y', 'Y',
  15. 'Y', 'Z', 'Z', 'Z', 'Z', 'Z', 'Ź', 'Ż',
  16. );
  17.  
  18. private static $SCR_VOWEL = array (
  19. 'A', 'Ą', 'E', 'Ę', 'I', 'O', 'Ó', 'U', 'Y' 
  20. );
  21.  
  22. private static $SCR_CONSONANT = array (
  23. 'B', 'C', 'Ć', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 
  24. 'Ł', 'M', 'N', 'P', 'R', 'S', 'Ś', 'T', 'W', 'Z',
  25. 'Ż', 'Ź'
  26. );
  27.  
  28. /**
  29.  * Check if letter is vowel or not
  30.  * 
  31.  * @return boolean true if is vowel
  32.  */
  33. public function isVowel($letter)
  34. {
  35. return in_array($letter,self::$SCR_VOWEL);
  36. }
  37.  
  38. /**
  39.  * Check if letter is consonant or not
  40.  * 
  41.  * @return boolean true if is consonant
  42.  */
  43. public function isConsonant($letter)
  44. {
  45. return in_array($letter,self::$SCR_CONSONANT);
  46. }
  47.  
  48. /**
  49.  * Draws from set of letter using {@param $sampleLength} letters
  50.  * @return arrat set of letters 
  51.  */
  52. public function draw($sampleLength)
  53. {
  54. $draw=array_rand(self::$SCR_LETTER_SET,$sampleLength);
  55. foreach ($draw as $key)
  56. $return[]=self::$SCR_LETTER_SET[$key];
  57. return $return;
  58. }
  59.  
  60.  
  61. /**
  62.  * Build set of letter using (@param $num} letters
  63.  * Set of letter is a permutation without repetition
  64.  * 
  65.  * @return list of potential words
  66.  */
  67. public function buildWordSetNoRepeat(array $set, $num)
  68. {
  69. $result=array();
  70. $this->addLetters($num,$set,array(),$result,array());
  71. echo TVarDumper::dump($result,2,true);
  72. return $result;
  73. }
  74. }
  75. ?>
Go to the top of the page
+Quote Post
PiXel2.0
post 15.05.2008, 18:43:52
Post #2





Grupa: Zarejestrowani
Postów: 110
Pomógł: 13
Dołączył: 16.03.2007
Skąd: Łódź

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


Mialem troche czasu i napisalem taka funkcje smile.gif
  1. <?php
  2. function permutacje($lancuch_wejsciowy){
  3. if(!is_string($lancuch_wejsciowy) or !strlen($lancuch_wejsciowy))
  4. return false;
  5. $a = str_split($lancuch_wejsciowy);
  6. sort($a);
  7. $lancuch = implode('', $a);
  8. $znaki = range(strlen($lancuch) - 1, 0);
  9. $wyniki = array();
  10. do{
  11. for($wynik = '', $i = count($znaki) - 1; $i >= 0; $i--)
  12. $wynik .= $lancuch{$znaki[$i]};
  13. if(!in_array($wynik, $wyniki))
  14. $wyniki[] = $wynik;
  15. $znaki_poprzednie = $znaki;
  16. for($i = 1; $i < count($znaki); $i++){
  17. for($znak_nr = $znaki[$i] + 1; $znak_nr < count($znaki); $znak_nr++){
  18. if(array_search($znak_nr, $znaki) > $i)
  19. continue;
  20. $znaki[$i] = $znak_nr;
  21. for($i2 = $i - 1; $i2 >= 0; $i2--){
  22. for($i3 = 0; $i3 < count($znaki); $i3++)
  23. if(!$pozycje = array_keys($znaki, $i3) or max($pozycje) <= $i2)
  24. break;
  25. $znaki[$i2] = $i3;
  26. }
  27. break 2;
  28. }
  29. }
  30. }while($znaki != $znaki_poprzednie);
  31. return $wyniki;
  32. }
  33. ?>

Jako argument podstawiasz lancuch i na wyjsciu masz tablice ze wszystkimi kombinacjami w kolejnosci alfabetycznej.
Dziala tak jak chciales dla ABC, ABA (...) i dla ABCBCCDJAJZZ tez biggrin.gif

PS:
Wydaje mi sie, ze taki problem wykracza poza te ktore powinny sie znajdowac w dziale Przedszkole i temat powinien trafic do dzialu o PHP.

Ten post edytował PiXel2.0 15.05.2008, 19:18:37
Go to the top of the page
+Quote Post
Aztech
post 15.05.2008, 22:56:25
Post #3





Grupa: Zarejestrowani
Postów: 276
Pomógł: 3
Dołączył: 22.10.2003
Skąd: Wrocław

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


Dwa słowa komentarza do Twojego kodu
Zaznaczyłem pomógł, bo faktycznie kod działa, tak jak napisałem w założeniach w pierwszym poście, ale jest ale smile.gif Rozjeżdża się całkowicie w przypadku kiedy w stringu są polskie litery - zwraca nieprawidłową ilość permutacji - trzeba używać funkcji mb_* . Ale z racji, że bez polskich literek działa, to zaznaczyłem iż pomogłeś - napracowałeś się i Ci się należy.

Mi również udało się spłodzić metodę (kombinując to co znalazłem w sieci wraz z tym co napisałem)
Zwracam sobie tablicę 2-wymiarową, gdzie pierwszy wymiar, to liczba liter. Funkcja ma dodatkowe opcje: zwracaj tylko permutacje o zadanej długości (od..do) spośród ciągu.
  1. <?php
  2. class LswVarSet
  3. {
  4.  
  5. private static $SCR_LETTER_SET = array (
  6. 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'Ą',
  7. 'B', 'B', 'C', 'C', 'C', 'Ć', 'D', 'D', 'D', 'E',
  8. 'E', 'E', 'E', 'E', 'E', 'E', 'Ę', 'F', 'G', 'G',
  9. 'H', 'H', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I',
  10. 'J', 'J', 'K', 'K', 'K', 'L', 'L', 'L', 'Ł', 'Ł',
  11. 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'N', 'Ń', 'O',
  12. 'O', 'O', 'O', 'O', 'O', 'Ó', 'P', 'P', 'P', 'R',
  13. 'R', 'R', 'R', 'S', 'S', 'S', 'S', 'Ś', 'T', 'T', 
  14. 'T', 'U', 'U', 'W', 'W', 'W', 'W', 'Y', 'Y', 'Y',
  15. 'Y', 'Z', 'Z', 'Z', 'Z', 'Z', 'Ź', 'Ż',
  16. );
  17.  
  18. private static $SCR_VOWEL = array (
  19. 'A', 'Ą', 'E', 'Ę', 'I', 'O', 'Ó', 'U', 'Y' 
  20. );
  21.  
  22. private static $SCR_CONSONANT = array (
  23. 'B', 'C', 'Ć', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 
  24. 'Ł', 'M', 'N', 'P', 'R', 'S', 'Ś', 'T', 'W', 'Z',
  25. 'Ż', 'Ź'
  26. );
  27.  
  28. /**
  29.  * Check if letter is vowel or not
  30.  * 
  31.  * @return boolean true if is vowel
  32.  */
  33. public function isVowel($letter)
  34. {
  35. return in_array($letter,self::$SCR_VOWEL);
  36. }
  37.  
  38. /**
  39.  * Check if letter is consonant or not
  40.  * 
  41.  * @return boolean true if is consonant
  42.  */
  43. public function isConsonant($letter)
  44. {
  45. return in_array($letter,self::$SCR_CONSONANT);
  46. }
  47.  
  48. /**
  49.  * Draws from set of letter using {@param $sampleLength} letters
  50.  * @return arrat set of letters 
  51.  */
  52. public function draw($sampleLength)
  53. {
  54. $draw=array_rand(self::$SCR_LETTER_SET,$sampleLength);
  55. foreach ($draw as $key)
  56. $return[]=self::$SCR_LETTER_SET[$key];
  57. return $return;
  58. }
  59.  
  60. public function buildCombinations($length, $fromSublength, $toSublength, array $letters) 
  61. { 
  62. $out_scheme = array(); 
  63.  
  64. if ($sublength>$length) $toSublength = $length;
  65.  
  66. $max = $this->factorial($length);
  67.  
  68. for ($a=0; $a<($length); $a++) 
  69. $options[$a]=$pattern[$a]=$a;
  70.  
  71. for ($x=0; $x<$max; $x++) 
  72. { 
  73. $N=$x; 
  74. for ($i=1; $i<= $length;) 
  75. { 
  76. $pattern[($length-$i)]=$N%$i; 
  77. $N=$N/$i; 
  78. $i++; 
  79. }
  80. unset($perm);
  81. $b=$options;
  82. foreach($pattern AS $offset) 
  83. { 
  84. list($char)=array_splice($b,$offset,1);
  85. $perm[]=$char; 
  86. }
  87. for($l=$fromSublength;$l<=$toSublength;$l++)
  88. {
  89. $m=array_slice($perm,0,$l);
  90. $out_scheme[$l][]=implode('-',$m);
  91. }
  92. }
  93. for($l=$fromSublength;$l<=$toSublength;$l++)
  94. {
  95. $out_scheme[$l]=array_unique($out_scheme[$l]);
  96. foreach ($out_scheme[$l] as $scheme)
  97. {
  98. $scheme=str_replace(array_keys($letters),$letters,$scheme);
  99. $return[$l][] = implode('',explode('-',$scheme));
  100. }
  101. }
  102.  
  103. return $return;
  104.  
  105. }
  106. ?>


Ten post edytował Aztech 15.05.2008, 23:10:39
Go to the top of the page
+Quote Post
Cysiaczek
post 15.05.2008, 23:49:02
Post #4





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Przenoszę na PHP


--------------------
To think for yourself you must question authority and
learn how to put yourself in a state of vulnerable, open-mindedness;
chaotic, confused, vulnerability, to inform yourself.
Think for yourself. Question authority.
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 16.06.2025 - 19:08