Find next greater element in AVL tree - avl-tree

Let's suppose I have following AVL tree and my task is to find next greater element of given element (i.e. it's 7 for 6). What algorithm can I use?

You walk recursivly through the nodes and if you found i.e. the node 6, then you return deepest left children..
pseudo code:
function find_bigger_key(key, node):
if node = null then
return null
else if node.key = key then
return min_node(node)
else if key < node.key then
return find_bigger_key(key, node.left)
else
return find_bigger_key(key, node.right)
function min_node(node):
if node.ltree = null then
return node
else
return min_node(node.ltree)
That is only a example how you could do it, but it depends how your AVLTree object model looks like.
A example implementation in python:
class AVLTree(object):
def __init__(self, key, ltree=None, rtree=None):
self.key = key ; self.ltree = ltree ; self.rtree = rtree ;
# perhaps some other attributes here....
# some other methods here ...
def find_bigger_key(self, key):
if not self: return None
elif self.key == key:
if self.rtree:
return self.rtree.min_node()
else:
return None
elif self.key > key:
return self.left.find_bigger_key(key)
else:
return self.right.find_bigger_key(key)
A example output of python:
>>> # aTree is a avltree object that represents your example
>>> key = 6
>>> found_node = aTree.find_bigger_key(key)
>>> print(found_node)
7
>>> key = 7
>>> found_node = aTree.find_bigger_key(key)
>>> print(found_node)
None

Related

Groovy dictionary map - how to sort according to a map's key's value - if the value is in x.x.x.x format - numberically sort version value with . char

