「이것이 풀 수 있는 수재는 모집하고 있지 않습니다^^」Prolog 「마카세로」

9666 단어 Prolog
어쩐지 Prolog 에서 풀기 쉬운 문제가 굴러 가고 있었으므로 풀어 본다.

문제문



問題文

인용 소스 : h tp // 아나고. 2ch. sc / st / re d. c/g는 rd/1437182679/#g는 rd/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는 최고야!

    (영어·코드의 지적 대환영입니다)

    좋은 웹페이지 즐겨찾기