Returning string not list for vehicle count from tuples in a list python - python

I need my function to use only a while loop and return the date, from a list of tuples, where the total number of vehicles reaches or exceeds n.
def date_reached_n_vehicles(vehicle_records, n):
"""Returns number of days taken to reach or exceed a total of n vehicles"""
cumulative_total = 0
num_days = 0
index = 0
date_count = None
while index < len(vehicle_records):
cumulative_total += vehicle_records[index][1]
index += 1
num_days += 1
if cumulative_total >= n:
date_count = vehicle_records[index][0]
break
return date_count
Currently for the below test code it is returning
2010-01-03
and not the correct output of
2010-01-02
can someone please tell me where it needs to be change? I think it is iterating one count ahead but not sure how to fix it.
vehicle_records = [('2010-01-01',1),
('2010-01-02',2),
('2010-01-03',3)]
date = date_reached_n_vehicles(vehicle_records, 3)
print(date)

You increase index too soon:
while index < len(vehicle_records):
cumulative_total += vehicle_records[index][1]
if cumulative_total >= n:
date_count = vehicle_records[index][0]
break
index += 1
num_days += 1

Here's a tip: If you've looked at your code and you're still stuck on where the bug is, an easy way for finding bugs in your code is to insert a couple of print calls around the problematic area, printing out relevant variables1. In your case, you probably want to print the value of index before you use it to index vehicle_records:
print('index:', index)
if cumulative_total >= n:
date_count = vehicle_records[index][0]
break
Once you do this, your problem should start to become clear. Here's the output of your modified code:
index: 1
index: 2
2010-01-03
On the first iteration of your loop, index is 1. As you correctly noted, since python list indexing starts at zero, index is one count ahead. Why is this though? Well, right before you index vehicle_records, you're updating index:
while index < len(vehicle_records):
cumulative_total += vehicle_records[index][1]
index += 1
num_days += 1
This is where your problem lies. On the first iteration, index should be zero until after you've indexed vehicle_records, to be able to reach vehicle_records's first element. Thus, you shouldn't only update index until after you've used it:
while index < len(vehicle_records):
cumulative_total += vehicle_records[index][1]
if cumulative_total >= n:
date_count = vehicle_records[index][0]
break
index += 1
num_days += 1
1Although using print is a convenient way to find bugs, you really should take the time to learn to use a debugger. There are plenty of good ones out there. In fact, Python has a debugger that comes shipped with it: pdb

Related

For loop over increasing range in a table

