How do I find the Subsets of given Set in Sage? - set

I have code that looks like this:
def Z(m,n):
return CartesianProduct(IntegerRange(m),IntegerRange(n))
for v in Subsets(Z(2,2)):
print v
However, when I try to run it, I get the following error:
Traceback (most recent call last):
File "x.py", line 13, in <module>
for v in Subsets(Z(_sage_const_2 ,_sage_const_2 )):
File "/opt/sage-4.8-linux-64bit-ubuntu_10.04.3_lts-x86_64-Linux/local/lib/python2.6/site-packages/sage/combinat/subset.py", line 234, in __iter__
lset = __builtin__.list(self.s)
File "/opt/sage-4.8-linux-64bit-ubuntu_10.04.3_lts-x86_64-Linux/local/lib/python2.6/site-packages/sage/sets/set.py", line 650, in __iter__
for x in self.set():
File "/opt/sage-4.8-linux-64bit-ubuntu_10.04.3_lts-x86_64-Linux/local/lib/python2.6/site-packages/sage/sets/set.py", line 719, in set
return set(self.object())
TypeError: unhashable type: 'list'
What is the canonical way of getting the set of all subsets of an arbitrary Set?

CartesianProduct returns a list of lists, e.g.:
>>> print list(Z(2,2))
[[0, 0], [0, 1], [1, 0], [1, 1]]
But Subsets can't cope with the elements being lists (it converts its argument to a set internally, and a set in Python is implemented as a hash set, hence the error about "unhashibility"). To fix this, you should convert the internal lists to tuples:
for v in Subsets(tuple(l) for l in Z(2,2)):
print v
Note that this is using a generator expression (rather than a list comprehension) to avoid constructing an intermediate list.
(One could also use map(tuple, Z(2,2)) or import itertools iterools.imap(tuple, Z(2,2)) in place of the generator expression, but the solution given above is the most Pythonic.)

Related

function to remove the smallest number in ruby

Currently trying to create a ruby function that deletes the smallest number , if that minimum number is duplicated, it should only remove the first minimum number . Here's the code that i tried
def RemoveSmallest(numbers)
if numbers.count(numbers.min.uniq) > 1
numbers.delete_at(numbers.index numbers.min.uniq)
numbers
else
numbers.delete(numbers.min)
numbers
end
end
puts RemoveSmallest([2,2,4,5,6])
this is the error
remove_small.rb:3:in `RemoveSmallest': undefined method `uniq' for 2:Fixnum (NoMethodError)
from remove_small.rb:15:in `<main>'
im not sure why the code passes wrong when i apply uniq method on it
numbers.min returns a number, not an array. You cannot invoke uniq on it, that's not a method on numbers.
Your code in the first branch would successfully remove only the first instance of the lowest number without .uniq, because numbers.index finds the first occurrence.
In fact, the entire if/else block is redundant. The first branch handles both types of input, so there is very little point in defining a special case for many vs one:
def remove_smallest(array)
array.delete_at(array.index(array.min))
array
end
p remove_smallest([1, 2, 3, 4]) # [2, 3, 4]
p remove_smallest([4, 3, 1, 2, 1]) # [4, 3, 2, 1]

How can one get the indices of duplicate elements in a list of OrderedDicts?

I have a list of OrderedDicts and I want to get the indices in that list of the elements that are duplicates. Conceptually, it is a bit like the following example, which features a list of ints:
>>> def indices_of_list_element_duplicates(x):
... seen = set()
... for index, element in enumerate(x):
... if isinstance(element, list):
... element = tuple(element)
... if element not in seen:
... seen.add(element)
... else:
... yield index
...
>>> a = [1, 2, 3, 4, 5, 6, 1, 1, 9, 1]
>>> indices = [index for index in indices_of_list_element_duplicates(a)]
>>> indices
[6, 7, 9]
How can the equivalent of this be done for a list of OrderedDicts? When I try to this function on the OrderedDicts, I encounter the following error:
TypeError: unhashable type: 'OrderedDict'
from collections import OrderedDict
# ...
if isinstance(element, OrderedDict): # checking for type dict would be enough
element = tuple(element.items())
# ...
This converts the dictionary to a tuple of tuples which can, in turn, be an element of your set. Before, you were trying to add an object to the set which does not implement hashing.
Be aware that the given dictionaries have to be recursively restricted to hashable value types. Otherwise you will experience a similar issue.
from collections import OrderedDict
d = OrderedDict(a=[1,2,3])
set().add(tuple(d.items()))
TypeError: unhashable type: 'list'

How do I slice an array into arrays of different sizes and combine them?

I want something as simple as the pseudocode below:
ar = [4,5,6,7,8,9]
last = ar.length-1
s = ar[0, 1..3, last] #fake code
puts s
Expected output has no 8:
4,5,6,7,9
Error:
bs/test.rb:12:in `[]': wrong number of arguments (3 for 2) (ArgumentError)
I know that it can accept only two args. Is there a simple way to get what I need ?
You almost have it, you're just using the wrong method, you should be using Array#values_at instead of Array#[]:
ar.values_at(0, 1..3, -1)
# => [4, 5, 6, 7, 9]
Also note that in Ruby, indices "wrap around", so that -1 is always the last element, -2 is second-to-last and so on.
You can do it this way also -
ar = [4,5,6,7,8,9]
arr = []
arr << ar[0..0] #arr[0] will return a single value but ar[0..0] will return it in array.
arr << ar[1..3]
arr << ar[-1..-1]
on printing arr it will give following output -
[[4], [5, 6, 7], [9]]

