Related
I have a list of version numbers like,
Versions = [0.0.10, 0.0.11, 0.0.13, 0.0.14, 0.0.15, 0.0.16, 0.0.17, 0.0.18, 0.0.19, 0.0.20, 0.0.21, 0.0.22, 0.0.23, 0.0.24, 0.0.25, 0.0.26, 0.0.27, 0.0.28, 0.0.29, 0.0.3, 0.0.30, 0.0.33, 0.0.34, 0.0.35, 0.0.36, 0.0.37, 0.0.38, 0.0.39, 0.0.4, 0.0.41, 0.0.42, 0.0.43, 0.0.44, 0.0.45, 0.0.46, 0.0.47, 0.0.48, 0.0.49, 0.0.5, 0.0.5-delivery.5, 0.0.50, 0.0.51, 0.0.52, 0.0.53, 0.0.54, 0.0.55, 0.0.56, 0.0.57, 0.0.58, 0.0.59, 0.0.6, 0.0.60, 0.0.61, 0.0.62, 0.0.63, 0.0.64, 0.0.7, 0.0.8, 0.0.9]'
And i need to get the last version (0.0.64), Versions.sort() && Collections.max(Versions) doesn't work for me.
So I developed this function blow
def mostRecentVersion(def versions) {
def lastversion = "0.0.0"
for (def items : versions) {
def version = items.tokenize('-')[0]
def ver = version.tokenize('.')
def lastver = lastversion.tokenize('.')
if (lastver[0].toInteger() < ver[0].toInteger() ){
lastversion = version
}else if(lastver[0].toInteger() == ver[0].toInteger()) {
if (lastver[1].toInteger() < ver[1].toInteger() ){
lastversion = version
}else if(lastver[1].toInteger() == ver[1].toInteger()){
if (lastver[2].toInteger() < ver[2].toInteger() ){
lastversion = version
}
}
}
}
return lastversion }
i'm asking if there is something better,
Thank you for help :)
the idea:
build map with sortable key and original version value, then sort map by keys, then get only values
to create sortable key for each value
split version to digits & not-digit strings array
prepend to each part 0 to have minimum length 3 (assume each number not longer then 3 digits)
join array to string
so, for 0.11.222-dev ->
1. [ '0', '.', '11', '222', '-dev' ]
2. [ '000', '00.', '011', '222', '-dev' ]
3. '00000.011222-dev'
the code
def mostRecentVersion(versions){
return versions.collectEntries{
[(it=~/\d+|\D+/).findAll().collect{it.padLeft(3,'0')}.join(),it]
}.sort().values()[-1]
}
//test cases:
def fullVersions = ['0.0.10', '0.0.11', '0.0.13', '0.0.14', '0.0.15', '0.0.16',
'0.0.17', '0.0.18', '0.0.19', '0.0.20', '0.0.21', '0.0.22', '0.0.23', '0.0.24',
'0.0.25', '0.0.26', '0.0.27', '0.0.28', '0.0.29', '0.0.3', '0.0.30', '0.0.33',
'0.0.34', '0.0.35', '0.0.36', '0.0.37', '0.0.38', '0.0.39', '0.0.4', '0.0.41',
'0.0.42', '0.0.43', '0.0.44', '0.0.45', '0.0.46', '0.0.47', '0.0.48', '0.0.49',
'0.0.5', '0.0.5-delivery.5', '0.0.50', '0.0.51', '0.0.52', '0.0.53', '0.0.54',
'0.0.55', '0.0.56', '0.0.57', '0.0.58', '0.0.59', '0.0.6', '0.0.60', '0.0.61',
'0.0.62', '0.0.63', '0.0.64', '0.0.7', '0.0.8', '0.0.9']
assert mostRecentVersion(fullVersions) == '0.0.64'
assert mostRecentVersion(['0.0.5-delivery.5', '0.0.3', '0.0.5']) == '0.0.5-delivery.5'
assert mostRecentVersion(['0.0.5.5', '0.0.5-delivery.5', '0.0.5']) == '0.0.5.5'
I believe this will work... it also keeps the original version strings around, incase 0.5.5-devel.5 is the latest... It relies on the fact that Groovy will use a LinkedHashMap for the sorted map, so the order will be preserved :-)
def mostRecentVersion(def versions) {
versions.collectEntries {
[it, it.split(/\./).collect { (it =~ /([0-9]+).*/)[0][1] }*.toInteger()]
}.sort { a, b ->
[a.value, b.value].transpose().findResult { x, y -> x <=> y ?: null } ?:
a.value.size() <=> b.value.size() ?:
a.key <=> b.key
}.keySet()[-1]
}
def fullVersions = ['0.0.10', '0.0.11', '0.0.13', '0.0.14', '0.0.15', '0.0.16', '0.0.17', '0.0.18', '0.0.19', '0.0.20', '0.0.21', '0.0.22', '0.0.23', '0.0.24', '0.0.25', '0.0.26', '0.0.27', '0.0.28', '0.0.29', '0.0.3', '0.0.30', '0.0.33', '0.0.34', '0.0.35', '0.0.36', '0.0.37', '0.0.38', '0.0.39', '0.0.4', '0.0.41', '0.0.42', '0.0.43', '0.0.44', '0.0.45', '0.0.46', '0.0.47', '0.0.48', '0.0.49', '0.0.5', '0.0.5-delivery.5', '0.0.50', '0.0.51', '0.0.52', '0.0.53', '0.0.54', '0.0.55', '0.0.56', '0.0.57', '0.0.58', '0.0.59', '0.0.6', '0.0.60', '0.0.61', '0.0.62', '0.0.63', '0.0.64', '0.0.7', '0.0.8', '0.0.9']
assert mostRecentVersion(fullVersions) == '0.0.64'
assert mostRecentVersion(['0.0.5-delivery.5', '0.0.3', '0.0.5']) == '0.0.5-delivery.5'
assert mostRecentVersion(['0.0.5.5', '0.0.5-delivery.5', '0.0.5']) == '0.0.5.5'
Edit:
Made a change so that 0.5.5.5 > 0.5.5-devel.5
regions([a,b,c,d,e,f]).
colors([brown,green,blue,red]).
hascolor(X,brown):-regions([X|_]).
hascolor(X,brown):-regions([_,_,_,_,X,_]).
hascolor(X,blue):-regions([_,X,_,_,_,_]).
hascolor(X,blue):-regions([_,_,_,X,_,_]).
hascolor(X,green):-regions([_,_,_,_,_,X]).
hascolor(X,red):-regions([_,_,X,_,_,_]).
conflict(X,Y):-hascolor(X,brown),hascolor(Y,brown).
Hey guys running ?-conflict(a,e). would get me true and false. Both a and e has the same color(brown) and conflict should return true only. Why does it return false also?
ABC abc = eMsg.getAbcCont().stream()
.filter(cnt -> (option.geiID().equals(cnt.getId()) && option.getIdVersion() == cnt.getIdVersion()))
.collect(Collectors.toList()).get(0);
delEmsg.getAbcCont().remove(abc);
Above code is giving me en exception as
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:657)
at java.util.ArrayList.get(ArrayList.java:433)
getAbcCont method will return the List of ABC objects.Currently my eMsg contains two object with the getAbcCont. When control reach to the .collect(Collectors.toList()).get(0); its giving the above mentioned exception. Any help suggestion must be appricaited.
This means that the result after the filter is zero elements, so you cannot do get(0).
A quick solution for this would be to first get the list of elements back, and then check if there is atleast one element.
List<ABC> list = ABC abc = eMsg.getAbcCont().stream()
.filter(cnt -> (option.geiID().equals(cnt.getId()) && option.getIdVersion() == cnt.getIdVersion()))
.collect(Collectors.toList());
if(list.size() > 0){
ABC abc = list.get(0);
}
Obviously there is a shorter way also using lambdas such as:
ABC abc = eMsg.getAbcCont().stream()
.filter(cnt -> (option.geiID().equals(cnt.getId()) && option.getIdVersion() == cnt.getIdVersion()))
.collect(Collectors.toList()).findFirst().orElse(null)
Reference: https://stackoverflow.com/a/26126636/1688441
But as User nullpointer , you might need to check if an element is found before you try to call remove() using object abc. I suspect trying to remove null from a collection might not do anything, but you could check to be sure!
if(abc != null){
delEmsg.getAbcCont().remove(abc);
}
You should do !list.isEmpty() rather than list.size() as per sonar
This following Code doesn't work, the Problem is inside of the calc_fitness method, the each block does not return an value, and i dont know why
# takes an array, splices them into groups of 2 and returns a sum of values read from the matrix
def calc_fitness(hypothesis_arr)
hypothesis_arr.each_slice(2).to_a.map{|v| $distances[v.first,v.last]}
end
def main
# filling the matrix, with random values
$distances = create_sym_matrix
p calc_fitness((0..99).to_a)
end
main
# => [67,67,67,67....67,] #these should not be the same, which means i the block alway returns the same value. Why?
This happens because each returns itself (an instance of Enumerator) and each_slice return nil.
https://ruby-doc.org/core/Enumerable.html#method-i-each_slice
You could try changing the each to a map
To simplify and get a visual of what was generated, I used:
(1..99).to_a.each_slice(2).map { |v| { first: v.first, last: v.last } }
=> [{:first=>1, :last=>2}, {:first=>3, :last=>4}, {:first=>5, :last=>6}, {:first=>7, :last=>8}, {:first=>9, :last=>10}, {:first=>11, :last=>12}, {:first=>13, :last=>14}, {:first=>15, :last=>16}, {:first=>17, :last=>18}, {:first=>19, :last=>20}, {:first=>21, :last=>22}, {:first=>23, :last=>24}, {:first=>25, :last=>26}, {:first=>27, :last=>28}, {:first=>29, :last=>30}, {:first=>31, :last=>32}, {:first=>33, :last=>34}, {:first=>35, :last=>36}, {:first=>37, :last=>38}, {:first=>39, :last=>40}, {:first=>41, :last=>42}, {:first=>43, :last=>44}, {:first=>45, :last=>46}, {:first=>47, :last=>48}, {:first=>49, :last=>50}, {:first=>51, :last=>52}, {:first=>53, :last=>54}, {:first=>55, :last=>56}, {:first=>57, :last=>58}, {:first=>59, :last=>60}, {:first=>61, :last=>62}, {:first=>63, :last=>64}, {:first=>65, :last=>66}, {:first=>67, :last=>68}, {:first=>69, :last=>70}, {:first=>71, :last=>72}, {:first=>73, :last=>74}, {:first=>75, :last=>76}, {:first=>77, :last=>78}, {:first=>79, :last=>80}, {:first=>81, :last=>82}, {:first=>83, :last=>84}, {:first=>85, :last=>86}, {:first=>87, :last=>88}, {:first=>89, :last=>90}, {:first=>91, :last=>92}, {:first=>93, :last=>94}, {:first=>95, :last=>96}, {:first=>97, :last=>98}, {:first=>99, :last=>99}]
Now at this point I'm not sure what that function is doing that is assigned to $distances. You might want to provide the code for that or give some more detail on what your are attempting to accomplish.
I am trying to implement a "Breadth-First" Algorithm as a variation of something I've seen in a book.
My issue is that the algorithm is not adding the elements of every node into the queue.
For instance, if I search for "black lab" under the name 'mariela' in the "search()" function, I will get the correct output: "simon is a black lab"
However, I ought to be able to look for "black lab" in "walter", which is connected to "mariela", which is connected to "simon", who is a "black lab'. This is not working.
Have I made a rookie mistake in my implementation of this algorithm, or have I set up my graph wrong?
As always, any/all help is much appreciated!
from collections import deque
# TEST GRAPH -------------
graph = {}
graph['walter'] = ['luci', 'kaiser', 'andrea', 'mariela']
graph['andrea'] = ['echo', 'dante', 'walter', 'mariela']
graph['mariela'] = ['ginger', 'simon', 'walter', 'andrea']
graph['kaiser'] = 'german shepherd'
graph['luci'] = 'black cat'
graph['echo'] = 'pitbull'
graph['dante'] = 'pitbull'
graph['ginger'] = 'orange cat'
graph['simon'] = 'black lab'
def condition_met(name):
if graph[name] == 'black lab':
return name
def search(name):
search_queue = deque()
search_queue += graph[name] # add all elements of "name" to queue
searchedAlready = [] # holding array for people already searched through
while search_queue: # while queue not empty...
person = search_queue.popleft() # pull 1st person from queue
if person not in searchedAlready: # if person hasn't been searched through yet...
if condition_met(person):
print person + ' is a black labrador'
return True
else:
search_queue += graph[person]
searchedAlready.append(person)
return False
search('walter')
#search('mariela')
You have lots of problems in your implementation - both Python and Algorithm wise.
Rewrite as:
# #param graph graph to search
# #param start the node to start at
# #param value the value to search for
def search(graph, start, value):
explored = []
queue = [start]
while len(queue) > 0:
# next node to explore
node = queue.pop()
# only explore if not already explored
if node not in explored:
# node found, search complete
if node == value:
return True
# add children of node to queue
else:
explored.append(node)
queue.extend(graph[node]) # extend is faster than concat (+=)
return False
graph = {}
graph['walter'] = ['luci', 'kaiser', 'andrea', 'mariela']
graph['andrea'] = ['echo', 'dante', 'walter', 'mariela']
graph['mariela'] = ['ginger', 'simon', 'walter', 'andrea']
# children should be a list
graph['kaiser'] = ['german shepherd']
graph['luci'] = ['black cat']
graph['echo'] = ['pitbull']
graph['dante'] = ['pitbull']
graph['ginger'] = ['orange cat']
graph['simon'] = ['black lab']
print search(graph, 'mariela', 'walter')
Here is a demo https://repl.it/IkRA/0