Search code examples
rubyf#treestructurecode-conversion

Need help converting Ruby code into F#


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 

Solution

  • 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!