Обоснуйте текст на Java - PullRequest
       3

Обоснуйте текст на Java

2 голосов
/ 15 декабря 2011

Мне нужно прочитать целое число, которое будет длиной последующих строк.(Строки текста никогда не будут длиннее указанной длины).

Затем я должен прочитать каждую строку текста и преобразовать пробелы в подчеркивание как можно более равномерно.Например:

Я бы ввел длину строки 30. Затем строка текста Hello this is a test string.Затем все пробелы будут преобразованы в подчеркивания и дополнены так, чтобы текст заполнял заданную длину строки следующим образом: Hello__this__is__a_test_string.Как вы можете видеть, исходный текст имел длину 27 символов, поэтому для его заполнения до 30 символов мне пришлось добавить 3 дополнительных пробела к исходному тексту, а затем преобразовать эти пробелы в символ подчеркивания.Пожалуйста, вы можете посоветовать, как я могу это сделать?

Ответы [ 9 ]

6 голосов
/ 15 декабря 2011

Что я делаю, так это делю предложение на слова. Затем выясните, сколько пробелов нужно добавить. Затем переберите слова и добавьте пробел к каждому из них, пока у вас не закончится пробел для добавления. Если у вас достаточно пробелов, где вам нужно добавить более одного слова (например, у вас есть 5 слов, но нужно добавить 13 пробелов), просто разделите количество пробелов на количество слов и добавьте это число к каждому сначала слово Затем вы можете взять остаток и перебрать слова, добавив пробел, пока не закончите. Также убедитесь, что вы добавляете только пробелы ко всем, кроме последнего слова в предложении.

4 голосов
/ 18 февраля 2014

Мне недавно пришлось сделать что-то похожее на Java. Сам код относительно прост. То, что я нашел, заняло больше всего времени, так это обдумал процесс оправдания.

Я начал с пошагового процесса выравнивания текста вручную.

  1. Узнайте, как долго линия
  2. Узнайте, какова длина строки в указанной строке
  3. Рассчитать количество пробелов, необходимых для добавления к строке, чтобы она равнялась длине строки
  4. Узнайте, сколько пробелов между словами в строке
  5. Вычислить, сколько пробелов добавить к каждому пробелу в строке
  6. Добавить результат к каждому разрыву
  7. Подсчитайте, сколько дополнительных пробелов нужно добавить к каждому пробелу последовательно (если количество пробелов не делится на количество пробелов, которые нужно добавить. Например, если у вас есть 5 пробелов и 6 пробелов для добавления)
  8. Добавить лишние пробелы к пробелам
  9. Преобразование пробелов в подчеркивания
  10. Возвращаемая строка

Делая это, я стал намного проще кодировать алгоритм!

Определение длины строки и строки в указанной строке

Вы сказали, что прочитали длину строки и текст в строке, поэтому 1 и 2 вы уже сделали. 2 - простой string.length() вызов.

Вычисление количества пробелов, необходимых для добавления к строке, чтобы она равнялась длине строки, - это просто взятие длины строки и вычитание длины строки.

lineLength - string.length() = noofspacestoadd;

Определение количества пробелов между всеми словами в строке

Вероятно, есть несколько способов сделать это. Я обнаружил, что самым простым способом сделать это было преобразование строки в тип char [], а затем итерация символов, проверяющих '', и установка счетчика для случаев, когда он находит ''

Расчет количества пробелов для добавления к каждому пробелу

Это простой расчет деления!

noofgaps / noofspacestoadd = noofspacestoaddtoeachgap;

Примечание: вы должны убедиться, что вы делаете это деление с целыми числами! При 5/2 = 2,5, поэтому вы ЗНАЕТЕ, что вы должны добавить 2 пробела к каждому пробелу между словами, а деления с использованием int пресекают десятичное число в целое число.

Добавьте результат к каждому разрыву

Прежде чем вы сможете добавить количество строк, необходимое для добавления к каждому пробелу, вам нужно преобразовать это число в строку пробелов. Таким образом, вам нужно написать метод для преобразования заданного целого числа в строку пробелов, равную этому заданному числу. Опять же, это можно сделать по-разному. То, как я это сделал, было что-то вроде этого

String s = "";
for(int i=noofspacestoaddtoeachgap; i>0; i--)
{
    s+= " ";
}

return s;

То, как я это сделал, было преобразовать строку в массив подстрок, причем подстроки были каждым словом в массиве. Если вы посмотрите на класс String в javadoc, вы должны найти методы в классе String, которые вы можете использовать для этого!

