Looking for revisions of previously written code [closed] - python

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I've noticed that lately my assignment grades have been getting lower as the class has advanced in Python, and I was wondering if anyone could help me see what I did wrong with these code snippets and why they were supposedly wrong. This may be a long post, but any help that'll stop me from making these mistakes in the future is appreciated.
def geometric(l):
'list(int) ==> bool, returns True if the integers form a geometric sequence'
res = False
if (l[1] / l[0]) == (l[2] / l[1]):
res = True
return res
This is a code that was considered wrong. As the code says, it takes a list of ints and returns whether or not they're in a geometric sequence. My book says a sequence is geometric if a1/a0 equals a2/a1, which worked just fine for 2, 4, 8, 16, etc. I just realized that the issue with this one is that it only checks the first two indices and ignores the rest of the numbers. What could I write that would fix this?
def letter2number(grade):
'''string ==> int, returns the numeric equivalent to the letter grade, adding 0.3 if the grade contains a +
and subtracts 0.3 if the grade contains a -'''
res = 0
if 'F' in grade:
res = 0
elif 'D' in grade:
res = 1
elif 'C' in grade:
res = 2
elif 'B' in grade:
res = 3
elif 'A' in grade:
res = 4
if '+' in grade:
res += 0.3
elif '-' in grade:
res -= 0.3
return res
This wasn't considered wrong, exactly, but it was much longer than he intended I guess. A comment he wrote on the file was "# set res to index of grade in grades," but since it was an independent lab I couldn't ask for help. I attempted to give each grade its value in a list but I couldn't index it correctly.
def leap(n):
'int ==> bool, returns True if the year is a leap year, False otherwise'
res = False
if n % 4 == 0 and n % 400 == 0 or not n % 100 == 0:
res = True
return res
Figuring out an if statement that translated into "A year is a leap year if it is divisible by 4 but not by 100, unless it is divisible by 400" was confusing for me. Apparently what I wrote works for all odd numbers, but I can't really figure out why.

It seems like at least half your problems aren't programming problems, but problems understanding the assignment. For example:
This is a code that was considered wrong. As the code says, it takes a list of ints and returns whether or not they're in a geometric sequence. My book says a sequence is geometric if a1/a0 equals a2/a1, which worked just fine for 2, 4, 8, 16, etc. I just realized that the issue with this one is that it only checks the first two indices and ignores the rest of the numbers.
Your code correctly implements what you thought the assignment was. It just doesn't implement what the assignment actually was, by checking all pairs of indices. Once you know that's what you need to do, presumably you can figure out how to write a loop that compares pairs of indices:
def geometric(l):
'list(int) ==> bool, returns True if the integers form a geometric sequence'
res = True
for i in range(len(l) - 2):
if (l[i+1] / l[i]) != (l[i+2] / l[i+1]):
res = False
return res
And then you might notice that you can short-circuit things at the first failure, or compare all the ratios to the first instead of comparing them as pairs (meaning you have to calculate most of them twice), or write a simple helper function that just checks one pair and use all to run it on all of them, etc., but those are all just refinements.
Then:
Figuring out an if statement that translated into "A year is a leap year if it is divisible by 4 but not by 100, unless it is divisible by 400" was confusing for me. Apparently what I wrote works for all odd numbers, but I can't really figure out why.
You first need to translate that into a sequence of and and or and not steps in English. What you did, "divisible by 4 and divisible by 400 or not divisible by 100", is not even close to the same thing. You then coded that incorrect algorithm correctly, but that's no help.
All you need to do is translate "but not" to "and not", and "unless" to "or": "visible by 4, and either not divisible by 100 or divisible by 400". The only tricky part about translating that to code is using parentheses instead of the command and "either":
if n % 4 == 0 and (not n % 100 == 0 or n % 400 == 0):

For your letter2number I would have used a dictionary instead to handle the mapping, something like this:
def letter2number(grade):
G = {'F': 0, 'D': 1, 'C': 2, 'B': 3, 'A': 4}
D = {'+': 0.3, '-': -0.3}
if len(grade) == 2:
return G[grade[0]] + D[grade[1]]
else:
return G[grade[0]]

Related

