перевести номер телефона в комбинацию букв на клавиатуре телефона
Помогите пожалуйста составить функцию перевода номера телефона в во всевозможную комбинацию букв с клавиатуры телефона.
Есть к примеру номер: 2345678
Мне надо составить комбинацию букв с каждой цифрой номера телефона:
ну вот так:
adgjmpt
adgjmpu
adgjmpv
adgjmqt
adgjmqu
adgjmqv
adgjmrt
adgjmru
adgjmrv
Все комбинации с клавиатуры могу составить, а вот из номера с клавиатуры не получается.
Помогите, плиз.
1 => array('a', 'b', 'c', 'd'),
2 => array('e', 'f', 'g'),
....
);
Ну и дальше циклами перебор делать. Делов на пару строк.
и как всевозможные комбинации тоже(сделал foreach'ами)
а вот как сделать так чтобы исходя из цифр номера телефона сделать комбинации - я не понимаю(
и как всевозможные комбинации тоже(сделал foreach'ами)
а вот как сделать так чтобы исходя из цифр номера телефона сделать комбинации - я не понимаю(
UAS написал. У тебя есть многомерный массив, где ключ первого порядка - это цифра от 0 до 9... вложенный массив - массив всевозможных значений... Перебираешь в том же foreach по одному...
Хотя, возможно и рекурсивная функция была бы здесь к месту (но и поджирала бы памяти по-больше).
У тебя, как я вижу, в любом варианте должны получиться вложенные foreach'и... Сколько цифр - столько вложений foreach...
я просто изначально хтел как функцию написать.чтобы любой длины номер сжирала)
я просто изначально хтел как функцию написать.чтобы любой длины номер сжирала)
Ну, я не мегопогромист... НО функцией (+рекурсивной) было бы с точки зрения красоты кода, правильнее. Тогда бы тебе пришлось просто передавать функции номер любой длины... Главное не переусердствовать... :) А-то скормишь 12-значное число и просчет 16млн комбинаций угробит сервер.
Можно поинтересоваться о цели разработки? Не уж-то шалишь и пароль подбираешь? )
Подбирает человек красивые короткие номера, которые соответствуют каким-нибудь словам на клавиатуре. Видел в пиратских фильмах надпись "Звоните нам - наш телефон 1-800-NOCOPIES"? Вот это оно и есть
При рекурсивной функции с подобной глубиной стека (т.е. при большом кол-ве цифр) получишь ошибку.
Так что в виду отсутствия оптимизации хвостовой рекурсии (привет, Nemerle:)) в таких случаях надо все только на циклах решать.
Так что в виду отсутствия оптимизации хвостовой рекурсии (привет, Nemerle:)) в таких случаях надо все только на циклах решать.
Ну я же написал, что с точки зрения красоты )))
Кстати, как в циклах организовывается глубина в данной задаче? читается strlen и... смутно представляю себе алгоритм, который делает вложения с учетом длинны...
В общем, в 8 утра затупил что-то.
Тут по идее все решается множествами вложенных for (т.е. влоб), либо придумать какие-то графы состояний и обернуть все это дело в красивую мат.модель (громко говоря). Код будет яснее, но не факт, что быстрее.
В общем, в 8 утра затупил что-то.
Тут по идее все решается множествами вложенных for (т.е. влоб), либо придумать какие-то графы состояний и обернуть все это дело в красивую мат.модель (громко говоря). Код будет яснее, но не факт, что быстрее.
Странно, я считал 4^коль-во цифр. ведь на одной цифре максимум 4 буквы...
class num2array{
private $ret;
private $txt;
private $phone=array(
'1'=>array('.',',','?','!','\'','"','1'),
'2'=>array('a','b','c','2'),
'3'=>array('d','e','f','3'),
'4'=>array('g','h','i','4'),
'5'=>array('j','k','l','5'),
'6'=>array('m','n','o','6'),
'7'=>array('p','q','r','s','7'),
'8'=>array('t','u','v','8'),
'9'=>array('w','x','y','z','9'),
'0'=>array(' ','0'));
private function skit_happens($tmp,$pos)
{
foreach($this->phone[$this->txt[$pos]] as $zz)
{
$ttt=$tmp.$zz;
if($pos+1<strlen($this->txt))
$this->skit_happens($ttt,$pos+1);
else
$this->ret[]=$ttt;
}
}
public function run($text)
{
$this->txt=$text;
$this->ret=array();
$this->skit_happens('',0);
return $this->ret;
}
}
$a=new num2array();
$b=$a->run('123456');
for($i=0;$i<count($b);$i++)
echo $b[$i].'<br />';
?>
Рекурсивно. Максимальная глубина рекурсии равна длине текста.
1) Зачем тут ООП?
2) Почему ключи 0-9 текстовые, а не числовые
3) Зачем тут foreach?
1)незачем :) просто накидал на скорую руку.
2)а почему должны быть числовые?
3)А почемубы и нет?
Вот по просьбам трудящихся без ооп и foreach'а
$phone=array(
'1'=>array('.',',','?','!','\'','"','1'),
'2'=>array('a','b','c','2'),
'3'=>array('d','e','f','3'),
'4'=>array('g','h','i','4'),
'5'=>array('j','k','l','5'),
'6'=>array('m','n','o','6'),
'7'=>array('p','q','r','s','7'),
'8'=>array('t','u','v','8'),
'9'=>array('w','x','y','z','9'),
'0'=>array(' ','0'));
function skit_happens($text,$tmp,$pos,&$arr)
{
global $phone;
for($i=0;$i<count($phone[$text[$pos]]);$i++)
{
$ttt=$tmp.$phone[$text[$pos]][$i];
if($pos+1<strlen($text))
skit_happens($text,$ttt,$pos+1,$arr);
else
$arr[]=$ttt;
}
}
skit_happens('123456','',0,$b);
for($i=0;$i<count($b);$i++)
echo $b[$i].'<br />';
?>
//Субьективно - отрабатывают скриты одинаковое время для 10-зачного номера.
2) На будущее - count лучше вынести за пределы цикла иначе при каждой итерации вновь и вновь эта конструкция будет вызываться
for($i=0; $i<$cnt; $i++)
{
/* БЛОК КОДА */
}
То же самое касается strlen($text) - зачем вы ее вызываете на каждой итерации? До входа в цикл один раз вычисляем длину и все.
Код правильный, но пахнет немного. Вам нужно прокачать знания касающиеся оптимизации.
1) да помоему без разницы
2) согласен, поэтому изначально и делал с ооп, чтобы все переменные, нужные только для данной задачи были внутри класса а не в глобале или статике
Да, это говнокод. Но это рабочее решение задачи, которая мне нафиг ненужна:) А оптимизации нет предела....
$num2letter = array(
2 => array('a', 'b', 'c'),
3 => array('d', 'e', 'f'),
4 => array('g', 'h', 'i'),
5 => array('j', 'k', 'l'),
6 => array('m', 'n', 'o'),
7 => array('p', 'q', 'r', 's'),
8 => array('t', 'u', 'v'),
9 => array('w', 'x', 'y', 'z')
);
$number_string = '2345678';
$len = strlen($number_string);
$current_letter = array();
for ($i = 0; $i < $len; $i++)
$current_letter[] = 0;
while ($current_letter[0] < count($num2letter[intval($number_string{0})])) {
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $num2letter[intval($number_string{$i})][$current_letter[$i]];
if ($i == $len-1) {
$current_letter[$i]++;
for ($j = $i; $j > 0; $j--) {
if ($current_letter[$j] >= count($num2letter[intval($number_string{$j})])) {
$current_letter[$j] = 0;
if ($j > 0)
$current_letter[$j-1]++;
}
}
}
}
echo $str.'<br/>';
}
?>
class num2array{
private $ret;
private $txt;
private $len;
private $phone=array(
1=>array('.',',','?','!','\'','"','1'),
2=>array('a','b','c','2'),
3=>array('d','e','f','3'),
4=>array('g','h','i','4'),
5=>array('j','k','l','5'),
6=>array('m','n','o','6'),
7=>array('p','q','r','s','7'),
8=>array('t','u','v','8'),
9=>array('w','x','y','z','9'),
0=>array(' ','0'));
private function skit_happens($tmp,$pos)
{
$a=$this->phone[$this->txt[$pos]];
$b=$pos+1;
$c=count($a);
for($i=0;$i<$c;$i++)
{
$ttt=$tmp.$a[$i];
if($b<$this->len)
$this->skit_happens($ttt,$b);
else
$this->ret[]=$ttt;
}
}
public function run($text)
{
$this->txt=$text;
$this->ret=array();
$this->len=strlen($text);
$this->skit_happens('',0);
return $this->ret;
}
}
$a=new num2array();
$time_start = microtime(1);
$b=$a->run('0501234567');
$time_end = microtime(1);
$time = $time_end - $time_start;
$counter=count($b);
echo "Found $counter in $time seconds<br />";
//for($i=0;$i<count($b);$i++)
//echo $b[$i].'<br />';
?>
Такой отрабатывает у мя на ноуте в среднем за 1.03 сек (без ооп - с постоянным вычислением strlen и count в среднем за 1.55 сек). А вариант Александа в среднем за 13.8 сек.
А заменив в варианте Александра конструкции вида intval($number_string{$j}) на $number_string[$i] скорость возросла до 7 секунд:)
А заменив в варианте Александра конструкции вида intval($number_string{$j}) на $number_string[$i] скорость возросла до 7 секунд
[/QUOTE]
Ну это уже вопросы к конкретному языку PHP. :)
А вообще, насчет скорости работы, - мне сдается, что без рекурсии вряд ли можно получить что-то существенно быстрее. Нам ведь нужно реализовать полный перебор, а перебор по определению - операция медленная.
$num2letter=array(
1=>array('.',',','?','!','\'','"','1'),
2=>array('a','b','c','2'),
3=>array('d','e','f','3'),
4=>array('g','h','i','4'),
5=>array('j','k','l','5'),
6=>array('m','n','o','6'),
7=>array('p','q','r','s','7'),
8=>array('t','u','v','8'),
9=>array('w','x','y','z','9'),
0=>array(' ','0'));
$number_string = '0501234567';
$time_start = microtime(1);
$len = strlen($number_string);
$current_letter = array();
$ff=array();
$pp=array();
for ($i = 0; $i < $len; $i++)
{
$current_letter[] = 0;
$ff[]=count($num2letter[$number_string[$i]]);
$pp[]=$num2letter[$number_string[$i]];
}
$counter=0;
$gg=$ff[$number_string[0]];
$aa=$len-1;
while ($current_letter[0] < $gg) {
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $pp[$current_letter[$i]];
}
$current_letter[$aa]++;
if($current_letter[$aa]>=$ff[$aa]);
for ($j = $aa; $j && ($current_letter[$j]>=$ff[$j]); $j--) {
$current_letter[$j] = 0;
$current_letter[$j-1]++;
}
$counter++;
//echo $str.'<br/>';
}
$time_end = microtime(1);
$time = $time_end - $time_start;
echo "Found $counter in $time seconds<br />";
?>
Отрабатывает теперь в среднем за 2.2 сек:)