Если у вас есть массив подстрок, вы можете добавить строку пробелов в конец каждой подстроки, чтобы сформировать новую подстроку!

Расчет количества лишних пробелов

Это опять простой расчет. Используя оператор%, вы можете выполнить деление остатка аналогично делению, которое мы делали ранее.

noofgaps % noofspacestoadd = noofspacestoaddtoeachgap;

Результат этого вычисления дает нам количество лишних пробелов, необходимых для выравнивания текста.

Добавлять дополнительные пробелы последовательно к каждому пробелу

Это, пожалуй, самая сложная часть алгоритма, поскольку вам нужно выработать способ перебора каждого пробела между словами и добавить дополнительный пробел, пока не останется больше лишних пробелов для добавления!

Возвращаемая строка

return String;
1 голос
/ 31 октября 2018

Я последовал ответу Шахроз Салима (но мой представитель слишком низок, чтобы комментировать: /) - однако мне потребовалось одно незначительное изменение, поскольку оно не учитывает слова длиннее длины строки (например, URL-адреса в тексте.)

import java.util.ArrayList;
import java.util.List;

public class Utils {

    public static List<String> fullJustify(String words, int maxWidth) {

        return fullJustify(words.split(" "), maxWidth);
    }

    public static List<String> fullJustify(String[] words, int maxWidth) {
        int n = words.length;
        List<String> justifiedText = new ArrayList<>();
        int currLineIndex = 0;
        int nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words);
        while (currLineIndex < n) {
            StringBuilder line = new StringBuilder();
            for (int i = currLineIndex; i < nextLineIndex; i++) {
                line.append(words[i] + " ");
            }
            currLineIndex = nextLineIndex;
            nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words);
            justifiedText.add(line.toString());
        }
        for (int i = 0; i < justifiedText.size() - 1; i++) {
            String fullJustifiedLine = getFullJustifiedString(justifiedText.get(i).trim(), maxWidth);
            justifiedText.remove(i);
            justifiedText.add(i, fullJustifiedLine);
        }
        String leftJustifiedLine = getLeftJustifiedLine(justifiedText.get(justifiedText.size() - 1).trim(), maxWidth);
        justifiedText.remove(justifiedText.size() - 1);
        justifiedText.add(leftJustifiedLine);
        return justifiedText;
    }

    public static int getNextLineIndex(int currLineIndex, int maxWidth, String[] words) {
        int n = words.length;
        int width = 0;
        int count = 0;
        while (currLineIndex < n && width < maxWidth) {
            width += words[currLineIndex++].length() + 1;
            count++;
        }
        if (width > maxWidth + 1 && count > 1)
            currLineIndex--;

        return currLineIndex;
    }

    public static String getFullJustifiedString(String line, int maxWidth) {
        StringBuilder justifiedLine = new StringBuilder();
        String[] words = line.split(" ");
        int occupiedCharLength = 0;
        for (String word : words) {
            occupiedCharLength += word.length();
        }
        int remainingSpace = maxWidth - occupiedCharLength;
        int spaceForEachWordSeparation = words.length > 1 ? remainingSpace / (words.length - 1) : remainingSpace;
        int extraSpace = remainingSpace - spaceForEachWordSeparation * (words.length - 1);
        for (int j = 0; j < words.length - 1; j++) {
            justifiedLine.append(words[j]);
            for (int i = 0; i < spaceForEachWordSeparation; i++)
                justifiedLine.append(" ");
            if (extraSpace > 0) {
                justifiedLine.append(" ");
                extraSpace--;
            }
        }
        justifiedLine.append(words[words.length - 1]);
        for (int i = 0; i < extraSpace; i++)
            justifiedLine.append(" ");
        return justifiedLine.toString();
    }

    public static String getLeftJustifiedLine(String line, int maxWidth) {
        int lineWidth = line.length();
        StringBuilder justifiedLine = new StringBuilder(line);
        //for (int i = 0; i < maxWidth - lineWidth; i++)
        //    justifiedLine.append(" ");
        return justifiedLine.toString();
    }
}

Примечание. Я также закомментировал заполнение пробелов в последней строке каждого абзаца (в getLeftJustifiedLine) и сделал методы статическими.

1 голос
/ 30 июня 2018

Вам просто нужно вызвать fullJustify() метод, в котором нужно передать список слов вместе с максимальной шириной каждой строки, которую вы хотите вывести.

