このディレクトリの索引

% 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1244449887/842 # [1] C言語 # [2]1〜5の数字の組み合わせをを2次元配列index[][]に格納し、表示しなさい。 t268(X) :- 組合せ([1,2,3,4,5],2,X). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1,M is N - 1,組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1,組合せ(Y,N,A). % *** user: '重複組合せ' / 3 *** '重複組合せ'(X,1,[A]) :- member(A,X) . '重複組合せ'([A|Y],N,[A|X]) :- N > 1, M is N - 1, '重複組合せ'([A|Y],M,X) . '重複組合せ'([_|Y],N,A) :- N > 1, '重複組合せ'(Y,N,A) . % *** user: '順列' / 3 *** '順列'(Y,0,[]). '順列'(Y,N,[A|X]) :- del(Z = Y - A), M is N - 1, '順列'(Z,M,X) . % *** user: del / 3 *** del(A,[A|X],X). del(A,[B|X],[B|Y]) :- del(A,X,Y) . % *** user: del / 1 *** del(X = [A|X] - A). del([B|Y] = [B|X] - A) :- del(Y = X - A) . % *** user: '重複順列' / 3 *** '重複順列'(L,N,X) :- length(X,N), '重複順列'(L,X) . % *** user: '重複順列' / 2 *** '重複順列'(L,[]). '重複順列'(L,[A|R]) :- member(A,L), '重複順列'(L,R) . % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1245853701/244 # 〔1〕授業単元:C言語 # 〔2〕問題文:http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9601.txt # ? 2つの整数型の変数を入れ替える関数 swapを定義して、それを用いて配列中の数字をランダムに入れ替えるプログラムを作りなさい。1から52までの数が順番に入った配列を用意し、十分に入れ替えた結果を表示すること。 # ? これができた人は、次のように表示を変更しなさい。 # ・ 52個の数字を1〜13、14〜26、27〜39、40〜52の4組に分けて考える # ・ それぞれ1番目から13番目の数字を、A、2、3、4、5、6、7、8、9、T、J、Q、K と表示する(TはTenのT) # 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2,0,21,22,… # ↓ # A,2,3,4,5,6,7,8,9,T,J,Q,K,A,2,3,4,5,6,7,8,9,T,… # ?これができた人は、次のように表示を変更しなさい。 # ・トランプの4つのスートをアルファベットで表示することにする(スペードは s, ハート #  はh、ダイヤはd、 クラブはc) # ・ 1〜13はスペード(s)、14〜26はハート(h)、27〜39はダイヤ(d)、40〜52はクラブ(c)とする # ・ それぞれの数字をA〜Kとshdcの組合せで表示する # ・ 例:1ならAs(スペードのA)、52ならKc(クラブのK) # As,2s,…..,Ks,Ah,2h,……,Kh,Ad,2d,……,Kd,Ac,2c,…..,Kc swap(A,B,L,LX) :- append(L1,[A|L2],[B|L3],L), append(L1,[B|L2],[A|L3],LX),!. swap(A,B,L,LX) :- append(L1,[B|L2],[A|L3],L), append(L1,[A|L2],[B|L3],LX),!. t319_2(X) :- findall(U,(for(1,N,52),t319_2_1(N,U)),X). t319_2_1(N,U) :- M is N mod 13, t319_2_2(M,U). 数字カード・絵カード(1,'A') :- !. 数字カード・絵カード(10,'T') :- !. 数字カード・絵カード(11,'J') :- !. 数字カード・絵カード(12,'Q') :- !. 数字カード・絵カード(0,'K') :- !. 数字カード・絵カード(N,N). トランプの準備(X) :- findall(U,(for(1,N,52),一枚のカードを作る(N,U)),_整列したカード), トランプを切る(100,_整列したカード,X). 一枚のカードを作る(N,U) :- M is N mod 13, M2 is (N - 1) // 13, 数字カード・絵カード(M,U1), カードの種類(M2,U2), atom_concat(U1,U2,U). カードの種類(0,s). カードの種類(1,h). カードの種類(2,d). カードの種類(3,c). トランプを切る(0,L,L) :- !. トランプを切る(N,L,X) :- M1 is (random mod 52) + 1, M2 is (random mod 52) + 1, swap_nth(M1,M2,L,L1), N2 is N - 1, トランプを切る(N2,L1,X). swap_nth(M,N,L1,L2) :- list_nth(M,L1,A), list_nth(N,L1,B), swap(A,B,L1,L2). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1136994325/954 # pascal pcpad # 1個の自然数nを適当決めて、nチームが参加する # リーグ戦の全試合を表示するプログラムを書きなさい。 リーグ戦の全試合を表示するプログラム(N) :- findall(M,for(1,M,N),L), 組合せ(L,2,[A,B]), write_formatted('%t-%t\n',[A,B]), fail; true. 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1153585095/900 # 3つの自然数の合計が10になるような組み合わせを # すべて列挙するプログラムを書け # 1+1+8と1+8+1のように並び順が異なるだけのものは # 同一と考え、重複して出力しないようにすることが望ましい t494 :- 重複組合せ([1,2,3,4,5,6,7,8,9],3,[A,B,C]), 10 is A + B + C, write_formatted('%t + %t + %t\n',[A,B,C]), fail. t494. 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1153585095/902 # 個数Nが与えられたとき # N個の自然数の合計が10になるような組み合わせをすべて列挙する # プログラムを書け t496(N) :- 重複組合せ([1,2,3,4,5,6,7,8,9,10],N,L), sum(L,10), concat_atom(L,' + ',S), write_formatted('%t\n',[S]), fail. t496(_). sum([],0) :- !. sum([A|R],X) :- sum(R,Y),X is A + Y. % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1255709298/651 # [1] 授業単元: C言語演習 # [2] 問題文(含コード&リンク): # 正の整数nの2乗の数に、2種類の数字しか現れない # 4桁の正の整数 n をすべて挙げなさい '正の整数nの2乗の数に、2種類の数字しか現れない4桁の正の整数 n をすべて挙げる'(L) :- findall(N,'正の整数nの2乗の数に、2種類の数字しか現れない4桁の正の整数 n '(N),L). '正の整数nの2乗の数に、2種類の数字しか現れない4桁の正の整数 n '(N) :- 組合せ([0,1,2,3,4,5,6,7,8,9],2,[A,B]), length(L,9), '2種類の数字しか現れないならび'(A,B,0,0,L), concat_atom(L,Atom), atom_to_term(Atom,N1,_), N is truncate(sqrt(N1)). N >= 1000,N =< 9999, U is N * N. '2種類の数字しか現れないならび'(_,_,1,1,[]) :- !. '2種類の数字しか現れないならび'(A,B,_,K,[A|R]) :- '2種類の数字しか現れないならび'(A,B,1,K,R). '2種類の数字しか現れないならび'(A,B,K,_,[B|R]) :- '2種類の数字しか現れないならび'(A,B,K,1,R). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1258158172/456 # [1] 授業単元: C++ # [2] 問題文(含コード&リンク): # http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10195.txt # # 今回はナップサック問題について考えプログラムを作成する。N個の荷物があって、個々の荷物の重さをWi、値段をPiとする。但しiは1からNの整数を意味する。 # 袋には最大Wの重さまで入れられるとすると、最大でいくら分を入れることができるか?という問題。 # データファイルは、始めの一行に荷物の個数Nが書かれており、次に重さが整数でN行分書かれている。その次の行からN行分、それぞれの荷物の価値が書かれているとする。 # 下のデータファイルの場合は、3個の荷物があり、重みは10、20、13、で # それぞれの値段は23、23、10という状況を表す。 # ------------------- # 3 # 10 # 20 # 13 # 23 # 23 # 10 # ------------------- # 荷物の重みと値段はともに、1から100までの乱数で与えることとする。 # void_write_data_file(char*file,intN)という関数を呼ぶとN個分のデータを乱数で生成し、文字列変数fileに入っている # ファイル名のファイルを開き、そこにデータを記録する。void_read_data_file(char*file)という関数を呼ぶと、文字列変数fileによって名前が指定されたファイルを開き、大域変数の荷物の重み配列W[]と値段配列[]\\\\\にデータを入力する。 ナップサック問題(_ファイル名,N,_許容最大重量,_詰めることのできる最高合計金額) :-   データファイルの読み出し(_ファイル名,N,_価格ならび,_重さならび),   findall(M,for(1,M,N),_1からNまで),   findmax(_合計価格,詰め物の作成(N,_1からNまで,_許容最大重量,_重さならび,_価格ならび,_合計価格),_詰めることのできる最高合計金額). データファイルの読み出し(_ファイル名,N,_重さならび,_価格ならび) :-   see(_ファイル名),get_integer(N),get_integers(L1),seen,   length(L2,N),length(L3,N),   append(_重さならび,_価格ならび,L1),!. 詰め物の作成(N,_1からNまで,_許容最大重量,_重さならび,_価格ならび,_合計価格) :-   for(1,M,N),   組合せ(_1からNまで,M,L),   findsum(Wi,(member(A,L),list_nth(A,_重さならび,Wi)),_合計重量),   _合計重量 =< _許容最大重量,   findsum(Pi,(member(A,L),list_nth(A,_価格ならび,Pi)),_合計金額). get_integers(L) :-   findall(I,(get_line(Line),(Line=end_of_file,!,fail;atom_to_term(Line,I,_))),L),!. % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1269438098/379 # [1] 授業単元: プログラム演習 # [2] 問題文(含コード&リンク):10000未満の正の整数を考える(xとする)。このとき、ある2つの整数の3乗の和として表す表し方が2通りある数をすべて求めなさい。つまり、異なる2通りの数の組(a,b)と(c,d)があって、 # x = a^3 + b^3 # = c^3 + d^3 # とできる数xを表示するプログラムを実行しなさい。例えば、1027は # 1027 = 3^3 + 10^3 # と表せますが、それ以外は表せません((3,10)と(10,3)は同じものと考える)。 # # # '10000未満の正の整数を考える(xとする)。このとき、ある2つの整数の3乗の和として表す表し方が2通りある数をすべて求める'(L) :- findall([A,B,C,D,X],'10000未満の正の整数を考える(xとする)。このとき、ある2つの整数の3乗の和として表す表し方が2通りある数をすべて求める'(A,B,C,D,X),L1), 重複削除(L1,[],L). '10000未満の正の整数を考える(xとする)。このとき、ある2つの整数の3乗の和として表す表し方が2通りある数をすべて求める'(A,B,C,D,X) :- findall([N,N3],(for(1,N,9999),N3 is N * N * N,N3 < 10000),L), 組合せ(L,2,[[A,A3],[B,B3]]), X is A3 + B3, X < 10000, 組合せ(L,2,[[C,C3],[D,D3]]), \+(member(C,[A,B])), \+(member(D,[A,B])), X is C3 + D3. 重複削除([],L,L). 重複削除([[A,B,C,D,X]|R1],L2,L) :- member([C,D,A,B,X],L2), 重複削除(R1,L2,L). 重複削除([[A,B,C,D,X]|R1],L2,L) :- \+(member([C,D,A,B,X],L2)), 重複削除(R1,[[A,B,C,D,X]|L2],L). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1269438098/553 # [1]Cプログラミング # [2] # 0から9までの数字を2回ずつ使用し掛け算の筆算を表示させよ # 図 #     □□□ #   ×□□□ #   ━━━━ #    □□□ #   □□□ # □□□ #  ━━━━━ # □□□□□ 0から9までの数字を2回ずつ使用し掛け算の筆算を表示させよ :- 0から9までの数字を2回ずつ使用し掛け算の筆算を表示させよ([_1,_2,_3],[_4,_5,_6],[_7,_8,_9],[_10,_11,_12],[_13,_14,_15],[_16,_17,_18,_19,_20]), write_formatted('  %t%t%t\n',[_1,_2,_3]), write_formatted(' ×%t%t%t\n',[_4,_5,_6]), write('---------\n'), write_formatted('  %t%t%t\n',[_7,_8,_9]), write_formatted('  %t%t%t\n',[_10,_11,_12]), write_formatted(' %t%t%t\n',[_13,_14,_15]), write('---------\n'), write_formatted(' %t%t%t%t%t\n',[_16,_17,_18,_19,_20]). 0から9までの数字を2回ずつ使用し掛け算の筆算を表示させよ([_1,_2,_3],[_4,_5,_6],[_7,_8,_9],[_10,_11,_12],[_13,_14,_15],[_16,_17,_18,_19,_20]) :- 乗算して桁あふれしない数字の組合せ(_1,_6), 乗算して桁あふれしない数字の組合せ(_1,_5), 乗算して桁あふれしない数字の組合せ(_1,_4), for(0,_2,9), for(0,_3,9), L6 = [_1,_2,_3,_4,_5,_6], 一段目の掛け算(_1,_2,_3,_6,_7,_8,_9,L6,L9), 二段目の掛け算(_1,_2,_3,_5,_10,_11,_12,L9,L12), 三段目の掛け算(_1,_2,_3,_4,_13,_14,_15,L12,L15), 四段目の加算(_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,L15,L20). 一段目の掛け算(_1,_2,_3,_6,_7,_8,_9,L6,L9) :- _9_p is _3 * _6, _9 is _9_p mod 10, 二個までは許される(_9,L6,L7), _9_f is _9_p // 10, _8_p is _2 * _6 + _9_f, _8 is _8_p mod 10, 二個までは許される(_8,L7,L8), _8_f is _8_p // 10, _7 is _1 * _6 + _8_f, _7 < 10, 二個までは許される(_7,L8,L9),!. 二段目の掛け算(_1,_2,_3,_5,_10,_11,_12,L9,L12) :- _12_p is _3 * _5, _12 is _12_p mod 10, 二個までは許される(_12,L9,L10), _12_f is _12_p // 10, _11_p is _2 * _5 + _12_f, _11 is _11_p mod 10, 二個までは許される(_11,L10,L11), _11_f is _11_p // 10, _10 is _1 * _5 + _11_f, _10 < 10, 二個までは許される(_10,L11,L12),!. 三段目の掛け算(_1,_2,_3,_4,_13,_14,_15,L12,L15) :- _15_p is _3 * _4, _15 is _15_p mod 10, 二個までは許される(_15,L12,L13), _15_f is _15_p // 10, _14_p is _2 * _4 + 15_f, _14 is _14_p mod 10, 二個までは許される(_14,L13,L14), _14_f is _14_p // 10, _13 is _1 * _4 + _14_f, _13 < 10, 二個までは許される(_13,L14,L15),!. 四段目の加算(_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,L15,L20) :- _20 = _9, 二個までは許される(_20,L15,L16), _19_p is _8 + _12, _19 is _19_p mod 10, 二個までは許される(_19,L16,L17), _19_f is _19_p // 10, _18_p is _7 + _11 + _13 + _19_f, _18 is _18_p mod 10, 二個までは許される(_18,L17,L18), _18_f is _18_p // 10, _17_p is _10 + _14 + _18_f, _17 is _17_p mod 10, 二個までは許される(_17,L18,L19), _17_f is _17_p // 10, _16 is _15 + _17_f, 二個までは許される(_16,L19,L20),!. 乗算して桁あふれしない数字の組合せ(0,0). 乗算して桁あふれしない数字の組合せ(0,1). 乗算して桁あふれしない数字の組合せ(0,2). 乗算して桁あふれしない数字の組合せ(0,3). 乗算して桁あふれしない数字の組合せ(0,4). 乗算して桁あふれしない数字の組合せ(0,5). 乗算して桁あふれしない数字の組合せ(0,6). 乗算して桁あふれしない数字の組合せ(0,7). 乗算して桁あふれしない数字の組合せ(0,8). 乗算して桁あふれしない数字の組合せ(0,9). 乗算して桁あふれしない数字の組合せ(1,1). 乗算して桁あふれしない数字の組合せ(1,2). 乗算して桁あふれしない数字の組合せ(1,3). 乗算して桁あふれしない数字の組合せ(1,4). 乗算して桁あふれしない数字の組合せ(1,5). 乗算して桁あふれしない数字の組合せ(1,6). 乗算して桁あふれしない数字の組合せ(1,7). 乗算して桁あふれしない数字の組合せ(1,8). 乗算して桁あふれしない数字の組合せ(2,2). 乗算して桁あふれしない数字の組合せ(2,3). 乗算して桁あふれしない数字の組合せ(2,4). 乗算して桁あふれしない数字の組合せ(3,3). 乗算して桁あふれしない数字の組合せ(1,0). 乗算して桁あふれしない数字の組合せ(2,0). 乗算して桁あふれしない数字の組合せ(3,0). 乗算して桁あふれしない数字の組合せ(4,0). 乗算して桁あふれしない数字の組合せ(5,0). 乗算して桁あふれしない数字の組合せ(6,0). 乗算して桁あふれしない数字の組合せ(7,0). 乗算して桁あふれしない数字の組合せ(8,0). 乗算して桁あふれしない数字の組合せ(9,0). 乗算して桁あふれしない数字の組合せ(2,1). 乗算して桁あふれしない数字の組合せ(3,1). 乗算して桁あふれしない数字の組合せ(4,1). 乗算して桁あふれしない数字の組合せ(5,1). 乗算して桁あふれしない数字の組合せ(6,1). 乗算して桁あふれしない数字の組合せ(7,1). 乗算して桁あふれしない数字の組合せ(8,1). 乗算して桁あふれしない数字の組合せ(3,2). 乗算して桁あふれしない数字の組合せ(4,2). 二個までは許される(A,L,_) :- append(_,[A|R],L), append(_,[A|_],R),!,fail. 二個までは許される(A,L,[A|L]). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1261057499/975 # たしてちょうど15になる7個の自然数の組合せをすべて列挙するとともに、 # すべての組合せを表示し終えたら、それらの組合せが全部でいくつあるの # かも出力するプログラムを作成しなさい。 # # #include<stdio.h> # # int main(void) # { # int i,num; # # printf("自然数の組合せ\n"); # # num=0; # # for(i=1;num<=14;i++){ # num=num+i; # printf("%d\t",i); # # } # # printf("組み合わせは%d通り\n",num); # # return 0; # } # # 現在ここまで作りましたが、プログラムがわかりません。 # 誰か教えてください。 # # 言語はC++ # 環境はVisual です。 # # たしてちょうど15になる7個の自然数の組合せをすべて列挙する([A,B,C,D,E,F,G]) :- たしてちょうど15になる7個の自然数候補の最大値(M), '1からMまでのならび'(M,L1), 重複組合せ(L1,7,[A,B,C,D,E,F,G]), 15 is A + B + C + D + E + F + G. 組合せが全部でいくつあるのか(_いくつ) :- いくつ(たしてちょうど15になる7個の自然数の組合せをすべて列挙する(L),_いくつ). たしてちょうど15になる7個の自然数候補の最大値(N) :- for(14,N,1), M is 15 - N, '1からMまでのならび'(M,L1), 重複組合せ(L1,6,L2), 整数加算(L2,M),!. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '1からMまでのならび'(M,L) :- findall(J,for(1,J,M),L). 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). 整数加算([],0) :- !. 整数加算([A|R],X) :- 整数加算(R,Y),X is A + Y. いくつ(_目標,_いくつ) :- count(_目標,_いくつ). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1276810079/602 # [1] 授業単元: プログラミング演習 # [2] 問題文(含コード&リンク):http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10791.txt # 問題文 # # 0から7までの数字が描かれたカードがある。ただし、0だけ2枚で、合計9枚とする。 # この中から4枚を選ぶ組合せを考える。ただし、6と7は同時に選ばない(両方選ばなくてもよい)。 # このような組合せを列挙し、何通りあるかを、C言語のプログラムで求める。何通りあるかは、数学的に解いて確認せよ。 # 例題プログラムEnumFull.c を修正する。 # # 部分問題への分解 0が現れる枚数で場合分けして、それぞれの個数を集計 # 弱化問題への緩和 0および6と7に関する条件を無視して、とりあえず全てを列挙し、題意に合わないものを排除 # 等価問題への還元 2枚の0を、0と8に読み換え、8は単独で選ばないという条件に置換 # 7は外して列挙し、6が現れる場合に、7に読み換えたものも追加 '0から7までの数字が描かれたカードがある。ただし、0だけ2枚で、合計9枚とする。この中から4枚を選ぶ組合せを考える。ただし、6と7は同時に選ばない(両方選ばなくてもよい)。このような組合せを列挙する'(U) :- findall(L,( 組み合わせ([0,0,1,2,3,4,5,6,7],4,L), 許される組み合わせ(L)), X), sort(X,Y), append(_[U|R],Y). 許される組み合わせ(A) :- append(_[6|_],A),append(_,[7|_],A),!,fail. 許される組み合わせ(A) :- append(B,[0|C],A),append(D,[0|E],C),!,fail. 許される組み合わせ(A). '0から7までの数字が描かれたカードがある。ただし、0だけ2枚で、合計9枚とする。この中から4枚を選ぶ組合せを考える。ただし、6と7は同時に選ばない(両方選ばなくてもよい)。このような組合せを列挙し何通りあるか'(_何通り) :- count('0から7までの数字が描かれたカードがある。ただし、0だけ2枚で、合計9枚とする。この中から4枚を選ぶ組合せを考える。ただし、6と7は同時に選ばない(両方選ばなくてもよい)。このような組合せを列挙する'(_),_何通り). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1279286575/56 # n 個のものの中から r 個のものを取り出すときの組合せの数 nCr を求める関数 CCO(int n, int r) を再帰型で作成しなさい. # ただし, x, y の入力と結果の出力は main関数で行わせること. # # #include <stdio.h> # # int CCO(int x,int y) # { # if((x < 0) || (x < y)){ # return -1; # }else if(x <= 1){ # return 1; # }else{ # (return x * CCO(x-1))/(return y * CCO(y-1)); # } # } # int main(void) # { # int a,b; # # printf("値を入力してください: "); # scanf("%d", &a); # # printf("値を入力してください: "); # scanf("%d", &b); # # printf("%dC%d = %d\n", input1,input2, CCO(a,b)); # return 0; # } # # nCr :- 催促付き整数入力('n : ',N), 催促付き整数入力('r : ',R), nCr(N,R,X), write_formatted('nCr = %tC%t = %t\n',[N,R,X]). %%%%%%%%%%%%%%%%%%%%%%%%%%% nCr(N,R,X) :- U is N - R + 1, 階乗(U,N,K1), 階乗(R,K2), X is K1 // K2 . %%%%%%%%%%%%%%%%%%%%%%%%%%%% 階乗(M,N,1) :- M > N,!. 階乗(M,N,X) :- M2 is M + 1, 階乗(M2,N,Y), X is M * Y. 階乗(0,1) :- !. 階乗(1,1) :- !. 階乗(N,X) :- N2 is N - 1, 階乗(N2,Y), X is N * Y, asserta((階乗(N,X) :- (!))). % 以下のサイトは 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R3]) :- N > 1, M is N - 1, 組合せ(R1,M,R3). 組合せ([_|R1],N,L) :- N > 1, 組合せ(R1,N,L). 単位節組合せ(_述語名/_アリティ,_選択項位置リスト,_組合せ数,X) :- length(_引数ならび,_アリティ), P =.. [_述語名|_引数ならび], findall(U,( call(P), 項の選択(_選択項位置リスト,_引数ならび,U)), L2), 組合せ(L2,_組合せ数,X). 項の選択([],_引数ならび,[]). 項の選択([_nth1|R1],_引数ならび,[X|R3]). nth1(_nth1,_引数ならび,X), 項の選択(R1,_引数ならび,R3). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R2]) :- 'Nを1減らして残り要素の組合せ'(R1,N,R2). 組合せ([_|R1],N,R2) :- 'Nはそのままで残り要素の組合せ'(R1,N,R2). 'Nを1減らして残り要素の組合せ'(R1,N,R2) :- succ(N_1,N), 組合せ(R1,N_1,R2). 'Nはそのままで残り要素の組合せ'(R1,N,R2) :- 組合せ(R1,N,R2). % 以下のサイトは # 三角形 # n本の棒があります。棒iの長さはaiです。あなたは、それらの棒から3本選んでできるだけ # 周長の長い三角形を作ろうと考えています。最大の周長を求めなさい。ただし、三角形が # 作れない際には0を答えとしなさい。 'n本の棒があります。棒iの長さはaiです。あなたは、それらの棒から3本選んでできるだけ周長の長い三角形を作ろうと考えています。最大の周長を求めなさい。ただし、三角形が作れない際には0を答えとしなさい。'(_棒の長さならび,_最大の周長) :- findmax(_周長,( 組合せ(_棒の長さならび,3,[_辺の一,_辺の二,_辺の三]), 三角形を構成できる(_辺の一,_辺の二,_辺の三), sum(L,_周長)), _最大の周長). 三角形を構成できる(_辺の一,_辺の二,_辺の三) :- _辺の一 < _辺の二 + _辺の三, _辺の二 < _辺の一 + _辺の三, _辺の三 < _辺の一 + _辺の二. % 以下のサイトは # [14回演習問題2.1.1]整数のリストを第一引数に与え,そのリストの要素の中から、 # 和が15になるような3つの数を選ぶ述語fifteen/2をつくりなさい、 # ただしあるひとつの組み合わせに関して、同じ数が重複してはいけない。 # fifteen(_整数のリスト,N1,N2,N3) :- setof(N,member(N,_整数のリスト),L), 組合せ(L,3,[N1,N2,N3]), 15 is N1 + N2 + N3. 組合せ(X,1,[A]) :- member(A,X) . 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは # prologでの冪集合が難しい。でも、たぶんできると思う。 冪集合(_集合,_冪集合) :- length(_集合,Len), findall(L,( for(1,N,Len), 組合せ(_集合,N,L)), LL), _冪集合 = [[]|LL],!. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). for(S,N,E) :- E >= S, for_2(S,N,E). for(S,N,E) :- E < S, for_1(S,N,E). for_1(S,_,E) :- S < E,!,fail. for_1(N,N,E). for_1(S,N,E) :- S1 is S - 1,for_1(S1,N,E). for_2(S,_,E) :- S > E,!,fail. for_2(N,N,E). for_2(S,N,E) :- S1 is S + 1,for_2(S1,N,E). % 以下のサイトは # prologでの冪集合が難しい。でも、たぶんできると思う。 冪集合(_集合,_冪集合) :- length(_集合,Len), length(LL,Len), findall(L2,( append(L,[_|_],[_|LL]), length(L,N), 組合せ(_集合,L,L2)), LL2), _冪集合 = [[]|LL2],!. '組合せ'(X,[_],[A]) :- member(A,X) . '組合せ'([A|Y],[_|L],[A|X]) :- '組合せ'(Y,L,X) . '組合せ'([_|Y],L,A) :- \+(L = [_]), '組合せ'(Y,L,A) . % 以下のサイトは http://hibari.2ch.net/test/read.cgi/tech/1305867431/165 # 【質問テンプレ】 # [1] 授業単元:プログラミング # [2] 問題文(含コード&リンク): # キーボードから入力した長さ10の文字列の任意の2つの文字を # 入れ換える関数void swap(char *address1, char *address2)を定義し、 # その動作を確認するkadai6-2.cを作りなさい。 # この関数は引数で与えられたアドレスのメモリにアクセスして中身を # 入れ換える作業を行う。 # ただし、文字列と入れ換える2つの文字の位置は次のように入力されるものとする。 # scanf("%s %d %d", str, &position1, &position2);//それぞれ文字列、位置1, 位置2を表している。 # 答えは以下で出力されるものとする。 # printf("answer = %s\n", str); # キーボードから入力した長さ10の文字列の任意の2つの文字を入れ換える(_文字列,_2つの文字を入れ換えた文字列) :- キーボードから入力した長さ10の文字列(_文字列), 組合せ([0,2,3,4,5,6,7,8,9],2,[Nth1,Nth2]), atom_chars(_文字列,Chars), ならびの任意の2つの文字を入れ換える(Chars,Nth1,Nth2,[],_2つの文字を入れ換えた文字列). ならびの任意の2つの文字を入れ換える(Chars,Nth1,Nth2,L,_2つの文字を入れ換えた文字列) :- length(L,45),!, fail. ならびの任意の2つの文字を入れ換える(Chars,Nth1,Nth2,L,_2つの文字を入れ換えた文字列) :- \+(append(_,[[Nth1,Nth2]|_],L)), length(L0,Nth1), append(L0,[A|R1],Chars), Nth3 is Nth2 - Nth1 - 1, length(L03,Nth3), length(L03,[B|R3],R1), append(L0,[B|L03],[A|R3],Chars2), atom_chars(_2つの文字を入れ換えた文字列,Chars2). ならびの任意の2つの文字を入れ換える(Chars,Nth1,Nth2,L,_2つの文字を入れ換えた文字列) :- \+(append(_,[[Nth1,Nth2]|_],L)), 組合せ([0,2,3,4,5,6,7,8,9],2,[Nth1_2,Nth2_2]), ならびの任意の2つの文字を入れ換える(Chars,Nth1_2,Nth2_2,[[Nth1,Nth2]|L],_2つの文字を入れ換えた文字列). ならびの任意の2つの文字を入れ換える(Chars,Nth1,Nth2,L,_2つの文字を入れ換えた文字列) :- append(_,[[Nth1,Nth2]|_],L), 組合せ([0,2,3,4,5,6,7,8,9],2,[Nth1_2,Nth2_2]), ならびの任意の2つの文字を入れ換える(Chars,Nth1_2,Nth2_2,L,_2つの文字を入れ換えた文字列). キーボードから入力した長さ10の文字列(_文字列) :- write('10の文字列の文字列を入力してください : '), findall(_文字,( for(1,N,10), get_char(_文字)), L), atom_chars(_文字列,L). % 以下のサイトは # 個数制限つき部分和問題 # n種類の数aiがそれぞれmi個ずつあります。 # これらの中からいくつか選び、その総和がちょうどすることができるか # 判定しなさい。 'n種類の数aiがそれぞれmi個ずつあります。これらの中からいくつか選び、その総和がちょうどすることができるか判定しなさい'(_n,_ai,_mi,K) :- ならびに展開する(_n,_ai,_mi,L), 和がKとなる部分和を求める(1,_n,K,L). 和がKとなる部分和を求める(M,_n,K,L) :- M > _n,!,fail. 和がKとなる部分和を求める(M,_n,K,L) :- 組合せ(L,M,L1), sum(L1,K),!. 和がKとなる部分和を求める(M,_n,K,L) :- M2 is M + 1, 和がKとなる部分和を求める(M2,_n,K,L). ならびに展開する([],[]) :- !. ならびに展開する([A|R1],[B|R2],L) :- length(L1,B), all(L1,A), ならびに展開する(R1,R2,L2), append(L1,L2,L). % 以下のサイトは http://pc12.2ch.net/test/read.cgi/tech/1260532772/487 [1] 授業単元:計算機入門及び演習 # [2] 問題文(含コード&リンク):http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10311.txt # # 以下の問題を解くプログラムをC言語を用いて作成しなさい. # # AさんとBさんは点数が書かれたカードを何枚か持っている. Aさんのカードと # Bさんのカードを1枚ずつ交換して,Aさんの持つカードの合計点数とBさんの持つ # カード合計点数が等しくなるようにしたい. # このときどのカードとどのカードを交換したらよいか.ただし,カードを # 交換しなくても合計点数が等しい場合でも,必ずカードの交換を行うものとする. # # 入力は,いくつかのデータセットからなる.各データセットは次の形式で与えられる. n m # s1 # s2 # ... # sn # sn+1 # sn+2 # ... # sn+m # 各データセットの最初の行は空白ひとつで区切られたふたつの数 n と m を含み, # n はAさんのカードの枚数,m はBさんのカードの枚数を表す.続く n+m 行には, # 各カードの点数が 1 行にひとつずつ並ぶ. # 最初の n 個の点数 (s1 から sn まで) はAさんのカードの点数,残りの # m 個の点数 (sn+1 から sn+m まで) はBさんのカードの点数を表す. # n および m は 100 以下の正の整数とし,カードの点数は 0 以上 100 以下の # 整数値とする.入力の終わりは,空白ひとつで区切られたふたつの 0 を含む # 1 行で示される. # 各データセットに対し,Aさん,Bさんの交換前のすべてのカードと交換すべき2つの # カードを出力すること.形式は特に問わない(実行例を参考にすること). # なお,合計を等しくするようなカードの交換の方法が複数ある場合は, # 交換するカードの点数の和が最小となるもののみを出力すること. # また,カードの点数の合計を等しくするような交換が存在しない場合はその旨を # 出力すること. # 'AさんとBさんは点数が書かれたカードを何枚か持っている. AさんのカードとBさんのカードを1枚ずつ交換して,Aさんの持つカードの合計点数とBさんの持つカード合計点数が等しくなるようにする'(LA,LB,LX) :- quicksort(LA,LA1), quicksort(LB,LB1), length(LA1,LenA), length(LB1,LenB), append(LA1,LB1,L), findall([L1,L2],( 組合せ(L,LenA,L1), sum(L1,Sum), 'L1分をLから取り除く'(L1,L,L3), 組合せ(L3,LenB,L2),sum(L2,Sum)), LX), 最短手順を探る(LA1,LX,_交換候補). 'L1分をLから取り除く'([],L,L) :- !. 'L1分をLから取り除く'([A|R1],L1,L2) :- 'AをL1から取り除く'(A,L1,L3), 'L1分をLから取り除く'(R1,L3,L2). 'AをL1から取り除く'(A,L1,L2) :- append(L0,[A|R],L1), append(L0,R,L2),!. sum([],0) :- !. sum([A|R],X) :- sum(R,Y), X is A + Y. 最短手順を探る(LA1,LL,_放出,_受け取り) :- findall([_放出,_受取],( append(_,[[L1,_]|_],LL), 交換候補(LA1,L1,_放出,_受取)), LX), findmin(Len,( append(_,[[U1,U2]|_],LX), length(U1,Len)), Min), append(_,[[_放出,_受け取り]|_],LX), length(U1,Min). 交換候補([],L,[],L) :- !. 交換候補(L,[],L,[]) :- !. 交換候補([A|R1],[A|R2],R3,R4) :- 交換候補(R1,R2,R3,R4),!. 交換候補([A|R1],[B|R2],[A|R3],R4) :- A < B, 交換候補(R1,[B|R2],R3,R4),!. 交換候補([A|R1],[B|R2],R3,[B|R4]) :- A > B, 交換候補([A|R1],R2,R3,R4),!. % 以下のサイトは # # 部分集合の生成 # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % 非決定性に作っておいて、findallで収集する。 % 全部分集合(_集合,_部分集合リスト) :- findall(_部分集合,( 部分集合(_集合,_部分集合)), _部分集合リスト). 部分集合(_集合,_部分集合) :- length(_集合,_要素数), for(1,N,_要素数), 組合せ(_集合,N,_部分集合). % ****** 組合せ / 3 *** 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % % forループを使わない場合 % % ****** 全部分集合 / 2 ******* 全部分集合(_集合,_部分集合リスト) :- length(_集合,_要素数), 全部分集合(_要素数,_集合,_部分集合リスト). % ***** 全部分集合 / 3 ******* 全部分集合(0,_,[]) :- !. 全部分集合(N,_集合,LL) :- findall(L,組合せ(_集合,N,L),LL1), N_1 is N - 1, 全部分集合(N_1,_集合,LL2), append(LL1,LL2,LL). %%%%%% for / 3 %%%%%%%% for(S,N,E) :- E >= S, for_2(S,N,E). for(S,N,E) :- E < S, for_1(S,N,E). for_1(S,_,E) :- S < E,!,fail. for_1(N,N,E). for_1(S,N,E) :- S1 is S - 1,for_1(S1,N,E). for_2(S,_,E) :- S > E,!,fail. for_2(N,N,E). for_2(S,N,E) :- S1 is S + 1,for_2(S1,N,E). % 以下のサイトは http://hibari.2ch.net/test/read.cgi/tech/1311089619/726 # [1] 授業単元:プログラミング演習 # [2] 問題文:char str[4]="ABCD" # 上記の変数strには"A" "B" "C" "D"がstrの[0]〜[3]が入っています。 # この文字を三つ取り出して文字が同じになってもいいので組み合わせを表示 # させるプログラムを教えてください。 # 例: # ABC # ACB # ADC # AAA # AAB # str('ABCD'). 'char str[4]="ABCD" 上記の変数strには"A" "B" "C" "D"がstrの[0]〜[3]が入っています。この文字を三つ取り出して文字が同じになってもいいので組み合わせを表示させる' :- str(_文字列), atom_char(_文字列,_4文字ならび), findall(_重複組合せ,( 重複組合せ(_4文字ならび,3,_重複組合せ)), _重複組合せならび), 表示させる(_重複組合せならび). 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). 表示させる(_重複組合せならび) :- append(_,[_重複組合せ|R],_重複組合せならび), writef('%t,%t,%t\n',_重複組合せ), R = []. % 以下のサイトは http://hibari.2ch.net/test/read.cgi/tech/1311089619/804 # [1] 授業単元:並列計算 # [2] 問題文(含コード&リンク):http://ime.nu/codepad.org/UfRWs3k5 # # 課題 ナップザック問題をOpenMPで並列化し,並列化効率などについて分析せよ. # (1) ナップザック問題とはいくつかの荷物を袋に入れるときに最大の値段に # なるように袋に詰める,組み合わせを求める問題 # (2) N個の荷物があって,個々の荷物の重さをWi,値段をPiとする. # 袋には最大Wの重さまでいれられる.このとき,最大でいくら分を # いれることができるのかを求める. # (3) 幅優先探索型にする ナップザック問題(_重量限界,_最大金額) :- findall((_金額,_重み),( 荷物(_重み,_金額)), L1), length(L1,Len), findmax(金額合計,( for(1,M,Len), 組合せ(L,M,L2), 重さ合計(L2,_重さ合計), _重さ合計=<_重量限界, 金額合計(L2,_金額合計)), _最大金額). 金額合計([],0). 金額合計([(_金額,_)|R1],_合計金額) :- 金額合計(R1,_金額合計_1), _合計金額 is _合計金額_1 + _金額. 重さ合計([],0). 重さ合計([(_重さ,_)|R1],_合計重さ) :- 重さ合計(R1,_重さ合計_1), _合計重さ is _合計重さ_1 + _重さ. % 以下のサイトは # 多重組合せを作る述語 poly_member/3 を作れ. # たとえば # ?- L=[1,2,3,4,5,6],Type=[2,3],poly_member(L,A,Type). # A = [[1,2],[3,4,5]] -> # となるものを作る. 多重組合せ(L,_型,X) :- poly_member(L,_型,[],X,R). 多重組合せ(L,_型,L0,_多重組合せ,_残りならび) :- poly_member(L,_型,[],_多重組合せ,_残りならび). poly_member(L,Type,L0,X,R) :- poly_member_2(L,Type,L0,X,R). poly_member(L,Type,L0,X,R) :- poly_member_2(L,Type,Y,R1), append(L0,[Y],L0_2), poly_member(R1,Type,L0_2,X,R). poly_member_2(L,[N|R2],[L0|R3],R) :- length(L0,N), append(L0,R1,L), poly_member_2(R1,R2,R3,R). poly_member_2(L,[],[],L). % 以下のサイトは http://hibari.2ch.net/test/read.cgi/tech/1312201995/6 # [1] 授業単元: C言語プログラミング # [2] 問題文(含コード&リンク):となりどおしの数字の差がその下の数字となるように、 # 1から15までの数を1回だけ使って例に従ってマスにいれなさい。 # 積み上げ(L) :- 組合せならびの生成(_組合せならびの生成), L = [[_],[_,_],[_,_,_],[_,_,_,_],[_,_,_,_,_]], 積み上げ(_組合せならびの生成,[],LY,L), reverse(L,L2), '5段から1段まで表示する'([' ',' ',' ',' ',' ',''],L2). 積み上げ(LX,LY1,LY,[L1,L2|R]) :- 一行積み上げ(L1,LX,LY1,LY2,L2), 積み上げ(LX,LY2,LY,[L2|R]). 一行積み上げ([],LX,LY,LY,[]) :- !. 一行積み上げ([S],LX,LY1,[N1,N2|LY1],[N1,N2]) :- member([S,N1,N2],LX), \+(member(N1,LY)), \+(member(N2,LY)), S is abs(N1-N2),!. 一行積み上げ([S|R1],LX,LY1,LY,[N1,N2|R2]) :- member([S,N1,N2],LX), \+(member(N1,LY)), \+(member(N2,LY)), S is abs(N1-N2), 一行積み上げ(R1,LX,[N1,N2|LY1],LY,[N2|R2]). 組合せならびの生成(_組合せならびの生成) :- findall([S,N1,N2],( 組合せ([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],2,[N1,N2]), S is abs(N1-N2), \+(member(S,[N1,N2]))), _組合せならび), '5段から1段まで表示する'([],[]) :- !. '5段から1段まで表示する'([_空白|R1],[L|R2]) :- concat_atom(L,' ',S), writef('%t%t\n',[_空白,S]), '5段から1段まで表示する'(R1,R2). % 以下のサイトは # 与えられた自然数 N にたいして,リスト L=[m1,m2,・・・,mr] で # 次の性質を持つものをすべてせいせいする述語 partition(N,L) を作れ. # m1+m2+・・・+mr=N # m1>=m2>=・・・>=mr>0 # 飯高茂著 「Prologで作る数学の世界」 第7章 問題6 p137-138 # より出題 partition(N,L) :- findall(M,for(N,M,1),L1), findall(L2,( for(N,M,1), 重複組合せ(L1,M,L2), sum_S(L2,N,0)), L). sum_S([A|R],S,M) :- M >= S,!,fail. sum_S([],N,N) :- !. sum_S([A|R],S,M) :- M2 is A + M, sum_S(R,S,M2). % 以下のサイトは # 与えられた自然数 N にたいして,リスト L=[m1,m2,・・・,mr] で # 次の性質を持つものをすべてせいせいする述語 partition(N,L) を作れ. # m1+m2+・・・+mr=N # m1>m2>・・・>mr>0 # 飯高茂著 「Prologで作る数学の世界」 第7章 問題6 p137-138 # より出題 partition(N,L) :- findall(M,for(N,M,1),L1), findall(L2,( for(N,M,1), 組合せ(L1,M,L2), sum_S(L2,N,0)), L). sum_S([A|R],S,M) :- M >= S,!,fail. sum_S([],N,N) :- !. sum_S([A|R],S,M) :- M2 is A + M, sum_S(R,S,M2). % 以下のサイトは # 重複組合せ # 組合せ 重複組合せ(L,1,[A]) :- member(A,L). 重複組合せ([A|R1],N,[A|R2]) :- N > 1, N_1 is N - 1, 重複組合せ([A|R1],N_1,R2). 重複組合せ([_|R1],N,R2) :- N > 1, 重複組合せ(R1,N,R2). 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R2]) :- N > 1, N_1 is N - 1, 組合せ(R1,N_1,R2). 組合せ([_|R1],N,R2) :- N > 1, 組合せ(R1,N,R2). % 以下のサイトは # x^2+y^2=z^2を満たす正の整数をピタゴラス数と呼び、三つ組(x,y,z)で表す。 # ピタゴラス数のリストを生成する関数pythsを定義せよ。 # ただし、ピタゴラス数の要素は、与えられた上限以下であるとする。 # ピタゴラス数ならび(_要素値上限,_ピタゴラス数ならび) :- findall([_x,_y,_z],( ピタゴラス数(_要素値上限,_x,_y,_z)), _ピタゴラス数ならび). ピタゴラス数(_要素値上限,_x,_y,_z) :- '1から_要素値上限までの整数リストを生成'(_要素値上限,L), 重複組合せ(L,3,[X,Y,_z]), 'X,Y,を三角形の短辺、_zを長辺だとみなすことができる'(X,Y,_z), ピタゴラスの定理を適用する(X,Y,_z), 短辺はひっくり返すことも可能(X,Y,_x,_y). '1から_要素値上限までの整数リストを生成'(_要素値上限,L) :- findall(N,for(1,N,_要素値上限),L). 'X,Y,を三角形の短辺、_zを長辺だとみなすことができる'(X,Y,_z) :- _z > X, _z > Y, _z < X + Y. ピタゴラスの定理を適用する(X,Y,Z) :- Z * Z =:= X * X + Y * Y. 短辺はひっくり返すことも可能(_x,_x,_x,_x) :- !. 短辺はひっくり返すことも可能(_x,_y,_x,_y). 短辺はひっくり返すことも可能(_y,_x,_x,_y). % 以下のサイトは http://hibari.2ch.net/test/read.cgi/tech/1086272325/886 # 木に一本だけ辺をつけ加えて最長となる閉路を探すアルゴリズム # 木に一本だけ辺をつけ加えて最長となる閉路を探す(_根,_辺起点,_辺終点) :- findall([_深さ,_葉に至る経路],( 葉を捜す(_根,_葉に至る経路), length(_葉に至る経路,_深さ)), LL1), sort(LL1,LL2), reverse(LL2,LL3), 一本辺をつけ加えて閉路とする(LL3,_辺起点,_辺終点). 葉を捜す(_根,[_根|R]) :- 木(_根,_葉), 葉を捜す(_葉,R). 葉を捜す(_根,[]). 一本辺をつけ加えて閉路とする([[N,L1],[N,L2]|R],_辺起点,_辺終点) :- findall(_葉,( member([N,L],[[N,L1],[N,L2]|R]), last(L,_葉)), _葉ならび), 組合せ(_葉ならび,2,[_辺起点,_辺終点]). 一本辺をつけ加えて閉路とする([[N1,L1],[N2,L2]|R],_辺起点,_辺終点) :- \+(N1 = N2), last(L1,_辺起点), member([N2,L],[[N2,L2]|R]), last(L,_辺終点). % 以下のサイトは http://toro.2ch.net/test/read.cgi/db/1316769778/323 # 【質問テンプレ】 # ・DBMS名とバージョン MySQL 5.1 # ・テーブルデータ # ・欲しい結果 # ・説明 # # テーブル「カート」 # カラム 「セッションID」「商品種別」「カートに入れた時刻」 # # テーブル「カート詳細」 # カラム 「セッションID」「商品コード」 # # テーブル「商品リスト」 # カラム「商品コード」「商品種別」 # # というテーブルがあります。 # # 最後にカートに入れた時刻から12時間以上経過したセッションIDを検索して、 # そのセッションIDを持つレコードを「カート」「カート詳細」の両方から # 全て削除したいのです。 # # 同じセッションIDを持つレコードは、両方のテーブルに複数あります。 # 「注文」テーブルで「セッションID」「商品種別」の組合せはユニークで、 # 「注文詳細」テーブルでは「セッションID」「商品コード」の組合せにユニークです。 # # 結合や副問い合わせを試してみましたが、うまいこと抽出できません。 # SQLで書くやり方があれば教えてください。よろしくお願いします。 # # '最後にカートに入れた時刻から12時間以上経過したセッションIDを検索して、そのセッションIDを持つレコードを「カート」「カート詳細」の両方から全て削除する' :- '最後にカートに入れた時刻から12時間以上経過したセッションIDを検索して'(_セッションID,R), 'そのセッションIDを持つレコードを「カート」「カート詳細」の両方から全て削除する'(_セッションID), R = []. '最後にカートに入れた時刻から12時間以上経過したセッションIDを検索して'(_セッションID,R) :- findsetof(_セッションID,( カート(_セッションID,_商品種別,_カートに入れた時刻)), _セッションIDならび), append(_,[_セッションID|R],_セッションIDならび), findmax(_カートに入れた時刻,( カート(_セッションID,_商品種別,_カートに入れた時刻)), _最後にカートに入れた時刻), 最後にカートに入れた時刻から12時間以上経過している(_セッションID,_最後にカートに入れた時刻). 'そのセッションIDを持つレコードを「カート」「カート詳細」の両方から全て削除する'(_セッションID) :- retractall(カート(_セッションID,_,_)), retractall(カート詳細(_セッションID,_)). 最後にカートに入れた時刻から12時間以上経過している(_セッションID,_最後にカートに入れた時刻) :- split(_最後に入れた時刻,['/',' ',':'],[_年,_月,_日,_時,_分]), 現在の時刻(_年_1,_月_1,_日_1,_時_1,_分_1), '12時間後の日時'(_年,_月,_日,_時,_分,_年_2,_月_2,_日_2,_時_2,_分_2), [_年_1,_月_1,_日_1,_時_1,_分_1] @>= [_年_2,_月_2,_日_2,_時_2,_分_2],!. '12時間後の日時'(_年,_月,_日,_時,_分,_年,_月,_日,_時_2,_分) :- _時_2 is _時 + 12, _時_2 < 24,!. '12時間後の日時'(_年,_月,_日,_時,_分,_年,_月,_日_2,_時_2,_分) :- _時_1 is _時 + 12, _時_2 is _時_1 - 24, _日_2 is _日 + 1,!. retractall(P) :- retract(P), fail. retractall(_). % 以下のサイトは http://toro.2ch.net/test/read.cgi/db/1316769778/334 # mysqlで質問です。 # # | col1 | col2 | col3 | col4 | col5 | col6 | # # | 3 | 1 | 0 | 5 | 4 | 12 | # # | 2 | 5 | 6 | 0 | 1 | 8 | # # のようなテーブルで # 複数の条件、例えばA,B,C,D,E,Fで # このうちの3つの条件がいずれかでもあえば # そのレコードを取得するというような # クエリは可能でしょうか。 # # イメージ的にはLOTO6で5等に該当するレコードは全て取得するといった # 感じなのですが。 # # # '複数の条件、例えばA,B,C,D,E,Fでこのうちの3つの条件がいずれかでもあえばそのレコードを取得する'([[_colA,A],[_colB,B],[_colC,C],[_colD,D],[_colE,E],[_colF,F]],_col1,_col2,_col3,_col4,_col5,_col6) :- テーブル(_col1,_col2,_col3,_col4,_col5,_col6), '3つの条件がいずれかでもあえば'([[_colA,A],[_colB,B],[_colC,C],[_colD,D],[_colE,E],[_colF,F]],[_col1,_col2,_col3,_col4,_col5,_col6]). '3つの条件がいずれかでもあえば'(_条件ならび,_列ならび) :- 条件の組合せ(_条件ならび,_3つの条件), 条件判定(_3つの条件,_列ならび),!. 条件の組合せ(_条件ならび,_3つの条件) :- 組合せ(_条件ならび,3,_3つの条件). 条件判定([],_) :- !. 条件判定([[_col,_条件]|R],_列ならび) :- member(_col,_列ならび), call(_条件), 条件判定(R,_列ならび). % % 条件ならびの書き方は % A,B,C,D,E,Fの中にそれぞれ_colA,_colB,_colC,_colD,_colE,_colFを含ませる。 % % 以下のサイトは # [1,2,3,4,5]というリストを受け取って、 # [[],[1],[2],[3],[4],[5],[1,2],[2,3],[3,4],[4,5],[5,1],[1,2,3]...]というリストを返す関数を作りたい 冪集合(_集合,_冪集合) :- findall(L,部分集合(_集合,L),_冪集合). 部分集合(L,X) :- length(L,M), for(1,N,M), 組合せ(L,N,X). 部分集合(_,[]). 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R3]) :- N > 1, N_1 is N - 1, 組合せ(R1,N_1,R3). 組合せ([_|R1],N,L) :- N > 1, 組合せ(R1,N,L). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1325685876/26 # 問題:4桁の数字が与えられたとき、その4個の数字で組み合わせって、作れる? # 1001 ならば 0011,0101,0110,1001,1010,1100 が出来るなど。 # 言語・コンパイラ:C gcc # '4桁の数字が与えられたとき、その4個の数字の組み合わせ'(_4桁の数字,_4個の数字の組み合わせ) :- atom_chars(_4桁の数字,Chars), setof(X,順列(Chars,4,X),_4個の数字の組合せ). % 以下のサイトは :- dynamic(cut,0). 最長共通部分列(_ならび1,_ならび2,_最長共通部分ならび) :- abolish(cut/0), findmin(_要素数,( member(L,[_ならび1,_ならび2]), length(L,_要素数)), _短い方のならびの要素数), 最長共通部分列(_短い方のならびの要素数,_ならび1,_ならび2,_最長共通部分ならび). 最長共通部分列(_短い方のならびの要素数,_ならび1,_ならび2,_最長共通部分ならび) :- for(_短い方のならびの要素数,N,1), ( cut,!,fail; 共通部分列(N,_ならび1,_ならび2,_最長共通部分ならび) ), cut_assert. cut_assert :- cut,!. cut_assert :- asserta(cut). 共通部分列(N,_ならび1,_ならび2,_共通部分ならび) :- 組合せ(_ならび1,N,_共通部分ならび), 組合せ(_ならび2,N,_共通部分ならび). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% findmin(V,P,Min) :- findall(V,P,L), min(L,Min). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは 最長共通部分列(_ならび1,_ならび2,_最長共通部分ならび) :- findmin(_要素数,( member(L,[_ならび1,_ならび2]), length(L,_要素数)), _短い方のならびの要素数), 最長共通部分列(_短い方のならびの要素数,_ならび1,_ならび2,_最長共通部分ならび). 最長共通部分列(_短い方のならびの要素数,_ならび1,_ならび2,_最長共通部分ならび) :- for(_短い方のならびの要素数,N,1), 共通部分列(N,_ならび1,_ならび2,_),!, 共通部分列(N,_ならび1,_ならび2,_最長共通部分ならび). 共通部分列(N,_ならび1,_ならび2,_共通部分ならび) :- 組合せ(_ならび1,N,_共通部分ならび), 組合せ(_ならび2,N,_共通部分ならび). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% findmin(V,P,Min) :- findall(V,P,L), min(L,Min). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは # 年俸1000万の会社の試験問題 <発展問題> # 単体テストなどやっていると、全ての要素について全ての組み合わせを # 求めたいことが結構あります。 # '単体テストなどやっていると、全ての要素について全ての組み合わせを求めたいことが結構あります。'(_グループならび,_組合せの順列) :- length(_グループならび,Len), 全ての組合せ(_グループならび,_組合せ_1), 順列(_組合せ_1,Len,_組合せの順列). 全ての組合せ([],[]). 全ての組合せ([L|R1],[A|R2]) :- member(A,L), 全ての組合せ(R1,R2). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1260922392/95 # どなたかご協力お願いします。 # 1からmまでの整数の集合 A = {nは自然数|1≦n≦m}の中からn個の整数を取り出す組み合わせすべてを生成するプログラムを作れ。また、5C3の場合を表示せよ。(Cはコンビネーションです) # # 組み合わせを a1,a2,a3,・・・an としていって、a1<a2<a3<・・・<an となることを利用して作ると思われるのですが、、、 # # %% 引数なし '5C3の場合を表示せよ' :- '1からmまでの整数の集合 A = {nは自然数|1≦n≦m}の中からn個の整数を取り出す組み合わせすべてを生成する'(5,3,_組合せ), writef('%t\n',[_組合せ]), fail. '5C3の場合を表示せよ'. %% 1引数で '5C3の場合を表示せよ'(L) :- findall(_組合せ,( '1からmまでの整数の集合 A = {nは自然数|1≦n≦m}の中からn個の整数を取り出す組み合わせすべてを生成する'(5,3,_組合せ), writef('%t\n',[_組合せ])), L). '1からmまでの整数の集合 A = {nは自然数|1≦n≦m}の中からn個の整数を取り出す組み合わせすべてを生成する'(_m,_n,_組合せ) :- findall(N,for(1,N,_m),L), 組合せ(L,_n,_組合せ). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは # # % ?- variablize([a,b,c], X, L). # % L = [[X, b, c], [a, X, c], [a, b, X]] # Now I am trying to extend this predicate to accept a list of variables, example: # # % ?- variablize([a,b,c], [X,Y], L). # % L = [[X, Y, c], [X, b, Y], [a, X, Y]] # My code so far is: # # replace_at([_|Tail], X, 1, [X|Tail]). # replace_at([Head|Tail], X, N, [Head|R]) :- M is N - 1, replace_at(Tail, X, M, R). # # replace_each([], _, _, [], _). # replace_each([_|Next], Orig, X, [Res|L], N) :- # replace_at(Orig, X, N, Res), # M is N + 1, # replace_each(Next, Orig, X, L, M). # # variablize(I, X, L) :- replace_each(I, I, X, L, 1). # Any pointers? Do I extend replace_at/4 to have a list of indexes that should be skipped? # variablize(L1,L2,L) :- append(L1,L2,L3), length(L1,Len1), length(L2,Len2), findall(L4,( 組合せ(L3,Len1,L4), 変数の個数(L4,Len2)), L). 変数の個数([],0). 変数の個数([V|R],N) :- var(V), 変数の個数(R,N1), N is N1 + 1. 変数の個数([_|R],N) :- 変数の個数(R,N). % 以下のサイトは # 2と3だけを複数回かけてある数Aにもっとも近い数を作りたーい :- dynamic('_m ^ _n'/3). '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数,_2を掛ける回数,_3を掛ける回数,_もっとも近い数) :- '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,2,1,1,_現在のある数Aとの差,_2を掛ける回数,_3を掛ける回数,_ある数Aにもっとも近い数). '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,_組合せ数,_現在のある数Aとの差,_m,_n,_ある数Aにもっとも近い数) :- findall(N,( for(1,N,_組合せ数)), L1), 差の絶対値と差(L1,_ある数A,_m_1,_n_1,_差の絶対値,_差), '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,_組合せ数,_m_1,_n_1,_差の絶対値,_差,_現在のある数Aとの差,_m,_n,_ある数Aにもっとも近い数). '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,_組合せ数,_m,_n,_差の絶対値,_差,_現在のある数Aとの差,_m,_n,_ある数Aにもっとも近い数) :- abs(_現在のある数Aとの差) =< _差の絶対値, _ある数Aにもっとも近い数 is _ある数A + _現在のある数Aとの差,!. '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,_組合せ数,_m_1,_n_1,_m,_n,_差の絶対値,_差,_現在のある数Aとの差,_ある数Aにもっとも近い数) :- _組合せ数の二 is _組合せ数 + 1, '2と3だけを複数回かけてある数Aにもっとも近い数を作る'(_ある数A,_組合せ数の二,_m,_n,_差,_ある数Aにもっとも近い数). 差の絶対値と差(L1,_ある数A,_m,_n,_差の絶対値,_差) :- findmin([_差の絶対値,_差,_m,_n],( 総当り(L1,_m,_n), Z is 2 ^ _m * 3 ^ _n, _差 is _ある数A - Z), _差の絶対値 is abs(_差)), [_差の絶対値,_差,_m,_n]),!. 総当り(L,_m,_n) :- member(_m,L), member(_n,L). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1335517816/49 # [1] 授業単元 情報工学 # [2] 問題文 # n枚のカードからr枚のカードを選ぶ組み合わせを計算するプログラムを作成せよ。 # 但し、n≧1  r≧1  n≧rを前提してよい。(入力エラーの処理は不要) # 'n枚のカードからr枚のカードを選ぶ組み合わせを計算する'(_n,_r,_n枚のカードからr枚のカードを選ぶ組み合わせ) :- findall(N,between(1,_n,N),L), count(組合せ(L,_r,_),_n枚のカードからr枚のカードを選ぶ組み合わせ). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nCr(_n,_r,_組合せ数) :- _z is _n - _r + 1, 階乗(_n,_z,_組合せ数). 階乗(_r,_r,_r). 階乗(_n,_r,_組合せ数) :- _n_1 is _n - 1, 階乗(_n_1,_r,_組合せ数_1), _組合せ数 is _組合せ数_1 * _n. % 以下のサイトは # I'm trying to figure out how to generate a list of sets, where each set has a length of N and the sum of each set is X. # # I found this code: # # num_split(0,[]). # num_split(N, [X | List]):- # between(1,N,X), # plus(X,Y,N), # num_split(Y,List). # And I can use that to get a list of sets with sum X: # # num_split(6,List),length(List,5). # List = [1, 1, 1, 1, 2] ; # List = [1, 1, 1, 2, 1] ; # List = [1, 1, 2, 1, 1] ; # List = [1, 2, 1, 1, 1] ; # List = [2, 1, 1, 1, 1] ; # false. # The problem is that those are all permutations, and I'm looking for combinations. The output I'm looking for should be something like get_combos(Sum,Length,List): # # get_combos(6,2,List). # List = [5,1]; # List = [4,2]; # List = [3,3]; # false. # Any pointers? # 重複組み合わせの合計(_重複組み合わせの合計,_要素数,_重複組み合わせ) :- _出現する最大数 is _重複組み合わせの合計 - _要素数 + 1, findall(N,( between(1,_出現する最大数,N)), _1から出現する最大数までのならび), 重複組合せ(_1から出現する最大数までのならび,_要素数,_重複組み合わせ), sum(_重複組み合わせ,_重複組み合わせの合計). % 重複組合せ/3 % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1339338438/89 # 質問テンプレ】 # [1] 授業単元:組合せ最適化 # [2] 問題文(含コード&リンク): # # 以下のアルゴリズムを実装せよ。 # Find(j) # if j=0 何もしない # else # ・e[i][j]+C+OPT(i-1)を最小にするiを計算する # ・{p[i],p[i+1],・・・・,p[j]}を出力し、Find(i-1)を実行。 # # なおFind()は関数とし、変数はすべて計算済みとする。 # # iの範囲-> 1<=i<=j を満たす。 # e[i][j]+C+OPT(i-1)の型 →型の意味がわからなくて説明の仕方がわかりません。 # pの型 →同上 # 出力形式 →printfで表示してください。 # OPT()も計算済みです。 # OPT(j)=e[i][j]+C+OPT(i-1)になります。 # e[i][j]=Σ(k=i〜j) (y[k]-a*x[k]-b)^2 # このy[k],x[k]は入力で与えられてます。 # a,bは最小二乗法で求めてあります。 # 'Find'(0). 'Find'(_j) :- findmin([X,_i],( between(1,_j,_i), 'e[i][j]+C+OPT(i-1)'(_i,_j,X)), [_,_i]), '{p[i],p[i+1],・・・・,p[j]}を出力し'(_i,_j), _j_1 is _i - 1, 'Find'(_j_1). % 以下のサイトは # [1] プログラミング # [2] 50円切手が 5 枚, 80円切手が 4 枚, 120円切手が 3 枚あるとき, キーボードから金額 t を入力し, 金額の合計がちょうど t 円になるような切手の枚数の組合せを求めるプログラムを作成せよ. # # 次のような出力が得られることを確認せよ (表示形式は各自工夫せよ). # o 310円 → 50円×3枚+80円×2枚+120円×0枚 # o 390円 → 50円×3枚+80円×0枚+120円×2枚, 50円×3枚+80円×3枚+120円×0枚 # [3] 環境 #  [3.1] winXP sp2 #  [3.2] cygwin #  [3.3] C # [4] 2006年10月23日23時59分 # [5] 途中までやったんで埋める形でお願いします # 途中までやったぶんは次書きます '50円切手が 5 枚, 80円切手が 4 枚, 120円切手が 3 枚あるとき, キーボードから金額 t を入力し, 金額の合計がちょうど t 円になるような切手の枚数の組合せを求めるプログラムを作成せよ. ' :- 'キーボードから金額 t を入力し'(_金額t), findsetof([_50円切手の枚数,_80円切の手枚数,_120円切手の枚数],( 組合せ合計が金額tと一致する(_金額t,_50円切手の枚数,_80円切手の枚数,_120円切手の枚数)), _切手枚数の組合せならび), 組合せを表示する(_切手枚数の組合せならび). 'キーボードから金額 t を入力し'(_金額t) :- 整数を得る('金額t',_金額t > 0,_金額t). 組合せ合計が金額tと一致する(_金額t,_50円切手の枚数,_80円切手の枚数,_120円切手の枚数) :- between(1,12,N), 組合せ([50,50,50,50,80,80,80,80,120,120,120],N,L), sum(L,_金額t), 組合せ枚数を数える(L,_50円切手の枚数,_80円切手の枚数,_120円切手の枚数). 組合せ枚数を数える(L,_50円切手の枚数,_80円切手の枚数,_120円切手の枚数) :- count(member(50,L),_50円切手の枚数), count(member(80,L),_80円切手の枚数), count(member(120,L),_120円切手の枚数). 組合せを表示する(_切手枚数の組合せならび) :- append(_,[[_50円切手の枚数,_80円切手の枚数,_120円切手の枚数]|R],_切手枚数の組合せならび), writef('50円切手%t枚,80円切手%t枚,120円切手%t枚\n',[_50円切手の枚数,_80円切手の枚数,_120円切手の枚数]), R = [],!. 組合せを表示する(_) :- write('切手の組合せは作れません\n'). findsetof(A,B,L) :- findall(A,B,C), setof(A,member(A,C),L). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1349527750/562 # 以下のような行列の積を求めるプログラムを作成して下さい # # 行列xを表示 # 1 2 # 3 4 # 5 6 # # 行列yを表示 # 1 2 4 # 3 6 9 # # 行列xとyの積を表示 # # # ^^^^^^^^^^^^^^^^^^^^^^^ # 行列xとyの積を表示の下には計算結果を表示するようなプログラムを教えて下さい # お願いします # 行列の積(L1,L2,X) :- 転置(L2,L4), 二つの行列の要素の全ての行と行の組合せに対して要素を乗算した上で合計した値による行列を作る(L1,L4,X). 二つの行列の要素の全ての行と行の組合せに対して要素を乗算した上で合計した値による行列を作る([],_,[]) :- !. 二つの行列の要素の全ての行と行の組合せに対して要素を乗算した上で合計した値による行列を作る([_行_1|R1],_行列_2,[_合計ならび|R3]) :- 二つのならびの要素を順に乗算した値の合計のならび(_行_1,_行列_2,_合計ならび), 二つの行列の要素の全ての行と行の組合せに対して要素を乗算した上で合計した値による行列を作る(R1,_行列_2,R3). 二つのならびの要素を順に乗算した値の合計のならび(_,[],[]) :- !. 二つのならびの要素を順に乗算した値の合計のならび(L1,[L2|R2],[_合計値|R3]) :- 二つのならびの要素を順に乗算した値の合計を取る(L1,L2,_合計値), 二つのならびの要素を順に乗算した値の合計のならび(L1,R2,R3). 二つのならびの要素を順に乗算した値の合計を取る([],[],0) :- !. 二つのならびの要素を順に乗算した値の合計を取る([A1 / A2|R1],[B1 / B2|R2],S) :- S01 is A1 * B1, S02 is A2 * B2, 約分(S01 / S02,S1), 二つのならびの要素を順に乗算した値の合計を取る(R1,R2,S2), 分数を含む加算(S1,S2,S),!. 二つのならびの要素を順に乗算した値の合計を取る([A1 / A2|R1],[B|R2],S) :- S0 is A1 * B, 約分(S0 / A2,S1), 二つのならびの要素を順に乗算した値の合計を取る(R1,R2,S2), 分数を含む加算(S1,S2,S),!. 二つのならびの要素を順に乗算した値の合計を取る([A|R1],[B1 / B2|R2],S) :- S0 is A * B1, 約分(S0 / B2,S1), 二つのならびの要素を順に乗算した値の合計を取る(R1,R2,S2), 分数を含む加算(S1,S2,S),!. 二つのならびの要素を順に乗算した値の合計を取る([A|R1],[B|R2],S) :- S1 is A * B, 二つのならびの要素を順に乗算した値の合計を取る(R1,R2,S2), 分数を含む加算(S1,S2,S). 分数を含む加算(A1 / A2,B1 / B2,C) :- S1 is A1 * B2 + A2 * B1, S2 is A2 * B2, 約分(S1 / S2,C),!. 分数を含む加算(A1 / A2,B,C) :- S1 is A1 + A2 * B, 約分(S1 / A2,C),!. 分数を含む加算(A,B1 / B2,C) :- S1 is B1 + B2 * A, 約分(S1 / B2,C),!. 分数を含む加算(A,B,C) :- C is A + B. 転置([[]|_],[]) :- !. 転置(L,[L1|R2]) :- 転置(L,L2,L1), 転置(L2,R2). 転置([],[],[]) :- !. 転置([[A|R1]|R2],[R1|R3],[A|R4]) :- 転置(R2,R3,R4). 約分(B / A,X) :- 最大公約数(B,A,C), _分子 is B // C, _分母 is A // C, 約分の二(_分子,_分母,X),!. 約分の二(_分子,1,_分子) :- !. 約分の二(_分子,1.0,_分子) :- !. 約分の二(_分子,_分母,_分子 / _分母). 最大公約数(M,N,X) :- 最大公約数をユークリッドの互除法で求める(M,N,X),!. 最大公約数をユークリッドの互除法で求める(M,N,N) :- 0 is M mod N,!. 最大公約数をユークリッドの互除法で求める(M,N,X) :- Mod is M mod N, 最大公約数をユークリッドの互除法で求める(N,Mod,X). % 以下のサイトは # # 単位節から選択された引数リストの組合せ # # 単位節から選択された引数リストの順列 # 単位節組合せ(_単位節項,_射影項ならび,_条件,_組合せ数,X) :- 単位節からならびへの射影(_単位節項,_射影項ならび,_条件,LL), 組合せ(LL,_組合せ数,X). 単位節順列(_単位節項,_射影項ならび,_条件,_組合せ数,X) :- 単位節からならびへの射影(_単位節項,_射影項ならび,_条件,LL), 順列(LL,_組合せ数,X). 単位節からならびへの射影(_単位節項,_射影項ならび,_条件,LL) :- list(_射影項ならび), _単位節項=..[_|_引数ならび], findall(_射影項ならび,( call((_単位節項,_条件))), LL). 単位節からならびへの射影(_単位節項,_射影項,_条件,LL) :- \+(list(_射影項)), _単位節項=..[_|_引数ならび], findall(_射影項,( call((_単位節項,_条件))), LL). % % 単位節組合せ/4と単位節順列/4は高階述語である。 % 高階述語を使用する場合、引数変数の扱いに注意する必要がある。 % % 射影項ならび、乃ちリストである場合はその要素は必ず単位節項の引数に含まれる必要がある。 % リストでなく単体で射影項が指定された場合も同様である。 % 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R3]) :- N > 1, M is N - 1, 組合せ(R1,M,R3). 組合せ([_|R1],N,L) :- N > 1, 組合せ(R1,N,L). 順列(Y,0,_,[]). 順列(Y,N,EL,[A|X]) :- \+(member(A,EL)), del(Z = Y - A), M is N - 1, 順列(Z,M,EL,X) . 順列(Y,N,EL,[_|X]) :- member(A,EL), 順列(Z,M,EL,X). 順列(Y,0,[]). 順列(Y,N,[A|X]) :- N > 0, del(A,Y,Z), M is N - 1, 順列(Z,M,X). del(A,[A|X],X). del(A,[B|X],[B|Y]) :- del(A,X,Y). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1357748713/303 # [1] 授業単元: 情報処理概論 # [2] 問題文(含コード&リンク): # 大、中、小の3 個のさいころを同時にふった時、出た目の和がm になるような目の出方をすべて求めるプログラムを作りなさい。 # ただし、m の値はキーボードから入力するものとする。表示を工夫して見やすい出力にすること。 # '大、中、小の3 個のさいころを同時にふった時、出た目の和がm になるような目の出方をすべて求めるプログラムを作りなさい。 ただし、m の値はキーボードから入力するものとする。表示を工夫して見やすい出力にすること。'(_大,_中,_小) :- 'm の値はキーボードから入力するものとする'(_m), '大、中、小の3 個のさいころを同時にふった時、出た目の和がm になるような目の出方をすべて求める'(_m,_大,_中,_小). 'm の値はキーボードから入力するものとする'(_m) :- 整数を得る('2以上18以下の整数',(_m >= 2,_m =< 18),_m). '大、中、小の3 個のさいころを同時にふった時、出た目の和がm になるような目の出方をすべて求める'(_m,_大,_中,_小) :- 重複組合せ([1,2,3,4,5,6],3,[_大,_中,_小]), _m is _大 + _中 + _小. 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1364700745/821 # [1] 授業数学の問題をC言語で解く # [2] 問題 # 整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら # その三素数を出力するプログラムを作成せよ。複数組み合わせの場合最初に # 見つけたものを出力せよ。 # [3.1] 7 # [3.2] gcc # [3.3] C # [4] 期限:25日 # [5] その他制限: 純粋Cライブラリ。 # '整数xを0から100000までの整数として,xが3つの素数の和で表現できるならその三素数を出力するプログラムを作成せよ。複数組み合わせの場合最初に見つけたものを出力せよ。'(_x) :- findall(N,between(1,100000,N),L1), エラトステネスの篩(L1,_100000以下の素数ならび), 組合せ(_100000以下の素数ならび,3,[N1,N2,N3]), _x is N1 + N2 + N3, writef('%t,%t,%t\n',[N1,N2,N3]),!. 組合せ(X,1,[A]) :- member(A,X) . 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X) . 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは 冪集合(_対象集合,_冪集合) :- findall(_部分集合,( 部分集合(_対象集合,_部分集合)), _冪集合). 部分集合([], []). 部分集合([_|R1], LL) :- 部分集合(R1,LL). 部分集合([L|R1], [L|R2]) :- 部分集合(R1,R2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 冪集合(_集合,_冪集合) :- length(_集合,Len), findall(L,( between(1,Len,N), 組合せ(_集合,N,L)), _冪集合_0), _冪集合 = [[]|_冪集合_0]. 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 以下のサイトは 冪集合和(_対象集合,_冪集合和) :- findall(_部分集合和,( 部分集合和(_対象集合,_部分集合和)), _冪集合和). 部分集合和([], 0). 部分集合和([_|R1],_部分集合和) :- 部分集合和(R1,_部分集合和). 部分集合和([N|R1], _部分集合和) :- 部分集合和(R1,_部分集合和_2), _部分集合和 is _部分集合和_2 + N. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 冪集合和(_集合,_冪集合和) :- length(_集合,Len), findall(S,( between(1,Len,N), 組合せ和(_集合,N,L,S)), LS), _冪集合和 = [0|LS]. 組合せ和(X,1,[A],A) :- member(A,X). 組合せ和([A|Y],N,[A|X],S) :- N > 1, M is N - 1, 組合せ和(Y,M,X,S1), S is S1 + A. 組合せ和([_|Y],N,A,S) :- N > 1, 組合せ和(Y,N,A,S). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1364700745/889 # [1] 授業数学の問題をC言語で解く # [2] 問題 # 整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら # その三素数を出力するプログラムを作成せよ。複数組み合わせの場合最初に # 見つけたものを出力せよ。 # [3.1] 7 # [3.2] gcc # [3.3] C # [4] 期限:28日9:00 # [5] その他制限: 純粋Cライブラリ。 # # '整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら その三素数を出力するプログラムを作成せよ。 複数組み合わせの場合最初に見つけたものを出力せよ。'(_素数_1,_素数_2,_素数_3) :- 整数を得る(整数x,(_x >= 2,_x =< 100000),_x), xが3つの素数の和で表現できる(_x,_素数_1,_素数_2,_素数_3), 'その三素数を出力せよ。'(_x,_素数_1,_素数_2,_素数_3),!. xが3つの素数の和で表現できる(_x,_素数_1,_素数_2,_素数_3) :- findall(N,between(2,_x,N),_2から_xまでの整数ならび), エラトステネスの篩(_2から_xまでの整数ならび,_2から高々_xまでの素数ならび), 組合せ(_2から高々_xまでの素数ならび,3,[_素数_1,_素数_2,_素数_3]), _x is _素数_1 + _素数_2 + _素数_3. 'その三素数を出力せよ。'(_x,_素数_1,_素数_2,_素数_3) :- writef('%t+%t+%t = %t\n',[_素数_1,_素数_2,_素数_3,_x). エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 整数を得る/3 % % % 注意 % % 「複数組み合わせの場合最初に見つけたものを出力せよ。」は述語定義できない。 % !(カット)を述語に置き換えることはできない。 % % 最初の述語の最後の ! が「複数組み合わせの場合最初に見つけたものを出力せよ。」の意味である。 % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1364700745/889 # [1] 授業数学の問題をC言語で解く # [2] 問題 # 整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら # その三素数を出力するプログラムを作成せよ。複数組み合わせの場合最初に # 見つけたものを出力せよ。 # [3.1] 7 # [3.2] gcc # [3.3] C # [4] 期限:28日9:00 # [5] その他制限: 純粋Cライブラリ。 # # '整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら その三素数を出力するプログラムを作成せよ。 複数組み合わせの場合最初に見つけたものを出力せよ。'(_素数_1,_素数_2,_素数_3) :- 整数を得る(整数x,(_x >= 2,_x =< 100000),_x), findall([_素数_1,_素数_2,_素数3],( xが3つの素数の和で表現できる(_x,_素数_1,_素数_2,_素数_3)), _3つの素数のならび), 'その三素数を出力せよ。複数組み合わせの場合最初に見つけたものを出力せよ。'(_x,_3つの素数のならび). xが3つの素数の和で表現できる(_x,_素数_1,_素数_2,_素数_3) :- findall(N,between(2,_x,N),_2から_xまでの整数ならび), エラトステネスの篩(_2から_xまでの整数ならび,_2から高々_xまでの素数ならび), 組合せ(_2から高々_xまでの素数ならび,3,[_素数_1,_素数_2,_素数_3]), _x is _素数_1 + _素数_2 + _素数_3. 'その三素数を出力せよ。複数組み合わせの場合最初に見つけたものを出力せよ。'(_x,_3つの素数のならび) :- member([_素数_1,_素数_2,_素数_3],_3つの素数のならび), 'その三素数を出力せよ。'(_x,_素数_1,_素数_2,_素数_3),!. 'その三素数を出力せよ。'(_x,_素数_1,_素数_2,_素数_3) :- writef('%t+%t+%t = %t\n',[_素数_1,_素数_2,_素数_3,_x). エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 整数を得る/3 % % 注意 % % ここでは、findall/3を用いて、xが3つの素数の和で表現できる/4の全解を % 一旦ならびに取得することによって、 % その後の出力述語を決定性にすることを可能にしている。 % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1370620300/140 # [1] 授業数学の問題をC言語で解く # [2] 問題 # 整数xを0から100000までの整数として,xが3つの素数の和で表現できるなら # その三素数を出力するプログラムを作成せよ。複数組み合わせの場合最初に # 見つけたものを出力せよ。 # [3.1] 7 # [3.2] gcc # [3.3] C # [4] 期限:28日9:00 # [5] その他制限: 純粋Cライブラリ。 # # 差が6となる素数ペアをリストアップする(L) :- 整数を得る(整数x,_x), findall([_素数_1,_素数_2],( 二つの素数の差が6となる(_x,_素数_1,_素数_2)), L). 二つの素数の差が6となる(_x,_素数_1,_素数_2) :- findall(N,between(2,_x,N),_2から_xまでの整数ならび), エラトステネスの篩(_2から_xまでの整数ならび,_2から高々_xまでの素数ならび), 組合せ(_2から高々_xまでの素数ならび,2,[_素数_1,_素数_2]), 6 is abs(_素数_1 - _素数_2). エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 整数を得る/2 % % 以下のサイトは # # お題:100以下の自然数でふたつの素数の積で表せる数を昇順にすべて表示せよ。 # '100以下の自然数でふたつの素数の積で表せる数を昇順にすべて表示せよ。' :- '100までの素数をエラトステネスの篩で求める'(_100までの素数ならび), '100以下の自然数でふたつの素数の積で表せる数を'(_100までの素数ならび,_ふたつの素数の積で表せる数ならび), '昇順にすべて表示せよ。'(_ふたつの素数の積で表せる数ならび). '100以下の自然数でふたつの素数の積で表せる数を'(_100までの素数ならび,_ふたつの素数の積で表せる数ならび) :- findall(_100までの自然数,( '100以下の自然数で'(_100以下の自然数), ふたつの素数の積で表せる数(_100までの自然数,_100までの素数ならび)), _ふたつの素数の積で表せる数ならび). '100以下の自然数で'(_100以下の自然数) :- between(1,100,_100以下の自然数). ふたつの素数の積で表せる数(_100以下の自然数,_100までの素数ならび) :- 組合せ(_100までの素数ならび,2,[_素数_1,_素数_2]), _100以下の自然数 is _素数_1 * _素数_2,!. '昇順にすべて表示せよ。'(_ふたつの素数の積で表せる数ならび) :- sort(_ふたつの素数の積で表せる数ならび,_整列したふたつの素数の積で表せる数ならび), atomic_list_concat(_整列したふたつの素数の積で表せる数ならび,' ',_表示文字列), writef('%t\n',[_表示文字列]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '100までの素数をエラトステネスの篩で求める'(_100までの素数ならび) :- findall(N,between(2,100,N),L), エラトステネスの篩(L,_100までの素数ならび). エラトステネスの篩(_,[],[]) :- !. エラトステネスの篩(N,[A|R1],R2) :- 0 is A mod N, エラトステネスの篩(N,R1,R2),!. エラトステネスの篩(N,[A|R1],[A|R2]) :- エラトステネスの篩(N,R1,R2). エラトステネスの篩([],[]) :- !. エラトステネスの篩([A|R1],[A|R2]) :- エラトステネスの篩(A,R1,L), エラトステネスの篩(L,R2). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). % 以下のサイトは 全順列(L,LL) :- length(L,Len), ダミー要素を付加する(Len,L,L_2), findall(L_4,( 順列(L_2,3,L_3), findall(A,(member(A,L_3),\+(var(A))),L_4)), LL_1), sort(LL_1,LL). 全組合せ(L,LL) :- length(L,Len), ダミー要素を付加する(Len,L,L_2), findall(L_4,( 組合せ(L_2,3,L_3), findall(A,(member(A,L_3),\+(var(A))),L_4)), LL_1), sort(LL_1,LL). ダミー要素を付加する(Len,L_1,L_2) :- length(L_v,Len), append(L_1,L_v,L_2),!. % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1376111807/98 # '10円と100円と1000円の買い物をした時に払う # 金額のリストを考えてみました # # map(sum)[[x,y,z]|x<-[0,10],y<-[0,100],z<-[0,1000]] # # これを任意の組に拡張するには # どういう方法があるでしょうか? # '10円と100円と1000円の買い物をした時に払う 金額のリストを考えてみました map(sum)[[x,y,z]|x<-[0,10],y<-[0,100],z<-[0,1000]] これを任意の組に拡張するには どういう方法があるでしょうか?'(_買い物をした時に支払う金額ならび,_金額組合せ) :- 買い物をした時に払う金額(_買い物をした時に支払う金額ならび,_重複を許す金額ならび), sort(_重複を許す金額ならび,_金額組合せ). 買い物をした時に払う金額(_買い物をした時に支払う金額ならび,_金額ならび) :- length(_買い物をした時に支払う金額ならび,_ならびの長さ), findall(_金額,( between(1,_ならびの長さ,N), 組合せ(_買い物をした時に支払う金額ならび,N,L), sum(L,_金額)), _金額ならび). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1354393458/650 # # 81以下の自然数で九九に現れない数を昇順にすべて表示せよ。 # '81以下の自然数で九九に現れない数を昇順にすべて表示せよ。' :- '81以下の自然数で'(_81以下の自然数), 九九に現れない数を(_81以下の自然数), '昇順にすべて表示せよ。'(_81以下の自然数), _81以下の自然数 = 81. '81以下の自然数で'(_81以下の自然数) :- between(1,81,_81以下の自然数). 九九に現れない数を(_81以下の自然数) :- \+(九九に現れる数を(_81以下の自然数)). 九九に現れる数を(_81以下の自然数) :- 組合せ([1,2,3,4,5,6,7,8,9],2,[M,N]), _81以下の自然数 is M * N,!. 表示せよ(_81以下の自然数) :- writef('%t ',[_81以下の自然数]). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1337692704/777 # 【課題】X * Y = 123 になる素数 XとYを求め、結果をすべて表示しなさい。 # 【 期限 】2013/10/15 # 【 Ver  】"1.7.0_11" # がんばってますが期限までに理解できる気がしないので # 基礎的なことだとは思いますが、よろしく御願いします 'X * Y = 123 になる素数 XとYを求め、結果をすべて表示しなさい。' :- forall('X * Y = 123 になる素数 XとYを求め、'(X,Y), '結果をすべて表示しなさい。'(X,Y)). 'X * Y = 123 になる素数 XとYを求め、'(X,Y) :- findall(N,between(2,123,N),L), エラトステネスの篩(L,_素数ならび), 重複組合せ(_素数ならび,2,[X,Y]), 123 is X * Y. '結果をすべて表示しなさい。'(X,Y) :- writef('X=%t,Y=%t\n',[X,Y]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X) . 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A) . エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). % 以下のサイトは # WinXP HomeでBorland C++ Compiler 5.5 # ・1からnまでの整数1個ずつで構成される全部でn個の要素から、 # r個の要素を重複なく取り出した場合の組み合わせを全て昇順で並べたものの中で、 # 具体的な組み合わせと具体的な序列が何番目かを相互に返すプログラム。 # 例 43C6なら、序数5054214は組み合わせ11,14,17,18,34,36 # 例 43C6なら、組み合わせ13,28,29,37,38,41は5498643 # コマンドはncr.exe [n],[r] [co][ra] x.txtの様な感じで '1からnまでの整数1個ずつで構成される全部でn個の要素から、 r個の要素を重複なく取り出した場合の組み合わせを全て昇順で並べたものの中で、 具体的な組み合わせと具体的な序列が何番目かを相互に返す'(_n,_r,_序数,_具体的な組合せ) :- findall(M,between(1,_n,M),L), findall(_組合わせ,組合せ(L,_r,_組合わせ),_組合わせならび), nth1(_序数,_組合わせならび,_具体的な組合わせ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R3]) :- N > 1, M is N - 1, 組合せ(R1,M,R3). 組合せ([_|R1],N,L) :- N > 1, 組合せ(R1,N,L). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1381909900/142 # [1] 授業単元:C言語 # [2] 問題文(含コード&リンク): # テキストファイルを作りそのなかに整数5個数字を入れるそのテキストファイルの中身を出力せよ # input関数とshow関数を作ること # コマンド引数にテキストファイルの名前を入れること # 'テキストファイルを作りそのなかに整数5個数字を入れるそのテキストファイルの中身を出力せよ。コマンド引数にテキストファイルの名前を入れること' :- コマンド引数からテキストファイルの名前を得る(_テキストファイル), テキストファイルを作りそのなかに整数5個数字を入れるそのテキストファイルの中身を出力せよ(_テキストファイル). コマンド引数からテキストファイルの名前を得る(_テキストファイル) :- current_prolog_flag(argv,ParameterList), append(_,['--'|[_テキストファイル]],ParameterList). テキストファイルを作りそのなかに整数5個数字を入れるそのテキストファイルの中身を出力せよ(_テキストファイル) :- テキストファイルを作りそのなかに整数5個数字を入れる(_テキストファイル,Outstream), そのテキストファイルの中身を出力せよ(_テキストファイル). テキストファイルを作りそのなかに整数5個数字を入れる(_テキストファイル) :- open(_テキストファイル,write,Outstream). そのなかに整数5個数字を入れる(Outstream), close(Outstream). そのなかに整数5個数字を入れる(Outstream) :- between(1,5,_何番目), 整数を得る(_整数), writef(Outstream,'%t\n',[_整数]), _何番目 = 5. そのテキストファイルの中身を出力せよ(_テキストファイル) :- open(_テキストファイル,read,Instream), copy_stream_data(Instream,user_output), close(Instream). % % ここではズルをして組込述語 copy_stream_data/2 を使って見た。 % % 本来ならget_lines/2とput_lines/2の組合せでコピーを表現するところ。 % % そのテキストファイルの中身を出力せよ(_テキストファイル) :- % get_lines(_テキストファイル,_行ならび), % put_lines(user_output,_行ならび). % % get_lines(_ファイル名,_行ならび) :- % open(_ファイル名,read,Instream), % findall(_行,( % repeat, % ( at_end_of_stream(Instream),!,fail; % get_line(Instream,_行))), % _行ならび), % close(Instream). % % put_lines(_ファイル名,_行ならび) :- % open(_ファイル名,write,Outstream), % forall(nth1(_,_行ならび,_行),writef(Outstream,'%t\n',[_行])), % close(Outstream). % % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1337692704/832 # 【課題】X * Y = 125 になる 素数Xと素数Yをクラスを3つ使って求め結果を表示しなさい # 【 期限 】2013/11/06 # 【 Ver  】"1.7.0_11" # # いまいちわからず困っています。 # よろしくお願いします。 'X * Y = 125 になる 素数Xと素数Yをクラスを3つ使って求め結果を表示しなさい' :- 'X * Y = 125 になる 素数Xと素数Yを求める'(_X_Y_組合せならび),!, forall(member([_X,_Y],_X_Y_組合せならび), 表示しなさい(_X,_Y)). 'X * Y = 125 になる 素数Xと素数Yをクラスを3つ使って求め結果を表示しなさい' :- writef('解がありません!\n'), fail. 'X * Y = 125 になる 素数Xと素数Yを求める'(_X_Y_組合せならび) :- '125以下の素数ならびを得る'(_125以下の素数ならび), findall([_X,_Y],( 組合せ(_125以下の素数ならび,2,[_X,_Y]), 125 is X * Y), _X_Y_組合せならび), \+(_X_Y_組合せならび=[]). '125以下の素数ならびを得る'(_125以下の素数ならび) :- findall(N,between(2,125,N),_2から125までの整数ならび), エラトステネスの篩(_2から125までの整数ならび,_125以下の素数ならび). 組合せ(X,1,[A]) :- member(A,X) . 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). 表示しなさい(_X,_Y) :- writef('%t %t\n',[_X,_Y]). % 以下のサイトは http://toro.2ch.net/test/read.cgi/tech/1337692704/835 # 【課題】X * Y = 115 になる 素数Xと素数Yをクラスを3つ使って求め結果を表示しなさい # 【 期限 】2013/11/06 # 【 Ver  】"1.7.0_11" # # いまいちわからず困っています。 # よろしくお願いします。 'X * Y = 115 になる 素数Xと素数Yをクラスを3つ使って求め結果を表示しなさい' :- forall('X * Y = 115 になる 素数Xと素数Yを求める'(_X,_Y), 表示しなさい(_X,_Y)). 'X * Y = 115 になる 素数Xと素数Yを求める'(_X,_Y) :- '115以下の素数ならびを得る'(_115以下の素数ならび), 組合せ(_115以下の素数ならび,2,[_X,_Y]), 115 is _X * _Y. '115以下の素数ならびを得る'(_115以下の素数ならび) :- findall(N,between(2,115,N),_2から115までの整数ならび), エラトステネスの篩(_2から115までの整数ならび,_115以下の素数ならび). 組合せ(X,1,[A]) :- member(A,X) . 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). エラトステネスの篩([],[]) :- !. エラトステネスの篩([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). 表示しなさい(_X,_Y) :- writef('%t\n',[_X,_Y]). % 以下のサイトは # 出題場所 :: http://toro.2ch.net/test/read.cgi/tech/1357191974/449 # お題:与えられた配列をなるべくN等分せよ。 # 要素の順番は入れ替えず、配列の配列として返す。 # Nは1以上とする。 # データ構造は、リスト、ベクタ、タプルなどでも可。 # # 回答例およびチェック用出力例: ruby 1.8.6 # def narudiv(a, n) # d, m = a.size.divmod(n) # (1..n).map {|i| a.slice!(0, d + (i <= m ? 1 : 0))} # end # p narudiv((1..10).to_a, 3) # p narudiv((1..15).to_a, 4) # ↓ # [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]] # [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15]] # # '与えられた配列をなるべくN等分せよ。 要素の順番は入れ替えず、配列の配列として返す。 Nは1以上とする。 データ構造は、リスト、ベクタ、タプルなどでも可。'(_N,_ならび,_N等文されたならび) :- length(_ならび,_要素数), _D is _要素数 // _N, _M is _要素数 mod N, '_Mを各_Dに割り振る'(_D,_M,_N,_N等分されたならび), flatten(_N等分されたならび,_ならび). '_Mを各_Dに割り振る'(_D,_M,_N,_N等分されたならび) :- length(_N等分されたならび,_N), findall(_n,between(1,_N,_n),L1), 組合せ(L1,_M,_組合せ), '_N等分されたならびを充実させる'(_D,_組合せ,_N等分されたならび). '_N等分されたならびを充実させる'(_D,_組合せ,_N等分されたならび) :- findall(L2,( nth1(_nth1,_N等分されたならび,L), length(L,_D), '_nth1が_組合せに存在するときには枠を追加する'(_nth1,L,_組合せ,L2)), _N等分されたならび). '_nth1が_組合せに存在するときには枠を追加する'(_nth1,L,_組合せ,[_|L]) :- member(_nth1,_組合せ),!. '_nth1が_組合せに存在するときには枠を追加する'(_,L,_組合せ,L). 組合せ(L,1,[A]) :- member(A,L). 組合せ([A|R1],N,[A|R3]) :- N > 1, M is N - 1, 組合せ(R1,M,R3). 組合せ([_|R1],N,L) :- N > 1, 組合せ(R1,N,L). % 以下のサイトは # teitter by @SaitoAtsushi 2014-02-16 # 問題 三人の年齢(_1,_2,_3) :- 'Bの年齢'(Bの年齢), '36の約数の重複組合せから年齢候補を得る'(_1,_2,_3), Bの年齢 is _1 + _2 + _3, 最も高い年齢の子供は一人(_1,_2,_3). 'Bの年齢'(Bの年齢) :- '36の約数の重複組合せから年齢候補を得る'(_1,_2,_3), 最も高い年齢の子供が複数いる(_1,_2,_3), Bの年齢 is _1 + _2 + _3. '36の約数の重複組合せから年齢候補を得る'(_1,_2,_3) :- '36の約数を得る'(1,_36の約数ならび), 重複組合せ(_36の約数ならび,3,[_1,_2,_3]), 36 is _1 * _2 * _3. '36の約数を得る'(36,[36]) :- !. '36の約数を得る'(N,[N|R]) :- 0 is 36 mod N,!, N_2 is N + 1, '36の約数を得る'(N_2,R). '36の約数を得る'(N,[N|R]) :- N_2 is N + 1, '36の約数を得る'(N_2,R). 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). 最も高い年齢の子供は一人(_1,_2,_3) :- append(L1,[_最大年齢|L2],[_1,_2,_3]), \+((member(A1,L1),A1 >= _最大年齢)), \+((member(A2,L2),A2 >= _最大年齢)),!. 最も高い年齢の子供が複数いる(_1,_2,_3) :- append(L1,[_最大年齢|L2],[_1,_2,_3]), \+((member(A1,L1),A1 > _最大年齢)), \+((member(A2,L2),A2 > _最大年齢)), (member(_最大年齢,L1);member(_最大年齢,L2)). % 以下のサイトは # 出典 :: http://pc12.2ch.net/test/read.cgi/tech/1136994325/954 # pascal pcpad # 1個の自然数nを適当に決めて、nチームが参加する # リーグ戦の全試合を表示するプログラムを書きなさい。 '1個の自然数nを適当に決めて、nチームが参加するリーグ戦の全試合を表示する' :- '1個の自然数nを適当に決めて、'(_n), 'nチームが参加するリーグ戦の全試合を表示する'(_n). '1個の自然数nを適当に決めて、'(_n) :- _n is random(16) + 3. 'nチームが参加するリーグ戦の全試合を表示する'(_n) :- 'nチームが参加する'(_n,_nチームが参加する), forall( リーグ戦の全試合を(_nチームが参加する,_チーム番号_1,_チーム番号_2), 表示する(_チーム番号_1,_チーム番号_2)). 'nチームが参加する'(_n,_nチームが参加する) :- findall(M,between(1,_n,M),_nチームが参加する). リーグの全試合を(_nチームが参加する,_チーム番号_1,_チーム番号_2) :- 組合せ(_nチームが参加する,2,[_チーム番号_1,_チーム番号_2]). 組合せ(X,1,[A]) :- member(A,X). 組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 組合せ(Y,M,X). 組合せ([_|Y],N,A) :- N > 1, 組合せ(Y,N,A). 表示する(_チーム番号_1,_チーム番号_2) :- チーム(_チーム番号_1,_チーム名_1), チーム(_チーム番号_2,_チーム名_2), writef('%t-%t\n',[_チーム名_1,_チーム名_2])). チーム(1,'サンフレッチェ広島). チーム(2,'横浜F・マリノス'). チーム(3,川崎フロンターレ). チーム(4,セレッソ大阪). チーム(5,鹿島アントラーズ). チーム(6,浦和レッズ). チーム(7,アルビレックス新潟). チーム(8,'FC東京'). チーム(9,清水エスパルス). チーム(10,柏レイソル). チーム(11,名古屋グランパス). チーム(12,サガン鳥栖). チーム(13,ベガルタ仙台). チーム(14,大宮アルディージャ). チーム(15,ヴァンフォーレ甲府). チーム(16,湘南ベルマーレ). チーム(17,ジュビロ磐田). チーム(18,大分トリニータ). % 以下のサイトは # 出典 :: スレ立てるまでもない質問はここで135匹目 #794" # 100という整数があります # これを25から40の範囲の整数として3等分します # 例 # 30, 30, 40 # 35, 35, 30 # 25, 40, 35 '100という整数があります。これを25から40の範囲の整数として3等分します。'(N1,N2,N3) :- findall(N,between(25,40,N),L), 重複組合せ(L,3,[N1,N2,N3]), 100 is N1 + N2 + N3. 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A). % 以下のサイトは # 出典 :: スレ立てるまでもない質問はここで135匹目 #794" # 100という整数があります # これを25から40の範囲の整数として3等分します # 例 # 30, 30, 40 # 35, 35, 30 # 25, 40, 35 '100という整数があります。これを25から40の範囲の整数として3等分します。'(N1,N2,N3) :- findall(N,between(25,40,N),L), 重複組合せ(L,3,[N1,N2,N3]), 100 is N1 + N2 + N3. 重複組合せ(_候補ならび,1,[A]) :- 要素数が1の場合は候補ならびから順にAを生成して行きます(_候補ならび,A). 重複組合せ([A|_候補ならび],_要素数,[A|_重複組合せ]) :- '候補ならびは変更せずに(重複の所以)生成要素数を減らしながら重複組合せを組み立てます'([A|_候補ならび],_要素数,_重複組合せ). 重複組合せ([_|_候補ならび],_要素数,_重複組合せ) :- 'バックトラックして来たら、候補ならびをひとつずつ減らしながら重複組合せを生成します'(_候補ならび,_要素数,_重複組合せ). 要素数が1の場合は候補ならびから順にAを生成して行きます(_候補ならび,A) :- member(A,_候補ならび). '候補ならびは変更せずに(重複の所以)生成要素数を減らしながら重複組合せを組み立てます'([A|_候補ならび],_要素数,_重複組合せ) :- _要素数 > 1, _要素数_1 is _要素数 - 1, 重複組合せ([A|_候補ならび],_要素数_1,_重複組合せ). 'バックトラックして来たら、候補ならびをひとつずつ減らしながら重複組合せを生成します'(_候補ならび,_要素数,_重複組合せ) :- _要素数 > 1, 重複組合せ(_候補ならび,_要素数,_重複組合せ). % 以下のサイトは 色(赤). 色(青). 色(緑). 色(黄). 区画(a). 区画(b). 区画(c). 区画(d). 隣接(a,b). 隣接(b,d). 隣接(a,c). 隣接(c,d). 区画変数([_1,_2,_3,_4]). 塗り絵(_区画変数ならび) :- 色組合せならび(_色組合せならび), 区画変数組合せ(_区画変数組合せ), 色合わせ(_色組合せならび,_区画変数組合せ). 色組合せならび(_色組合せならび) :- findall(_色,色(_色),_色ならび), findall([_色_1,_色_2],( 色を双方向に順列で取る(_色_1,_色_2)), _色組合せならび). 色を順列で双方向に取る(_色_1,_色_2) :- 順列(_色ならび,2,[A,B]), 双方向に取る(A,B,_色_1,_色_2). 双方向に取る(A,B,A,B). 双方向に取る(A,B,B,A). 色合わせ(_,[]). 色合わせ(L1,L2) :- select([A,B],L2,R2), member([A,B],L1), 色合わせ(L1,R2). 区画変数組合せ(_区画変数ならび,_区画変数組合せならび) :- findall(_区画名,区画(_区画名),_区画名ならび), findall([_区画変数_1,_区画変数_2],( 順列(_区画名ならび,2,[_区画名_1,_区画名_2]), 区画変数に変換(_区画名_1,_区画名_2,_区画変数_1,_区画変数_2)), _区画変数組合せならび). 区画変数に変換(_区画名_1,_区画名_2,_区画変数_1,_区画変数_2) :- nth1(_nth1,_区画名ならび,_区画名_1), nth1(_nth2,_区画名ならび,_区画名_2), nth1(_nth1,_区画変数ならび,_区画変数_1_1), nth1(_nth2,_区画変数ならび,_区画変数_2_1), 双方向にに変換(_区画変数_1_1,_区画変数_2_1,_区画変数_1,_区画変数_2). 双方向に変換(_区画変数_1_1,_区画変数_2_1,_区画変数_1_1,_区画変数_2_1). 双方向に変換(_区画変数_1_1,_区画変数_2_1,_区画変数_2_1,_区画変数_1_1). % 以下のサイトは 色(赤). 色(青). 色(緑). 色(黄). 区画(a). 区画(b). 区画(c). 区画(d). 隣接(a,b). 隣接(b,d). 隣接(a,c). 隣接(c,d). 塗り絵(_区画の定義順に対応した区画色変数ならび) :- 色組合せならび(_色組合せならび), 区画変数組合せ(_区画の定義順に対応した区画色変数ならび,_区画変数組合せならび), 色合わせ(_色組合せならび,_区画変数組合せならび). 色組合せならび(_色組合せならび) :- findall(_色,色(_色),_色ならび), findall([_色_1,_色_2],( 色を双方向に順列で取る(_色_1,_色_2)), _色組合せならび). 色を順列で双方向に取る(_色_1,_色_2) :- 順列(_色ならび,2,[A,B]), 双方向に取る(A,B,_色_1,_色_2). 双方向に取る(A,B,A,B). 双方向に取る(A,B,B,A). 色合わせ(L1,L2) :- select([A,B],L2,R2), member([A,B],L1), 色合わせ(L1,R2). 区画変数組合せ(_区画変数ならび,_区画変数組合せならび) :- 区画名ならびと区画変数ならびを得る(_区画名ならび,_区画変数ならび), findall([_区画変数_1,_区画変数_2],( 順列(_区画名ならび,2,[_区画名_1,_区画名_2]), 区画変数に変換(_区画名_1,_区画名_2,_区画変数_1,_区画変数_2)), _区画変数組合せならび). 区画名ならびと区画変数ならびを得る(_区画名ならび,_区画変数ならび) :- findall(_区画名,区画(_区画名),_区画名ならび), length(_区画名ならび,_要素数), length(_区画変数ならび,_要素数),!. 区画変数に変換(_区画変数ならび,_区画名_1,_区画名_2,_区画変数_1,_区画変数_2) :- nth1(_nth1,_区画名ならび,_区画名_1), nth1(_nth2,_区画名ならび,_区画名_2), nth1(_nth1,_区画変数ならび,_区画変数_1_1), nth1(_nth2,_区画変数ならび,_区画変数_2_1), 双方向にに変換(_区画変数_1_1,_区画変数_2_1,_区画変数_1,_区画変数_2). 双方向に変換(_区画変数_1_1,_区画変数_2_1,_区画変数_1_1,_区画変数_2_1). 双方向に変換(_区画変数_1_1,_区画変数_2_1,_区画変数_2_1,_区画変数_1_1). % 以下のサイトは # 出典: プログラミングのお題スレ Part3 #877 # # お題:長さが3文字以上の文字列が与えられたとき、2文字の組合せを求める。 # 例 # today -> to td ta ty od oa oy da dy ay # '長さが3文字以上の文字列が与えられたとき、2文字の組合せを求める。'(_文字列,_文字組合せ) :- sub_atom(_文字列,0,1,_,_文字_1), sub_atom(_文字列,1,_,0,_文字列_2), '長さが3文字以上の文字列が与えられたとき、2文字の組合せ'(_文字列_2,_文字_1,_文字組合せ). '長さが3文字以上の文字列が与えられたとき、2文字の組合せ'(_文字列_2,_文字_1,_文字組合せ) :- sub_atom(_文字列_2,_,1,_,_文字_2), atom_concat(_文字_1,_文字_2,_文字組合せ). '長さが3文字以上の文字列が与えられたとき、2文字の組合せ'(_文字列_2,_,_文字組合せ) :- '長さが3文字以上の文字列が与えられたとき、2文字の組合せを求める。'(_文字列_2,_文字組合せ). % 以下のサイトは # 出題: プログラミングのお題スレ Part3 #902 # # お題:文字列sにあるn個の文字からなる集合を # 要素とする集合をつくる # # 例1:以下n=2 # "today"-> {to td ta ty od oa oy da dy ay} # "book" -> {bo bk ok} # "ababab" -> {ab} # "ab" -> {ab} # "aa" -> {} # "a" -> {} # "" -> {} # # 例2:以下n=3 # "today"-> {tod toa toy oda ody day dat ayt ayo} # "book" -> {boo bok okb} # "abc" -> {abc} # "ababab" ->{} # "ab" -> {} # "a" -> {} # "" -> {} 文字列にあるn個の文字からなる集合を要素とする集合をつくる(_文字列,_n,_文字列集合要素) :- 文字列の重複文字を取り除く(_文字列,_重複を取り除いた文字列), 文字列組合せ(_重複を取り除いた文字列,_n,_文字列集合要素). 文字列の重複文字を取り除く(_文字列,_重複を取り除いた文字列) :- findall(_文字,( 既に採用されていない文字(_文字列,_文字)), _重複を取り除いた文字ならび), atom_chars(_重複を取り除いた文字列,_重複を取り除いた文字ならび). 既に採用されていない文字(_文字列,_文字) :- sub_atom(_文字列,S,1,_,_文字), sub_atom(_文字列,0,S,_,_前文字列), \+(sub_atom(_前文字列,_,1,_,_文字)). 文字列組合せ(_文字列,1,_文字) :- sub_atom(_文字列,_,1,_,_文字). 文字列組合せ(_文字列_1,N,_文字列) :- 先頭文字と残り文字列(_文字列,N,M,_先頭文字,_残り文字列), 文字列組合せ(_残り文字列,M,_残り文字列_2), atom_concat(_先頭文字,_残り文字列_2,_文字列). 文字列組合せ(_文字列_1,N,_文字列) :- 先頭文字を除く残り文字列(_文字列,1,_,0,_残り文字列), 文字列組合せ(_残り文字列,N,_文字列). 先頭文字と残り文字列(_文字列,N,M,_先頭文字,_残り文字列) :- N > 1, M is N - 1, sub_atom(_文字列,0,1,_,_先頭文字), sub_atom(_文字列,1,_,0,_残り文字列). 先頭文字を除く残り文字列(_文字列,1,_,0,_残り文字列) :- N > 1, sub_atom(_文字列,1,_,0,_残り文字列). % 以下のサイトは # 出題: プログラミングのお題スレ Part3 #902 # # お題:文字列sにあるn個の文字からなる集合を # 要素とする集合をつくる # # 例1:以下n=2 # "today"-> {to td ta ty od oa oy da dy ay} # "book" -> {bo bk ok} # "ababab" -> {ab} # "ab" -> {ab} # "aa" -> {} # "a" -> {} # "" -> {} # # 例2:以下n=3 # "today"-> {tod toa toy oda ody day dat ayt ayo} # "book" -> {boo bok okb} # "abc" -> {abc} # "ababab" ->{} # "ab" -> {} # "a" -> {} # "" -> {} 文字列にあるn個の文字からなる集合を要素とする集合をつくる(_文字列,_n,_文字列集合要素) :- atom_chars(_文字列,_文字ならび), 文字列の要素の重複を取り除いた文(_文字ならび,_要素に重複のない文字ならび), 組合せ(_要素に重複のない文字ならび,_n,_組合せ), atom_chars(_文字列集合要素,_組合せ). 文字列の要素の重複を取り除いた文(_文字ならび,_要素に重複のない文字ならび) :- findall(_文字,( append(L1,[_文字|_],_文字ならび), \+(member(_文字,L1))), _要素に重複のない文字ならび). 組合せ(L,1,[A]) :- member(A,L). 組合せ([_先頭要素|_残りならび],N,[_先頭要素|_組合せ]) :- 'Nが1より大きい時、_残りならびから、一個少ない選択の組合せの前に先頭要素を付加する'(_残りならび,N,L). 組合せ([_|_残りならび],N,_組合せ) :- 'Nが1より大きい時、ならびの先頭要素を取り去った_残りならびから同じくN個取り出す組合せ'(_残りならび,N,L). 'Nが1より大きい時、_残りならびから、一個少ない選択の組合せの前に先頭要素を付加する'(_残り要素,N,_組合せ) :- N > 1, _一個少ない選択 is N - 1, 組合せ(_残りならび,_一個少ない選択,_組合せ). 'Nが1より大きい時、ならびの先頭要素を取り去った_残りならびから同じくN個取り出す組合せ'(_残りならび,N,_組合せ) :- N > 1, 組合せ(_残りならび,N,_組合せ). % 以下のサイトは # 出題: プログラミングのお題スレ Part3 #902 # # お題:文字列sにあるn個の文字からなる集合を # 要素とする集合をつくる # # 例1:以下n=2 # "today"-> {to td ta ty od oa oy da dy ay} # "book" -> {bo bk ok} # "ababab" -> {ab} # "ab" -> {ab} # "aa" -> {} # "a" -> {} # "" -> {} # # 例2:以下n=3 # "today"-> {tod toa toy oda ody day dat ayt ayo} # "book" -> {boo bok okb} # "abc" -> {abc} # "ababab" ->{} # "ab" -> {} # "a" -> {} # "" -> {} 文字列にあるn個の文字からなる集合を要素とする集合をつくる(_文字列,_n,_文字列集合要素) :- atom_chars(_文字列,_文字ならび), 要素の重複を取り除いた文字ならび(_文字ならび,_要素に重複のない文字ならび), 組合せ(_要素に重複のない文字ならび,_n,_組合せ), atom_chars(_文字列集合要素,_組合せ). 要素の重複を取り除いた文字ならび(_文字ならび,_要素に重複のない文字ならび) :- findall(_文字,( append(L1,[_文字|_],_文字ならび), \+(member(_文字,L1))), _要素に重複のない文字ならび). 組合せ(L,1,[A]) :- !, member(A,L). 組合せ([A|R1],N,[A|R2]) :- N_1 is N - 1, 組合せ(R1,N_1,R2). 組合せ([_|R1],N,L) :- 組合せ(R1,N,L). % 以下のサイトは # 出典: 問題 # 詳細な問題文 # 私のツイート(1) # 私のツイート(2) # 私のツイート(3) # Dは前に二人いると言っているから3人以上の部屋にいる。 # 部屋は4人1部屋か、3人と1人の二つの可能性しかない。 # 自分が前から2人目を主張するCは必然的に4人または3人の部屋にいる # この部屋のCの主張から先頭が白で、Dの主張から1人目2人目は白か黒のどちらだから2人目のCは黒とわかる # 'Dは前に二人いると言っているから3人以上の部屋にいる。部屋は4人1部屋か、3人と1人のふた部屋の、二つの可能性しかない'(LL) :- length([_,_,D|_],N), findall(L,'3人以上の部屋がある'(L),LL). '3人以上の部屋にいる'(L) :- 総組合せ([1,2,3,4],L), sum_list(L,4), member(M,L), M >= 3. 総組合せ([],_). 総組合せ(L1,L2) :- length(L1,N), between(1,N,D), 重複組合せ(L1,D,L2). 重複組合せ(X,1,[A]) :- member(A,X). 重複組合せ([A|Y],N,[A|X]) :- N > 1, M is N - 1, 重複組合せ([A|Y],M,X). 重複組合せ([_|Y],N,A) :- N > 1, 重複組合せ(Y,N,A).