CodingBat - Warmup2 - ARRAY_FRONT9 - python-3.x

I'm very new to programming and I'd like your expertise on a problem I've come across on CodingBat.
But I am not sure why my solution doesn't work. What am I missing here?
THE PROBLEM
Given an array of ints, return True if one of the first 4 elements in the array is a 9. The array length may be less than 4.
array_front9([1, 2, 9, 3, 4]) → True
array_front9([1, 2, 3, 4, 9]) → False
array_front9([1, 2, 3, 4, 5]) → False
MY SOLUTION
def array_front9(nums):
for i in range(0,len(nums)):
if len(nums)> 0 and nums[i] == 9:
return True
else:
return False
SOLUTION ONLINE
def array_front9(nums):
# First figure the end for the loop
end = len(nums)
if end > 4:
end = 4
for i in range(end): # loop over index [0, 1, 2, 3]
if nums[i] == 9:
return True
return False
Your assistance is appreciated. Thank you all.
Screenshot with the expected answers

Your solution is exiting prematurely with its return False line. As it's currently written, the code says, "Check the first number in the list. If it's a 9, end the function and return True. Otherwise, end the function and return False." That's what return statements do: end the function and (optionally) return something.
All you need to do to fix this is remove the else block and change the indentation of return False:
def array_front9(nums):
for i in range(0,len(nums)):
if nums[i] == 9:
return True
return False
(Your extra check for len(nums) > 0 is unnecessary since range(0, 0) will simply do nothing and the for loop will be skipped.)
By unindenting return False, that line will now run only after the for loop has completed, which is what you want. Note you'll still need to modify this code to check only the first 4 items in the array.
Also, outside of a learning context like CodingBat, in the real world Python does all of this work for you. You can just write 9 in nums[:4] and get your answer.

ANSWER UPDATE
Thanks to user JDAZ, I've come up with a working solution. Hoping this can shed some light towards beginners.
SOLUTION:
def array_front9(nums):
for i in range(0,len(nums)):
if nums[i] == 9 and i < 4:
return True
return False

Your code will always return False.
In your code, you create an empty list mylist and don't put anything in it. Length of such list is always 0. So, the condition in your if loop will never be true.

Solution:
def array_front9(nums):
for i in nums[0:3]:
if i == 9:
return True
return False

Related

Checking if the integer only contains odd number

I can't figure out what I'm doing wrong, but my solution seems to be not working.
Check that the given positive integer n contains only odd digits (1, 3, 5, 7 and 9) when it is written out. Return True if this is the case, and False otherwise. Note that this question is not asking whether the number n itself is odd or even. You therefore will have to look at every digit of the given number before you can proclaim that the number contains no odd digits.
My solution (for Python)
def only_odd_digits(n):
b = list(str(n))
onlyodd = [1,3,5,7,9]
for index, value in enumerate(b):
if value in onlyodd:
return True
else:
return False
Can someone help? Thanks
You can also use all to avoid the loops, and then use modulo as already suggested by alparslan mimaroğlu to avoid the lookup:
def only_odd_digits(n):
digits = map(int, str(n))
return all(dig % 2 for dig in digits)
I liked the set-based answer which got deleted now. It works when using it like this:
def only_odd_digits(n):
return set(str(n)).issubset(set("13579"))
You already created the list of integers you want to check.
You just have to check every digit if it is divisible by 2.
If any of them are you can just return False. If none of them are you can return True
def only_odd_digits(n):
digits = [int(digit) for digit in str(n)]
for digit in digits:
if digit % 2 == 0:
return False
return True
Use the following codes:
def odd(n):
return set(str(n))-set('13579')==set()

cant break out of Python While loop

