0

特定の銀行に属さない一連の番号をリストしようとしています。

これが私のコードです

種類

     type NI = Int
     type Age = Int
     type Balance = Int
     type Person = (NI, Age, Balance)
     type Bank = [Person]
     type Market = [Bank]
     type Pop = [NI]

銀行

     rbs :: Bank
     rbs = [ (1, 73, 1000)
         , (2, 18, -50)
         , (3, 60, 190)
         , (4, 26, 300)
         , (5, 24, 456)
         , (6, 32, 7500)
         , (7, 41, -46)
         , (8, 59, -850)
         , (9, 44, 348)
         , (10, 66, -1000)

     clyde :: Bank
     clyde = [(1, 73, 240)
           , (2, 18, -70)
           , (23, 30, 800)
           , (14, 16, 30)
           , (5, 24, 800)
           , (19, 81, 750)
           , (17, 49, 946)
           , (20, 59, -850)
           , (29, 24, -348)
           , (30, 76, -100)

    sco :: Pop
    sco = [1..20]

そして、これはNIが銀行にないかどうかを確認するための私のコードです

    bankFree :: Pop -> Market -> Pop
    bankFree [] x = []
    bankFree x [] = error "No Banks selected"
    bankFree x [[]] = []
    bankFree (x:xs) [[],((n,a,b):ys)] = if x == n then bankFree (xs) [[],ys]
                                else x : bankFree xs [[],ys]
    bankFree x [[],[]] = []
    bankFree (x:xs) (((n,a,b):ys):zs) = if x == n then bankFree (xs) ((ys):zs)
                                else if x /= n then x : bankFree xs ((ys):zs)
                                else bankFree (xs) zs

bankFree sco [rbs,clyde] を実行すると [11,12,13,15,16,18,20] と表示されますが、表示されるのは [2..20] です。

何が間違っているのか、どのように進めればよいのかわからないので、この問題に関する助けをいただければ幸いです

4

3 に答える 3

5

繰り返しになりますが、以前の質問への回答で示唆したように、これが非常に困難な理由は、問題を効果的に細かく分割していないためであり、標準のユーティリティに役立っていないためです。リストを管理する関数。一度に噛み砕こうとしているのは大きすぎるピースであり、それが解決を困難にしています。

したがって、問題を単独で解決しやすいサブパーツに分割し、これらを組み合わせて大きな問題に対する大きな解決策を作成する必要があります。

import Data.List (any)

type Market = [Bank]
type Bank = [Person]
data Person = Person { ni :: NI, age :: Age, balance :: Balance } 
    deriving (Eq, Show)

bankFree :: Pop -> Market -> Pop
bankFree pop banks = filter checkBanks pop
    where checkBanks n = not (any (bankHasNI n banks))

bankHasNI :: NI -> Bank -> Bool
bankHasNI n bank = any (\person -> ni person == n) bank

必読:

于 2012-11-11T23:07:19.227 に答える
2

それを小さな問題に分割します。また、手動再帰の代わりに高階関数を使用して、アルゴリズムを理解しやすくします。

inBank :: NI -> Bank -> Bool
ni `inBank` bank = any (\(ni', _, _) -> ni' == ni) bank

inMarket :: NI -> Market -> Bool
ni `inMarket` market = any (ni `inBank`) market

bankless :: Pop -> Market -> Pop
bankless pop market = filter (not . (`inMarket` market)) pop

テストすると、次のようになります。

>>> bankless sco [rbs, clyde]
[11,12,13,15,16,18]
于 2012-11-11T23:09:51.603 に答える
2

これは宿題だと思いますので、問題を解決するだけでは問題ありませんが、ヒントをいくつか示します。

  • これは、関数が何をすべきかを質問として形式化するのに役立ちます。
  • 上記の問題の定式化を考えると、bankFree関数をフィルターと考えるのが自然になります。ここに何人かの人々がいますが、それぞれの人は、銀行口座を持っていない場合にのみ保管してください。

リストのフィルタリングは、さまざまな方法で実装できます。初心者にとって最も簡単なのは、おそらくリスト内包表記を使用することです。

bankFree :: Pop -> Market -> Pop
bankFree pop market = [p | p <- pop, not (isBankCustomer market p)]

次のように読む必要があります: return all persons in Pop that not the bank customers。の定義はisBankCustomer次のとおりです。

isBankCustomer :: NI -> Market -> Bool   
isBankCustomer ni market = ?   

ここでやりたいことは、顧客の銀行リストのいずれかに ni が存在するかどうかを何らかの方法でチェックすることです。

于 2012-11-11T23:11:28.013 に答える