public List<String> fullJustify(String[] words, int maxWidth) {
    int n = words.length;
    List<String> justifiedText = new ArrayList<>();
    int currLineIndex = 0;
    int nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words);
    while (currLineIndex < n) {
        StringBuilder line = new StringBuilder();
        for (int i = currLineIndex; i < nextLineIndex; i++) {
            line.append(words[i] + " ");
        }
        currLineIndex = nextLineIndex;
        nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words);
        justifiedText.add(line.toString());
    }
    for (int i = 0; i < justifiedText.size() - 1; i++) {
        String fullJustifiedLine = getFullJustifiedString(justifiedText.get(i).trim(), maxWidth);
        justifiedText.remove(i);
        justifiedText.add(i, fullJustifiedLine);
    }
    String leftJustifiedLine = getLeftJustifiedLine(justifiedText.get(justifiedText.size() - 1).trim(), maxWidth);
    justifiedText.remove(justifiedText.size() - 1);
    justifiedText.add(leftJustifiedLine);
    return justifiedText;
}

public static int getNextLineIndex(int currLineIndex, int maxWidth, String[] words) {
    int n = words.length;
    int width = 0;
    while (currLineIndex < n && width < maxWidth) {
        width += words[currLineIndex++].length() + 1;
    }
    if (width > maxWidth + 1)
        currLineIndex--;
    return currLineIndex;
}

public String getFullJustifiedString(String line, int maxWidth) {
    StringBuilder justifiedLine = new StringBuilder();
    String[] words = line.split(" ");
    int occupiedCharLength = 0;
    for (String word : words) {
        occupiedCharLength += word.length();
    }
    int remainingSpace = maxWidth - occupiedCharLength;
    int spaceForEachWordSeparation = words.length > 1 ? remainingSpace / (words.length - 1) : remainingSpace;
    int extraSpace = remainingSpace - spaceForEachWordSeparation * (words.length - 1);
    for (int j = 0; j < words.length - 1; j++) {
        justifiedLine.append(words[j]);
        for (int i = 0; i < spaceForEachWordSeparation; i++)
            justifiedLine.append(" ");
        if (extraSpace > 0) {
            justifiedLine.append(" ");
            extraSpace--;
        }
    }
    justifiedLine.append(words[words.length - 1]);
    for (int i = 0; i < extraSpace; i++)
        justifiedLine.append(" ");
    return justifiedLine.toString();
}

public String getLeftJustifiedLine(String line, int maxWidth) {
    int lineWidth = line.length();
    StringBuilder justifiedLine = new StringBuilder(line);
    for (int i = 0; i < maxWidth - lineWidth; i++)
        justifiedLine.append(" ");
    return justifiedLine.toString();
}

Ниже приведен пример преобразования, где maxWidth было 80 символов: следующий абзац содержит 115 слова точно, и потребовалось 55 мс , чтобы записать преобразованный текст во внешний файл.

Я проверил этот код для абзаца примерно 70k + слова и для записи преобразованного текста в файл требуется 400 мс .

Ввод

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

Вывод

These  features  tend  to make legal writing formal. This formality can take the
form   of  long  sentences,  complex  constructions,  archaic  and  hyper-formal
vocabulary,  and  a  focus  on content to the exclusion of reader needs. Some of
this formality in legal writing is necessary and desirable, given the importance
of  some  legal documents and the seriousness of the circumstances in which some
legal  documents  are used. Yet not all formality in legal writing is justified.
To   the   extent  that  formality  produces  opacity  and  imprecision,  it  is
undesirable.  To  the  extent that formality hinders reader comprehension, it is
less   desirable.  In  particular,  when  legal  content  must  be  conveyed  to
nonlawyers, formality should give way to clear communication.                   
1 голос
/ 24 ноября 2014

Я написал простой метод для обоснования текста. Он не на 100% точен, но работает по большей части (так как он полностью игнорирует знаки пунктуации, а также могут отсутствовать некоторые крайние случаи). Кроме того, Word оправдывает текст более богатым способом (не добавляя пробелы для заполнения пробела, а равномерно распределяя ширину пробела, что сложно сделать здесь).