Find The Parity Outlier using dictionary {Python}

during the Kata on Codewars called 'Find The Parity Outlier' I faced a problem, and have been trying to solve it using dictionary. I pass almost all tests except 4.
Instruction for the Kata is:
You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N.
The function is:
def find_outlier(integers):
d = dict()
count = 0
count1 = 0
for i in range(len(integers)):
if integers[i] % 2 != 0 :
d['odd'] = integers[i]
else:
d['even'] = integers[i]
for j in range(len(integers)):
if integers[j] % 2 == 0:
count += 1
else:
count1 += 1
if count > count1:
return d['odd']
return d['even']
Test Results:
2 should equal 1
36 should equal 17
36 should equal -123456789
0 should equal 1
So the question is? Why is it so? Can you help me to sort the problem out? Thanks a lot!
I'm not sure what exactly you're referring to with that list of test results. In general though, your method with the dictionary seems like it might be overcomplicating things a bit as well. You shouldn't need to use a dict, and you shouldn't need two for loops either. Here's an alternative solution to this problem using only list comprehension.
def find_outlier(arr):
# input should be an array-like of integers (and length >= 3) with either only one odd element OR only one even element
odd_mask = [n%2 != 0 for n in arr] # boolean array with True in the location(s) where the elements are odd
even_mask = [n%2 == 0 for n in arr] # boolean array with True in the location(s) where the elements are even
N_odd = sum(odd_mask) # number of odd elements in the input
N_even = sum(even_mask) # number of even elements in the input
if N_even == 1: # if even is the 'outlier'...
return arr[even_mask.index(True)] # return the element of the input array at the index we determined we had an even
elif N_odd == 1: # if odd is the 'outlier'...
return arr[odd_mask.index(True)] # return the element of the input array at the index we determined we had an odd
else: # something has gone wrong or the input did not adhere to the standards set by the problem
return None
And even this is technically not as efficient as it could be. Let me know if you try this and whether it solves whatever issue you were experiencing with expected results.
In your code the final part should not be in the else block, nor even in the for loop:
if count > count1:
return d['odd']
return d['even']
Like this is may give a wrong result. For instance, if the first number in the input is odd, and is the only odd one, then this code will return d['even'] which is obviously wrong.
Place these lines after the loop (with correct indentation) and it should work.
However, this problem can be solved without dictionary or extra lists. Have a go at it.
def find_outlier(integers):
parity = integers[-2] % 2
if integers[-1] % 2 != parity:
if integers[0] % 2 != parity:
return integers[-2]
else:
return integers[-1]
for i in integers:
if i % 2 != parity:
return i

Using recursion to determine a semiperfect number

I am in need of your help again. I'm writing a code that determines whether a number is a semiperfect number or not by returning a boolean value. So first I thought I would make a list of the factors of the number excluding the number itself
def isSemiPerfect(n):
factor = []
for i in range(n-1, 0, -1):
if n%i == 0:
factor.append(i)
If I were to check for the number 12, it would return
factor = [1, 2, 3, 4, 6]
Then I need to make a code to use recursion to check if you add certain numbers it would be equal to 12
True = 6 + 4 + 2 or 6 + 3 + 2 + 1
Can someone tell me how I can use recursion to do trial and error? Like I'll always start with the biggest number and try a path with the next biggest number until I've tried all combinations.
I know there isn't a lot to go on with I just hope that you can tell me how I can use recursion effectively. Thank you!
You can think about it this way.
The question "Can [1,2,3,4,6] sum to 12"?
Is the same as "Can [2,3,4,6] sum to 11" or "Can [2,3,4,6] sum to 12"?
One uses the first element (and has lower sum) and the other does not use the first element and has the same sum.
so a start function would be:
def f(lst,sum_left):
return f(lst[1:], sum_left-lst[0]) or f(lst[1:],sum_left)
However, this function does not know when to stop. So we need some base cases.
Obviously, if sum is 0, the answer is trivially yes:
if sum_left == 0:
return true
Another base case is, if the sum is < 0, we have taken a too big element and we can never recover.
if sum_left < 0:
return true
Also, we can risk running out of elements like [1,2] can never sum to 50, so we add a base case if there are no elements in the list:
if not lst:
return false
Putting it all together:
def f(lst, left):
if left == 0:
return True
if left < 0:
return False
if not lst:
return False
return f(lst[1:],left-lst[0]) or f(lst[1:],left)

