I am new to python, and was going through some pre written code to get a better grip at it.
This code tries to get the number of digits each non-termination cycle has when a number is at the denominator to 1. For eg. 1/3 = 0.(3) it has a cycle of 1.
similary 7 has a cycle of 6 as 1/7 = 0.(142856)
def get_decimals(num, div, current=([], [])):
"""Return a tuple (integer_part, decimal_part, cycle_length) for num/div"""
headtail = lambda lst: (lst[0], lst[1:])
memory, values = current
if values and num == 0:
integer, decimals = headtail(values)
return integer, decimals, 0
elif num in memory:
integer, decimals = headtail(values)
print integer, decimals
lencycle = len(memory) - memory.index(num)
return integer, decimals, lencycle
a, b = divmod(num, div)
return get_decimals(10*b, div, (memory+[num], values+[a]))
print max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
could anyone please explain me in context of the code pasted above. I could not understand the following:
the subscripts [2] and [1] in the last print statement.
memory.index(num) this one inside the get_decimals function at the line 4th to last.
get_decimals(1, num)[2]
get_decimals returns a tuple containing 3 items, named integer, decimals and lencycle. So the subscript [2] picks out lencycle.
max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
The subscript [1] picks out num from a tuple of the form (get_decimals(1, num)[2], num). Note that the max function is applied before the [1] subscript. In this case max is operating on a iterable of tuple pairs and uses lexicographic ordering to compare items.
memory.index(num) calls the method index on the object memory passing num as the parameter. Since memory is a list then this is simply finding the index of the first occurrence of the value num in that list.
Unless you are very new, the above explanation would have made sense. If not, i try explaining in a simpler manner:
for a list a = [1, 2, 3] you would access first element as: a[0]
similarly a subscript of 2 after get_decimals(1, num)[2] means if the function is returning a tuple/dictionary access the third element, in your case the length of the cycle of the non-terminating series. For the input number 7, the output would be 6 as it has a non terminating cycle of 142856.
similarly for line: max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
if you go without the subscript [1] you will see two values printing, but the coder was concerned only with the second value being returned. Apparently the code says:
call the function get_decimals for the values 2 to 10.
Find the max of the tuple being returned and print the second item of the tuple which has been filtered as the max.
Index has been explained pretty clearly and needs no further explanation. Just another simplification:
[1, 2, 3] the index of 2 in list is 1. This will clarify the stuff.
Please refer to the official python documentation, before reading codes. IMHO.
Related
I'm curious as to why the comma can be added at the end of len(list) to refer to the last item in the list. Can anyone explain this?
Does it work only in list? How about the other items in the list - Can I access by using len(list) as well?
list=[10,20,30,40,50,60]
for num in len(list),:
print(num,end=" ")
Output num is 6.
len(list) returns a single integer, corresponding to the number of elements in your list list (which, as an aside, is poorly named as you should avoid using built-in names for your variables). The comma in for num in len(list), turns it into a one-tuple, meaning that the for loop can iterate one item, which you can see by running in the interactive interpreter:
len(list),
Output:
(6,)
Your for loop, as you indicate, will print: 6, which is the length of list. It does not access the last element of list, which is 60.
This for loop is unusual usage of this syntax, as it's obvious that there will only be a single element and no need to iterate.
for num in len(nums),:
Is the equivalent of:
>>> nums = [10,20,30,40,50,60]
>>> for num in (len(nums), ):
... print(num)
...
6
Where (len(nums), ) is a one-tuple, a tuple with 1 single element.
The reason for this notation is because if I do
(len(nums)) without the ending , (comma) then Python decides that is just the same as len(nums) and not a tuple at all, since we need the ability to use brackets for many things eg. for operations like
(1 + 2) * 3
So we have the ending comma to distinguish a tuple
With lists this is not necessary and we can simply write something like [len(nums)]
I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.
The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v
Try:
min([val for val in z if val % 2 != 0])
It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!
You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.
min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))
I have a list:
l = [1,3,4,6,7,8,9,11,13,...]
and a number n.
How do I efficiently check if the number n can be expressed as the sum of two numbers (repeats are allowed) within the list l.
If the number is in the list, it does not count unless it can be expressed as two numbers (e.g for l = [2,3,4] 3 would not count, but 4 would.
This, embarrassingly, is what I've tried:
def is_sum_of_2num_inlist(n, num_list):
num_list = filter(lambda x: x < n, num_list)
for num1 in num_list:
for num2 in num_list:
if num1+num2 == n:
return True
return False
Thanks
def summable(n, l):
for v in l:
l_no_v = l[:]
l_no_v.remove(v)
if n - v in l_no_v:
return True
return False
EDIT: Explanation...
The itertools.cominations is a nice way to get all possible answers, but it's ~4x slower than this version since this is a single loop that bails out once it gets to a possible solution.
This loops over the values in l, makes a copy of l removing v so that we don't add v to itself (i.e. no false positive if n = 4; l = [2, 1]). Then subtract v from n and if that value is in l then there are two numbers that sum up to n. If you want to return those numbers instead of returning True just return n, n - v.
Although you can check this by running through the list twice, I would recommend for performance converting the list to a set, since x in set() searches in linear time.
Since n can be the sum of the same number, all you have to do is iterate through the set once and check if n - i occurs elsewhere in the set.
Something like the following should work.
>>> def is_sum_of_numbers(n, numbers):
... for i in numbers:
... if n - i in numbers:
... return True
... return False
...
>>>
>>>
>>> numbers = {2,7,8,9}
>>> is_sum_of_numbers(9, numbers) # 2 + 7
True
>>> is_sum_of_numbers(5, numbers)
False
>>> is_sum_of_numbers(18, numbers) # 9 + 9
True
If the list is ordered you could use two variables to go through the list, one starting at the beginning of the list and one at the end, if the sum of the two variables is greater than N you assign to the variable at the end the values that precedes it, if the sum is less than N you assign to the variable at the beginning the following value in the list. If the sum is N you've found the two values. You can stop when the two variables meet eachother.
If the list is not ordered you start from the beginning of the list and use a variable x to go through the list. You'll need another structure like an hashset or another structure. At every step you'll look up in the second hashset if the value N-x is in there. If there is, you've found the two numbers that add up to N. If there isn't you'll add N-x in the hashset and assign to x the following value. I recommend using an hashset because both the operations of looking up and inserting are O(1).
Both algorithms are linear
I'm sorry I couldn't write directly the code in python because I don't use it.
As I said in the comment HERE there's a video in wich your problem is solved
If I got the OP's concern then-
As the question says repeats are allowed within the list l this process i think is good though a bit slower.So if you need to count the occurances along with the existence of a condition then go with this answer but if you want a bolean esixtence check the go with the others for the mere performance issue nothing else.
You can use itertools.combinations. It will give you all the combinations, not permutations. Now you can just use the sum function to get the sum.
from itertools import combinations
l = [1,3,4,6,7,8,9,11,13]
checks = [4,6] #these are the numbers to check
for chk in checks:
for sm in combinations(l,2):
if chk == sum(sm): #sum(sm) means sum(1,3) for the first pass of the loop
#Do something
I am trying to find the number of duplicate (repeated) digits in a number, for each unique digit. eg. For 21311243 there would be 3 1's and 2 2's and 2 3's, so I would just need [3,2,2] where order doesn't matter. I am trying to do this as follows, where number_list = ['2','1','3','1','1','2','4', '3']. The code below works for the above number and I get that repeated_numbers = [2, 2, 3] as expected. However, for 213112433 repeated_numbers = [2, 3, 3, 2] for some reason and I don't know why this is and how to rectify the code below as such:
repeated_numbers = [] #The number of repeated digits for each unique digit
for a in number_list:
i = 0
for b in number_list:
if (a == b):
i = i + 1
if i > 1: #If the particular digit is repeated
repeated_numbers.append(i)
number_list.remove(a) #Get rid of the digit that gets repeated from the list
Also, I am open to better ways of doing this as my way has O(n^2) complexity, but need that number_list is considered as a list of characters.
Removing elements in a list while iterating on it is not a good idea.
Look at this related question: Remove items from a list while iterating
I suggest using list comprehension to solve your problem.
As far as the specific bug in your program, I think you meant to remove all occurences of a specific number when performing remove but that's not what happens:
Look at: https://docs.python.org/2/tutorial/datastructures.html
list.remove(x)
Remove the first item from the list whose value is x. It is an error
if there is no such item.
I'm asked to create a method that returns the number of occurrences of a given item in a list. I know how to write code to find a specific item, but how can I code it to where it counts the number of occurrences of a random item.
For example if I have a list [4, 6 4, 3, 6, 4, 9] and I type something like
s1.count(4), it should return 3 or s1.count(6) should return 2.
I'm not allowed to use and built-in functions though.
In a recent assignment, I was asked to count the number of occurrences that sub string "ou" appeared in a given string, and I coded it
if len(astr) < 2:
return 0
else:
return (astr[:2] == "ou")+ count_pattern(astr[1:])
Would something like this work??
def count(self, item):
num=0
for i in self.s_list:
if i in self.s_list:
num[i] +=1
def __str__(self):
return str(self.s_list)
If this list is already sorted, the "most efficient" method -- in terms of Big-O -- would be to perform a binary search with a count-forward/count-backward if the value was found.
However, for an unsorted list as in the example, then the only way to count the occurrences is to go through each item in turn (or sort it first ;-). Here is some pseudo-code, note that it is simpler than the code presented in the original post (there is no if x in list or count[x]):
set count to 0
for each element in the list:
if the element is what we are looking for:
add one to count
Happy coding.
If I told you to count the number of fours in the following list, how would you do it?
1 4 2 4 3 8 2 1 4 2 4 9 7 4
You would start by remembering no fours yet, and add 1 for each element that equals 4. To traverse a list, you can use a for statement. Given an element of the list el, you can check whether it is four like this:
if el == 4:
# TODO: Add 1 to the counter here
In response to your edit:
You're currently testing if i in self.s_list:, which doesn't make any sense since i is an element of the list and therefore always present in it.
When adding to a number, you simply write num += 1. Brackets are only necessary if you want to access the values of a list or dictionary.
Also, don't forget to return num at the end of the function so that somebody calling it gets the result back.
Actually the most efficient method in terms of Big-O would be O(log n). #pst's method would result in O(log n + s) which could become linear if the array is made up of equal elements.
The way to achieve O(log n) would be to use 2 binary searches (which gives O(2log n), but we discard constants, so it is still O(log n)) that are modified to not have an equality test, therefore making all searches unsuccessful. However, on an unsuccessful search (low > high) we return low.
In the first search, if the middle is greater than your search term, recurse into the higher part of the array, else recurse into the lower part. In the second search, reverse the binary comparison.
The first search yields the right boundary of the equal element and the second search yields the left boundary. Simply subtract to get the amount of occurrences.
Based on algorithm described in Skiena.
This seems like a homework... anyways. Try list.count(item). That should do the job.
Third or fourth element here:
http://docs.python.org/tutorial/datastructures.html
Edit:
try something else like:
bukket = dict()
for elem in astr:
if elem not in bukket.keys():
bukket[elem] = 1
else:
bukket[elem] += 1
You can now get all the elements in the list with dict.keys() as list and the corresponding occurences with dict[key].
So you can test it:
import random
l = []
for i in range(0,200):
l.append(random.randint(0,20))
print l
l.sort()
print l
bukket = dict()
for elem in l:
if elem not in bukket.keys():
bukket[elem] = 1
else:
bukket[elem] += 1
print bukket