我习惯于使用程序编程语言,而且我很喜欢使用prolog - 在线资源的缺乏也是一种无赖。
获取给定变量的第一个字符并检查它是否是元音的最常见的方法是什么?
我认为这样的事情是我所追求的?这都是伪代码 - 但是你是如何解决的呢?
isVowel(Word) :-
vowels = [a, e, i, o, u],
firstLetter(Word[0]),
(
firstLetter in vowels ->
Vowel!
; Not a vowel!
).
非常感谢,
奥利
答案 0 :(得分:3)
在Prolog中,你为谓词写了明确的条款(规则)。谓词描述逻辑关系。例如,您可能有一个谓词is_vowel/1
,如果给定的参数是元音,则该谓词为真。
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 ...
答案 1 :(得分:0)
这可以通过多种方式完成。在这个特定的解决方案中,我使用了Definite Clause Grammar(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的。在其他Prolog中,代码列表将出现在双引号内。
如果某个单词是其他内容,那么您首先需要转换为代码。例如,atom_codes(answer, Codes)
如果一个单词由一个原子表示。
答案 2 :(得分:0)
您已获得答案,但是:
不要member
或memberchk
。相反,只需使用表格:
vowel(a).
vowel(e).
vowel(i).
vowel(o).
vowel(u).
然后,你不会说你有什么样的变量。如果你有一个原子:
?- sub_atom(Word, 0, 1, _, First), vowel(First).
您可以轻松地将几乎任何东西转换为原子。请参阅示例here。
如果atom的第一个字符是元音,则此查询将成功,否则将失败。为了使它成为一个谓词:
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/2
或memberchk/2
?
更干净;它更节省内存,而且速度更快;它使程序的意图明显;这是(而且一直是)这样做的首选方式:查看this page的最底部(顺便说一下,讨论许多有趣的事情)。
以下是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/2
或memberchk/2
的参数,更喜欢事实表的理由只是风格和&# 34;实际" (记忆效率,速度)。