What is the star (*) doing in this FizzBuzz solution?

Learning programming in Python and I am doing some challenges. I've run into something I haven't learned yet and was curious what this code is doing.
So my challenge is called the "FizzBuzz" challenge. The instructions are simple:
Create a function that takes a number as an argument and returns
"Fizz", "Buzz" or "FizzBuzz".
If the number is a multiple of 3 the output should be "Fizz". If the
number given is a multiple of 5, the output should be "Buzz". If the
number given is a multiple of both 3 and 5, the output should be
"FizzBuzz". If the number is not a multiple of either 3 or 5, the
number should be output on its own.
I wrote this code to solve it (obviously it can be better):
def fizz_buzz(num):
if num % 3 == 0 and num % 5 == 0:
return 'FizzBuzz'
elif num % 3 == 0:
return 'Fizz'
elif num % 5 == 0:
return 'Buzz'
else:
return str(num)
But, once I submitted my solution I was able to see the top solution, which is:
def fizz_buzz(num):
return "Fizz"*(num%3==0) + "Buzz"*(num%5==0) or str(num)
My question is what is the * doing here? Can someone point me to documentation or resources that addresses what this persons code has done? I don't find it super readable but it is apparently the best solution to the problem.
bool in Python is a subclass of int; True has the value 1, False, 0.
Sequences (including str) in Python can be multiplied, to get the sequence repeated that many times, so:
"Fizz"*(num%3==0)
multiplies "Fizz" by 1 (numeric value of True) when num % 3 == 0, producing the original string, and by 0 (numeric value of False) otherwise, producing the empty string.
The same work is done with "Buzz" and concatenated. If both of them produced the empty string (which is falsy), then the or means str(num) is evaluated and returned (Python's or and and don't evaluate to strict True or False, they evaluate to the last item evaluated, and short-circuit, so or always evaluates to the first truthy item, or the last item in the or chain regardless of truthiness).
Firstly, shorter doesn't always mean better. In this case, your solution is fine, and the "top solution" is clever, but needlessly confusing, as you're aware :P
The star is doing string multiplication, and it's exploiting the fact that False == 0 and True == 1. So if num is divisible by 3, you get 'Fizz' once, and if num is divisible by 5, you get 'Buzz' once. Otherwise you get an empty string, '', and because an empty string is falsy, the or clause means it will be replaced by str(num).
The * is string multiplication as usual. It's just multiplying by 0 or 1 based on whether the condition to print the phrase is met. If neither condition is met, it defaults to returning the number, as it should.
I don't know about a resource, but I can tell you what it does. The phrase num%3==0 is a Boolean which is true if the number is divisible by 3. If that's the case, this phrase returns a 1 (or 0 if False). Same for num%5==0 and divisible by 5. This is then being multiplied by the string Fizz and/or Buzz and concatenated together, where multiplying by 1 returns the string and 0 nothing. If neither of those holds, it returns str(num).
I do not know the link to any documentation or resource about it, but I can explain it to you.
Firstly in python str can be multiplied by a number, for instance 'Fizz' * 3 will return 'FizzFizzFizz' or 'Fizz' * 0 will return '', an empty string.
Secondly bool in python can be also recognized as int, i.e. True is 1 and False is 0.
Thirdly in python strings can be added e.g. 'Fizz'+'Buzz' will return 'FizzBuzz'
What the best solution guy does is very simple by num%3==0 he gets bool and just multiplies the str 'Fizz' or 'Buzz' by it and returns.

program that among the given numbers finds one that is different in evenness, and return a position of this number

