2

日付のリストと月のリストを取得し、リストされた月のいずれかに含まれる日付の総数を取得する必要があります。したがって、単一の整数を返します

number_in_month日付のリストと単一の月を取り、その月に含まれる日付の量を返す、以前に定義された関数がありました。テスト済みで、正しく動作します。これを後者の関数の基礎として使用します。私はnumber_in_months関数を何度もトレースしましたが、何が悪いのかわからないようですが、正しい答えが得られていません

fun number_in_month (datelist : (int*int*int)list, month : int)  = 

let
fun count(x : int , datelist : (int*int*int)list)=
if null (tl datelist)
then x
else if #2(hd datelist) = month
then count(x+1, tl datelist)
else count(x, tl datelist)

in

if #2(hd datelist) = month
then count(1, datelist)
else count(0, datelist)

end
fun number_in_months (datelist : (int*int*int)list, monthlist : (int)list)=
let 
fun count(x : int, monthlist : (int)list)=
if null (tl monthlist)
then x
else count((x + number_in_month(datelist, hd monthlist)), tl monthlist) 

in
count (( number_in_month(datelist, hd monthlist), tl monthlist))
end
4

2 に答える 2

7

あなたが述べたように、あなたはただ前の関数を使う必要がありますnumber_in_monthnumber_in_monthこれは、日付のリストと1か月を取り、日付のリストで一致する月の数を返すことを思い出してください。したがって、作成する必要があるのは、チェックする日付の元のリストを使用して、新しい月のリストの各要素number_in_monthsを呼び出すことだけです。number_in_month

そのような解決策は次のようになります

fun number_in_months (dates, months) =
    if null months then
      0
    else
      number_in_month(dates, hd months) + number_in_months(dates, tl months)

ただし、パターンマッチングを使用すると、パターンマッチングを短くして、さらに読みやすくすることができます。

fun number_in_months (dates, []) = 0
  | number_in_months (dates, d::ds) =
      number_in_month(dates, d) + number_in_months(dates, ds)

count「状態」を持ち歩く関数を作成する理由はまったくありません。これは、プレイ中のあなたの命令法のようです:)たとえば、リストのすべての要素を合計するこの単純な関数を考えてみましょう。

fun sum [] = 0
  | sum (x::xs) = x + sum xs

または、長さ関数(実際にはカウント関数に似ています)を作成することもできます

fun length [] = 0
  | length (x::xs) = 1 + length xs

すでに述べた多くの良いことを何度も繰り返すのではなく、これらの質問とその回答を読んでいただくことをお勧めします。

アップデート

また、コードをより適切にフォーマットする方法も紹介したいと思います。

fun number_in_month (datelist : (int*int*int) list, month : int)  =
    let
      fun count (x : int , datelist : (int*int*int) list) =
          if null (tl datelist)
          then x
          else if #2(hd datelist) = month
            then count (x+1, tl datelist)
            else count (x, tl datelist)
    in
      if #2(hd datelist) = month
      then count (1, datelist)
      else count (0, datelist)
    end


fun number_in_months (datelist : (int*int*int) list, monthlist : int list)=
    let
      fun count (x : int, monthlist : int list)=
          if null (tl monthlist)
          then x
          else count (x + number_in_month(datelist, hd monthlist), tl monthlist)
    in
      count (number_in_month (datelist, hd monthlist), tl monthlist)
    end

ネストされたifをフォーマットする方法は、私がどこから来たのか常に大きな議論です。個人的にはそれらを避け、代わりにユースケースを使用しますが、将来的にはそれについて学ぶことになると思います。

しかし、私はあなたのカウント機能にも間違いを見つけました。2番目の引数(両方のカウント関数)がで空のリストであるかどうかをテストするときnullは、引数の末尾でテストします。これは、引数が実際に空のリストである場合は失敗します。

- null (tl []);

uncaught exception Empty

たとえば、この入力

- number_in_months ([(1,1,1)], [1]);

uncaught exception Empty

また、の頭がに等しいかどうかをテストしているため、の論理number_in_monthは間違っていますが、どちらの場合も、尾の代わりに全体を使用します。これは、以下が結果として2を返さないはずであるために見られますdatelistmonthcountdatelist

- number_in_month([(1,1,1), (2,2,2), (3,3,3)], 1);
val it = 2 : int

このエラーは、number_in_month関数が例外をスローしないようにしている唯一のことです。

于 2013-01-23T01:41:21.173 に答える
1

コードの問題は、月と一致している場合、最後の日付を計算していないことです。このコードは正常に動作します。

fun number_in_month (datelist : (int*int*int) list, month : int)  =
    let
      fun count (x : int , datelist : (int*int*int) list) =
          if null (tl datelist)
          then 
              if #2(hd datelist) <> month
                      then x
                     else x+1
         else if #2(hd datelist) = month
            then count (x+1, tl datelist)
            else count (x, tl datelist)
    in
          count (0, datelist)
    end
于 2013-10-12T08:46:05.933 に答える