Prolog技术咨询:如何判断X是否为A、B、C的中位数
Hey there! Great question—testing for a median is a perfect starting problem in Prolog, and your initial approach is totally on the right track. Let's break this down step by step.
Your Initial Approach: Sorting a List
First, let's tackle the "how to turn three values into a list" part—it's way simpler than you might think! In Prolog, you can just wrap the three variables in square brackets to create a list: [A, B, C]. That's it, no extra hoops to jump through.
Next, sorting the list. A quick heads-up: Prolog's built-in sort/2 predicate removes duplicates, which could cause issues if you have repeated numbers (e.g., sort([2,2,3], Sorted) gives [2,3], which only has two elements). Instead, use msort/2—it sorts the list without stripping duplicates, which is exactly what we need for our median check.
Here's a concise implementation using your original idea:
is_median(X, A, B, C) :- msort([A, B, C], [_, X, _]).
How this works:
msort([A,B,C], Sorted)takes your three numbers and returns a sorted list (ascending order, duplicates preserved).- We then match the sorted list to
[_, X, _]—the underscores are "don't care" variables, meaning we only care that the middle element isX.
Test it out with these queries:
is_median(2, 1, 2, 3).→trueis_median(2, 2, 2, 2).→true(all elements are the same, so 2 is the median)is_median(3, 1, 2, 4).→false
Efficiency Concerns
Don't stress about efficiency here! Sorting three elements is a constant-time operation—no matter what values you pass, it's just a fixed number of comparisons. This approach is more than efficient enough for any use case involving three numbers.
Alternative: Logical Condition Checks
If you want to avoid sorting entirely, you can write logical conditions that directly verify X is the median. This is a bit more verbose but highlights Prolog's logical roots:
is_median(X, A, B, C) :- % X sits between A and B (in either order) (X >= A, X =< B ; X =< A, X >= B), % X sits between A and C (in either order) (X >= A, X =< C ; X =< A, X >= C), % X sits between B and C (in either order) (X >= B, X =< C ; X =< B, X >= C).
Or, if you prefer handling duplicates explicitly with min/max values, here's another take (with a helper predicate to count occurrences):
% Helper to count how many times a value appears in a list count(_, [], 0). count(X, [X|T], N) :- count(X, T, N1), N is N1 + 1. count(X, [Y|T], N) :- X \= Y, count(X, T, N). is_median(X, A, B, C) :- min_list([A,B,C], Min), max_list([A,B,C], Max), ( % X is the minimum and appears at least twice X = Min, count(Min, [A,B,C], Count), Count >= 2 ; % X is the maximum and appears at least twice X = Max, count(Max, [A,B,C], Count), Count >= 2 ; % X is strictly between min and max X > Min, X < Max ).
Final Thoughts
Your initial idea is excellent—sorting the list is intuitive and easy to read, which is perfect when you're learning Prolog. The msort/2 trick fixes the duplicate issue, and the whole thing is super efficient.
Content from Stack Exchange, question author: Westfall

