Товарищи имеется такой вопрос. Есть массив например состоящий из 3 элементов (букв) array("a","b","c"), как можно перебрать все возможные варианты слов составленных (типа aaa,abb,abc, cab и т.д) из этих цифр и вывести их на экран либо сохранить в массиве. Согласно теории вероятности должно быть 3*3=27 вариантов. У меня не было под рукой соответсвующей литературы поэтому я хотел поступить так: например выражению abc относительно индексов букв в массиве соответсвует 012 aac - 002 abb- 001 То есть получим дипазон от 000 до 222. И нужно выбрать числа которые содержать цифры 0,1,2 но не содержат 3,4,5...9. (001, 100,120,211 и т.д) всего должно было по идее получитьс тоже 27 вариантов. Затем сохранить эти числа в массиве. Получиться массив ("000","001","211","210" и т.д). Потом сопоставить числа из ячеек полученного массива с индексами массива ("a","b","c") и получить 000 - aaa 001 - aab 211 - cbb и т.д. Вот код который листает дипазон но почему то не работает: for ($one=0;$one<=9;$one++) { for ($two=0;$two<=9;$two++) { for ($three=0;$three<=9;$three++) { $password=$one.$two.$three; settype($password,"string"); if (ereg("[0-2]",$password)) $new_password=$password; echo $new_password."<br>"; if (ereg("[^3-9]",$new_password)) echo $new_password."<br>"; if ($password=="222") die("Stop..."); } } } Подскажите pls что не так или другой вариант.
если не получается придумать алгоритм, то можно просто написать $result = array('aaa', 'aab', 'aac', ..., 'ccc'); это конечно если на три буквы надо)
Сомневаюсь, что это идеальный алгоритм )) но вот поправил твой: PHP: <?php $cnt = 0; for($one = 0; $one <= 9; $one++) { for($two = 0; $two <= 9; $two++) { for($three = 0; $three <= 9; $three++) { $password = $one . $two . $three; //settype($password, "string"); if(ereg('[0-2]{3}', $password)) { $new_password = $password; echo($new_password . '<br />'); $cnt++; } /*if(ereg('[^3-9]', $new_password)) echo($new_password . '<br />');*/ if($password == '222') die('Stop... Cnt = ' . $cnt); } } } ?>
В строчке settype($password, 'string') нет смысла, после того, как делаешь канкатенацию (вот это: $password = $one . $two . $three; ) - переменная $password уже становится типа string. Если так хочется самому задать тип переменным, напиши: $password = ((string) $one) . ((string) $two) . ((string) $three); но смысла в этом нету...
sobachnik Спасибо заработало. А нет ли такого алгоритма без вложеных циклов, не очень удобно если перебирать например не 3 а поболее вариантов. Например массив из всех букв английского алфавита ("a","b"...."z")
А как вы добились этой строкой нужного результата. Я думал она ищет равно три повторения чисел из дипазона 0-2, типа 000, 111, 222. Или как она вооще работает. И не пойму почему мой не работал $password=$one.$two.$three; if (ereg("[0-2]",$password))//вроде бы здесь выбираются числа где присутсвует 0-2 $new_password=$password;//затем числа где есть 0,1,2 присваиваются новой пременной if (ereg("[^3-9]",$new_password))// а зетем из выбранных с 0-2 отбрасываются с 3,4,5 и т.д до 9 echo $new_password."<br>"; Но почему не заработало не понял? Если ставить if (ereg("[^0-9]",$password)) то тогда работает, т.е ничего не выбирается.
Регулярка '[0-2]' значит наличие хотя бы одного символа из этого диапазона (0...2) в заданной строке. Регулярка '[0-2]{3}' значит наличие трёх подряд идущих символов из указанного диапазона в заданной строке
PHP: <?php $data=array('a','b','c'); $countIter=pow(count($data),count($data))-1; for($i=0;$i<=$countIter;$i++) { $curMask = base_convert($i,10,count($data)); while(strlen($curMask)<count($data)) { $curMask = '0'.$curMask; } $newWorld=''; $FLAG = false; for ($j=0;$j<strlen($curMask);$j++) { if(strpos($newWorld,$data[$curMask[$j]])!==FALSE) { $FLAG = true; } $newWorld .=$data[$curMask[$j]]; } if((strlen($newWorld)<count($data))or($FLAG)) { continue; }; echo $newWorld."<br>"; } ?>
PHP: <pre> <?php $arr = array('a', 'b', 'c', 'd'); $cnt = count($arr); $result = array(); calcAllCombs(); print_r($result); function calcAllCombs($letters = array(), $depth = 0) { global $arr, $cnt, $result; for($i = 0; $i < $cnt; $i++) { $letters[$depth] = $arr[$i]; if($depth < ($cnt - 1)) calcAllCombs($letters, $depth + 1); else $result[] = implode('', $letters); } } ?> </pre> работает с любым количеством буков в исходном массиве. Правда не очень хорошо то, что global, но так короче...
Спасибо за код попробую в действии. Написал сам но более примитивный, хочу тоже свой доработать может получиться. Хоть сам дойду до сути.
Задачка боянистая, делал похожее недавно (надо было пересчитывать HEX в base32 получилось по сути тоже самое) PHP: <?php $map = array('a', 'b', 'c'); $num = pow(count($map), count($map)); $result = array(); for($i=0; $i<$num; $i++) { $temp = base_convert($i,10,count($map)); $temp = str_pad($temp, count($map), "0", STR_PAD_LEFT); $temp = str_split($temp); foreach ($temp as $key=>$val) $temp[$key] = $map[$val]; $result[] = implode($temp); } ?> Это было бы комбинаторкой на Си или ASM (или даже на бейсике с паскалем) а тут все готовые функции есть, только подставь как в детском конструкторе...
Э... У меня выскакивает "Fatal error: Call to undefined function: str_split() in ...", причём на хостинге, а не на локалхосте. Это как так? Это ж вроде функция из тех, которые должны быть всегда доступны?
Мож у тебя на хостинге РНР4 ? Функция появилась в Код (Text): Version 5.0.0 Beta 1 29-Jun-2003 © http://www.php.net/ChangeLog-5.php
Да эти функции вроде и в php4 были доступны...? Хостюсь на sweb.ru, сайт древний (с 2004-го года там висит), не знаю какой php был тогда, но даже если 4, то наверняка обновляли же они потом с выходом пятого...