2016-11-08 3 views
3

F#で、条件が満たされた場合にセット内の発生を削除しようとしていますが、実際には動作しません。F#の構文とセットと更新の場合

+2

あなたの試行されたソリューション:他の言葉では、そのセクションこのように見えているはず? –

+2

何がうまくいかないのか、どんなコードを試してみることができますか?あなたのコード例は、あなたが求めている質問に一致するようには見えません。あるセットから要素を削除するには、 'Set.remove item set'を使うか、特定のテストに合った要素をフィルタリングするために' Set.filter booleanTest set'を使うことができます。 –

+0

あなたの最新の編集は、 "ノート"、 "ギア"、 "タンブラー"を含むコードではまったく関係のない質問のようです。あなたは誤ってコードの間違ったセクションに貼り付けましたか?あなたの編集を以前のリビジョンに戻しています。ノート、ギア、タンブラーでそのコードについての質問がある場合は、別の質問として質問して、それぞれの質問が1つのテーマになるようにしてください。 – rmunn

答えて

4

セットから要素を削除するトリックは、引数として関数を取る関数Set.filter、ある - filterはあなたの関数へのセットのすべての値にフィード、および機能はtrueを返した場合、新しいセットに追加します。実装例は、filter : ('T -> bool) -> Set<'T> -> Set<'T>のタイプの

let filter f (original : Set<'T>) = 
    set [ for value in original do if f value then yield value ] 

である可能性があります。それを使用する例が

filter (fun x -> x % 2 = 0) (set [ 1; 2; 3; 4; 5 ]) 

だろうこれは、偶数のためのセットをフィルタリングし、その戻り値はset [ 2; 4 ]だろう。


は、私は完全にあなたが正確に持っているものを問題わからないんだけど、ここではむしろ、「1122」の彼の選択よりも、ランダム開始推測とはいえ、Knuthのアルゴリズムを用いたゲームの首謀者を解決します。

checkGuess関数を記述するのが私のための最も難しい部分でしたが、私はそれはかなり素晴らしい運動だと思いました!

テストを実行するには、F#インタラクティブで関数playMastermind()を実行してテストを実行します。これにより、その推測が表示されます。

/// The colours that pegs are allowed to be. 
type Peg = Blue | Red | Green | Yellow | Purple | Brown 

/// A shared instance of the System.Random() class for all the random number 
/// generators. 
let private rnd = new System.Random() 

/// Make a random set of four peg colours. 
let randomGuess() = 
    let randomPeg() = 
     match rnd.Next(1, 6) with 
     | 1 -> Blue 
     | 2 -> Red 
     | 3 -> Green 
     | 4 -> Yellow 
     | 5 -> Purple 
     | 6 -> Brown 
     | _ -> failwith "Random number generation failed." 
    [ randomPeg(); randomPeg(); randomPeg(); randomPeg() ] 

/// Iterate over the colours to make all of the possible combinations. 
let allPossibles = 
    let colours = [ Blue; Red; Green; Yellow; Purple; Brown] 
    set [ for a in colours do for b in colours do for c in colours do for d in colours -> [ a; b; c; d ] ] 

/// Get the number of white and black pegs when comparing solution to guess. 
let checkGuess solution guess = 
    /// Create a map of (colour -> count). 
    let toMap = List.countBy id >> Map.ofList 
    /// Compute how many pegs' colours are shared in the guesses. 
    let mapIntersect map1 map2 = 
     let overlap peg count = 
      match Map.tryFind peg map2 with 
      | None -> 0 
      | Some num -> min num count 
     Map.fold (fun acc peg count -> acc + overlap peg count) 0 map1 
    /// Simply compare to see if each peg is in the correct place. 
    let blacks = List.map2 (fun x y -> if x = y then 1 else 0) solution guess |> List.sum 
    // The number of pegs of the right colour but the wrong location is the 
    // same as the total number of pegs of the right colour subtract the ones 
    // that are also in the right place. 
    let whites = mapIntersect (toMap solution) (toMap guess) - blacks 
    whites, blacks 

/// Get a random element of a set. 
let randomSetElement set = 
    let arr = Set.toArray set 
    arr.[rnd.Next (Array.length arr)] 

let playMastermind() = 
    // This creates a closure so we can check our guess against the solution, 
    // without storing the actual value of the solution. 
    let checkAnswer = checkGuess (randomGuess()) 
    let rec loop turnCount remaining = 
     if Set.count remaining = 1 then 
      let answer = Set.maxElement remaining 
      printfn "The answer is %A, which I calculated in %d turns." answer (turnCount - 1) 
     else 
      let guess = randomSetElement remaining 
      let (whites, blacks) = checkAnswer guess 
      printfn "On turn %d I guessed %A, which gave %d white pins and %d black pins." turnCount guess whites blacks 
      /// Remove all possibilities from the solution that wouldn't give the 
      /// same numbers of white and black pins and continue. 
      loop (turnCount + 1) (Set.filter (fun possible -> (whites, blacks) = checkGuess possible guess) remaining) 
    // Play the game! 
    loop 1 allPossibles 
1

私はこのコメント作ると思いますが、それはあまりにも長いですので、それはそれはあなたの問題へ完全な答えはありませんにもかかわらず、代わりに答えする必要があります。 Pythonのように、ブロックを示すためにインデントを使用して、

for candidate in candidateSet do 
    let scString = candidate.ToString() 

    let mutable secretList = [] 
    for i = 0 to 3 do 
     let digit = (int scString.[i])-(int '0') 
     secretList <- secretList @ [digit] 
    let tempCode = List.map (fun x -> numberToCodeColorPlus (x)) secretList 
//Validate works and returns a peg set (b,w)..e.g. (0,0)  
let secretCodePegs = validate guess tempCode 
    if secretCodePegs <> guessPegs then 
     candidateSet <- Set.remove candidate candidateSet 

F番号:あなたのコードで

一つの問題は、それが今であるとして、このセクションです。だからlet secretCodePegs = validate guess tempCode行がforのループではなく、forのループはあなたが明らかにそれを意図した方法です。そして、F#に関する限り、if secretCodePegs <> guessPegs thenの行は、の新しいブロックの一部であり、forループの一部ではなくなりました(let secretCodePegs = ...の行がforループを終了したため)。あなたがする必要があるのは、let secretCodePegs = ...行を1レベルインデントして、コードが機能するだけです。

for candidate in candidateSet do 
    let scString = candidate.ToString() 

    let mutable secretList = [] 
    for i = 0 to 3 do 
     let digit = (int scString.[i])-(int '0') 
     secretList <- secretList @ [digit] 
    let tempCode = List.map (fun x -> numberToCodeColorPlus (x)) secretList 
    //Validate works and returns a peg set (b,w)..e.g. (0,0)  
    let secretCodePegs = validate guess tempCode 
    if secretCodePegs <> guessPegs then 
     candidateSet <- Set.remove candidate candidateSet 
関連する問題