Relations between special vectors in python - python

I am wondering if there is a way to establish a relation between some special "vectors".
Example:
Suppose these are my vectors (I will only choose 3 special vectors):
a=[1,2,[1]]
b=[1,2,[2]]
c=[1,3,[1]]
and I want to add the following rules when comparing them (lexicographic order):
I wish to say that
a<b
because
a[0]=b[0] and a[1]=b[1] but *a[2]<b[2]*
but I also want to say
a<c
because
a[0]=b[0] and a[1]<c[1] and a[2]<=c[2]
but note that things are a little different for "b" and "c" since these are not comparable because even though
b[0]=c[0] and b[1]<c[1], the last term changes everything since b[2]>c[2]
In other words, the rules I am applying, will first compare the "normal" entries of two vectors x and y, if a certain entry of vector x is bigger than a certain entry of vector y, we take a look at the last entry. If the last entry of vector x is greater than Or equal, then we say x>y, if this is not the case, then x and y are not comparable.
In case all "normal" entries of x and y are the same, we compare the last entry. If the last entry of x is bigger than the last entry of y, we also say x>y.
I am thinking that this has to do with a while loop.

You can easily write a function to do what you described.
def special_lt(vec1, vec2):
You've defined the "normal" values as all but the last one, and the "special" values as the last one, so that's easy:
normal1, normal2 = vec1[:-1], vec2[:-1]
special1, special2 = vec1[-1], vec2[-1]
Now, if I understand it correctly, you want to do a lexicographical comparison of the normal values, and then defer to the special values if they're equal…
if normal1 == normal2:
return special1 < special2
… but otherwise use the special values as a check to make sure they're ordered in the same way as the normal values:
elif normal1 < normal2:
if special1 <= special2:
return True
raise ValueError('not comparable')
else:
if special2 <= special1:
return False
raise ValueError('not comparable')
Notice that for comparing the lists of normal values, and the lists of special values, I didn't use a loop; I just compared the lists. That's because lists already compare lexicographically (which, internally, is done with a loop, of course, but I don't have to write it).

You can make vector a subclass of list and overload the __lt__ and __gt__ methods so that the last item is checked before the default behavior. Also overload the __le__ and __ge__ methods for completeness:
class vector(list):
def __lt__(self, other):
lt = super().__lt__(other)
if lt and self[-1] > other[-1]:
return False
return lt
def __gt__(self, other):
gt = super().__gt__(other)
if gt and self[-1] < other[-1]:
return False
return gt
def __le__(self, other):
if self == other:
return True
return self < other
def __ge__(self, other):
if self == other:
return True
return self > other
so that:
a=vector([1,2,[1]])
b=vector([1,2,[2]])
c=vector([1,3,[1]])
print(a<b)
print(a<c)
print(b<c)
print(c<b)
print(b>c)
print(c>b)
print(b<=c)
print(c<=b)
will output:
True
True
False
False
False
False
False
False
EDIT: In light of the comments made below, I would also like to point out that this is case where functools.total_ordering doesn't work because of the atypical logic required by the OP, where one object can be not less than, not greater than and not equal to the other at the same time.
So if we define only the __lt__ method for the vector class and apply the total_ordering decorator:
from functools import total_ordering
#total_ordering
class vector(list):
def __lt__(self, other):
lt = super().__lt__(other)
if lt and self[-1] > other[-1]:
return False
return lt
The test code above would produce the following incorrect output instead:
True
True
False
False
False
True
True
False

Related

Optimizing Several True/False Functions in Python

While the provided code I created works, it is non-scalable and slow. I need a way to determine if a token (t) is the same as any element in several arrays. However, it cannot match more than one array, as one list might supersede the other. Is there any way to succinctly and quickly program this in python other than using tons of individual functions?
def keyword(t):
for n in keywords:
if t == n:
return True
break
else:
return False
def separator(t):
for n in separators:
if t == n:
return True
break
else:
return False
def operator(t):
for n in operators:
if t == n:
return True
break
else:
return False
def identifier(t):
if keyword(t) is False and operator(t) is False and separator(t) is False:
return True
else:
return False
The keyword function is just n in keywords - a test of containment. This is generally faster using a set. So, combine call of your categories and test from there.
identifiers = {(*keywords, *separators, *operators)}
def identifier(t):
return t in identifiers
the way I find that you could do what you ask is simply using a function that requires 2 parameters and creating an array that contains all the arrays you need to compare, making a function that cycles through each of the arrays trying to find a match.
I do it this way:
keywords = ["Hi", "World"]
separators = ["Hola", "Mundo"]
operators = ["My", "name"]
lists = [keywords, separators, operators]
t = "F"
def comparator(token, arrays):
for array in arrays:
for item in array:
if token == item:
return False
else:
return True
print(comparator(token=t, arrays=lists))

Nesting Structure Comparisons

I'm trying to write Nesting Structure Comparison with recursion. Seems pretty basic but doesn't work: when I compare len(original) and len(other) they're different, but it doesn't return False. Why?
def same_structure_as(original,other):
if type(original) != type(other) or len(original) != len(other):
return False
for i in range(len(original)):
if type(original[i]) != type(other[i]):
return False
if type(original[i]) is list and type(other[i]) is list:
same_structure_as(original[i],other[i])
return True
print (same_structure_as([1,[1,1]], [2,[2]]))
As commented, your code did not consider the recursion result. I corrected it and used a combined loop instead of the repeated cumbersome indexing. (I still don't like the multiple return construction). Note that you don't compare simple values in the loop, so an else part for the list type comparison is still needed. Otherwise this works as expected:
def same_structure_as(original, other):
if type(original) != type(other) or len(original) != len(other):
return False
for org_val, other_val in zip(original, other):
if type(org_val) != type(other_val):
return False
if type(org_val) is list and type(other_val) is list:
if not same_structure_as(org_val, other_val):
return False
return True
print (same_structure_as([1,[1,1]], [2,[2]]))
Scratching my original answer, but this is more related to your nested array length.
len([1,[1,1]]) will have a length of 2. It will not count the inner nest items. Therefore, comparing this nested list with other list will pass on your if check.

How do I compare two linked lists in python 3.7?

first of all, my current code:
class linkedlist(object):
def __init__(self, value, next = None):
self.value = value
self.next = next
def traverse(self):
field = self
while field != None:
print(field.value)
field = field.next
def equal(self, other):
while self and other and self.value== other.value:
self = self.next
other = other.next
if self and other:
if self.value!= other.value:
return False
else:
return True
My task is to compare two linked lists. If they are identical, the "equal"-Function should return "True", if not "False". The functionhead has to stay that way.
I tried to find a solution on my own for 3h and now i'm braindead. Can anyone give me some tips/help? I'm not the best programmer, so i'm sorry :(
You are almost there. You are using the correct strategy to traverse both linked lists and skipping any paired elements that are equal (your first loop).
Where you go wrong is that you then don't handle what comes after for all the possible scenarios. You know now that the two linked lists have a prefix of between 0 and N elements that are equal. You now have one of 4 options to consider:
self is exhausted, but other is not; other is longer so not equal, return False
other is exhausted, but self is not; self is longer so not equal, return False
self and other still have more elements, but the next elements for the two linked lists have unequal values. Return False
self and other are both exhausted, so have equal length. Their prefixes were equal, so the linked lists are equal. Return True.
You only handle option 3 right now. Given that 3 out of 4 scenarios lead to return False, it is easier to just test for scenario 4:
if not self and not other:
return True
return False
or, as a full method:
def equal(self, other):
while self and other and self.value == other.value:
self = self.next
other = other.next
if not self and not other:
return True
return False

Question about my code for returning longest word

Write a python function named longest, that takes two arguments (you can safely assume that all arguments will always be strings).
When this function is called, it should determine which string is longer, and return that string.
My code:
def longest(word1, word2):
if word1 < word2:
return word2
else:
return word1
When this function is called, it should determine which string is longer, and return that string.
The < operator doesn't compare the length of strings, but rather what order they would sort alphabetically. Instead try len(word1) < len(word2).
In order to use < for length comparison of length of strings, you need to create your own class which should be subclass of built-in str. Lets give this subclass the same name as str.
< operator is implemented using a method called as __lt__() and in your subclass you need to implement this method. You can implement __le__() as well for <= operator. You might need to override other operators according to your requirement.
So your subclass definition will look like this:
class str(str):
def __lt__(self, other):
return len(self) < len(other)
def __le__(self, other):
return len(self) <= len(other)
Now you can use your method to get the longest word as:
def longest(word1, word2):
if str(word1) < str(word2):
return word2
else:
return word1
str(word1) is important here because by default string creation will use build-in str class but you should use your subclass str class. This method is rather complicated, so you can just use len(word) to get the length of the word and use this to find the longest string.

all builtin function of empty list

Can anybody explain why in python builtin buinction all return True in this case all([])?
In [33]: all([])
Out[33]: True
In [34]: all([0])
Out[34]: False
In [35]: __builtins__.all([])
Out[35]: True
I'm not convinced that any of the other answers have really address the question of why this should be the case.
The definition for Python's all() comes from boolean logic. If for example we say that "all swans are white" then a single black swan disproves the statement. However, if we say that "all unicorns are pink" logicians would take that as a true statement simply because there are no non-pink unicorns. Or in other words "all " is vacuously true.
Practically it gives us a useful invariant. If all(A) and all(B) are both true then the combination of all(A + B) is also true. If all({}) was false we should have a less useful situation because combining two expressions one of which is false suddenly gives an unexpected true result.
So Python takes all([]) == True from boolean logic, and for consistency with other languages with a similar construct.
Taking that back into Python, in many cases the vacuous truth makes algorithms simpler. For example, if we have a tree and want to validate all of the nodes we might say a node is valid if it meets some conditions and all of its children are valid. With the alternative definition of all() this becomes more complex as we have to say it is valid if it meets the conditions and either has no children or all its children are valid.
class Node:
def isValid(self):
return some_condition(self) and all(child.isValid for child in self.children)
From the docs:
Return True if all elements of the iterable are true (or if the iterable is empty).
So, roughly, it's simply defined this way.
You can get around that by using
list = []
if list and all(list):
pass
As the docs say, all is equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
For an empty iterable the loop body is never executed, so True is immediately returned.
Another explanation for this is that all and any are generalisations of the binary operators and and or for arbitrarily long numbers of parameters. Thus, all and any can be defined as:
def all(xs):
return reduce(lambda x,y: x and y, xs, True)
def any(xs):
return reduce(lambda x,y: x or y, xs, False)
The True and False parameters show that all([]) == True and any([]) == False.
Any expression with all can be rewritten by any and vice versa:
not all(iterable)
# is the same as:
any(not x for x in iterable)
and symmetrically
not any(iterable)
# is the same as:
all(not x for x in iterable)
These rules require that all([]) == True.
The function all is very useful for readable asserts:
assert all(required_condition(x) for x in some_results_being_verified)
(It is not so bad if a task has no results, but something is very broken if any result is incorrect.)

Categories