class Flor::Pro::Sort

Public Instance Methods

pre_execute() click to toggle source
# File lib/flor/pcore/sort.rb, line 52
def pre_execute

  @node['atts'] = []

  @node['col'] = nil # collection
  @node['fun'] = nil # function

  unatt_unkeyed_children
end
receive_last() click to toggle source
# File lib/flor/pcore/sort.rb, line 82
def receive_last

  @node['col'] ||= node_payload_ret

  if @node['col'].empty?
    wrap('ret' => @node['col'])
  elsif @node['fun']
    quick_sort
  else
    default_sort
  end
end
receive_non_att() click to toggle source
Calls superclass method Flor::Procedure#receive_non_att
# File lib/flor/pcore/sort.rb, line 62
def receive_non_att

  if @node['ranges']

    quick_partition_receive

  else

    r = payload['ret']

    if Flor.is_func_tree?(r)
      @node['fun'] ||= r
    elsif Flor.is_collection?(r)
      @node['col'] ||= r
    end

    super
  end
end

Protected Instance Methods

default_sort() click to toggle source

default_sort

When no function is given, turns to a collection of string (or JSON representations) and sorts

# File lib/flor/pcore/sort.rb, line 114
def default_sort

  col =
    @node['col']
  classes =
    col.collect(&:class).uniq
  f =
    (classes.count > 1 || [ Hash ].include?(classes[0])) ?
    lambda { |e| e.is_a?(String) ? e : JSON.dump(e) } :
    lambda { |e| e }

  ret = col.sort_by(&f)
  ret = col.inject({}) { |h, (k, v)| h[k] = v; h } if col.is_a?(Hash)

  wrap('ret' => ret)
end
quick_compare(ra, a, b) click to toggle source
# File lib/flor/pcore/sort.rb, line 174
def quick_compare(ra, a, b)

  col = @node['col']
  va, vb = col[a], col[b]

  ra['kab'], ra['kba'] = quick_kab(va, vb)
  kab = ra['kab']

  if kab && @node['memo'].has_key?(kab)
    quick_partition_receive(ra['sub'], @node['memo'][kab])
  else
    apply(@node['fun'], [ [ 'a', va ], [ 'b', vb ] ], tree[2])
      .tap { |ms| ra['sub'] = Flor.sub_nid(ms.first['nid']) }
  end
end
quick_kab(va, vb) click to toggle source
# File lib/flor/pcore/sort.rb, line 160
def quick_kab(va, vb)

  return [] unless @node['memo']

  kab = [ va, vb ]
    .collect { |e|
      case e
      when Array, Hash, String then Digest::SHA256.hexdigest(JSON.dump(e))
      else JSON.dump(e)
      end }

  [ kab.join('__'), kab.reverse.join('__') ]
end
quick_partition_execute(lo, hi) click to toggle source
# File lib/flor/pcore/sort.rb, line 190
def quick_partition_execute(lo, hi)

  return [] if lo >= hi

  ra = @node['ranges']["#{lo}_#{hi}"] ||= { 'i' => lo, 'j' => lo }

  quick_compare(ra, ra['j'], hi)
    # compare element at j with pivot (element at hi)
end
quick_partition_receive(sn=from_sub_nid, r=:none) click to toggle source
# File lib/flor/pcore/sort.rb, line 200
def quick_partition_receive(sn=from_sub_nid, r=:none)

  rk, ra = @node['ranges'].find { |_, v| v['sub'] == sn }
  lo, hi = rk.split('_').collect(&:to_i)
  i, j = ra['i'], ra['j']

  if r == :none
    ret = payload_ret
    r = ret == true || (ret.is_a?(Numeric) && ret < 0)
    if m = @node['memo']
      m[ra['kab']], m[ra['kba']] = r, ! r
    end
  end

  if r
    quick_swap(i, j)
    ra['i'] = i = (i + 1)
  end

  ra['j'] = j = (j + 1)

  return quick_partition_execute(lo, hi) if j < hi # loop on

  # partition loop is over...

  quick_swap(i, hi)

  @node['ranges'].delete(rk)

  # partition at i...

  ms =
    quick_partition_execute(lo, i - 1) +
    quick_partition_execute(i + 1, hi)

  if ms.any?
    ms
  elsif @node['ranges'].any?
    []
  else # quicksort is over
    col = @node['col']
    wrap('ret' => (@node['colk'] === 'object' ? Hash[col] : col))
  end
end
quick_sort() click to toggle source

quick_sort

A quicksort drives the game

# File lib/flor/pcore/sort.rb, line 136
def quick_sort

  col = @node['col']
  @node['colk'] = col.is_a?(Hash) ? 'object' : 'array'
  @node['col'] = col.to_a

  @node['ranges'] = {}

  @node['memo'] =
    att('memo', 'cache') == false ?
    nil :
    {}

  quick_partition_execute(0, col.length - 1)
end
quick_swap(a, b) click to toggle source
# File lib/flor/pcore/sort.rb, line 152
def quick_swap(a, b)

  return if a == b

  col = @node['col']
  col[a], col[b] = col[b], col[a]
end
receive_argument() click to toggle source
# File lib/flor/pcore/sort.rb, line 97
def receive_argument

  @node['args'] << payload['ret']

  if children[@ncid]
    execute_child(@ncid)
  else
    iterate
  end
end