I feel confused about the code as follows:
define this findmin function to find the smallest number in alist, O(n^2)
def findMin(alist):
overallmin=alist[0]
for i in alist:
issmallest=True
for j in alist:
if i>j:
issmallest=False
if issmallest:
overallmin = i
return overallmin
I can't understand: why the author set "issmallest = True" below the first for loop? Commonly when we feel like to use boolean values like this situation(such as assign boolean value to a variable at the beginning of the code or put the boolean values as the if-statement conditions)? Thanks!
Okay so first off, to erase a few of the mistakes in the code, a working example would be:
def findMin(alist):
overallmin=alist[0]
for i in alist:
issmallest=True
for j in alist:
if i>j:
issmallest=False
if issmallest:
overallmin = i
return overallmin
The idea behind this code is to compare all elements in a list with all others and keep the one that is smaller than all others. In the loop it is therefore assumed that the current element is the smallest issmallest = True until a smaller one is found. If a smaller one is found, the value of issmallest is changed to False. So if, after comparison with all others, issmallest is still True, then the element is truly the smallest and therefore fixed as such.
You could simplify this code , as there is no need in further comparing once the smallest element is found, i.e. you can leave the function. Also in this algorithm there is no need of keeping a variable for the smallest element. The corresponding code might read something like:
def findMin(alist):
for current_el in alist:
issmallest = True
for other_el in alist:
if other_el < current_el:
issmallest = False
if issmallest:
return current_el
But: Even for beginners, this is not a good code to find the minimum. I can say that as a beginner myself. It is much cleaner to go through the list once, with an element at hand, compare it while going through, and always keep the smallest.
So even with low afford you can write a much faster algorithm like this:
def findMin(alist):
smallest_el = alist.pop() # take out an element, no need to compare with itself
for other_el in alist:
if other_el < smallest_el:
smallest_el = other_el
return smallest_el
The condition of while always must evaluate to boolean. if it evaluates to true, the loop continues, otherwise, the statements after the loop will be executed. Please note: the code in your question did not involve a while loop. This code is very bad, please forget it, and everything that came with it. For learning, try this: https://www.learnpython.org/.
Related
I've seen some posts about this same question, and I think my logic is pretty much the same as their answers. But I cannot find where exactly I'm wrong here.
My code first checks the length of the provided sequence, if it is 2 or less it automatically returns True.
Next, it removes(pops) the first element and check if the rest are in ascending order.
If the sequence isn't in order, it replaces it with the original sequence and repeats the second step, but this time it removes the next element (pop(i)).
This continues until there are no more elements to remove, which ultimately returns as False
If in any of the iterations, the list is found to be in ascending order, the function returns True.
This is the code:
def almostIncreasingSequence(sequence):
original = sequence.copy()
if len(sequence) <= 2: return True
for i in range(len(sequence)):
sequence.pop(i)
# print(sequence)
for j in range(len(sequence)-1):
if sequence[j+1] <= sequence[j]:
sequence = original.copy()
elif j+1 == len(sequence)-1:
return True
if i == len(sequence)-1:
return False
And this is my result :'(
I think my logic may not be correctly implemented in the code. But I don't know how to test it. It'd be helpful if you can give me a sequence where this function will give a wrong answer.
Solve almostIncreasingSequence (Codefights)
This is one of the posts I was referring to at the very beginning. It also explains the almostIncreasingSequence(sequence) question and the answer explains the logic behind the code.
You don't have to try every element. Just find the violation of the ascension, and try to resolve it by removing one of the violators. Then check the rest of the list.
More formally, suppose that the sequence[:i] is in the ascending order, but sequence[i] < sequence[i+1]. You cannot keep them both; one must be gone. Which one, depends on sequence[i-1].
If sequence[i+1] < sequence[i-1], removal of sequence[i] wouldn't help: a violation will remain. Therefore, remove sequence[i+1]. Otherwise, remove sequence[i] (do you see why?). Finally, check that the rest of sequence is ascending.
I am confused about when using a while-loop or for-loop is better? I am particularly worried about producing optimized answers to coding questions. I find myself solving problems just to find out a while-loop would've been faster but am confused about what leads people to choose to use it instead of a for-loop, like what criteria should I be looking for?
Here's an example of a coding question I answered which checks if a string of parentheses is balanced.
def parenCheck(str):
stack = Stack()
for x in str:
if x == '(':
stack.push(x)
else:
if stack.isEmpty():
return False
else:
stack.pop()
return stack.isEmpty()
Here is the answer I saw for it , which I know is faster because it doesnt use a for-loop:
def parChecker(symbolString):
s = Stack()
balanced = True
index = 0
while index < len(symbolString) and balanced:
symbol = symbolString[index]
if symbol == "(":
s.push(symbol)
else:
if s.isEmpty():
balanced = False
else:
s.pop()
index = index + 1
if balanced and s.isEmpty():
return True
else:
return False
For the same number of iterations, and content, my guess is that a for loop and wihile have practically the same speed. But I haven't tested that - mostly I answer numpy questions where we try to avoid either loop (preferring iterations in compiled code).
Your examples show the basic case where for results in cleaner, if not faster, code:
for x in an_iterator:
<do something>
versus
i = 0
while i < len(an_iterator):
x = an_iterator[x]
<do something>
i += 1
If you must have an index as well, you can use:
for i, x in enumerate(an_iterator):
....
That ability to iterate directly on things like lists and dictionaries was the main neat feature that caught my attention when I first saw Python in the 1990.
A common subcase of a for loop accumulates values, so common, that Python provides the popular list comprehension, and extended the syntax to generator expressions and dictionary comprehensions.
while still has its uses. Other languages have do while and do until variants, which attempt to streamline stepping the variable and testing. Python has just the one version with separate steps. The new walrus operator has the potential of cleaning that up:
https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions
while (block := f.read(256)) != '':
process(block)
while is most useful when the steps aren't regular, or from a well defined iterator. for can break and continue, but otherwise the sequence is fixed (at the start of iteration).
In addition to enumerate, zip lets us iterate on several things at once.
The convenience of list comprehensions encourages us to decompose a complicated task into a sequence of comprehensions. And to make that even more convenient (and faster/memory efficient) Python provides generators and all sort so itertools. In Python 3, range and dictionary keys/items/values all became generator like expressions.
This cannot be decided by your code that while loop worked faster than for loop. As of your question on when to use while and for loop, it is decided on the basis of whether we know the number of iterations. If number of iterations is known, for loop is preferred, whereas while loop is preferred when the iterations are indefinite.
for (int i : mynumber_list)
Iterator it = mynumber_list.iterator()
while (it.hasNext())
As can be seen from above, for loop is more readable, simple, and easy in traversing. Moreover, iterator.hasNext() has a very high probability of entering into an infinite loop
while can also be useful for user choice input questions, like keep executing the program until the user presses any other key except y. This is difficult to achieve with for loop.
The leetcode twosum problem:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
I read someone's python code as following:
vis = {}
for i,num in enumerate(nums):
diff = target - num
if diff in vis:
return[vis[diff],i]
vis[num] = i
I can understand the majority of logic behind this code. However why the last line have to be in this order? It seems weird to me to make assignment after the return statement.
So I tried to move it to other places, but this will output null. Why does the last line have to be at that place?
The return statement is within the if statement, so it will only execute if diff is in vis, i.e., when you have found a diff you wanted, such that nums[diff] + nums[i] == target is True. If that doesn't happen, only then the final statement will be executed. So, it would add the diff for a later comparison and would move on with the next iteration.
I'm trying to do a bingo game, I had some struggle with it but finally sorted it out.
However, my main "problem" (more like, I've heard its bad programming) is that with my function I'm calling my function inside it in an else statement. I don't think that it's how you suppose to do it, i have not found any way around it though.. Because this function is called from another function called menu() so when i use a loop, it goes back to the menu if false.
Here's my code:
def selectingNumbers():
numbers = []
dupl = []
j = 0
print("Now you are gonna select 5 number\n")
while j < 5:
nummer = int(input("Your choice:\n"))
numbers.append(int(nummer))
j = j+1
for i in numbers:
if i not in dupl:
dupl.append(i) #New list without duplicates
if dupl == numbers: #Comparing new list with old list
print("No equal numbers found")
dragning(numbers)
else:
print("Equal numbers found")
selectingNumbers() #Is there a better way to do it?
I also had some issues with the list at the beginning, I know I can use the set() function but i want to keep the original list as it is and compare the new one with the old one, can I do that in a better way with "real" programming instead of import modules?
Hope you can answer or guide me on these two questions with alternatives and if so, say why my code is "bad" if it is.
Well you have to decide if you want to use recursion to solve the problem. This line is a recursive call:
selectingNumbers() #Is there a better way to do it?
Which is fine, and does not equate to bad programming. However, the rest of your function does no cater to a recursive function. You reset your variables and have no true base case because of that. See google, or here for examples.
Recursion is confusing for beginners, so I would take an iterative only approach. Here is a bingo python example.
In addition, I'm not sure this line works:
if dupl == numbers: #Comparing new list with old list
I am not too familiar with python, but in my experience, arrays are treated as objects, so in that line you would be asking python to compare two seperate objects with unique references in memory. So they will never be equal, even if the values inside of them are the same because they are both referenced seperately. I found this link to answer that concern.
Recursion isn't "bad". In fact it can sometimes greatly simplify a solution to a problem. However in the case of your code it isn't necessary. Fortunately, it can sometimes be replaced with a loop. In the case of your code it looks like it could just loop until it gets a list from the user that doesn't contain any duplicates. That means it could be rewritten as shown below (I also simplified a few other things):
def selectingNumbers():
while True:
print("Now you are gonna select 5 different numbers\n")
numbers = []
for _ in range(5):
number = int(input("Your choice:\n"))
numbers.append(number)
unique = set(numbers) # will remove any duplicates
if len(unique) == len(numbers): # no dups?
print("No equal numbers found")
break # <--- terminates loop
else:
print("Equal numbers found")
# allow loop to continue
dragning(numbers)
I was wondering if someone can help me to fix the error my code for quick sort has:
It does not compile and highlights the last line of the code in red.
I can not figure out what is wrong. sort is already defined as a function so why is it highlighted as red?
def sort(*myarray):
less = []
equal = []
greater = []
if len(myarray) > 1:
pivot = myarray[0]
for x in myarray:
if x < pivot:
less.append(x)
if x == pivot:
equal.append(x)
if x > pivot:
greater.append(x)
return sort(less)+sort(equal)+sort(greater)
else:
return myarray
print sort([12,4,5,6,7,3,1,15])
You're defining the function as taking a variable number of arguments (the *myarray bit), but then using myarray inside as a single argument (the list to sort), when it is a list containing the list to sort.
You probably should remove the * from your function parameter. This questions esplains it quite thoroughly.
You could keep the *, but then you would have to play a bit with tuple unpacking to get the same result.
edit
Although the above is true, this might not be the issue you're encountering.
IDLE will give you the invalid syntax error on the ast line, because in interactive mode - with lines starting with >>>, it accepts only one statement at a time. In your case that statement is the sort() definition.
Try hitting enter 2 times after the function definition, this should get you back to the repl, where you can introduce another statement (print sort([12,4,5,6,7,3,1,15]))
There are a couple things wrong which makes me curious how you are testing this:
Python code is not "compiled", it is interpreted. (Okay, not precisely true; it's parsed into a sort of byte-code; still, it's not compiled in the same sense as a language such as C, where the entire program has to be converted into machine instructions before any of it can be run.) Also you mention the last line of code is highlighted in red -- by what?
This code actually works, but only if you remote the star/asterisk in front of myarray in def sort(*myarray):. Otherwise it actually returns a single-element tuple containing the original array.
Assuming you have two or more elements that equal a pivot at some point, you get an infinite loop, because you will get: equal = [x,x] (two elements at least), and then invoke sort([x,x]), which in its turn will take x as a pivot, and create equal = [x,x], and cause sort([x,x]), ....
Simple solution to this problem: What should be the output of the sort(equal)? How do you sort a list of identical elements?
Edit: Well, your comments show that you are looking for a different problem, but I'll leave it here because it explains a different issue you have with your code and should be solved.
If it is a function for quick sorting, can you really use the function sort in it?
Wouldn't something like this work?
def qsort(list):
pivind=0
left, right, pivot= [], [], []
for x in list:
if list[pivind]==x: pivot.append(x)
elif list[pivind]>x: left.append(x)
else: right.append(x)
if len(left)>1: left=qsort(left)
if len(right)>1: right=qsort(right)
return (left + pivot + right)