Search code examples
rubyartificial-intelligencepath-finding

Select the object who has the minimum Schwartzian transform from a collection


I am implementing A* for http://aichallenge.org/specification.php and was wondering a slick way to select the minimum of a collection based of the schartzian transform.

Basically, I have a collection of suitable squares to move to, and I want to move to the square with the lowest cost.

Basically I will be selecting the square from my neighbors who has the lowest cost in a loop.

The only way I can think to do this is with something like

next_spot = spot.neighbors.sort_by |a,b| { a.cost(dest) <=> b.cost(dest) }.first

But I would really like something higher performance, because I don't really want to sort the collection, I just want the one with the minimum transform value

Note, I could write something more verbose and "C-style" looping and keeping track of a previous minimum, but I was hoping for something clear and compact.


Solution

  • Why not use min_by?

    next_spot = spot.neighbors.min_by { |x| x.cost(dest) }
    

    And if a "_by" version of an Enumerable-ish method doesn't exist you can get old school and do the Schwartzian Transform by hand with this sort of pseudo-Ruby pattern:

    a.map { |x| [ expensive(x), x ] }.       # Do the expensive part once and cache it
      op  { |x| something_with x.first... }. # Do what you really came to do
      map { |x| x.last }                     # Unwrap the caching