Как мне сгенерировать все возможные расположения строк строки (x) над строками (y) в PHP?

Я пытаюсь написать функцию, которая принимает следующие 2 параметра:

  1. Предложение как строка
  2. Количество строк в виде целого числа

Итак, если бы я позвонил formatLines («Меня зовут Гэри», 2); ...

Возможные результаты:

  • array («Меня зовут», «Гэри»);
  • array («Меня зовут», «это Гэри»);
  • array ("Мой", "зовут Гэри");

Он вернет: array («Меня зовут», «это Гэри»);, потому что разница в количестве символов для каждой строки настолько мала, насколько это возможно.

Итак, часть, на которой я в конечном итоге застрял, - это создание массива возможных результатов, в котором слова находятся в правильном порядке, разделенные на x строк. Как только у меня будет набор возможных результатов, я смогу определить лучший результат.

Итак, как мне создать все возможные комбинации?

С Уважением

Джо

перестановки - это слово, которое вы ищете.

Tschallacka 22.03.2018 16:08

«потому что разница в количестве символов для каждой строки настолько мала, насколько это возможно» - это то, чего вы хотите достичь?

NoOorZ24 22.03.2018 16:10

я думаю, вы найдете то, что ищете, в этом посте: stackoverflow.com/questions/5506888/…

wayneOS 22.03.2018 16:10

@ NoOorZ24 да, я хочу, чтобы функция возвращала комбинацию, в которой средняя разница в количестве символов для каждой строки минимальна.

Joeseppi 22.03.2018 16:16

Спасибо @wayneOS, но это не поможет, так как возможные перестановки должны быть в правильном порядке слов

Joeseppi 22.03.2018 16:18

Разница в длине строки или разнице в количестве слов?

Anthony 22.03.2018 16:48

Так что для чего-то вроде «Миссисипи такой красивый», вернет ли он ["Mississippi is", "so nice"] (одинаковое количество слов) или ["Mississippi", "is so nice"] (наименьшее различие в длине строк)?

Anthony 22.03.2018 16:57

@Anthony, он должен вернуть ["Миссисипи", "это так красиво"], поскольку это наименьшая разница в длине строки. Да.

Joeseppi 22.03.2018 17:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
8
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, что создание всех возможных способов разделения текста с последующим определением лучшего было бы излишне неэффективным. Вы можете подсчитать символы и разделить их на количество строк, чтобы найти приблизительно правильное количество символов в строке.

function lineSplitChars($text, $lines) {
    if (str_word_count($text) < $lines) {
        throw new InvalidArgumentException('lines must be fewer than word count', 1);
    }

    $width = strlen($text) / $lines;                        // initial width calculation

    while ($width > 0) {

        $result = explode("\n", wordwrap($text, $width));   // generate result

        // check for correct number of lines. return if correct, adjust width if not
        $n = count($result);
        if ($n == $lines) return $result;
        if ($n > $lines) {
            $width++;
        } else {
            $width--;
        };
    }
}

Спасибо @ Don't Panic, но эта функция, если дана строка из 3 слов на 2 строки, возвращает массив с 3 словами ... функция должна возвращать только массив со счетом, таким же, как количество строк

Joeseppi 22.03.2018 16:39

Ах, да, я понимаю, как это могло случиться. Я думаю, что это все еще может работать таким образом. Я внесу поправку.

Don't Panic 22.03.2018 16:41

Спасибо за вашу помощь

Joeseppi 22.03.2018 16:42

@Joeseppi Я изменил функцию, чтобы повторить попытку с увеличенной шириной строки, пока не будет получено правильное количество строк.

Don't Panic 22.03.2018 16:57

Следует иметь в виду, что некоторые сценарии не могут быть выполнены, в частности: formatLines("Hello World", 3). Должно ли это вызвать исключение? Или вернуть массив с 2 записями? Или вернуть массив типа ["Hello", "World", ""]?

Anthony 22.03.2018 17:04

Это работает лучше, но после прохождения некоторых тестовых примеров, таких как: lineSplitChars ("hukjfbvsjvbnvlsknv j kjds", 3);, где первое слово довольно длинное, он возвращает только 2 строки!

