このディレクトリの索引
#  [1] 授業単元: プログラミング基礎 
#  [2] 問題文(含コード&リンク): 
#  10000以下の自然数のうち素因数分解を行ったときにその因子の数が最多となる数を求め,その数,因子の数,素因数分解の結果を表示するプログラムを作成して下さい. 
#  
#  出力形 
#  8192 = 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 
#  因子数:13 
#  
#  [3] 環境 
#   [3.1] OS: Linux 
#   [3.2] コンパイラ名とバージョン: gcc 3.4 
#   [3.3] 言語: C 
#  [4] 期限: 3月30日まで 
#  [5] その他の制限: 
#  ヒントを教授に聞きに行ったら自分で考えろと一蹴されました 
#  よろしくお願いします 

'10000以下の自然数のうち素因数分解を行ったときにその因子の数が最多となる数を求め,その数,因子の数,素因数分解の結果を表示するプログラムを作成して下さい.' :-
        '10000以下の素数を求める'(_10000以下の素数ならび),
        '10000以下の自然数のうち素因数分解を行ったときに'(_10000以下の自然数,_10000以下の素数ならび,_素因子分解ならび),
        'その因子の数が最多となる数を求め、'(_素因子分解ならび,_最多因子数),
        'その数,因子の数,素因数分解の結果を表示する'(_素因子分解ならび,_最多因子数).

'10000以下の自然数のうち素因数分解を行ったときに'(_10000以下の自然数,_10000以下の素数ならび,_素因子分解ならび) :-
        findall([_10000以下の自然数,_10000の素因子の数,_素因子ならび],(
                    between(1,10000,_10000以下の自然数),
                    '10000の素因子分解'(_10000以下の素数ならび,_素因子ならび),
                    length(_素因子ならび,_10000の素因子の数)),
                _素因子分解ならび).

'10000以下の素数を求める'(_10000以下の素数ならび) :-
        エラトステネスの篩によって10000以下の素数を求める(_10000以下の素数ならび).

エラトステネスの篩によって10000以下の素数を求める(_10000以下の素数ならび) :-
        findall(N,between(1,10000,N),_10000以下の自然数ならび),
        エラトステネスの篩(_10000以下の自然数ならび,_10000以下の素数ならび).

'10000以下の自然数のうち素因数分解を行ったときに'(_,[],[]) :- !.
'10000以下の自然数のうち素因数分解を行ったときに'(M,[N|R1],[N|R2]) :-
        0 is M mod N,
        M_1 is M // N,
        '10000以下の自然数のうち素因数分解を行ったときに'(M_1,[N|R1],R2).
'10000以下の自然数のうち素因数分解を行ったときに'(M,[_|R1],R2) :-
        '10000以下の自然数のうち素因数分解を行ったときに'(M,R1,R2).

'その因子の数が最多となる数を求め、'(_素因子分解ならび,_最多因子数) :-
        findmax(_素因子の数,(
                      member([_,_因子の数,_],_素因子分解ならび)),
                _最多因子数).

'その数,因子の数,素因子分解の結果を表示する'(_素因子分解ならび,_最多因子数) :-
        forall(   member([_数,_最多因子数,_素因子分解の結果],_素因子分解ならび),
                  writef('%t,%t,%t\n',[_数,_最多因子数,_素因子分解の結果])).

findmax(_選択項,_評価項,_最大値) :-
        findall(_選択項,_評価項,_評価ならび),
        最大値(_評価ならび,_最大値).

最大値(_ならび,_最大値) :-
        append(L1,[_最大値|L2],_ならび),
        ならび要素に最大値を超えるものはない(L1,_最大値),
        ならび要素に最大値を超えるものはない(L2,_最大値).

ならびの要素に最大値を超えるものはない(_ならび,_最大値) :-
        \+((member(_要素,_ならび),_要素 @> _最大値)).

エラトステネスの篩([],[]) :- !.
エラトステネスの篩([A|R1],[A|R2]) :-
        エラトステネスの篩(A,R1,L),
        エラトステネスの篩(L,R2).

エラトステネスの篩(_,[],[]) :- !.
エラトステネスの篩(N,[A|R1],R2) :-
        0 is A mod N,
        エラトステネスの篩(N,R1,R2),!.
エラトステネスの篩(N,[A|R1],[A|R2]) :-
        エラトステネスの篩(N,R1,R2).