Как удалить все пробелы и знаки препинания в строке, чтобы код распознавал палиндромы?

Мне потребовалось некоторое время, чтобы понять, что происходит, потому что я использовал одно слово для тестирования кода, но оно может игнорировать знаки препинания. Не могу понять почему, но по какой-то причине он игнорирует пробелы и знаки препинания, но не одновременно. Пока искал проблему, я изменил ****replaceAll("\p{Punct}", ""); к ****replaceAll("[^A-Za-z ]+", "")

Хотя, похоже, он делает то же самое. Но проблема, с которой я здесь сталкиваюсь, заключается в том, что программа распознает одни вещи, но не другие. И я попытался разделить код на две части: сначала удалить знаки препинания, а вторую - удалить пробелы, оба с одинаковым результатом. примером является то, что «поп», «поп», «поп», «поп!» работает, но другим нравится «Никогда нечетное или четное!» нет.

Я даже не знаю, куда идти, не могли бы вы указать мне правильное направление?

import java.util.Scanner;

class Palindrome {
    public static void main(String[] args) {
        System.out.println("CSE110 Palindrome - TAOLIN DEINIOL\n");

        String userInput;
        while (true) {
            Scanner in = new Scanner(System.in);
            System.out.println("Input statement, or type'done' to quit:");
            userInput = in.next();      
            userInput = userInput.toLowerCase();
            userInput = userInput.replaceAll("\\p{Punct}", "");
            userInput= userInput.replaceAll(" ", "");
            if (userInput.equals("done")) {
                break;
            }


            Palindrome(userInput);
        }
    }

    public static boolean Palindrome(int i, int j, String A) {

        if (i >= j) {
            System.out.println("That is a Palindrome.\n");
            return true;
        }
        if (A.charAt(i) != A.charAt(j)) {
            System.out.println("That is NOT a Palindrome.\n");
            return false;
        }
        return Palindrome(i + 1, j - 1, A);
    }

    public static boolean Palindrome(String A) {
        return Palindrome(0, A.length() - 1, A);
    }
}

На ваш вопрос дан ответ, но есть еще небольшое предложение. Нетрадиционно иметь обычные методы с такими же именами, как и у включающего класса. В данном случае у вас есть метод под названием «Палиндром». Сначала я подумал, что это конструктор, но потом понял, что это не так. Чтобы избежать путаницы, используйте рекомендуемые соглашения об именах: поскольку это логический метод, его желательно называть isPalindrome. И он не должен ничего печатать сам, а вместо этого выполнять печать в main после проверки возвращаемого значения.

k314159 08.07.2024 21:44

"вроде бы делает то же самое" - нет, один удаляет только знаки препинания, а второй заменяет все, кроме заданных символов, то есть удаляет не только знаки препинания, но и цифры, символы, пробелы и прочее

user85421 08.07.2024 22:03

Вам лучше читать строки с Scanner, поскольку палиндромы часто представляют собой предложения (в любом случае интересные). Тогда можно делать String s = userInput.codePoints().map(Character::toLowerCase).filter(Ch‌​aracter::isAlphabeti‌​c).mapToObj(Characte‌​r::toString).collect‌​(Collectors.joining(‌​));boolean isPalindrome = s.equals(new StringBuilder(s).reverse().toString()); Вот и все

g00se 08.07.2024 22:39

Между прочим, тип char практически не работает начиная с Java 2 и является устаревшим начиная с Java 5. Будучи 16-битным значением, char физически неспособен представлять большинство символов. Вместо этого научитесь использовать целые числа с кодовой точкой 🔁, как показано в комментарии от g00se.

Basil Bourque 08.07.2024 23:31

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

k314159 09.07.2024 18:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
83
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Видимо, это вопрос Java, а не JavaScript.

Хороший способ выяснить, почему ваш код не делает того, что, по вашему мнению, он должен делать, — это отладить его. Любая современная IDE может вам в этом помочь. Или просто распечатывайте значения соответствующих переменных (здесь userInput) после каждого изменения.

После этого вы увидите, что userInput имеет значение "Never" после того, как вы набрали Never odd, or even!. Это потому, что in.next() дает вам следующий токен (следующее слово). Если вы замените это на in.nextLine(), код будет работать как положено. Значит, проблема не имела никакого отношения к звонку replaceAll.

Спасибо! это сработало. Уму непостижимо, что что-то такое маленькое перенаправило весь код таким образом.

Taolin Deiniol 09.07.2024 18:56

Я внес в вашу программу несколько исправлений и одно дополнение.

import java.text.Normalizer;
import java.util.Scanner;

public class Palindrome {

   public void init() {
      System.out.println( "CSE110 Palindrome - TAOLIN DEINIOL\n" );    
      String userInput;
      while( true ) {
         Scanner in = new Scanner( System.in );
         System.out.println( "Input statement, or type'done' to quit:" );

           // change "next" to "nextLine", to read a complete entry
         userInput = in.nextLine();
         userInput = userInput.toLowerCase();
         userInput = userInput.replaceAll( "\\p{Punct}", "" );

           // remove accents and other modifiers
         userInput = Normalizer.normalize( userInput, Normalizer.Form.NFD )
                .replaceAll( "[^\\p{ASCII}]", "" );
         System.out.println( userInput );
         userInput = userInput.replaceAll( " ", "" );
         System.out.println( userInput );
         if ( userInput.equals( "done" ) ) {
            break;
         }

           // remove the intermediate step, call directly to "isPalindrome"
           // change the name of this method, to avoid collision with the name of the class
         isPalindrome( 0, userInput.length() -1, userInput );
      }
   }

   public boolean isPalindrome( int i, int j, String A ) {
      if ( i >= j ) {
         System.out.println( "That is a Palindrome.\n" );
         return true;
      }
      if ( A.charAt( i ) != A.charAt( j ) ) {
         System.out.println( "That is NOT a Palindrome.\n" );
         return false;
      }
      return isPalindrome( i + 1, j - 1, A );
   }


   public static void main( String[] args ) {
      Palindrome aa = new Palindrome();
      aa.init();
   }
}

В основном методе создайте только объект Palindrome и вызовите свой метод init, таким образом я избегаю уродливой (ненужной) статики.

Это работает путем удаления всех небукв [^a-z] (путем замены на ничего) и использования StringBuilder для переворачивания символов:

Scanner in = new Scanner(System.in);
while (true) {
    System.out.println("Input statement, or type 'done' to quit:");
    String userInput = in.nextLine();
    if (userInput.equals("done")) {
        break;
    }
    userInput = userInput.toLowerCase().replaceAll("[^a-z]", "");
    boolean isPalindrome = new StringBuilder(userInput).reverse().toString().equals(userInput);
    System.out.format("%s is%s a palindrome\n", userInput, isPalindrome ? "" : " not");
}

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