2012-07-17 45 views
1

我寫了F#程序來解決「Escape from Zurg」拼圖F#的解決方案「從Zurg逍遙遊」之謎

我的代碼如下。但不知何故,當我解決謎題時,返回布爾值的方式有些問題。

上線

retVal = Move (cost + (MoveCost toy1 toy2)) Right remainingElements 

我得到一個警告

表達的類型應該是「單位」,但有類型「布爾」。如果分配一個屬性使用語法'obj.Prop < - expr'

並且我發現即使該函數在謎題被渲染時返回true。當它返回時retVal保持爲假。

以下是我的代碼。

open System 

type Direction = 
    | Left 
    | Right 

type Toy = {Name: string; Cost: int} 

let toys = [ 
       {Name="Buzz"; Cost=5}; 
       {Name="Woody"; Cost=10}; 
       {Name="Rex"; Cost=20}; 
       {Name="Hamm"; Cost=25}; 
      ] 

let MoveCost toy1 toy2 = 
    if (toy1.Cost > toy2.Cost) then 
     toy1.Cost 
    else 
     toy2.Cost 

let rec Move cost direction group = 
    match group with 
    | [] -> if (cost > 60) then 
       false 
      else 
       Console.WriteLine("Solution Found!") 
       true 
    | _ -> 
     match direction with 
     | Left -> 
      let retVal = false 
      let combinations = Set.ofSeq (seq {for i in group do for j in group do if i <> j then if i < j then yield i, j else yield j, i}) 
      for pair in combinations do 
       let (toy1, toy2) = pair     
       let remainingElements = List.filter (fun t-> t.Name <> toy1.Name && t.Name <> toy2.Name) group     
       retVal = Move (cost + (MoveCost toy1 toy2)) Right remainingElements 
       if (retVal) then 
        Console.WriteLine ("Move " + toy1.Name + " and " + toy2.Name + " with the total cost of " + cost.ToString()) 
      retVal 
     | Right -> 
      let retVal = false 
      let toysOnRightBank = List.filter (fun t-> not(List.exists (fun g-> g = t) group)) toys 
      for toy in toysOnRightBank do 
       let cost = cost + toy.Cost 
       let retVal = Move cost Left (toy :: group) 
       if (retVal) then 
        Console.WriteLine("Move " + toy.Name + " back with the cost of " + toy.Cost.ToString()) 
      retVal 

[<EntryPoint>] 
let main args = 
    let x = Move 0 Left toys 
    0 
+2

請注意,您的'MoveCost'實現可以更簡潔有效地實現爲'let inline MoveCost {Cost = cost1} {Cost = cost2} = max cost1 cost2'。 – ildjarn 2012-07-17 20:26:11

回答

4

您不能重新分配let綁定。它應該是:

let mutable retVal = false 

...

retVal <- Move (cost + (MoveCost toy1 toy2)) Right remainingElements 

然而,你可以很容易地改寫,使mutable不需要:

let res = 
    [ 
    for i in group do 
     for j in group do 
     if i < j then yield i, j elif i > j then yield j, i 
    ] 
    |> List.filter (fun (toy1, toy2) -> 
    let remainingElements = List.filter (fun t-> t.Name <> toy1.Name && t.Name <> toy2.Name) group     
    Move (cost + (MoveCost toy1 toy2)) Right remainingElements) 

match res with 
| [] -> false 
| _ -> 
    res |> List.iter (fun (toy1, toy2) -> 
    Console.WriteLine ("Move " + toy1.Name + " and " + toy2.Name + " with the total cost of " + cost.ToString())) 
    true 

編輯:我貼了complete solution on gist,如果你需要一個參考實現。