33
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「これが解けるような秀才は募集しておりません^^」Prolog「まかせろ」

Last updated at Posted at 2015-07-20

なんか Prolog で解きやすそうな問題が転がっていたので解いてみる。

問題文

問題文

引用元: http://anago.2ch.sc/test/read.cgi/ghard/1437182679/#ghard/1437182679/218

Prolog による解法

コード

  • 2015/07/21: 考慮漏れがあったので修正しました。なお、結果は変わりませんでした。
count(List, X, Count) :- count_sub(List, X, 0, Count).
count_sub([], _, N, N).
count_sub([Head | Xs], X, N, Count) :-
    (Head == X -> N1 is N + 1; N1 is N),
    count_sub(Xs, X, N1, Count).

% トランプの数は1〜13まで。
card(X) :- between(1, 13, X).

% さやかのヒントにあてはまる(かつ、CardAはCardBより小さい)。
is_satisfy_sayaka_said(CardA, CardB) :-
    card(CardA),
    card(CardB),
    CardA =\= 1,
    CardB =\= 1,
    CardA =\= CardB,
    CardB mod CardA =:= 0.

% 相手の数字を確定できる。
can_guess(WinnerCard, AllCandidates) :-
    flatten(AllCandidates, AllCandidateCards),
    card(WinnerCard),
    count(AllCandidateCards, WinnerCard, 1).

% どちらのカードからも、相手の数字を確定できない。
cannot_eiter_guess(CardA, CardB, AllCandidates) :-
    card(CardA), card(CardB),
    not(can_guess(CardA, AllCandidates)),
    not(can_guess(CardB, AllCandidates)).

% カードの組は、解候補に含まれる。
is_candidate(CardA, CardB, AllCandidates) :-
    member([CardA, CardB], AllCandidates);
    member([CardB, CardA], AllCandidates).

% 以下の条件を満たす解である。
%   (1) さやかのヒントにあてはまる
%   (2) どちらも相手の数字を確定できない
%   (3) (2)を知ると、どちらかが相手の数字を確定できる
is_answer(WinnerCard, LoserCard) :-
    findall([CardA, CardB], (
        is_satisfy_sayaka_said(CardA, CardB)
    ), CandidatesSatisfySayakaSaid),

    findall([CardA, CardB], (
        % (1)
        is_satisfy_sayaka_said(CardA, CardB),

        % (2)
        cannot_eiter_guess(CardA, CardB, CandidatesSatisfySayakaSaid)
    ), CandidatesWhenEitherCannotGuess),

    % (3)
    can_guess(WinnerCard, CandidatesWhenEitherCannotGuess),

    is_candidate(WinnerCard, LoserCard, CandidatesWhenEitherCannotGuess).

基本的に英語がひどいのはお許しください。

結果

?- is_answer(CardA, CardB, Minami).
CardA = Minami, Minami = 10,
CardB = 2 ;
false.

みなみさんが10、かおりさんが2のようですね。

結論

やっぱり Prolog は最高だぜ!

(英語・コードのご指摘大歓迎です)

33
26
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?