2

I have the following code in Ruby which takes a list of 'melds' and creates a Tree Structure in order to find the best combination of melds and returns that. I am wanting to convert this code into a F# equivalent but I am having a hard time thinking of a way to do it seeing as F# doesn't have a simple way to create a Tree of nodes(at least that I know of).

I have not been working with F# for very long so I don't have a great understanding of it or a lot of knowledge in using Higher Order Functions, so if anyone would know how to convert this code it would be greatly appreciated! Thanks.

class MeldNode
  attr_accessor :cards, :deadwood, :parent
  def initialize(cards, parent)
    @parent = parent
    @cards = cards
    @deadwood = count_deadwood(cards)
    if (parent != nil)
      @deadwood = @parent.deadwood + @deadwood
    end
  end
end

def build_meld_tree(melds, root_meld)
  best = root_meld
  melds.each do |m|
    n = MeldNode.new(m, root_meld)
    new_tree = build_meld_tree(clean_meld_group(melds, m), n)
    best = new_tree if (best == nil) || (new_tree.deadwood > best.deadwood)
  end
  best
end 
jambrothers
  • 1,540
  • 1
  • 15
  • 21
TJ8
  • 121
  • 5
  • 3
    What have you tried? F# has recursion so I don't see anything in that code that wouldn't be 'simple'. – ildjarn Apr 20 '17 at 13:38
  • 3
    I don't understand what you mean by "F# doesn't have a simple way to create a Tree of nodes". F♯ is a fully-featured imperative impure OO language (even if that's not the preferred way of using it), so you can do the same thing you did in Ruby. Plus, F♯ has Algebraic Sum Types (called *Discriminated Unions* in F♯) that are *perfect* for representing trees, in fact, that's probably one of the most widely-used examples for motivating Algebraic Data Types: `type Tree<'a> = Leaf of 'a | Node of Tree<'a> * Tree<'a>`. [Note: I don't actually know F♯ well, there might be syntax errors.] – Jörg W Mittag Apr 20 '17 at 13:56
  • 1
    I don't know anything about F# but a couple of quick Googles suggests that Ruby -> C# and C# -> F# translators exist, so maybe you could do it in two steps. – Cary Swoveland Apr 20 '17 at 17:39

1 Answers1

1

So taking exactly your code and porting it to F#:

type MeldNode<'a> =
  { cards : 'a; deadwood : int; parent : MeldNode<'a> option }

  static member New cards (parent:MeldNode<'a> option) =
    {
      cards = cards;
      deadwood = (Array.length cards) + (if parent.IsSome then parent.Value.deadwood else 0);
      parent = parent
    }


let rec buildMeldsTree rootMeld (melds:'a[] list) =
  if List.isEmpty melds then None // ensure terminating case
  else
    melds
    |> List.map (fun m ->
      let n = MeldNode<'a>.New m rootMeld
      buildMeldsTree (Some n) (cleanMeldGroup melds m)
    )
    |> List.append (if rootMeld.IsNone then [] else [ rootMeld.Value ])
    |> List.maxBy (fun (n:MeldNode<'a>) -> n.deadwood)
    |> Some

I saw that you updated a var called best. F# prefers immutable vars, so using this way of getting the "best" combination meets that preference. Hope this helps!

ildjarn
  • 62,044
  • 9
  • 127
  • 211
czifro
  • 784
  • 7
  • 24