I have the following dictionary aka MAP in Groovy.
list = [
[
name:ProductA-manifest-file.json,
path:ProductA,
properties: [
[
key:release,
value:RC1.0
],
[ key:PIPELINE_VERSION,
value:1.0.0.11
]
],
repo:some-generic-repo-local,
],
[
name:ProductA-manifest-file.json,
path:ProductA,
properties: [
[
key:release,
value:RC1.0
],
[ key:PIPELINE_VERSION,
value:1.0.0.75
]
],
repo:some-generic-repo-local,
],
[
name:ProductA-manifest-file.json,
path:ProductA,
properties: [
[
key:release,
value:RC1.0
],
[ key:PIPELINE_VERSION,
value:1.0.0.1104
]
],
repo:some-generic-repo-local,
],
[
more similar entries here containing
],
[
more similar entries here
]
]
I'm trying to sort this map acc. to properties's key = PIPELINE_VERSION's value which is in the format of x.x.x.x i.e. 4 digit set case.
I tried the following command but it's not giving me the entry which contains 1.0.0.1104 as PIPELINE_VERSION. It's giving me 1.0.0.75 (which seems like some kind of string type sort.
// Sort the list entries acc. to pipeline version
def sortedList = list.sort { it.properties.PIPELINE_VERSION.value }
println "###### sortedList" + sortedList
println "\n^^^^\n"
println sortedList.last() // this should return me the entry which contains 1.0.0.1104 but I'm getting 1.0.0.75
}
Also tried using .toInteger() as def sortedList = list.sort { it.properties.PIPELINE_VERSION.toInteger().value } but that didn't work giving an error.
17:07:22 Caught: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.toInteger() is applicable for argument types: () values: []
17:07:22 Possible solutions: toUnique(), toUnique()
17:07:22 groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.toInteger() is applicable for argument types: () values: []
17:07:22 Possible solutions: toUnique(), toUnique()
Tried:list.sort {it.value.tokenize('.').last()} that didn't do either.
Smaller example will be:
map = ['a':'1.0.0.11', d:'1.0.0.85', 'b':'1.0.0.1104', 'c':"1.0.0.75"]
println " before sorting : " + map
//map = map.sort {it.value } // this doesn't work if the value is not a pure number format aka x.x.x. format ok lets try the following
map = map.sort {it.value.tokenize('.').last()} // cool that didn't work either
println " after sorting : " + map
Questions:
How can I get the entry which has the highest PIPELINE_VERSION value?
How can I get the Nth array index entry which contains the highest PIPELINE_VERSOIN in its value.
How to handle N no. of digit set set cases? i.e. 1.0.0 or 1.2 or 1.0.0.12 or 1.4.1.9.255
Below should work (assuming the format X.X.X.X always has X as a number)
def sortClosure = { a, b ->
// Extract the pattern
def extract = {
it.properties.find { it.key == 'PIPELINE_VERSION' }?.value?.tokenize(/./)
}
// Transpose the numbers to compare
// gives [[1,1], [0,0], [0,0], [11, 1104]] for example
def transposed = [extract(a), extract(b)].transpose()
// Then compare the first occurrence of non-zero value (-1 or 1)
def compareInt = transposed.collect {
it[0].toInteger() <=> it[1].toInteger()
}.find()
compareInt ?: 0
}
list.sort(sortClosure)
This one-liner solution worked.
For the smaller example!
def versions = ['a':'1.0.0.11', d:'1.0.0.85', 'b':'1.0.0.1104', 'c':"1.0.0.75"]
map = map.sort {it.value.tokenize('.').last().toInteger() }
OK, found the shenzi(one-liner) solution for the complex structure (hint from dmahapatro's answer):
i.e. a map > containing array > containing another map for PIPELINE_VERSION.
println "\n\n before sorting : " + list
list = list.sort {it.properties.find { it.key == 'PIPELINE_VERSION' }?.value?.tokenize('.').last().toInteger() }
println " after sorting : " + list
println "\n\n The last entry which contains the sorted shenzi is: " + map.last()
NOTE: The above solution and other answers so far, will only if the PIPELINE first 3 digit sets are 1.0.0 i.e. it's only deciding the highest number based on the 4th digit set (.last()). It'd be fun to use a similar one-liner to find highest PIPELINE_VERSION which actually covers all 4 or N no. of digit sets.
def versions = ['a':'1.0.0.11', d:'1.0.0.85', 'b':'1.0.0.1104', 'c':"1.0.0.75"]
//sort:
def sorted = versions.sort{ (it.value=~/\d+|\D+/).findAll() }
result:
[a:1.0.0.11, c:1.0.0.75, d:1.0.0.85, b:1.0.0.1104]
Given this:
def map = ['a':'1.0.0.11', d:'1.0.0.85', 'b':'1.0.0.1104', 'c':"1.0.0.75"]
map = map.sort { a, b ->
compareVersion(a.value, b.value)
}
the goal becomes to write a compareVersion function that satisfies these (incomplete) tests:
assert 0 == compareVersion('1.0.0.0', '1.0.0.0')
assert 1 == compareVersion('1.1.0.0', '1.0.0.0')
assert -1 == compareVersion('1.1.0.0', '1.2.0.0')
assert 1 == compareVersion('1.1.3.0', '1.1.2.0')
assert 1 == compareVersion('1.1.4.1104', '1.1.4.11')
Here is one implementation. It's not the shortest but is quite "Groovy" in style:
//
// e.g. a = '1.0.0.11', b = '1.0.0.85'
//
def compareVersion = { a, b ->
// e.g. [1, 0, 0, 11]
def listA = a.tokenize('.').collect { it as int }
// e.g. [1, 0, 0, 85]
def listB = b.tokenize('.').collect { it as int }
// e.g. [0, 0, 0, -1]
def compareList = [listA, listB].transpose().collect { it[0] <=> it[1] }
// return first non-zero value in compareList, or 0 if there are none
compareList.inject(0) { result, item ->
(result) ?: item
}
}
Output of the original map, and sorted:
$ groovy Q.groovy
before sorting : [a:1.0.0.11, d:1.0.0.85, b:1.0.0.1104, c:1.0.0.75]
after sorting : [a:1.0.0.11, c:1.0.0.75, d:1.0.0.85, b:1.0.0.1104]

How to check for Hash value in an array?

Heres my set up
project_JSON = JSON.parse
teamList = Array.new
project = Hash.new()
project["Assignee Name"] = issue["fields"]["assignee"]["displayName"]
project["Amount of Issues"] = 0
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
project_JSON.each do |x|
project["Amount of Issues"] += 1
teamList.push(project)
end
Im having trouble with this line.
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
It always returns true even after the .push. I want to make an array of my team members and list how many times their name appears in my JSON. What am I doing wrong and how do I dynamically refer to a hash value in an if statement(thats where I think its wrong because if I am saying .include?(issue["fields"]["assignee"]["displayName"]) wrong then its nil and the if statement will always be true)?
In your code teamList is an empty array, so it does not include? anything, it will always return false. Now because you are using ! operator it always returns true.
EDIT
If understood it right, you have to loop through the array checking each element for the value specified.
Below is a way to do it, mind you I replaced keys for symbols as it's a good practice in Ruby:
issue = {
:fields => {
:assignee => {
:displayName => 'tiago'
}
}
}
teamList = Array.new
def teamList.has_assignee?(assignee)
self.each do |e|
return e[:assignee] == assignee
end
false
end
project = Hash.new
project[:assigneeName] = issue[:fields][:assignee][:displayName]
project[:amountOfIssues] = 0
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
puts teamList.inspect # only one object here
As Sergio pointed out you could use .detect
def teamList.has_assignee?(assignee)
self.detect { |e| e[:assigneeName] == assignee }
end

Shortest way to get File object from resource in Groovy

Right now I'm using Java API to create file object from resource:
new File(getClass().getResource('/resource.xml').toURI())
Is there any more idiomatic/shorter way to do that in Groovy using GDK?
Depending on what you want to do with the File, there might be a shorter way. Note that URL has GDK methods getText(), eachLine{}, and so on.
Illustration 1:
def file = new File(getClass().getResource('/resource.xml').toURI())
def list1 = []
file.eachLine { list1 << it }
// Groovier:
def list2 = []
getClass().getResource('/resource.xml').eachLine {
list2 << it
}
assert list1 == list2
Illustration 2:
import groovy.xml.*
def xmlSlurper = new XmlSlurper()
def url = getClass().getResource('/resource.xml')
// OP style
def file = new File(url.toURI())
def root1 = xmlSlurper.parseText(file.text)
// Groovier:
def root2 = xmlSlurper.parseText(url.text)
assert root1.text() == root2.text()

PyQt iterate over a a QTreeView with checkbox

i am trying to make a UI that display folders from a given directory,
and the user can check or uncheck the folder.
i would like to get the information of what was checked and return the folder
i know i can loop / iterate in a QTableWidget, but if its a view, or its comming from a Qt.Dir how its done?
(even might be a easier way to add the check boxes to the dir view model than making another class)
thanks.
from PyQt4 import QtCore, QtGui
import sys
import argparse
def parseOpt():
parser = argparse.ArgumentParser(description="Check if the files in this folder are valid EXRs")
parser.add_argument("-file", dest="filepath", help="The file path to be checked.")
return parser.parse_args()
ARGS = parseOpt()
class CheckableDirModel(QtGui.QDirModel):
#a class to put checkbox on the folders
def __init__(self, parent=None):
QtGui.QDirModel.__init__(self, None)
self.checks = {}
def data(self, index, role=QtCore.Qt.DisplayRole):
if role != QtCore.Qt.CheckStateRole:
return QtGui.QDirModel.data(self, index, role)
else:
if index.column() == 0:
return self.checkState(index)
def flags(self, index):
return QtGui.QDirModel.flags(self, index) | QtCore.Qt.ItemIsUserCheckable
def checkState(self, index):
if index in self.checks:
return self.checks[index]
else:
return QtCore.Qt.Unchecked
def setData(self, index, value, role):
if (role == QtCore.Qt.CheckStateRole and index.column() == 0):
self.checks[index] = value
self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
return True
return QtGui.QDirModel.setData(self, index, value, role)
#def filtering(self, index):
# self.checks.setFilter(QtCore.QDir.Dirs|QtCore.QDir.NoDotAndDotDot)
class Ui_Dialog(QtGui.QDialog):
def __init__(self,parent=None):
QtGui.QDialog.__init__(self,parent)
self.setObjectName("Dialog")
self.resize(600, 500)
self.llayout = QtGui.QVBoxLayout(parent)
self.model = CheckableDirModel()
self.model.setFilter(QtCore.QDir.Dirs|QtCore.QDir.NoDotAndDotDot)
#self.tree = QtGui.QTreeWidget()
self.tree = QtGui.QTreeView()
self.tree.setModel(self.model)
self.tree.setSortingEnabled(True)
self.tree.setRootIndex(self.model.index(ARGS.filepath))
#self.tree.hideColumn(1)
#self.tree.hideColumn(2)
#self.tree.hideColumn(3)
self.tree.setWindowTitle("Dir View")
self.tree.resize(400, 480)
self.tree.setColumnWidth(0,200)
self.but = QtGui.QPushButton(QtCore.QString("Run"))
self.llayout.addWidget(self.tree)
self.llayout.addWidget(self.but)
self.setLayout(self.llayout)
self.but.clicked.connect(self.print_path)
def print_path(self):
print "hello"
root = self.tree.childCount()
print root
for i in range(root):
print i.text()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = Ui_Dialog()
ui.show()
sys.exit(app.exec_())
If I understand you correctly, what you want is to replace your print_path method with the following:
def print_path(self):
print "hello"
for index,value in self.model.checks.items():
if value.toBool():
print self.model.filePath(index)

Find key/value pairs deep inside a hash containing an arbitrary number of nested hashes and arrays

A web service is returning a hash that contains an unknown number of nested hashes, some of which contain an array, which in turn contains an unknown number of nested hashes.
Some of the keys are not unique -- i.e. are present in more than one of the nested hashes.
However, all the keys that I actually care about are all unique.
Is there someway I can give a key to the top-level hash, and get back it's value even if the key-value pair is buried deep in this morass?
(The web service is Amazon Product Advertising API, which slightly varies the structure of the results that it gives depending on the number of results and the search types permitted in each product category.)
Here's a simple recursive solution:
def nested_hash_value(obj,key)
if obj.respond_to?(:key?) && obj.key?(key)
obj[key]
elsif obj.respond_to?(:each)
r = nil
obj.find{ |*a| r=nested_hash_value(a.last,key) }
r
end
end
h = { foo:[1,2,[3,4],{a:{bar:42}}] }
p nested_hash_value(h,:bar)
#=> 42
No need for monkey patching, just use Hashie gem: https://github.com/intridea/hashie#deepfind
user = {
name: { first: 'Bob', last: 'Boberts' },
groups: [
{ name: 'Rubyists' },
{ name: 'Open source enthusiasts' }
]
}
user.extend Hashie::Extensions::DeepFind
user.deep_find(:name) #=> { first: 'Bob', last: 'Boberts' }
For arbitrary Enumerable objects, there is another extension available, DeepLocate: https://github.com/intridea/hashie#deeplocate
Combining a few of the answers and comments above:
class Hash
def deep_find(key, object=self, found=nil)
if object.respond_to?(:key?) && object.key?(key)
return object[key]
elsif object.is_a? Enumerable
object.find { |*a| found = deep_find(key, a.last) }
return found
end
end
end
Ruby 2.3 introduces Hash#dig, which allows you to do:
h = { foo: {bar: {baz: 1}}}
h.dig(:foo, :bar, :baz) #=> 1
h.dig(:foo, :zot) #=> nil
A variation of barelyknown's solution: This will find all the values for a key in a hash rather than the first match.
class Hash
def deep_find(key, object=self, found=[])
if object.respond_to?(:key?) && object.key?(key)
found << object[key]
end
if object.is_a? Enumerable
found << object.collect { |*a| deep_find(key, a.last) }
end
found.flatten.compact
end
end
{a: [{b: 1}, {b: 2}]}.deep_find(:b) will return [1, 2]
Despite this appearing to be a common problem, I've just spent a while trying to find/come up with exactly what I need, which I think is the same as your requirement. Neither of the links in the first response are spot-on.
class Hash
def deep_find(key)
key?(key) ? self[key] : self.values.inject(nil) {|memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
end
end
So given:
hash = {:get_transaction_list_response => { :get_transaction_list_return => { :transaction => [ { ...
The following:
hash.deep_find(:transaction)
will find the array associated with the :transaction key.
This is not optimal as the inject will continue to iterate even if memo is populated.
I use the following code
def search_hash(hash, key)
return hash[key] if hash.assoc(key)
hash.delete_if{|key, value| value.class != Hash}
new_hash = Hash.new
hash.each_value {|values| new_hash.merge!(values)}
unless new_hash.empty?
search_hash(new_hash, key)
end
end
I ended up using this for a small trie search I wrote:
def trie_search(str, obj=self)
if str.length <= 1
obj[str]
else
str_array = str.chars
next_trie = obj[str_array.shift]
next_trie ? trie_search(str_array.join, next_trie) : nil
end
end
Note: this is just for nested hashes at the moment. Currently no array support.
Because Rails 5 ActionController::Parameters no longer inherits from Hash, I've had to modify the method and make it specific to parameters.
module ActionController
class Parameters
def deep_find(key, object=self, found=nil)
if object.respond_to?(:key?) && object.key?(key)
return object[key]
elsif object.respond_to?(:each)
object = object.to_unsafe_h if object.is_a?(ActionController::Parameters)
object.find { |*a| found = deep_find(key, a.last) }
return found
end
end
end
end
If the key is found, it returns the value of that key, but it doesn't return an ActionController::Parameter object so Strong Parameters are not preserved.

Resources