Мой код проходит все указанные тесты для CodingBat, но не проходит «другие тесты». Я не уверен, в чем моя проблема

Я работаю над CodingBat для класса и не могу понять, почему мой код не работает. Он проходит все перечисленные тесты, но не проходит «другие тесты». Если бы вы могли помочь мне понять, что не так, это было бы очень полезно. Вот проблема: Учитывая строку, подсчитайте количество слов, оканчивающихся на «y» или «z», так что учитываются «y» в «heavy» и «z» в «fez», но не «y» в «желтом». (нечувствительный к регистру). Мы будем говорить, что буква y или z стоит в конце слова, если сразу за ней не следует буква алфавита. (Примечание: Character.isLetter(char) проверяет, является ли char буквой алфавита.)

Вот тесты, которые он перечислил, и я прошел.

countYZ("fez day")    
countYZ("day fez")    
countYZ("day fyyyz")    
countYZ("day yak")    
countYZ("day:yak")    
countYZ("!!day--yaz!!")    
countYZ("yak zak")    
countYZ("DAY abc XYZ")   
countYZ("aaz yyz my")    
countYZ("y2bz")    
countYZ("zxyx")

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

public int countYZ(String str) {
  int count = 0;
  str = str.toLowerCase();
  for (int i=0; i<str.length()-1; i++) {
    if (!Character.isLetter(str.charAt(i)) && i>0 && (str.substring(i-1,i).equals("y") || str.substring(i-1,i).equals("z")))
    { count++; }
  }
  if (str.endsWith("y") || str.endsWith("z")) { count++; }
  return count;
}

Пожалуйста, предоставьте входные данные, где вы терпите неудачу, ожидаемый результат и фактический результат.

Joe C 22.01.2019 21:42

Какие "другие тесты" проваливаются?

David 22.01.2019 21:43

Если я правильно помню из codingbat, «другие тесты» — это категория тестов, которые не раскрываются. Я бы проверил крайние случаи, чтобы увидеть, сможете ли вы найти тот, который не проходит

GBlodgett 22.01.2019 21:45

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

Koray Tugay 22.01.2019 21:49

хорошо countYZ(null) выглядит как кандидат.

Joakim Danielson 22.01.2019 21:53

Вы пробовали тестировать пустую строку? Прямо сейчас вы не проверяете, поэтому str.substring(i-1) будет исключением за пределами допустимого диапазона.

Stalemate Of Tuning 22.01.2019 21:55

Я не могу читать эти длинные строки -> ошибка

user85421 22.01.2019 22:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
7
311
2

Ответы 2

Проблема: Как вы настроили свою логику, ваш цикл просматривает до одного символа до конца String, а затем вы проверяете последний символ с помощью вашего оператора if. тем не мение, ваш цикл эффективно проверяет только символ перед i, поэтому вы не проверяете символ. String, на котором это не сработает:

"y z "

(Обратите внимание на дополнительный пробел в конце. Это может быть любой другой небуквенный символ, который определяется как окончание предшествующего слова)

Этот String должен возвращать 2, но возвращает 1. Легко исправить это, изменив цикл на:

for (int i=0; i<str.length(); i++)

Возможно, лучший подход:

Прямо сейчас у вас есть куча логических условий, чтобы узнать, является ли символ перед ним не буквенным, является ли символ на i буквенным и так далее. На вашем месте я бы просто использовал toLower(), а потом разбил бы на любые небуквенные символы. Затем для каждого String в разделенном массиве используйте функцию endsWith, чтобы легко проверить, заканчивается ли он на z или y. Вот одно из возможных решений:

public int countYZ(String str) {
    if (str == null) return 0;
    str = str.toLowerCase();
    int count = 0;
    for(String s : str.split("[^a-z]")) {
        if (s.endsWith("y") || s.endsWith("z")) {
           count++;
        }
    }
    return count;
}

Или java 8+ вы можете просто сделать:

public int countYZ(String str) {
    if (str == null) return 0;
    return (int)Arrays.stream(str.toLowerCase().split("[^a-z]"))
                      .filter(e -> e.endsWith("y") || e.endsWith("z"))
                      .count();
}

Который решает весь тестовый пример:


Ссылка на проблему

Но это все равно технически не работает для нулевых строк.

Stalemate Of Tuning 22.01.2019 22:28

Очистка вашего кода облегчит чтение и отладку.

Не повторяйтесь! Каждый раз, когда вы пишете один и тот же фрагмент кода, вы создаете потенциальные ошибки из-за простых опечаток. Вместо этого вы можете переместить все проверки в один метод и использовать equalsIgnoreCase, чтобы проверить, соответствует ли данный символ Y или Z:

public static boolean isYOrZ(String s) {
    if (s.equalsIgnoreCase("y") || s.equalsIgnoreCase("z")) return true;
    else return false;
}

Прямо сейчас ваш код не работает для нулевых строк и для пустых строк, поэтому добавьте проверку перед выполнением какой-либо обработки:

int count = 0;
if (str == null || str.length() == 0) //check null first or you will get NPE!
    return count;

Наконец, вы можете обновить свой код с помощью созданного вами нового вспомогательного метода. Если вы понимаете, как работает регулярное выражение, проще использовать String.split() для обработки ваших слов:

public static int countYZ(String str) {
    int count = 0;
    if (str == null || str.length() == 0) {
        return count;
    }
    String[] words = str.split("[^A-z]"); //"not an alphabetic letter immediately following it"
    for(String word : words) {
        if (word.length() > 0) { //sanity check
            if (isYOrZ(word.substring(word.length()-1))) {
                ++count;
            }
        }
    }
    return count;
}

Теперь вы можете тестировать, писать столько странных тестов, сколько сможете придумать. Например, огромная строка пробелов, пустая строка и т. д. Вот некоторые из них, которые я пробовал:

System.out.println(countYZ("heavY yummy TASTY yellow zed buzz"));
System.out.println(countYZ(""));
System.out.println(countYZ(null));
System.out.println(countYZ("fiZz yay"));
System.out.println(countYZ("zzzZZza yyy"));
System.out.println(countYZ("z"));
System.out.println(countYZ("                     "));
System.out.println(countYZ("heavy&testy@!@#BuzZ")); //3

Который дает:

4
0
0
2
1
1
0
3

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

Похожие вопросы