public static void justifyText (String text) {
    int STR_LENGTH = 80;
    int end=STR_LENGTH, extraSpacesPerWord=0, spillOverSpace=0;
    String[] words;

    System.out.println("Original Text: \n" + text);
    System.out.println("Justified Text: ");

    while(end < text.length()) {

        if(text.charAt(STR_LENGTH) == ' ') {
            // Technically, this block is redundant
            System.out.println (text.substring(0, STR_LENGTH));
            text = text.substring(STR_LENGTH);
            continue;
        }

        end = text.lastIndexOf(" ", STR_LENGTH);
        words = text.substring(0, end).split(" ");
        extraSpacesPerWord = (STR_LENGTH - end) / words.length;
        spillOverSpace = STR_LENGTH - end + (extraSpacesPerWord * words.length);

        for(String word: words) {
            System.out.print(word + " ");
            System.out.print((extraSpacesPerWord-- > 0) ? " ": "");
            System.out.print((spillOverSpace-- > 0) ? " ": "");
        }
        System.out.print("\n");
        text = text.substring(end+1);

    }
    System.out.println(text);

}
1 голос
/ 18 февраля 2014

Самое сложное в этой проблеме - определить «как можно более равномерно».

Ваш пример:

 Hello__this__is__a_test_string

... делает все более длинные промежутки слева.Не будет ли:

 Hello__this_is__a_test__string

... лучше соответствовать неточному описанию проблемы, с более длинными промежутками, равномерно распределенными по выходной строке?

Однако давайте решим это так, чтобы это далопример ответа.

  • Сначала вам нужно узнать, сколько дополнительных символов нужно вставить - numNewChars == lengthWanted минус inputString.length()
  • Далее вам нужнопосчитайте, сколько пробелов нужно распределить между этими новыми символами - назовите это numGaps - это количество слов минус один.
  • В каждый пробел вы вставите либо n, либо n+1 newпространства.n is numNewChars / numGaps - целочисленное деление;округляет вниз.
  • Теперь, сколько раз вам нужно вставить n+1 новых пробелов вместо n?Это остаток: plusOnes = numNewChars % numGaps

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

  • Для первых plusOnes пробелов вставьте n+1 пробелов, в дополнение к уже существующим пробелам.
  • Для остальных пробелов вставьте n пробелов.

Один очень простой метод будет следующим:

String output= "";
for(int i=0; i<input.length(); i++) {
    char c = input.charAt(i);
    if(c == ' ' {
        output += ...; // appropriate number of "_" chars
    } else {
        output += "" + c; // "" + just turns the char into a String.
    }
}
1 голос
/ 15 декабря 2011

Я бы хотел использовать цикл с заменами регулярных выражений.

  1. Заменить все пробелы подчеркиванием.
  2. Для каждого символа, необходимого для получения длины до желаемой длины, замените одно подчеркивание двумя подчеркиваниями. Используйте регулярные выражения, чтобы убедиться, что эти замены происходят только тогда, когда нужное количество подчеркиваний еще не существует. См. JavaDoc для .ReplaceFirst () . Вам также необходимо учитывать возможность замены двойных подчеркиваний на тройки.

После того, как вы сделаете первоначальную замену, я бы предложил вам использовать цикл while, ограниченный по длине строки, которая меньше целевого размера. Инициализируйте int numUnderscores = 1; вне времени. Тогда шаги внутри цикла будут:

  1. Построить шаблон замены. Это должно быть что-то вроде "/[^_](_{" + numUnderscores + "})[^_]/", в котором говорится, что «любой символ, который не является подчеркиванием, сопровождается экземплярами numUnderscores символа подчеркивания, за которым следует любой символ, не являющийся подчеркиванием»
  2. Позвоните .ReplaceFirst(), чтобы выполнить замену
  3. Проверьте, содержит ли строка какие-либо оставшиеся экземпляры текущего числа подчеркиваний; если это не так, вы должны увеличить numUnderscores

Очевидно, что поскольку это домашнее задание, я оставляю сам процесс написания кода в качестве упражнения. Если у вас есть конкретные вопросы о какой-то его части или о некотором компоненте логической структуры, которую я описал, просто задавайте в комментариях!

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

1 голос
/ 15 декабря 2011

Давайте попробуем разобрать проблему:

Вычтите длину строки из 30 - это количество лишних пробелов, которые вы где-то добавите (3 в данном случае).

Подсчитать количество существующих пробелов (в данном случае 5).

Теперь вы знаете, что вам нужно распределить это первое число лишних пробелов в существующие пробелы как можно более равномерно (в данном случае распределите 3 на 5).

Подумайте, как бы вы распространили что-то подобное в реальной жизни, скажем, шарики в ведра. Вы, вероятно, вращали бы свои ведра, опуская шар в каждом, пока не кончились. Так что подумайте, как вы можете достичь этого в своем Java-коде (подсказка: посмотрите на различные виды циклов).

0 голосов
/ 16 декабря 2011

Первая часть этой презентации содержит алгоритм динамического программирования для обоснования текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...