Joeseppi 22.03.2018 17:05

@Anthony, я фактически рассмотрел это за пределами функции, чтобы определить, меньше ли количество слов, чем количество строк, а затем строк = количество слов, а затем передается в функцию.

Joeseppi 22.03.2018 17:07

@ Энтони Да, это правда. Я должен упомянуть об этом в ответе. Я не думаю, что это действительно законченный продукт. Просто идея другого способа сделать это, которую можно расширить. Тем не менее, я все же хотел бы попытаться заставить его работать. Думаю, это интересная проблема.

Don't Panic 22.03.2018 17:07

@Joeseppi О да, я думаю, он должен изменить ширину линии, если count <lines.

Don't Panic 22.03.2018 17:08

Это хорошо, но функция этого не узнает. Как бы вы хотели, чтобы он отреагировал, если бы столкнулся с таким сценарием?

Anthony 22.03.2018 17:09

@Anthony Я написал сценарий, который автоматически генерирует рекламные объявления нескольких размеров для 200+ продуктов, поэтому, учитывая размеры рекламы, у меня есть выделенный размер для названия продукта, поэтому сценарий всегда будет знать, сколько строк в нем доступно, Затем скрипт выполнит цикл по строкам, возвращаемым проблемной функцией, и применит текст к изображениям. Таким образом, в случае, если слов меньше, чем доступных строк, доступные строки, переданные в функцию, будут равны количеству слов.

Joeseppi 22.03.2018 17:15

@Joeseppi, хорошо, новая версия, ха-ха. теперь уменьшает ширину, если count <строк. Также добавлено исключение для недопустимого ввода. Не знаю, как вы хотите справиться с этим, но, по крайней мере, условие есть.

Don't Panic 22.03.2018 17:21

@ Не паникуй, ты спас мне день! Пройдены все тесты, которые я настроил. Огромное спасибо!

Joeseppi 22.03.2018 17:27

@Joeseppi отлично! Думаю, я немного недооценил сложность.

Don't Panic 22.03.2018 17:31

@ Don't Panic, ты должен увидеть, сколько у меня каракулей на бумаге благодаря моему оригинальному подходу! Я ценю вашу помощь.

Joeseppi 22.03.2018 17:45

Это действительно впечатляет. Одна из возможных ошибок заключается в том, как str_word_count определяет границы слов. Из примера в их документации fri3nd будет считаться 2 словами.

Anthony 22.03.2018 17:47

@ Энтони, спасибо! Я никогда не замечал этого в str_word_count. Возможно, было бы лучше просто подсчитать пробелы или использовать для этой части регулярное выражение. (Говоря о регулярных выражениях, вероятно, есть какой-то способ сделать все это с помощью одного preg_split или чего-то еще, что заставит этот подход выглядеть глупо. К сожалению, я не очень разбираюсь в регулярных выражениях, поэтому я даже не знаю, с чего начать.)

Don't Panic 22.03.2018 18:00

Здесь был принят ответ, но это кажется мне довольно громоздким методом решения проблемы, когда PHP уже предоставляет функцию wordwrap (), которая выполняет большую часть тяжелой работы:

 function format_lines($str, $lines)
 {
     $guess_length=(integer)(strlen($str)/($lines+1));
     do {
         $out=explode("\n", wordwrap($str, $guess_length));
         $guess_length++;
     } while ($guess_length<strlen($str) && count($out)>$lines);
     return $out;
 }

В его нынешнем виде это скорее метод грубой силы, и для очень больших входных данных лучшее решение будет использовать оптимальный поиск (добавление / удаление большего начального интервала, а затем уменьшение его в итерациях)

Мне нравится идея уменьшить длину предположения в начале с $lines+1, поэтому вам нужно только увеличить длину предположения! Это все упрощает. Это похоже на то, как будто вы говорите, что мой ответ не использует wordrap. Я неправильно понял?

Don't Panic 22.03.2018 20:19

Другие вопросы по теме