I'm quite new to Python so sorry in advance, I'm trying to break out of a While loop if a random number is not within a List of numbers.
Despite testing the output of the functions and confirming that an integer is in the List and it is in fact an integer and other methods return both True and False the While Statement ignores the value. See demo code.
import random,time
list=[i for i in range(10)]
print(list)
print(list[6]*10) # this returns an integer
if list[6]==12/2:
print('this evaluates as a int')
this=99 # sentry to run the while loop **** but cant index by
if 10/2 in list:
print('this also evaluates as an integer')
print(type(list))
print(type(this))
while this not in list:
this = random.randrange(9)
print(this,this in list)
time.sleep(.200)
list[this] = '*'
>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
60
this evaluates as a int
this also evaluates as an integer
<class 'list'>
<class 'int'>
6 True
3 True
4 True
5 True
5 False
Its obvious there's a flaw in the While function where it is unable see True or False correctly, thank you to those who proposed suggestions but i come up with my own.
I created a sentry boolean to pass the value to the While function
sentry=True
while sentry:
this = random.randrange(9)
print(this,this in list)
if this not in list:
sentry=False
time.sleep(.200)
list[this] = '*'
The while loop condition should evaluate to False when you want to break out of the loop. In your case, since you want to exit when this is not in list, then set your condition to this in list.
Here is your code with the fixed condition, keep in mind that since the list is directly modified from inside the loop, the loop will terminate after one iteration.
import random, time
list=[i for i in range(10)]
print(list)
this = random.randrange(9)
while this in list:
this = random.randrange(9)
print(this, this in list)
time.sleep(.200)
list[this] = '*'
print(list)
If you did not want the loop to terminate after one iteration, you may want to consider relocating the expression list[this] = '*'. (Though this solution may also end after one iteration based on probability)
import random, time
list=[i for i in range(10)]
print(list)
this = random.randrange(9)
while this in list:
list[this] = '*' # moved here
print(list)
this = random.randrange(9)
print(this, this in list)
time.sleep(.200)
EDIT based on comment
Since the goal is to replace integers with *'s until no integers remain in the original list, here are some modifications.
The while loop exits when the number of elements replaced is equal to the number of items in the original array. The indices that have not been replaced yet are stored in the array called available.
import random, time
lst = [i for i in range(10)]
print(lst)
num_replaced = 0
# available = list.copy()
available = list(range(len(lst)))
while num_replaced < len(lst):
this = random.choice(available)
available.remove(this) # the index just chosen is no longer available
lst[this] = '*'
num_replaced += 1

canConstruct a memorization dynamic programming problem

I am stating to solve some dynamical programming problem, I came across the problem to solve if a string can be constructed from a list of string.
I have use this following method in python 3.8.
def canConstruct(target,workbank,memo={}):
if (target in memo):
return(memo[target])
if len(target)==0:
return(True)
for i in range (len(workbank)):
pos=target.find(workbank[i])
if (pos != -1):
suffix=target[pos:pos+len(workbank[i])]
out=canConstruct(suffix,workbank,memo)
if (out==True):
memo[target]=True
return(True)
memo[target]=False
return(False)
print(canConstruct('aabbc',['aa','b','c']))
instead of getting true I am getting the error maximum recursion depth exceeded in comparison.
I have checked my recursion limit it is 1000.
Can anyone tell me if I am doing anything wrong.
Thank you in advance.
Ok, there are few pitfalls in your code.
The main issue was, the for loop, because every time it calls the function, it started a new loop, hence the index of i was always one, this was creating the maximum recursion depth error.
The memo parameter, was been redundant to make it as a Dictionary,better in this case as a List.
This suffix=target[pos:pos+len(workbank[i])] had wrong position, it is supposed to be:
suffix = target[len(workbank[idx]):]]
Becase you need to leave behind was is already call and move forward right?
You were doing [0:2] which is 'aa' again. Insted you should do [2:] which is bbc
Solution
Note: I create as I understood the issue, if you expect a different output, please let me know in a comment below.
def canConstruct(target,workbank,memo=[], idx=0):
pos = target.find(workbank[idx])
if pos != -1:
memo.append(True)
idx += 1
try:
suffix = target[len(workbank[idx]):]
canConstruct(suffix,workbank,memo, idx)
except IndexError: # Here we exit the recursive call
pass
else: # In case it did not find string, append False
memo.append(False)
return all(memo) # in order to be True, all item in memo must be True
print(canConstruct('aabbc',['aa','bb','c']))
Output
# True
def canConstruct(target, wordbank, memo=None):
if memo is None:memo={}
if target in memo:return memo[target]
if target == '':return True
for word in wordbank:
if target.startswith(word):
suffix = target.replace(word, '', 1)
if canConstruct(suffix, wordbank, memo) == True:
memo[target] = True
return True
memo[target] = False
return False

Is there a way to return true for an empty list in a sort invariant?