Pythonic way of summing lists and lists of lists

I'm trying to find a neat way of summing a list and a list of lists in the same function, so far I've got:
import operator
"""
Fails late for item = ['a', 'b']
"""
def validate(item):
try:
return sum(item) == sum(range(1, 10))
except TypeError:
return sum(reduce(operator.add, item)) == sum(range(1, 10))
"""
Not valid for item = [1,2,[3,4,5]]
"""
def validate2(item):
if isinstance(item[0], int):
return sum(item) == sum(range(1, 10))
else:
return sum(reduce(operator.add, item)) == sum(range(1, 10))
print validate([1, 2, 3, 4, 5, 6, 7, 8, 9])
print validate([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print validate2([1, 2, 3, 4, 5, 6, 7, 8, 9])
print validate2([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
...but neither of these seem quite right to me (reasons in the doc strings). What I want to know is if there is a better way of summing lists and lists of lists that doesn't require me to catch exceptions or actually analyse the list before the function decides what to do.
Obviously, I'm still expecting ['a', 'b'] to be invalid.
Perhaps you'd find it easier to flatten the list first?
def flatten(xs):
for x in xs:
try:
sub = iter(x)
except TypeError:
yield x
else:
for y in flatten(sub):
yield y
With the above, you can do this:
In [4]: fs = flatten([1,2,[3,4,[5,6],7],8,[9,10]])
In [5]: list(fs)
Out[5]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Don't forget to describe exactly what you're trying to do. I'm assuming you mean to sum all values to a single value, and not to get eg. [[1,2],[3,4]] -> [3,7]. Here's simple recursion; five lines of code if you skip the tests:
def sums(it):
"""
>>> sums(1)
1
>>> sums([1,2,3])
6
>>> sums([1,2,3,[4,5]])
15
>>> sums(['a','b'])
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'int' and 'str'
"""
if getattr(it, "__iter__", None):
return sum(map(sums, it))
else:
return it
if __name__ == "__main__":
import doctest
doctest.testmod()
The external numpy module has many operations (including sum()) which work similarly on scalars, vectors, matrices and even higher-dimensional arrays...
Note however that it doesn't work on mixed lists like [1,2,[3,4,5]], only square matrices! So it doesn't exactly answer your question.

Why is this Haskell incorrect?

I have a Haskell file which looks like this:
longest::[Integer]->[Integer]->[Integer]
max a b = if length a > length b then a else b
llfs::[Integer]->Integer
llfs li = length(foldl longest group(li))
llfs([1, 2, 3, 3, 4, 5, 1, 1, 1])
Which should print out the result of the function call at the end, however when I run the file I get this error:
parse error (possibly incorrect indentation)
I don't understand what I'm doing wrong. What should I do to fix it?
Edit
After putting the last line inside the main function, like this:
import List
longest::[Integer]->[Integer]->[Integer]
longest a b = if length a > length b then a else b
llfs::[Integer]->Integer
llfs li = length(foldl longest group(li))
main = print (llfs [1, 2, 3, 3, 4, 5, 1, 1, 1])
I now get the following error:
C:\Users\Martin\Desktop\Haskell\Q1.hs:7:31:
Couldn't match expected type `[Integer]'
against inferred type `[a] -> [[a]]'
In the second argument of `foldl', namely `group'
In the first argument of `length', namely
`(foldl longest group (li))'
In the expression: length (foldl longest group (li))
This one looks a little more difficult! How do I solve it?
Your code isn't correct.
This
longest::[Integer]->[Integer]->[Integer]
max a b = if length a > length b then a else b
should be
longest::[Integer]->[Integer]->[Integer]
longest a b = if length a > length b then a else b
And you need a main function
main = do print llfs([1, 2, 3, 3, 4, 5, 1, 1, 1])
Just for the sake of improving your code, if you have a function signature and give it a lower case letter(s) as its type (say the letter a), it becomes generic. For example
longest:: [a] -> [a] -> [a]
longest x y = if length x > length y then x else y
Means that rather than just working on lists of Integers, it works on lists of anything. Suddenly you have a very reusable function.
In the line
llfs li = length(foldl longest group(li))
the interpreter is treating group as the second argument to foldl. Writing group(li) is no different from writing group li.
Also, foldl needs an initial value. foldl1, on the other hand, uses the first list element for its initial value. Try:
llfs li = length (foldl1 longest (group li))
(Edited to remove the first, wrong answer.)
module Main where
import Data.List
longest::[Integer]->[Integer]->[Integer]
longest a b = if length a > length b then a else b
llfs::[Integer]->Int
llfs li = length $ foldl1 longest $ group li
main = do
putStrLn $ show $ llfs [1, 2, 3, 3, 4, 5, 1, 1, 1]
The problem was that the last line did not define a function, as others have stated. More things are wrong in your code. It appears this is what you want to do:
import Data.List
longest_group_size :: [Integer] -> Int
longest_group_size = maximum . map length . group
main :: IO ()
main = print $ longest_group_size [1, 2, 3, 3, 4, 5, 1, 1, 1]
Observe that:
You need to import Data.List in order to use group.
No need to use foldr in this case: by using map the length of each group is only calculated once.
This does mean, of course, that we call in the help of another function, maximum.
You cannot call a function at file scope like you would do in python or other scripting languages. Therefore the "call" to llfs in the last line is an error. Try printing the result in main:
main = print (llfs [1, 2, 3, 3, 4, 5, 1, 1, 1])
At the moment the "function call" looks like an incomplete function definition, where the right side is missing, which leads to the surprising error message:
llfs (...) = abc
The problem is this line:
llfs([1, 2, 3, 3, 4, 5, 1, 1, 1])
That's not a function declaration. I think you're trying to make a function call, in which case you need to put it inside a main declaration. You can also load the Haskell file into an interpreter (e.g., ghci) and execute the function call in the interpreter console.
This isn't the direct cause of either error, but I think it's a contributing factor to your misunderstanding. In Haskell, you would never write group(li). Parenthesizing a single argument is pointless — it's exactly equivalent to group li. If you're trying to pass the result of this function call to another function, you need to parenthesize the whole expression — (group li) — or use the $ operator like Caleb suggested.
Two small issues with the update. First, it looks like you're trying to pass the group result as an argument to foldl. The right way to say that is (group li) rather than group(li) The second is that foldl needs a base case. Caleb's suggestion to use foldl1 is one option that will probably work for you.

Resources