Neighbours of same sign exercise in Python - help needed - python

I have the following exercise.
Neighbours of same sign
Given a sequence of numbers, find and print the first adjacent elements which have the same sign. If there is no such pair, print NONE.
Please note that the output must be the same as indicated in the example.
Example
Input:
-1 2 -3 -4 -5 1 2
Output:
-3 -4
this is my code, but it does not work when I try to catch the case when the pairs are not the same sign, can someone help?
The code works fine, but when i add the ELSE things break down.
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
else:
print ('NONE')

just add a found flag
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
found=False
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
found=True
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
found=True
break
if not found:
print ('NONE')
you should check the else part once

I would suggest keeping track of the sign of the previous and current numbers and a found flag. For example like this:
list = [-1, 2, -3, 4, -5, 1]
prev_sign = -1
found = 0
for i in range(len(list)):
this_sign = list[i] < 0
if this_sign == prev_sign:
print("{} {}".format(list[i - 1], list[i]))
found = 1
break
prev_sign = this_sign
if not found:
print("NONE")
Or even more concise, the for loop could look like this:
for i in range(1, len(list)):
if (list[i] < 0) == (list[i - 1] < 0):
print("{} {}".format(list[i - 1], list[i]))
found = 1
break

One error I see with the code is the placement of the else statement inside the for-loop. In the existing code, if the first two elements have mismatched sign, then it will immediately print 'NONE' because it reaches that else statement, and will continue printing 'NONE' until it does find matching neighbors. I would rewrite your for-loop as follows:
found_pair = False
for i in range(len(my_list)-1):
if my_list[i] * my_list[i+1] > 0: # matching sign
found_pair = (my_list[i], my_list[i+1])
break
if found_pair:
print(found_pair[0], found_pair[1])
else:
print('NONE')
In the above code, the result must necessarily only print once after it's already finished the for-loop. If a pair is found, it is stored and we break, otherwise we exhaust the loop without ever assigning found_pair, leading 'NONE' to be printed only once at the end. Let me know if this doesn't work or if you have any questions!
David

