За последние 24 часа нас посетили 36947 программистов и 7019 роботов. Сейчас ищут 1587 программистов ...

Наши любимые алгоритмы.

Тема в разделе "PHP для новичков", создана пользователем Dayken, 25 дек 2022.

  1. Dayken

    Dayken Новичок

    С нами с:
    4 окт 2020
    Сообщения:
    23
    Симпатии:
    0
    Всем добрый вечер, кому то добрый день, а кому то возможно и утро)
    Я застрял на задаче. Есть массив. Допустим ["волк","волейбол","восток"]
    Далее в чем же суть задачи? Нужно найти у слов данного массива общую часть в данном случае это "во". Звучит то просто, а вот на деле уже часа 2 сижу и мыслей ноль. Перебирать каждую букву как вариант, но реализацию этого тоже сложно сделать, что если общая часть у одного слова начинается с начала слова а у второго с конца или в центре. Накидайте идей))
     
  2. dantemgs

    dantemgs Новичок

    С нами с:
    24 дек 2022
    Сообщения:
    47
    Симпатии:
    9
    Можно упростить до перебора из массива с наименьшей длинной. Наверно, регулярки надо писать.
     
  3. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.543
    Симпатии:
    623
    Имеется ввиду именно общая часть вначале слова?
     
  4. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.874
    Симпатии:
    753
    Адрес:
    Татарстан
    Берём самое короткое слово в массиве
    Из него формируем перебором всевозможные части, типа первый символ с 0 позиции, два символа итд, потом переходим к 1 позиции где точно так же, цикл в цикле... Каждое полученное сочетание проверяем на вхождени во всё слова массива
     
    [vs] нравится это.
  5. dantemgs

    dantemgs Новичок

    С нами с:
    24 дек 2022
    Сообщения:
    47
    Симпатии:
    9
    1) Нашел минимальную строку в массиве, если несколько одинаковых, берем любую.
    2) Не забыл установить php_mbstring.dll, чтобы работать с русским текстом (кому я вру?)
    3) Решил найти все возможные шаблоны для регулярок из той самой строки с 1-го пункта.
    4) Для создания шаблонов иду от всех символов по убыванию, заменяя символы на ".*". Хочу для этого использовать substr_replace (), но для работы с русским текстом нету mb_substr_replace() - значит пишу такую функцию (гуглю в инете). Вспоминаю как делать рекурсию.
    5) Не забываю добавить в массив с шаблонами строку из 1-го пункта (почему-то делаю это вне функции (потому что криворук)).
    6) Чищу массив с шаблонами от дубликатов и 1-го мусорного шаблона. Как он там оказался? (смотри комментарий пункта 5).
    7) Использую все шаблоны в регулярках, там нахожу по всем строкам из начального условия совпадения и кидаю эти шаблоны в отдельный массив.
    8) Нахожу шаблоны, в которых у меня меньше всего ".*", а значит там самое длинное совпадение. Вывожу этот массив.

    Для интереса к "волейбол" добавил в конце символ "к".
    Собственно вот мое чудовище, но зато работает (пока лень полировать, и вообще готовое решение для слабых):
    PHP:
    1. <?php
    2. $having_arr = ["волк", "волейболк", "восток"];
    3.  
    4. if (!function_exists('mb_substr_replace')) {
    5.     function mb_substr_replace($original, $replacement, $position, $length)
    6.     {
    7.         $startString = mb_substr($original, 0, $position, 'UTF-8');
    8.         $endString = mb_substr($original, $position + $length, mb_strlen($original), 'UTF-8');
    9.         $out = $startString . $replacement . $endString;
    10.         return $out;
    11.     }
    12. }
    13.  
    14. function get_min_str_in_arr($arr)
    15. {
    16.     $str = $arr["0"];
    17.     for ($i = count($arr) - 1; $i > 0; $i--) {
    18.         if (!is_string($arr[$i])) {
    19.             continue;
    20.         };
    21.         if (mb_strlen($arr[$i]) <= mb_strlen($str)) {
    22.             $str = $arr[$i];
    23.         };
    24.     };
    25.     return $str;
    26. };
    27.  
    28. function find_math($pattern, $str)
    29. {
    30.     return preg_match("/$pattern/iu", $str);
    31. };
    32.  
    33. function is_math_all($maths_arr)
    34. {
    35.     $boolean = 1;
    36.     for ($i = 0; $i < count($maths_arr); $i++) {
    37.         $boolean = $boolean * $maths_arr[$i];
    38.     }
    39.     return $boolean;
    40. }
    41.  
    42. function get_all_pattern($str, $patterns_arr)
    43. {
    44.     if ($str == ".*.*.*.*") {
    45.         return $patterns_arr;
    46.     }
    47.     for ($i = mb_strlen($str) - 1; $i >= 0; $i--) {
    48.         if (mb_substr($str, $i, 1, "UTF-8") == "." || mb_substr($str, $i, 1, "UTF-8") == "*") {
    49.             continue;
    50.         }
    51.         $replaced_str = mb_substr_replace($str, ".*", $i, 1);
    52.         array_push($patterns_arr, $replaced_str);
    53.         $patterns_arr = get_all_pattern($replaced_str, $patterns_arr);
    54.     }
    55.     return get_all_pattern($replaced_str, $patterns_arr);
    56. }
    57.  
    58. function clean_pattern($arr)
    59. {
    60.     $arr = array_unique($arr);
    61.     $cleaned_arr = [];
    62.     $i = 0;
    63.     foreach ($arr as $key => $value) {
    64.         //Удаляю плохой шаблон для регулярки, лень доводить до ума, чтобы она туда не попадала.
    65.         if ($value == ".*.*.*.*") {
    66.             unset($arr[$key]);
    67.             $i++;
    68.             continue;
    69.         }
    70.         $cleaned_arr[$i] = $arr[$key];
    71.         $i++;
    72.     }
    73.     return $cleaned_arr;
    74. }
    75.  
    76. function find($having_arr, $patterns_arr)
    77. {
    78.     $almost_end = [];
    79.     foreach ($patterns_arr as $pattern) {
    80.         $maths_arr = [];
    81.         foreach ($having_arr as $key => $having_str) {
    82.             array_push($maths_arr, find_math($pattern, $having_str));
    83.         };
    84.         if (is_math_all($maths_arr)) {
    85.             array_push($almost_end, $pattern);
    86.         }
    87.     }
    88.     return $almost_end;
    89. }
    90. function end_this($arr)
    91. {
    92.     $end_arr = [];
    93.     $nubmer_arr = [];
    94.     foreach ($arr as $key => $value) {
    95.         $new_value = preg_match_all("/\.\*/", $value);
    96.         array_push($nubmer_arr, $new_value);
    97.     }
    98.  
    99.     $min = min($nubmer_arr);
    100.  
    101.     foreach ($arr as $key => $value) {
    102.         if (preg_match_all("/\.\*/", $value) == $min) {
    103.             array_push($end_arr, $value);
    104.         }
    105.     }
    106.     return $end_arr;
    107. }
    108.  
    109. $min_str = get_min_str_in_arr($having_arr);
    110. $patterns_arr = get_all_pattern($min_str, $patterns_arr = []);
    111. array_unshift($patterns_arr, $min_str);
    112. $patterns_arr = clean_pattern($patterns_arr);
    113. $almost_end_arr = find($having_arr, $patterns_arr);
    114.  
    115. var_dump(end_this($almost_end_arr));
     
  6. dantemgs

    dantemgs Новичок

    С нами с:
    24 дек 2022
    Сообщения:
    47
    Симпатии:
    9
    Причесал:
    PHP:
    1. <?php
    2. $having_arr = ["волк", "волейболк", "восток"];
    3.  
    4. if (!function_exists('mb_substr_replace')) {
    5.     function mb_substr_replace($original, $replacement, $position, $length)
    6.     {
    7.         $startString = mb_substr($original, 0, $position, 'UTF-8');
    8.         $endString = mb_substr($original, $position + $length, mb_strlen($original), 'UTF-8');
    9.         $out = $startString . $replacement . $endString;
    10.         return $out;
    11.     }
    12. }
    13.  
    14. function get_min_str_in_arr($arr)
    15. {
    16.     $str = $arr["0"];
    17.     for ($i = count($arr) - 1; $i > 0; $i--) {
    18.         if (mb_strlen($arr[$i]) <= mb_strlen($str)) {
    19.             $str = $arr[$i];
    20.         };
    21.     };
    22.     return $str;
    23. };
    24.  
    25. function get_all_pattern($str, $patterns_arr, $max_str_replaced)
    26. {
    27.     if (preg_match_all("/\.\*/iu", $str) == $max_str_replaced) {
    28.         return $patterns_arr;
    29.     }
    30.     for ($i = mb_strlen($str) - 1; $i >= 0; $i--) {
    31.         if (mb_substr($str, $i, 1, "UTF-8") == "." || mb_substr($str, $i, 1, "UTF-8") == "*") {
    32.             continue;
    33.         }
    34.         $replaced_str = mb_substr_replace($str, ".*", $i, 1);
    35.         array_push($patterns_arr, $replaced_str);
    36.         $patterns_arr = get_all_pattern($replaced_str, $patterns_arr, $max_str_replaced);
    37.     }
    38.     return get_all_pattern($replaced_str, $patterns_arr, $max_str_replaced);
    39. }
    40.  
    41. function clean_pattern($arr)
    42. {
    43.     $arr = array_unique($arr);
    44.     //Rename key after deleting doubles
    45.     $cleaned_arr = [];
    46.     $i = 0;
    47.     foreach ($arr as $key => $value) {
    48.         $cleaned_arr[$i] = $arr[$key];
    49.         $i++;
    50.     }
    51.     return $cleaned_arr;
    52. }
    53.  
    54. function find_math($pattern, $str)
    55. {
    56.     return preg_match("/$pattern/iu", $str);
    57. };
    58.  
    59. function is_math_all($maths_arr)
    60. {
    61.     $boolean = 1;
    62.     for ($i = 0; $i < count($maths_arr); $i++) {
    63.         $boolean = $boolean * $maths_arr[$i];
    64.     }
    65.     return $boolean;
    66. }
    67.  
    68. function find_the_same($having_arr, $patterns_arr)
    69. {
    70.     $almost_end = [];
    71.     foreach ($patterns_arr as $pattern) {
    72.         $maths_arr_boolean = [];
    73.         foreach ($having_arr as $key => $having_str) {
    74.             array_push($maths_arr_boolean, find_math($pattern, $having_str));
    75.         };
    76.         if (is_math_all($maths_arr_boolean)) {
    77.             array_push($almost_end, $pattern);
    78.         }
    79.     }
    80.     return $almost_end;
    81. }
    82.  
    83. function end_this($arr)
    84. {
    85.     $end_arr = [];
    86.     $nubmer_arr = [];
    87.     foreach ($arr as $key => $value) {
    88.         $new_value = preg_match_all("/\.\*/iu", $value);
    89.         array_push($nubmer_arr, $new_value);
    90.     }
    91.  
    92.     $min = min($nubmer_arr);
    93.  
    94.     foreach ($arr as $key => $value) {
    95.         if (preg_match_all("/\.\*/iu", $value) == $min) {
    96.             array_push($end_arr, $value);
    97.         }
    98.     }
    99.     return $end_arr;
    100. }
    101.  
    102. $min_str = get_min_str_in_arr($having_arr);
    103. $max_str_replaced = mb_strlen($min_str) - 1;
    104. $patterns_arr = get_all_pattern($min_str, $patterns_arr = [], $max_str_replaced);
    105. array_push($patterns_arr, $min_str);
    106. $patterns_arr = clean_pattern($patterns_arr);
    107. $almost_end_arr = find_the_same($having_arr, $patterns_arr);
    108. var_dump(end_this($almost_end_arr));
     
    Dayken нравится это.
  7. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    dantemgs нравится это.
  8. dantemgs

    dantemgs Новичок

    С нами с:
    24 дек 2022
    Сообщения:
    47
    Симпатии:
    9
    Тут поиск общих символов только подряд. Решение красивое. Я так понимаю, поиск по ключам происходит намного быстрее?


    Через глобальную переменную моя рекурсия простая и понятная становится:
    PHP:
    1. function get_all_pattern($str, $max_str_replaced)
    2. {
    3.     if (preg_match_all("/\.\*/iu", $str) == $max_str_replaced) {
    4.         return;
    5.     }
    6.     for ($i = mb_strlen($str) - 1; $i >= 0; $i--) {
    7.         if (mb_substr($str, $i, 1, "UTF-8") == "." || mb_substr($str, $i, 1, "UTF-8") == "*") {
    8.             continue;
    9.         }
    10.         $replaced_str = mb_substr_replace($str, ".*", $i, 1);
    11.         array_push($GLOBALS["patterns_arr"], $replaced_str);
    12.         get_all_pattern($replaced_str, $max_str_replaced);
    13.     }
    14. }
    15. $max_str_replaced = mb_strlen($min_str) - 1;
    16. $patterns_arr = [];
    17. get_all_pattern($min_str, $max_str_replaced);