So I am supposed to write a function that returns true if the said sequence is arranged from smallest to largest. I am able to understand strings and num lists but for an empty list, I am unable to understand why it won't return as true.
This is for understanding and possibly help me understand how to manipulate my loops better.
def is_sorted(seq):
for i in range(0, len(seq)):
if seq[i]<seq[i+1]:
return True
else:
return False
print(is_sorted([])) # expected to be true but returns none
The obvious problem is that with an empty list you are returning None which evaluates to false. The other problem is that you are using return inside of a loop, which means that you aren't evaluating every sequence in the iterable.
#hiro protagonist's answer is one solution to this problem. I offer my alternative using all and a generator expression.
def is_sorted(seq):
return all(seq[i] < seq[i + 1] for i in range(len(seq) - 1))
# All evaluate True
print(is_sorted(['a', 'b', 'c']))
print(is_sorted([1, 2, 3]))
print(is_sorted([]))
# Both evaluate False
print(is_sorted(['a', 'c', 'b']))
print(is_sorted([0, 1, -1]))
Edit with explanation
As best I understand it, all works by stepping through an iterable and returns False if any value in it evaluates to False, otherwise returning True.
As the comments may show you, I don't have a good understanding of Python generators. A generator is an iterable object that calculates the next value and yields it back each time it is referenced.
The generator defined above, each time that all references it, calculates seq[i] < seq[i + 1] and gives that value back. If this is False at any time then all will return False.
I hope this helps. I'm sure one of the good people in the comments will correct any flawed understanding that I have.
Your implementation is wrong. It will return True for [1, 3, 2] since it only compares the first 2 elements (return returns after the first iteration).
It can be fixed by checking for the opposite condition, then return True after the loop.
You should also iterate until len(seq) - 1 otherwise the last iteration will cause an IndexError.
def is_sorted(seq):
for i in range(0, len(seq) - 1):
if seq[i] > seq[i + 1]:
return False
return True
print(is_sorted([1, 2, 3]))
# True
print(is_sorted([1, 3, 2]))
# False
print(is_sorted([]))
# True
And of course there is the trivial, naive solution,
def is_sorted(seq):
return seq == sorted(seq)
this is a variant that also works for empty lists and lists of length 1:
from itertools import islice
def is_sorted(seq):
return all(i <= j for i, j in zip(seq, islice(seq, 1, None)))
it iterates over seq[k] and seq[k+1] using zip and islice. and only if all elements satisfy the requirement True will be returned.
Its because for an empty list the code inside the for is not reached. So neither return statement isnt reached. Also you should take into account that a list with only one element should also return True. Solution:
def is_sorted(seq):
for i in range(0, len(seq)-1):
if seq[i]>=seq[i+1]:
return False
return True

Trying to understand this simple python code

I was reading Jeff Knupp's blog and I came across this easy little script:
import math
def is_prime(n):
if n > 1:
if n == 2:
return True
if n % 2 == 0:
return False
for current in range(3, int(math.sqrt(n) + 1), 2):
if n % current == 0:
return False
return True
return False
print(is_prime(17))
(note: I added the import math at the beginning. You can see the original here:
http://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/)
This is all pretty straightforward and I get the majority of it, but I'm not sure what's going on with his use of the range function. I haven't ever used it this way or seen anyone else use it this way, but then I'm a beginner. What does it mean for the range function to have three parameters, and how does this accomplish testing for primeness?
Also (and apologies if this is a stupid question), but the very last 'return False' statement. That is there so that if a number is passed to the function that is less than one (and thus not able to be prime), the function won't even waste its time evaluating that number, right?
The third is the step. It iterates through every odd number less than or equal to the square root of the input (3, 5, 7, etc.).
import math #import math module
def is_prime(n): #define is_prime function and assign variable n to its argument (n = 17 in this example).
if n > 1: #check if n (its argument) is greater than one, if so, continue; else return False (this is the last return in the function).
if n == 2: #check if n equals 2, it so return True and exit.
return True
if n % 2 == 0: #check if the remainder of n divided by two equas 0, if so, return False (is not prime) and exit.
return False
for current in range(3, int(math.sqrt(n) + 1), 2): #use range function to generate a sequence starting with value 3 up to, but not including, the truncated value of the square root of n, plus 1. Once you have this secuence give me every other number ( 3, 5, 7, etc)
if n % current == 0: #Check every value from the above secuence and if the remainder of n divided by that value is 0, return False (it's not prime)
return False
return True #if not number in the secuence divided n with a zero remainder then n is prime, return True and exit.
return False
print(is_prime(17))

Resources