Lots of suggestions for a found flag, but you don't need one. This is where the else on a for loop comes in:
lst = [-1, 2, -3, 4, -5, 1]
# zip lst with a slice of itself to get corresponding
# elements offset by 1 position
for a, b in zip(lst, lst[1:]):
if a * b > 0:
print(f"Found pair {a} {b}")
break
else:
print("NONE")
The else will only trigger if the for loop completes (isn't ended early by break)

Related

list out of range in python adjacent numbers question

I have a question which is asking to compare 2 numbers in a list, specifically if the adjacent numbers are positive or negatives
However I am stuck on the first part of the question. My idea is to compare the first number using its index with the second number so i+1, but inevitably is goes out of range.
I am missing something here, help is appreciated.
my_list=[-1,2,-3,-4,-5,1,2]
for i in range(len(my_list)):
print (my_list[i])
print (my_list[i+1])
I have been working on it and this is the full questions
Given a sequence of numbers, find and print the first pair of adjacent elements which have the same sign. If there is no such pair, print NONE.
I'm not allowed to use zip in this case.
However I cannot do the last bit where it ask pro print none if no pairs are there
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
Two points:
Most of the time it is considered "unpythonic" to use indices to iterate over a list
The for-loop has the option to close with an else-condition: The code in the else condition is only executed if the for-loop isn't left via a break
So, you could try the following:
for first, second in zip(my_list[:-1], my_list[1:]):
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
break
else:
print("NONE")
EDIT: If you need to use indices, then you could do:
for i in range(len(my_list) - 1):
first, second = my_list[i], my_list[i+1]
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
break
else:
print("NONE")
If you are not allowed to use the else-option of the for-loop, then you could try:
found = False
for i in range(len(my_list) - 1):
first, second = my_list[i], my_list[i+1]
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
found = True
break
if not found:
print("NONE")
Because you want to print (my_list[i+1])
Your list size is 7 -> when i = 6 -> [i+1] = 7
=> my_list[7] <- out of range
You can do it like below:
my_list=[-1,2,-3,-4,-5,1,2]
list_len = len(my_list)
for i in range(list_len-1):
print(f'comparison {i+1}')
print (my_list[i])
print (my_list[i+1])
my_list=[-1,2,-3,-4,-5,1,2]
list_len = len(my_list)
x = 7 # any positive number
for i in range(x):
if i < list_len:
print (my_list[i])
if i+1 < list_len:
print (my_list[i+1])

How can i remove the break from find_frequent(s) code since our teacher told us we can't use it on the test and I'm trying to practice not using it?

I wrote this code, and I'm struggling to replace using break since it says in the homework that we are not allowed to use continue/break statements in our loops.
The code's goal is:
finds the character that appears most frequently in the input parameter string and returns it. For Example, if the string is "Canada day" the function returns the string "a"
If there are two characters or more with the same frequency, the function should return the first of many values with the same frequency.
def find_frequent(s):
"""
-------------------------------------------------------
description
Use:
-------------------------------------------------------
Parameters:
name - description (type)
Returns:
name - description (type)
------------------------------------------------------
"""
L = []
count = 0
char = 0
i = 0
words = True
while i < 1 and words:
x = s[i]
for j in range(len(L)):
if x == L[j]:
words = False
L[j + 1] = L[j + 1] + 1
else:
L.append(x)
L.append(1)
for i in range(1, len(L), 2):
if L[i] > count:
count = L[i]
char = L[i - 1]
return char
the output should look like this
`Enter a string: Hello Hi`
output should be
`Most frequent characters: H`
I'm getting this output
Enter a string: canada
Most frequent character: c
You can replace the break statement in a for loop with a while loop.
print("using for loop + break")
for i in range(0, 5):
print(i)
if i == 3:
break
print("using while")
i = 0
keep_searching = True
while i < 5 and keep_searching:
print(i)
if i == 3:
keep_searching = False
i += 1
The output is:
using for loop + break
0
1
2
3
using while
0
1
2
3
I think you can figure it out from here, but if you need help with finding the most frequent character (a different issue from the break), take a look here and here.
No need for a break if you don't use a loop in the first place :-)
def find_frequent(s):
return max(s, key=s.count)
(I'm actually serious... forbidding break sounds to me like your teacher didn't want you to write it with such nested loops.)
Or if you want to teach your teacher a lesson (the lesson being that they shouldn't forbid stuff), you could fake the break:
for i in range(0, len(s), 1):
x = s[i]
it = iter(range(len(L))) # make it an iterator
for j in it:
if x == L[j]:
L[j + 1] = L[j + 1] + 1
*it, # exhaust the iterator
it = None # make it false
if it: # instead of `else`
L.append(x)
L.append(1)

How compare variable to Array[i] in Python

I am learning python, one the the question I have is how can check if variable x is equal to array[i]. I am trying to use divide and conquer to find element in array
x = 12
arr = [12,31,33]
middle = len(arr)//2
print ("Find",x)
print ("Middle ", arr[middle])
print ("Middle Left",arr[middle] +1)
print ("Middle Right", arr[middle] -1)
if x == arr[middle]:
print ("found it")
elif x == arr[middle] - 1 :
print ("found on left")
elif x == arr[middle] + 1:
print ("found on right")
else:
print("Not found")
if you want to find element at left/right based on index, you need to minus/add on index.
x = 12
arr = [12,31,33]
middle = len(arr)//2
print ("Find",x)
print ("Middle ", arr[middle])
print ("Middle Left",arr[middle + 1] )
print ("Middle Right", arr[middle -1])
if x == arr[middle]:
print ("found it")
elif x == arr[middle - 1] :
print ("found on left")
elif x == arr[middle + 1]:
print ("found on right")
else:
Unless your problem specifically says that you must use divide and conquer to do this, you could just use .index(x) to get its index - i.
So for your example:
x = 12
arr = [12,31,33]
then:
arr.index(x)
gives 0 for i (the index). This is much neater and unless you have a massive list, will be perfectly fast enough.
If it turns out you must write your own divide and conquer for this, then the place you are going wrong is when indexing from arr with arr[middle] and then adding and subtracting from that value. What you want to do instead, is index one further or one before with arr[middle - 1] or arr[middle + 1].
Hopefully you can implement these changes to your code yourself if you don't want to use the much easier .index().
How about creating a function like this?
arr = [12,31,33,31]
def position(array,key):
# find all entries
positions = [ind for ind,i in enumerate(array) if i==key]
# return No match if nothing is found
if not positions:
return "No match!"
# set mid to middle of array
mid = len(arr) / 2
# loop through all found elements and print
for i in positions:
if i < mid:
where = "left"
elif i > mid:
where = "right"
else:
where = "mid"
print("found {} on {}".format(key,where))
print(position(arr,31)) # 'found 31 on left \n found 31 on right'
print(position(arr,19)) # 'No match!'

map(int, raw_input().split()) gets infinite input

Here's the code:
a = input()
b = map(int, raw_input().split())
maxcnt=1
for k in range(0,a):
cnt=1
j=k+1
while b[k]%b[j] == 0 or b[j]%b[k] == 0 :
cnt += 1
if maxcnt < cnt:
maxcnt = cnt
print maxcnt
While giving the list values, after giving the values separated with spaces, I press enter and it still keeps getting the input. What's the issue?
The statement b = map(int, raw_input().split()) is perfectly okay. The problem is that you are encountering an infinite loop in the later while part of your code. There should be some issue with the logic.
So, you are taking modulo of consecutive numbers in the list b ? So, an input like this:
b = [1,2,3,4]
will cause an infinite loop, since 1%2 == 0 or 2%1 ==0 => True. It is clearly an input dependent scenario.
Your code shows a while statement which does not change it's conditions while looping:
while (b[s] % b[j]) == 0 or
(b[j] % b[s]) == 0:
cnt += 1
As you can see here, cnt is not in the condition (b[s] % b[j]) == 0 or (b[j] % b[s]) == 0, therefore, it will just keep on incrementing cnt and will not stop.
What you see is an empty console (which you then thought meant it was asking for more input) which was actually just the while loop running continuously.

Generate triangular numbers

This function is supposed to take an integer, generate the list of triangular numbers within range of that integer, check that list for the longest list of numbers whose sum == number and return them in a list, otherwise if there is no such list within that range of triangular numbers, return an empty list. I thought I had it somewhat, and it runs on python tutor.com, but when I run it in IDLE, nothing happens.
def checkio(number):
x = 4
lst = [1, 3, 6]
new = []
if number == 0:
return []
elif number == 1:
return [1]
elif number == 3:
return []
elif number == 6:
return []
elif number == 4:
return [1, 3]
elif number == 7:
return [1, 6]
elif number == 10:
return [1, 3, 6]
elif number > 10:
while number > lst[-1]: # Generates a list of all the triangular numbers up to number
for item in range(lst[-1]):
lst.append(x + lst[-1])
x += 1
go = []
start = 0
end = 0
count = 0
while count < len(lst) * 2:
if sum(lst[start:end+1]) < number:
end += 1
count += 1
elif sum(lst[start:end+1]) > number:
start += 1
count += 1
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
break
return go
if count >= len(lst) * 2:
return []
In the code you post you are just declaring a function. In order to run it, you have to make a call to that function. In your case, it receives one argument, so you have to pass it inside the parentheses ():
number = 5 # for example
checkio(number) # this is the function call
As Bakuriu commented: If you want to get a result change the order of this lines:
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
break
return go
To :
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
return go
break
This will return a value before escaping the while loop. As noted in the comments (thanks Andrea Corbellini) you can also remove the break statement and it will work well. Because after the return statement by definition escapes the function.
Also to run in idle once defined (you copied the code and pressed return), call it as Christian says.
This way you will check if works.
Note that you don't check in the ifelse clauses for the numbers 2, 5, 8 and 9. If you call this function with checkio(5), like suggested by Crhistian, it will not return anything because it doesn't have anything to return!

Categories

Resources