I am having an issue with calling a for loop if it's range is increasing.
I have a table (list of lists):
for i in range(0, len(table)):
if len(table[i]) > 10:
new_row = table[i][11:]
table.insert(i+1, [])
for val in new_row:
table[i+1].append(val)
e.g The length of table was 50 and there are a number of rows where I have more than 10 values. After every new row is created (table.insert(i+1, []), the length of the table increases, so by the time the loop gets to row 49 where the row list is greater than 10, it's actual row number becomes greater than the range of the loop.
How can I make the loop know that the range increases? At the moment, only rows upto 50 have if condition applied
I tried adding a count variable before the loop:
count = 0
for i in range(0, len(table)+count):
if len(table[i]) > 10:
new_row = table[i][11:]
table.insert(i+1, [])
for val in new_row:
table[i+1].append(val)
count = count + 1
This did not seem to help! Maybe some sort of recursive function within the for loop to constantly poll the table length? I'm not too sure.
Thanks
Is this what you are looking for?
idx = 0
while True:
try:
lst = table[idx]
except IndexError:
break
if len(lst) > 10:
table.insert(idx+1, lst[10:])
# You probably want to cut current lst here as well?
# table[idx] = lst[:10]
idx += 1
you can use while loop for this purpose!
count = 0
i=0 #initial value
while table: #your iterating loop until table holds a value!
if len(table[i]) > 10:
new_row = table[i][11:]
table.insert(i+1, [])
for val in new_row:
table[i+1].append(val)
count = count + 1
i+=1 #increment by 1

How to get an index in a list without calling index function or ANY built in functions?

I am currently trying to build a function that finds the second divisor of a number (n) and returns the index of the second divisor WITHOUT calling the build-in index function.
xs is a list and n is the number to be divided
example would be: locate_second_divisor([20,3,4,2],12) yields 2
My current code
count=0
def locate_second_divisor(xs,n):
count=0
for num in xs:
if n % num==0:
count+=1
if count==2:
return
At return, I need to write the index of the second divisor but I can't think of how to do it without calling index.
This is not a duplicate question as I am not allowed to use ANY built in functions. I can only use append, int, float, str, and loops with booleans and operators. I cannot use enumerate like similar questions can. I need some sort of way around the built in functions.
Updated code (only fails because I have to include None if there is no second divisor)
def locate_second_divisor(xs,n):
count=0
index=0
for num in xs:
if (n % num)==0:
count+=1
if count ==2:
return index
else:
return None
If I understand correctly, you can just track the index the same way you're tacking the count of the times your condition is met.
def locate_second_divisor(xs, n):
count = 0
index = 0
for num in xs:
count += (n % num) == 0
if count == 2:
return index
else:
index += 1
print(locate_second_divisor([20,3,5,3,4], 12))
# 3
Fun note:
Since (n % num) == 0 evaluates to True or False, which safely cast to 1
and 0, you can simplify your first if block to: count += (n % num) == 0

Finding the number of matching letters in two different string at the same indices

I am having trouble finish python code.
overlap('','hello') → 0.
I have managed to get the number back when the length of the strings match but if one of the strings has a smaller length than the other. I keep getting index out of range. Can someone help me finish this.
def overlap(string1,string2):
count = 0
for i in range(len(string1)):
for j in range(len(string2)):
if string1[i] == string2[j]:
count = count + 1
i+=1
else:
i+=1
return count
When running this with a function call. if both strings are equal it gives me the correct number, but if one is smaller or longer then its index out of range.
Thanks
Create one for loop which iterates through min(len(string1), len(string2)) and you would avoid problem when one string is smaller than another, see sample below:
def overlap(string1,string2):
count = 0
for i in range(min(len(string1), len(string2))):
if string1[i] == string2[i]:
count = count + 1
return count
print overlap('summer','winter') #2
print overlap('abcb','dbeb') #2
print overlap('summer','sum') #3
print overlap('','winter') #0
Good Luck!
Replace the nested loops and repeat only for the smaller length.
def overlap(string1, string2):
count=0;
len1= len(string1)
len2= len(string2)
smallLen= len1
if len2<len1:
smallLen= len2
for i in range(smallLen):
if string1[i]== string2[i]:
count+= 1
return count
Thinking about it in order of things that need to be done, you have to first figure out which of the two given strings have the shortest length because that will be your bound for the amount of loop iterations. In Python you can do a conditional assignment like:
maxloop = len(str1) if len(str1) <= len(str2) else len(str2)
You make the condition <= because it doesnt matter which is chosen if they're equal, so just pick the first.
Now that you have the amount of iterations you'll do, you can set up the loop and counter:
count = 0
for i in range(maxloop):
if str1[i] == str2[i]:
count += 1
The single if statement is checking the character at position i in both strings and seeing if they are equal, and if they are, then it'll add one to the overlap counter. Then simply return the count after the loop has terminated.
Try this:
count = 0
if len(string1) < len(string2):
for i in range(len(string1)):
if string1[i] == string2[i]:
count += 1
else:
for i in range(len(string2)):
if string1[i] == string2[i]:
count += 1
return count

What is the difference of using arrayName and arrayName[:] in Python? [duplicate]

This question already has an answer here:
Understanding Python's slice notation
29 answers
I just had a problem with Python which I eventually fixed myself. Although I'm still wondering what's the difference of using
arrayName
and
arrayName[:]
even if they have the same values. Here's my code where I had the problem:
def quickSort(ar, start, end):
count = 0
if end - start >= 2:
p = ar[end-1]
pos = start
for i in range(start, end-1):
if ar[i] < p:
if i != pos:
ar[i], ar[pos] = ar[pos], ar[i]
pos += 1
count += 1
ar[pos], ar[end-1] = ar[end-1], ar[pos]
count += 1
count += quickSort(ar, start, pos)
count += quickSort(ar, pos+1, end)
return count
def insertion_sort(ar):
shift = 0
for i in range(1, len(ar)):
j = i-1
key = ar[i]
while (j > -1) and (ar[j] > key):
ar[j+1] = ar[j]
shift += 1
j -= 1
ar[j+1] = key
return shift
n = int(input())
ar = list(map(int, input().split()))
print(insertion_sort(ar) - quickSort(ar, 0, n))
The above will print -18 but if I change the last line into
print(insertion_sort(ar[:]) - quickSort(ar[:], 0, n))
it will print 1 which is the correct (the return value of insertion_sort() is 9 and the return value of quickSort() is 8). Why is it returning a wrong value when I didn't use list slicing?
The [:] notation is a known "syntactic sugar" to duplicate the list (it's not an array).
It's a slice that takes the whole list - effectively duplicating it.
In your code you are not passing the same list when you use the ar[:] notation - you're passing an entirely new list (with the same members). This way each frame in the quickSort recursion has it's own, exclusive list (ar).
This does not happen when you pass the original list as is - which is mutable. Letting two (or way more...) frames modify the same list causes havoc.

How do I get my num_digit function to give me the correct output and how do I get it to return any integer value in python?

How do I get my num_digit function to return 1 instead of 0 whenever I put in 0 as the parameter in the function?
How do I get the function to return any integer such as negative numbers?
def num_digits(n):
count = 0
while n:
count = count + 1
n = abs(n) / 10
return count
I was working on question number 2 first. Even if I put the abs(n) in the line of code where while is, I still get an infinite loop which I still do not really understand why. I figured if I can get my n value to always be positive and input in say -24, it would convert it to 24 and still count the number of values.
On question 1, I do not know where to start, ive tried:
def num_digits(n):
count = 0
while n:
if n == 0:
count = count + 1
n = n / 10
return count
I forgot to add I have limited tools to use since I am still learning python. I have gotten up to iterations and am studying the while loops and counters. I have not gotten to break yet although I have an idea of what it does.
When in doubt, brute force is always available:
def num_digits(n):
if n == 0:
return 1
if n < 0:
return num_digits(abs(n))
count = 0
while n:
count = count + 1
n = n / 10
return count
Process the exceptional cases first, and then you only have to deal with the regular ones.
If you want to avoid the conditionals, I suggest taking abs(n) only once, at the beginning, and using an infinite loop + break for the 0 case:
def num_digits(n):
n = abs(n)
count = 0
while True:
count = count + 1
n = n / 10
if n == 0:
break
return count
For a more practical solution, you can either count the number of digits in the string (something like len(str(n)) for positive integers) or taking log base 10, which is a mathematical way of counting digits.
def num_digits(n):
if n == 0:
return 0
return math.floor(math.log10(math.abs(n)))

Resources