Добрый день. Устраивался я на работу программистом на удаленке. Мне прислали тест для проверки моих проф. знаний. Мне требовалось решить 18 задач и отправить результат работы обратно по почте.
Пока решал тест пришлось пару задач я пропустить. В них я не до конца понимал, что требуется.
Итог — я не прошел тест, мне сказали, что у меня слабые знания регулярных выражений.
Если кому-то пригодится моя работа буду рад.
Если что-то не понятно, пишите комменты.
1. Дан набор чисел. Необходимо найти в нём все числа меньше 4.
Пример: 1 0 2 9 3 8 4 7 5 6 8 9 10 11 -1 -65 432 3 74
Здесь при решении я не использовал регулярные выражения
$var_txt = explode(" ", $txt);
foreach ($var_txt as $key => $value)
{
if ($value < 4)
echo ‘ , ‘.$value.’ ‘;
}
//Решение: , 1 , 0 , 2 , 3 , -1 , -65 , 3
[/php]
2. Дана строка произвольной длины. В строке перечислены разнообразные символы, буквы разных алфавитов и прочее. Необходимо получить все буквы русского алфавита, а также все числа от 0 до 6.
Пример: 4504569ук432534345345890456.43=3503245axc4521kdx230k023то94о289076с2
$str = iconv(‘windows-1251′,’utf-8’,$str); // у меня не понимал русские пока не преобразовал. Работал в денвере WIN7x64
preg_match_all("/[0-6А-Яа-я]/",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
echo ‘ , ‘.$value;
}
//результат
//Решение: , 4 , 5 , 0 , 4 , 5 , 6 , С , Р , 4 , 3 , 2 , 0 , 4 , 5 , 6 , 4 , 3 , 3 , 2 , 4 , 5 , 4 , 5 , 2 , 1 , 2 , 3 , 0 , 0 , 2 , 3 , С , Р , 4 , Р , 2 , 0 , 6 , С , 2
[/php]
3. Дана строка произвольной длины, состоящая из одинаковых символов. Требуется написать два рег. выражения, которые бы возвращали первый символ и всю строку, соответственно.
Пример: «11111111111111».
preg_match("/.{1}/",$str, $res);
echo ‘ Первый символ: ‘.$res[0];
preg_match("/.*/",$str, $res);
echo ‘ Вся строка: ‘.$res[0];
[/php]
4. Дана строка «a1 b3 a8 c2 a9 d7 a4 e5 a3 f8 a0 g1».
Требуется написать ОДНО регулярное выражение, которое бы сматчило только числа согласно следующему условию: если перед числом стоит буква «a», то это число должно быть меньше 5, иначе – больше либо равно 5.
НЕ РЕШЕНО
5. Дана произвольная html-страница, необходимо получить содержимое всех тегов div, внутри которых находится минимум 5 подряд идущих цифр.
[php] //Например: "<div>asd 764 1234457 абвы</div>
<div>asd абвы</div>
<div>asd 764 1257 абвы</div>
".
$str = ‘
<div>asd 764 1234457 абвы</div>
<div>asd абвы</div>
<div>asd 764 1257 абвы</div>
‘;
preg_match_all("!
<div>(.*?[0-9]{5}.*?)</div>
!",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
echo ‘ , ‘.$value;
}
//Решение: , asd 764 1234457 абвы
[/php]
6. Дан текст. Необходимо найти в нём все слова, состоящие из 5 букв.
Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала».
//$str = iconv(‘windows-1251′,’utf-8’,$str);
$str = ‘ ‘.$str.’ ‘; //Добавил пробелы
$str = str_replace(" ", " ", $str);
preg_match_all("/\s([а-я]{5})\s/",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
echo ‘ , ‘.$value;
}
/*
Решение: , дождь , школа , арбуз , бутан , город , шпала
*/
[/php]
7. Дано множество строк (каждая строка – с новой строки), состоящих из чисел, разделённых пробелом. Необходимо найти все строки, в которых 5-е число было бы таким же, как и 18-е, а также являлось бы чётным числом и было больше 9.
[php] //имеем набор чисел 1-15 в виде нескольких строк$str = ’10 12 6 14 10 4 7 3 4 10 10 7 1 11 11 2 14 10 14 8 8 15 2 7 14 9 12 13 15 2
11 8 7 7 12 4 3 7 3 2 8 3 5 6 1 6 12 2 14 5 12 14 6 3 4 8 5 15 10 13
12 6 13 1 10 2 14 3 13 7 5 9 2 5 3 14 8 10 2 13 8 5 8 11 2 11 9 15 6 5
14 2 6 15 12 7 6 7 2 5 1 9 13 2 9 15 2 10 12 14 4 6 15 2 6 10 14 10 14 13
2 7 10 5 15 7 3 6 9 7 7 4 14 9 7 15 6 1 11 4 10 2 1 7 4 9 14 11 1 2
8 6 13 1 5 10 8 14 7 10 3 6 7 14 11 4 10 2 4 2 1 2 1 5 9 13 15 6 15 14
‘;
//получил все строки
preg_match_all ("/(.*?)\n/", $str,$res);
foreach ($res[0] as $value)
{
//разбиваю строку на числа
preg_match_all ("/\s?[0-9]*\s/", $value,$num_array);
$var5 = (int)$num_array[0][4];
$var18 = (int)$num_array[0][17];
//строка, в которой 5-е число такоеже как и 18-е, и больше 9 и оно четное
if ($var5 == $var18 and $var5 > 9 and ($var5%2)==0)
{
echo ‘
‘.$value;
}
}
//результат работы
/*
10 12 6 14 10 4 7 3 4 10 10 7 1 11 11 2 14 10 14 8 8 15 2 7 14 9 12 13 15 2
12 6 13 1 10 2 14 3 13 7 5 9 2 5 3 14 8 10 2 13 8 5 8 11 2 11 9 15 6 5
*/
8. Дан текст. Необходимо найти в нём все слова, содержащие букву «а».
Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала».
preg_match_all("/\s*[а-я]*\s?/",$str, $res); //нашел все слова в строке
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
if (strrpos($value, ‘а’) == true) // ищем букву
echo ‘ , ‘.$value;
}
/*
Решение: , лопата , два , школа , стройка , голова , бутан , шпала
*/
[/php]
9. Дана строка, содержащая имя человека, и дано регулярное выражение: «/(?#Имя)[А-Я][а-я]+\s(?#Отчество)[А-Яа-я]+\s(?#Фамилия)(?:[а-я]+)/». Необходимо изменить последнюю подмаску (следующую за комментарием «Фамилия») так, чтобы регулярное выражение сработало и вернуло бы всю строку (изменять или добавлять символьные классы нельзя).
Пример имени: «Иван Семенович Петров».
[php] echo ‘Решение: "/(?#Имя)[А-Я][а-я]+\s(?#Отчество)[А-Яа-я]+\s(?#Фамилия)(?[а-я]+)/" ‘;
[/php]
10. Дан текст. Требуется написать регулярное выражение, которое бы матчило все строки, НЕ начинающиеся с числа «2».
[php] //Пример текста:1 http://www.yandex.ru
2 http://lenta.ru
3 www.google.com
02 facebook.com
36 twitter.com
12 www.imdb.com
1 blizzard.com
2 http://kinopoisk.ru
21 ozon.ru
0029 http://www.bicotender.ru’;
[/php]
НЕ РЕШЕНО
11. Дан набор тегов, необходимо получить содержимое всех тегов div, которые НЕ вложены в другие теги div. Учесть, что в тег div может быть вложено неограниченное количество других тегов div (рекурсивно) – требуется получить всё содержимое самого внешнего тега div.
Пример текста:
[html]
<div>Блок1</div>
<div style="display:none;">Блок2</div>
<div><h1>Заголовок</h1>Блок3</div>
<table>
<tr><td>
<div>Вложенный
<div>блок
<div>4</div>
</div>
и ещё чуть-чуть.
</div>
</td>
</tr>
</table>’;
[/html]
[php]
//Решить можно было бы используя http://simplehtmldom.sourceforge.net/
//подгружаем библиотеку
//require_once ‘library/simplehtmldom.php’;
//создаём новый объект
//$html = new simple_html_dom();
//загружаем в него данные
//$html = file_get_html($str2);
//Ищем все
<div>
//$ret = $html->find(‘div’);
//пример можно глянуть тут http://web2033.com/parsing-php-simple-html-dom/
//но я использовал свой алгоритм + регулярные выражения
// исходная строка из задания для работы
$str2 = ‘
<div>Блок1</div>
<div style="display:none;">Блок2</div>
<div>
<h1>Заголовок</h1>
блока3</div>
<table>
<tr>
<td>
<div>
Вложенный
<div>
блок
<div>4</div>
</div>
и ещё чуть-чуть.</div>
</td>
</tr>
</table>’;
//echo $str2;
$str2 = str_replace(" style=\"display:none;\"", "",$str2); //убираю стиль
// находим все дивы
preg_match_all("/
<div>
/",$str2, $res);
$id = 0; // количество блоков div
$pos = 0; // позиция
//пронумеруем их <div1> <div2> и т.д. но закрывающие теги не трогаем
foreach ($res[0] as $value)
{
$id++;
$pos = strpos($str2,’
<div>
‘); // смотрю позицию где тег в строке
$str2 = substr_replace($str2,'<div’.$id.’>’,$pos,5); // вставляю на его место тег с номером
}
//echo $str2;
// ЗАДАЧА необходимо получить содержимое всех тегов
//<div>
//, которые НЕ вложены в другие теги
//<div>
// все просто надо найти дивы по номерам <div1..> и содержимым в котором нет других тегов DIV. Закрываются они также тегом </div>
for ($i = 1; $i <= $id; $i++){
preg_match_all("!<div".$i.">.*?</div>
!",$str2, $res);
foreach ($res[0] as $value)
{
$count = substr_count ($value,'<div’); //смотрю сколько div у нас есть. Если 1 то нет вложенных
if ($count == 1)
echo ‘ , ‘.$value;
}
}
//Результат работы: <div1>Блок1</div>
, <div2>Блок2</div>
, <div3>
<h1>Заголовок</h1>
блока3</div>
, <div6>4</div>
// ЗАДАЧА требуется получить всё содержимое самого внешнего тега
//<div>. Я так понимаю это Див в котором Максимальное количество вложенных DIV
// если нет, то я не верно решил
$counter = 0; // для запоминания макс количества
$number = 0; // номер тега с максимальным вложением тегов
for ($i = 1; $i <= $id; $i++){
preg_match_all("!<div".$i.">.*?</div>
*?.*?</div>
*?.*?!",$str2, $res);
foreach ($res[0] as $value)
{
$count = substr_count ($value,'<div’); //смотрю сколько div у нас есть. Если 1 то нет вложенных
if ($counter<=$count)
{
$counter = $count;
$number = $i;
}
}
}
echo ‘Div с номером ‘.$number.’ имеет ‘.($counter-1).’ вложенных Div’;
//Div с номером 4 имеет 2 вложенных Div
//
<div>
Вложенный
<div>
блок
<div>4</div>
</div>
и ещё чуть-чуть.</div>
//Ну и выведем его на экран
preg_match_all("!<div".$number.">.*?</div>
*?.*?</div>
*?.*?!",$str2, $res);
echo ‘
‘.$res[0][0];
//Можно было конечно удалить все лишние теги по краям, но я оставил для наглядности
[/php]
12. Дана html страница сблоками:
Блок 1Внутренний блок 1
|
Блок 2Какой-то текст 2 |
Какой-то текст 3 Блок 3Внутренний блок 3
|
Требуется получить содержимое всех блоков, внутри которых нет других блоков div.
Регулярное выражение должно отрабатывать быстро даже при очень большой вложенности тегов.’;
[php]
$str2 =’ //строка с html кодом
<table>
<tbody>
<tr>
<td>
<div>
<h1>Блок 1</h1>
<div>Внутренний блок 1</div>
</div></td>
<td>
<div>
<h1>Блок 2</h1>
Какой-то текст 2
</div></td>
</tr>
<tr>
<td>
<div>
Какой-то текст 3
<h1>Блок 3</h1>
<div><strong>Внутренний блок</strong> 3</div>
</div></td>
</tr>
</tbody>
</table>
‘;
// находим все дивы
preg_match_all("/
<div>
/",$str2, $res);
$id = 0; // количество блоков div
$pos = 0; // позиция
//пронумеруем их и т.д. но закрывающие теги не трогаем
foreach ($res[0] as $value)
{
$id++;
$pos = strpos($str2,’
<div>’); // смотрю позицию где тег в строке
$str2 = substr_replace($str2,’<div’.$id.’>’,$pos,5); // вставляю на его место тег с номером
}//echo $str2;
// ищу div без вложений
for ($i = 1; $i <= $id; $i++){
preg_match_all("!<div".$i.">.*?
</div>
!",$str2, $res);
foreach ($res[0] as $value)
{
$count = substr_count ($value,’<div’); //смотрю сколько div у нас есть. Если 1 то нет вложенных
if ($count == 1)
echo ‘ , ‘.$value;
}
}
//результат работы
//Внутренний блок 1
</div>
, <strong>Внутренний блок</strong> 3
</div>
//также div`ы не вырезал для наглядности результата
[/php]
13. Дан текст. Необходимо найти в нём все слова, состоящие из 5 букв и содержащие букву «а».
Пример текста: «дождь лопата два школа арбуз стройка пять дом голова бутан город шпала»‘;
[php]
$str = ‘дождь лопата два школа арбуз стройка пять дом голова бутан город шпала’;
$str = ‘ ‘.$str.’ ‘; //Добавил пробелы
$str = str_replace(" ", " ", $str);
preg_match_all("/\s([а-я]{5})\s/",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
if (strrpos($value, ‘а’) == true) // ищем букву
echo ‘ , ‘.$value;
}
//Решение: , школа , арбуз , бутан , шпала
[/php]
14. Дан текст. Необходимо найти все предложения, в которых НЕ встречается слово «два». Предложения разделены точками. Точка используется исключительно как знак окончания предложения. Все предложения начинаются с заглавной буквы и больше заглавных букв в себе не содержат.
Пример текста:
Два на два – четыре. Три на три – девять. Два на четыре – восемь. Четыре на пять – двадцать. Восемь на два – шестнадцать. Семь на восемь – пятьдесят шесть. Шесть на четыре – двадцать четыре. Пять на два – десять.
preg_match_all("/([А-Я])(.*?)\./",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
echo ‘
‘.$value;
}
/*
Решение:
Два на два – четыре.
Три на три – девять.
Два на четыре – восемь.
Четыре на пять – двадцать.
Восемь на два – шестнадцать.
Семь на восемь – пятьдесят шесть.
Шесть на четыре – двадцать четыре.
Пять на два – десять.
*/
[/php]
15. Дан html. Необходимо получить содержимое всех тегов «P», которые находятся в закомментированных блоках.
[php]
//готовим данные
$str = ‘
Комментарий в html коде
<!—
комментарий .
еще один.
—>
<!—
коммент 3 .
четвертый 4.
—>
‘;
//данный пример работает если комментарий умещен в одну строку
//получаем комментарии
preg_match_all("/<!—(.*?)—>/",$str, $res);
$p = »;
foreach ($res[0] as $value)
{
//получаем содержимое тега P
preg_match_all("!
(.*?)
!",$value, $p);
foreach ($p[0] as $teg_p)
{
echo ‘
‘.strip_tags($teg_p, »);
}
}
/*
РЕШЕНИЕ:
комментарий .
еще один.
коммент 3 .
четвертый 4.
*/
[/php]
16. Дан SQL-запрос SELECT с непредсказуемым форматированием, но валидный. Получить в одну строку список всех столбцов, выбираемых запросом (звездочку преобразовывать в имена не нужно: все равно не получится). Учесть, что в именах столбцов могут быть такие вещи, как from, join, `inner join` и даже `from from from join cross outer from`’;
надо найти все что между select и последним словом FROM.
как правила имена задаются ковычками рядом с выбираемым столбцом, но и столбец может быть c ковычками, также между ними ОБЯЗАН быть пробел.
[php]
//пример запроса SELECT f1 `from`, `f2` `join`, f3 `inner join`, f4 `from from from join cross outer from` FROM users;
$str = "SELECT f1 `from`,`f2` `join`,f3 `inner join`,f4 `from from from join cross outer from` FROM users;";
//$str = str_replace(" `", "
", $str);
//echo ‘
‘.$str;
preg_match_all("/(^`.*?`)?\s`(.*?)`/",$str, $res);
foreach ($res[0] as $value)
{
echo ‘
‘.$value;
}
/*результат работы
`from`
`join`
`inner join`
`from from from join cross outer from`
*/
[/php]
17. Дан html с множеством тегов. Требуется проверить, имеет ли каждый тег соответствующую закрывающуюся пару либо, если тег одиночный, оканчивается ли он на «/>». Html-комментарии, а также конструкции вида 123”> можно не учитывать.
[php]
// проверять будем
<div></div>
<h1></h1>
т.е. теги без классов
// решить данную задачу можно разными способами. Я выбрал самый простой. Так как у каждого тега должен быть закрывающий
// я решил посчитать количество тегов открывающих и закрывающих. Их должно быть одинаковое количество. Если есть расхождения значит тег либо не открыт, либо не закрыт.
// возьмем для примера этот текст"
$html =’
<table>
<tbody>
<tr>
<td>
<div>
<h1>Блок 1</h1>
<div>Внутренний блок 1
</div>
</div></td>
<td>
<div>
<h1>Блок 2</h1>
Какой-то текст 2
</div></td>
</tr>
<tr>
<td>
<div>
Какой-то текст 3
<h1>Блок 3</h1>
<div><strong>Внутренний блок</strong> 3</div>
</div></td>
</tr>
</tbody>
</table>
‘;
//найдем все открывающие теги которые есть в коде
preg_match_all("/<([a-zA-Z0-9]*)>/",$html, $res);
//убираю повторения. Для убыстрения работы. Потомучто в массиве $res несколько одних и тех же тегов. Например
$res[0] = array_unique($res[0]);foreach ($res[0] as $value)
{
//посчитаю сколько тегов есть открывающих
$begin_count_teg = substr_count ($html,$value);
//делаю из отквающего тега закрывающий
$value = str_replace("<", " $close_count_teg) //открытых больше чем закрытых
echo ‘
Тег: ‘.$value.’ необходимо проверить он не зарыт’;
}
//результат работы
//Тег:
необходимо проверить либо он не зарыт. И он действительно не закрыт в исходной строке $html.
//
//Проверяю если тег одиночный, оканчивается ли он на «/>»
//снова беру все теги только одиночные например
preg_match_all("/<([a-zA-Z0-9]*)\s/",$html, $res); $res[0] = array_unique($res[0]); // убираю лишние теги foreach ($res[0] as $value) { //найденный тег пробую найти в коде в виде правильно написанного. Если не найду значит не имеет он на концу />
$count = substr_count ($html,$value.’/>’);
if ($count<1) { echo ‘Тег: ‘.$value.’ /> Не закрыт’;
}
}
// результат работы
//Тег:
Не закрыт
18. Дан текст. Требуется ко всем конструкциям вида «(.[\w\d]+)+» присоединить произвольную подстроку. Данная конструкция может быть обрамлена с обеих сторон знаками «%»: в этом случае подстрока должна быть присоединена после первого «%» (перед первой точкой), в остальных случаях подстроку нужно присоединить просто в начало конструкции. Пример текста: «fff .key1.key4.kkk22% %.key2.key4% %.key1 key5 .key6.key7.tumba».
[php]
// исходная строка
$str = ‘fff .key1.key4.kkk22% %.key2.key4% %.key1 key5 .key6.key7.tumba’;
// рандомный текст для добавления к знаку процента %
$random_txt = md5( microtime() . mt_rand());
preg_match_all("/(%?.[\w\d]+%?)+/",$str, $res);
echo ‘
Решение: ‘;
foreach ($res[0] as $value)
{
// первое условие
// конструкция может быть обрамлена с обеих сторон знаками «%»: в этом случае подстрока должна быть присоединена после первого «%» (перед первой точкой)
// проверяем обрамлена она % или нет
if ($value[0]==’%’ and substr($value, -1)==’%’){
//подставляем в начало нашу сгенерированную строку
$value = str_replace("%.", ‘%’.$random_txt.".", $value);
}else{
// второе условие
//в остальных случаях подстроку нужно присоединить просто в начало конструкции. Что я и сделал
$value = $random_txt.$value;
}
echo ‘
‘.$value;
}
/*Результат работы
266aad662801151d58dcbdb263481f51fff
266aad662801151d58dcbdb263481f51.key1.key4.kkk22%
%266aad662801151d58dcbdb263481f51.key2.key4%
266aad662801151d58dcbdb263481f51%.key1 key5
266aad662801151d58dcbdb263481f51.key6.key7.tumba
*/
</div>
[/php]