找出第一个字母是否是元音序词



我已经习惯了程序编程语言,而且我有点挣扎于prolog-缺乏在线资源也是一个遗憾。

获取给定变量的第一个字符并检查它是否是元音的最"prolog"方法是什么?

我想,这样的东西就是我所追求的吗?这都是伪代码 - 但这就是你解决它的方式吗?

isVowel(Word) :-    
    vowels = [a, e, i, o, u],
    firstLetter(Word[0]),
    (
        firstLetter in vowels ->
            Vowel!
        ; Not a vowel!
    ).

非常感谢,

奥利

在Prolog中,你为谓词编写定子句(规则)。谓词描述逻辑关系。例如,您可能有一个谓词is_vowel/1如果给定参数是元音,则该谓词为 true。

is_vowel(Letter):-
    member(Letter, "aeiouAEIOU").

为了查看一个单词是否以元音开头,你必须取第一个字母:

starts_with_vowel(Word):-
    Word = [First|_],
    is_vowel(First).

现在,您可以像这样同时进行统一和模式匹配:

starts_with_vowel([FirstLetter|_]):-
    is_vowel(FirstLetter).

几个示例查询:

?- starts_with_vowel("Italy").
true ;
false.
?- starts_with_vowel("Vietnam").
false.
?- Letters = [_|"pple"], starts_with_vowel(Letters), string_to_atom(Letters, Word).
Letters = [97, 112, 112, 108, 101],
Word = apple ;
Letters = [101, 112, 112, 108, 101],
Word = epple ;
Letters = [105, 112, 112, 108, 101],
Word = ipple ...

你有答案,但是:

不要做member,或者memberchk。相反,只需使用一个表:

vowel(a).
vowel(e).
vowel(i).
vowel(o).
vowel(u).

然后,你不说你有什么样的变量。如果你有一个原子:

?- sub_atom(Word, 0, 1, _, First), vowel(First).

您可以轻松地将几乎任何东西转换为原子。例如,请参阅此处。

如果原子的第一个字符是元音,则此查询将成功,否则将失败。要使其成为谓词:

first_letter_vowel(Word) :-
    sub_atom(Word, 0, 1, _, First),
    vowel(First).

或者,例如:

nth_letter_vowel(N, Word) :-
    sub_atom(Word, N, 1, _, Letter),
    vowel(Letter).

如果您使用的是SWI-Prolog,您还可以使用downcase_atom/2

nth_letter_vowel(N, Word) :-
    sub_atom(Word, N, 1, _, Letter),
    downcase_atom(Letter, Lower_Case),
    vowel(Lower_Case).

编辑:为什么是事实表而不是member/2memberchk/2

更干净;它更节省内存,速度更快;它使程序的意图显而易见;它是(并且一直是)首选的方式:请参阅本页的最底部(顺便说一下,它讨论了许多有趣的事情)。

以下是使用 vowel/1 的可能查询的详尽列表,当它被定义为事实表时:

?- vowel(r).
false.
?- vowel(i).
true.
?- vowel(V).
V = a ;
V = e ;
V = i ;
V = o ;
V = u.
?- vowel(foobar(baz)). % or anything, really
false.

现在我们知道member/2会留下选择点,所以memberchk/2肯定是首选(除非我们打算使用选择点!但即便如此:

?- memberchk(a, [a,b,c]).
true. % that's fine
?- memberchk(x, [a,b,c]).
false. % ok
?- memberchk(a, L).
L = [a|_G1190]. % what?
?- memberchk(X, [a,b,c]).
X = a. % what?

所以是的,在原始问题的上下文中,假设我们确保仔细检查member/2memberchk/2的论点,更喜欢事实表的原因只是风格和"实用"(记忆效率、速度)。

这可以通过多种方式完成。在这个特定的解决方案中,我使用定句语法(DCG)。

此外,答案有点取决于"词"是什么。如果是字符代码列表,则以下内容就足够了:

starts_with_vowel --> vowel, dcg_end.
vowel --> [X], {memberchk(X, [0'a,0'A,0'e,0'E,0'i,0'I,0'o,0'O,0'u,0'U])}.
dcg_end(_, []).

使用示例:

?- phrase(starts_with_vowel, `answer`).
true.
?- phrase(starts_with_vowel, `question`).
false.

PS:请注意,此处使用反引号是特定于SWI7的。在其他Prologs中,代码列表将显示在双引号内。

如果一个单词是其他东西,那么你首先需要转换为代码。 例如,atom_codes(answer, Codes)一个单词是否由原子表示。

最新更新