このディレクトリの索引

# 出典 :: C/C++の宿題片付けます 132代目 #157 # [1] 授業単元: アルゴリズム&アプリケーション # [2] 問題文(含コード&リンク):売掛表がcsvファイルで作られています。 # 各行の情報は、 # 顧客名,前月繰越高,当月入金高,当月売上高,締め日付 # であり、締め日付で昇順に整列していて、見出し等冗長部分はありません。 # 今回は問題を単純化するため、一人の顧客分しか扱わないことにします。 # さて更新プログラムのバグから、或る月の前月繰越高が # その前月の 前月繰越高-当月入金高+当月売上高 と不整合になってしまいました。 # 不整合になった以降の情報が正しく、 # それ以前の情報の当月入金高、当月売上高、締め日付については誤りがないとして、 # 1) 不整合部分を探し # 2) それ以前のすべての前月繰越高を全体が整合するように書き換えなさい。 # ファイルは一旦別のファイル(例えば/tmp/xxxxxx)に正しいものをつくり、 # その後、元のcsvファイルに書き戻しなさい。 # [3] 環境 #  [3.1] OS: Linux #  [3.2] コンパイラ名とバージョン: gcc 3.4 #  [3.3] 言語: C # [4] 期限: 期限はありません # [5] その他の制限: 日付などの持ち方は自由に工夫してよい。 # # 売掛表の遡行修正(_ファイル名) :- 'ファイルから項目区切り行ならびを得る'(_ファイル名,[','],LL), '不整合が生じた二行とそれ以前のならびを遡り修正した上で更新済みならびを構成する'(LL,_更新済みのLL), 更新済みならびをファイルに書き戻す(_ファイル名,_更新済みのLL). 'ファイルから項目区切り行ならびを得る'(_ファイル名,[','],LL) :- open(_ファイル名,read,_入力), 項目区切り行ならび(_入力,[','],LL), close(_入力). 項目区切り行ならび(_入力,_区切り文字列ならび,LL) :- findall(L,( repeat,(at_end_of_stream(_入力),!,fail;行入力(_入力,_行),項目区切り(_行,_区切り文字列ならび,L)),LL). 行入力(_入力,_行) :- read_line_to_codes(_入力,_文字コードならび), atom_codes(_行,_文字コードならび). '不整合が生じた二行とそれ以前のならびを遡り修正した上で更新済みならびを構成する'(LL,_更新済みのLL) :- 不整合が生じた二行を切り出し不整合を修正する(LL,_それ以前のならび,_不整合が生じた二行,_それ以後のならび,_顧客名,_遡り修正額,_修正済みの不整合が生じた二行), 'それ以前のならびの修正'(_顧客名,_遡り修正額,_それ以前のならび,_修正済みのそれ以前のならび), append([_修正済みのそれ以前のならび,_修正済みの不整合が生じた二行,_それ以後のならび],_更新済みのLL). 不整合が生じた二行を切り出し不整合を修正する(LL,_それ以前のならび,_不整合が生じた二行,_それ以後のならび,_顧客名,_遡り修正額,_修正済みの不整合が生じた二行) :- 不整合が生じた二行(LL,_それ以前のならび,_不整合が生じた二行,_それ以後のならび,_顧客名,_遡り修正額), 不整合が生じた二行の修正(_顧客名,_遡り修正額,_不整合が生じた二行,_修正済みの不整合が生じた二行). 不整合が生じた二行(LL,LL1,[[_顧客名,_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1],[_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付]],LL2,_顧客名,_遡り修正額) :- append([LL1,[[_顧客名,_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1],[_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付]],LL2],LL), '前の月の請求額と当月の繰越額が不整合である。遡り修正額が発生する。'(_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1,_前月繰越高,_遡り修正額). '前の月の請求額と当月の繰越額が不整合である。遡り修正額が発生する。'(_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1,_前月繰越高,_遡り修正額) :- '前の月の請求額と当月の繰越額が不整合である。'(_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1,_前月繰越高), '遡り修正額が発生する。'(_前月繰越高,_当月請求高_1,_遡り修正額). '前の月の請求額と当月の繰越額が不整合である。'(_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1,_前月繰越高) :- _当月請求高_1 is _前月繰越高_1 - _当月入金高_1 + _当月売上高_1, _当月請求高_1 \== _前月繰越高. '遡り修正額が発生する。'(_前月繰越高,_当月請求高_1,_遡り修正額) :- _遡り修正額 is _前月繰越高 - _当月請求高_1. '不整合が生じた二行の修正'(_顧客名,_遡り修正額,[[_顧客名,_前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1],[_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付]],[[_顧客名,_修正済みの前月繰越高_1,_当月入金高_1,_当月売上高_1,_締め日付_1],[_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付]]) :- _修正済みの前月繰越高_1 is _前月繰越高_1 + _遡り修正額. 'それ以前のならびの修正'(_顧客名,_遡り修正額,_それ以前のならび,_修正済みのそれ以前のならび) :- findall([_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付],( 'それ以前のならびから行を取り出し、指定された顧客名の前月繰越高だけ修正する'(_顧客名,_遡り修正額,_それ以前のならび,[_顧客名,_前月繰越高,_当月入金高,_当月売上高,_締め日付])),_修正済みのそれ以前のならび). 'それ以前のならびから行を取り出し、指定された顧客名の前月繰越高だけ修正する'(_顧客名,_遡り修正額,_それ以前のならび,[_顧客名_1,_前月繰越高,_当月入金高,_当月売上高,_締め日付]) :- 'それ以前のならびから行を取り出し、'(_それ以前のならび,[_顧客名_1,_前月繰越高_1,_当月入金高,_当月売上高,_締め日付]), 指定された顧客名の前月繰越高だけ修正する(_顧客名,顧客名_1,_遡り修正額,_前月繰越高_1,_前月繰越高). 'それ以前のならびから行を取り出し、'(_それ以前のならび,[_顧客名_1,_前月繰越高_1,_当月入金高,_当月売上高,_締め日付]) :- member([_顧客名_1,_前月繰越高_1,_当月入金高,_当月売上高,_締め日付],それ以前のならび). 指定された顧客名の前月繰越高だけ修正する(_顧客名,_顧客名,_遡り修正額,_前月繰越高_1,_前月繰越高) :- _前月繰越高 is _前月繰越高_1 + _遡り修正額,!. 指定された顧客名の前月繰越高だけ修正する(_顧客名,_顧客名_1,_遡り修正額,_前月繰越高,_前月繰越高) :- _顧客名 \== _顧客名_1. 更新済みならびをファイルに書き戻す(_ファイル名,_更新済みのLL) :- tell(_ファイル名), forall( member(L,_更新済みのLL), writef('%w,%w,%w,%w,%w\n',L)), told. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 項目区切り(_文字列,_区切り文字列ならび,_区切られた文字列ならび) :- 項目区切り(_文字列,_区切り文字列ならび,_使われている区切り文字ならび,_区切られた文字列ならび_1), 文字列ならびの中で数値に変換可能なものは変換する(_区切られた文字列ならび_1,_区切られた文字列ならび). 項目区切り(_文字列,_区切り文字列ならび,_使われている区切り文字ならび,_区切られた文字列ならび) :- 先頭から区切り文字列で区切って行く(_文字列,_区切り文字列ならび,_使われている区切り文字ならび,_区切られた文字列ならび),!. 項目区切り(_文字列,_,[],[_文字列]). 先頭から区切り文字列で区切って行く(_文字列,_区切り文字列ならび,[_区切り文字列|R1],[_前文字列|R2]) :- '区切り文字列で前文字列、後文字列に区切る'(_文字列,_区切り文字列ならび,_前文字列,_区切り文字列,_後文字列), 項目区切り(_後文字列,_区切り文字列ならび,R1,R2). '区切り文字列で前文字列、後文字列に区切る'(_文字列,_区切り文字列ならび,_前文字列,_区切り文字列,_後文字列) :- 副文字列(_文字列,_前文字列,_区切り文字列,_後文字列), member(_区切り文字列,_区切り文字列ならび). 副文字列(_文字列,_前文字列,_副文字列,_後文字列) :- atom_concat(_前文字列,_残り文字列,_文字列), atom_concat(_副文字列,_後文字列,_残り文字列). 文字列ならびの中で数値に変換可能なものは変換する(_文字列ならび,_項目ならび) :- findall(_項目,( 文字列を取り出し数値に変換可能なものは変換する(_文字列ならび,_項目)),_項目ならび). 文字列を取り出し数値に変換可能なものは変換する(_文字列ならび,_項目) :- member(_文字列,_文字列ならび), 数値に変換可能なものは変換する(_文字列,_項目). 数値に変換可能なものは変換する(_文字列,_項目) :- atom_number(_文字列,_項目),!. 数値に変換可能なものは変換する(_文字列,_文字列).