Подсчитайте количество символов » a » и » A » в строке, используя только рекурсию и сопоставление шаблонов

#haskell #count #counting

Вопрос:

Реализуйте countA :: [Char] -> Int функцию, которая подсчитывает количество вхождений символов a и A в строке.

Подсказка: Является ли элемент a A или какой-либо другой элемент, можно проверить с помощью сопоставления с образцом.


Например:

 countA "Appleapplet" == 2

countA "Nietzsche" == 0
 

Я новичок в изучении Хаскелла, и первое, что пришло мне в голову, — это сделать if then else утверждение, но это не может быть ответом, потому что я должен делать это с помощью сопоставления шаблонов. Я даже не знаю, с чего начать, и я не до конца понимаю, как работает сопоставление шаблонов в списках. Я не могу использовать какие-либо импортированные функции в этом упражнении.

Комментарии:

1. Ответ if then else определенно может быть частью ответа.

Ответ №1:

Вы можете использовать if then else , чтобы проверить, является ли первый символ списка 'a' или 'A' , хотя сопоставление шаблонов может быть более элегантным.

Что вам нужно, так это рекурсивная функция с пустым списком (1) в качестве базового случая, в этом случае общее количество раз, когда это a происходит или A происходит 0 . В рекурсивном случае мы работаем с непустым списком с x первым символом и xs (возможно, пустым) хвостом списка. В этом случае мы можем проверить, равен ли первый символ x 'a' или 'A' , и в этом случае увеличить результат рекурсивного вызова. Таким образом, мы можем реализовать это как:

 countA :: String -> Int
countA [] = …  -- (1)
contaA (x:xs) = if x == 'a' || x == 'A' then … else …  -- (2) 

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

Комментарии:

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

2. @AWheelbarrow: вместо contaA (x:xs) = if x == 'a' || x == 'A' then … else … вас используйте три строки: contaA ('a':xs) = ... , contaA ('A':xs) = ... и contaA (x:xs) = ... . Последний случай будет соответствовать только в том случае, если сопоставление шаблонов для ('a': xs) и ('A': xs) завершится неудачно.

3. И что мне нужно написать вместо …-ов? Если я попытаюсь countA ('a':xs) = countA('A':xs) countA(xs) countA ('A':xs) = countA('a':xs) countA(xs) , countA (x:xs) = 0 моя программа зависнет и ничего не распечатает.

4. @AWheelbarrow: вы должны сделать рекурсивный вызов на хвосте xs , а не на голове. Для некоторых предложений , которые вы должны добавить 1 , countA (x:xs) следует также выполнить рекурсивный вызов.

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