Bob is preparing to pass IQ test. The most frequent task in this test is to find out which one of the given numbers differs from the others. Bob observed that one number usually differs from the others in evenness. Help Bob — to check his answers, he needs a program that among the given numbers finds one that is different in evenness, and return a position of this number.
! Keep in mind that your task is to help Bob solve a real IQ test, which means indexes of the elements start from 1 (not 0)
Examples :
iq_test("2 4 7 8 10") => 3 // Third number is odd, while the rest of the numbers are even
iq_test("1 2 1 1") => 2 // Second number is even, while the rest of the numbers are odd
My Code:
def iq_test(a):
b=[]
c=[]
for i in range(len(a)):
if a[i]%2 == 0:
b.append(a[i])
else:
c.append(a[i])
if len(b)==1:
for i in range(len(a)):
if [a[i]]==b:
return i+1
if len(c)==1:
for i in range(len(a)):
if [a[i]]==c:
return i+1
This works for the given inputs in my IDE, but when I put it in webpage IDE I obtain
Traceback (most recent call last):
File "main.py", line 3, in <module>
Test.assert_equals(iq_test("2 4 7 8 10"),3)
File "/home/codewarrior/solution.py", line 6, in iq_test
if a[i]%2 == 0:
TypeError: not all arguments converted during string formatting
What is the mistake here? Is my code correct?
The parameter given to your function is "2 4 7 8 10". You're iterating over that string and applying a modulo operation, which throws the error you're seeing since Python doesn't do automatic type conversion and can't apply a module to the string "2" (and, if it did, would throw an error at the second iteration when it'd try to apply the modulo operation to " ").
The simplest fix here is to check if it's not a space, then convert to int before the module:
for (i in range (len(a)):
if a[i] != " ":
if int(a[i])%2 == 0:
b.append(a[i])
...
By the way, the index, and range above is not neccessary for strings. You can also iterate over the string directly:
for char in a:
if char != " ":
if int(char)%2 == 0:
b.append(char)
...
You could also split the string into an array and iterate over that:
array = a.split(" ") # results in ["2","4","7","8","10"]
for (item in array):
if int(item)%2 == 0:
b.append(item)
...
In a real world application, I would also opt to check if the character at the current position is convertible to int, but for your case this solution is sufficient.
Also, as someone who recently looked over their own assignments from the first two semesters, get into the habit of using explicitly named variables. e.g instead of b use evenNumbers and instead of c use oddNumbers. This makes your code a lot more readable and better to understand what you did and why.
def iq_test(numbers):
lst = numbers.split()
evens = []
odds = []
for i in lst:
if int(i) % 2 == 0:
evens.append(int(i))
else:
odds.append(int(i))
if len(evens) == 1:
for i in lst:
if int(i) == evens[0]:
return lst.index(i)+1
if len(odds) == 1:
for i in lst:
if int(i) == odds[0]:
return lst.index(i)+1
I got it right

Why is there a None in output? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Help, I'm trying to create a function that uses modulus to print numbers that are divisible by an integer, in this case, multiples of 17:
def nextDivisible(n):
if n % 17 == 0:
print n
else:
nextDivisible(n+1)
But the output is for example:
n: 93 next divisible: 102
None
n: 59 next divisible: 68
None
Why is there a None?! and how do I remove it, thanks!
I think your problem is that you are printing out the result instead of returning it from the function.
If you change your code to be like this it should fix it:
def nextDivisible(n):
if n % 17 == 0:
return n
return nextDivisible(n + 1)
How this works with recursion is that your function nextDivisible is going to be repeatedly called until it reaches its base case of n being divisible by 17. When that case occurs it will return n all the way back up the recursive stack to where the original first call to the function was done.
You also don't need an else statement because return statements break out of the function code. But sometimes else's are good for readability.
You don't need to:
print(nextDivisible(n))
I think you get None printed because your function doesn't return anything. It is also redundant to print the return of the function because you print the numbers inside the loop.
All you need is:
nextDivisible(n)
And it will print the divisible numbers.
If you are use nextDivisible() in other functions, it may be worth nothing that a return statement may be required depending on the nature of how you are using it.
For all intents and purposes this should work just fine.
And python 3.x:
x = [x for x in range(1000)]
def nextDivisible(x, mod=17):
c = 0
for n in x:
if n % mod == 0:
print(n)
c += 1
else:
#nextDivisible(n+1)
pass
print('{} numbers divisible by {} in {}'.format(c, mod, len(x)))
nextDivisible(x)
Expected output:
59 total numbers divisible by 17 in 1000

Categories