I am trying to get the max pair wise product using python this time around and the concepts of certain aspects are still new to me. I continue to get a list index out of bounds error and stackoverflows of which I do not know how to deal with given the fact that I can not choose types in Python.
I looked into enumerate and other iterate(ble) functions but to no avail. Id answered this could help future people with simple for loop questions in migration from C to python.
def max_pairwise_product(numbers):
n = len(numbers)
max_product = 0
for first in range(n):
for second in range(first + 1, n):
max_product = max(max_product,
numbers[first] * numbers[second])
return max_product
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = 1
for i in range(2,n,1):
if (numbers[i]>numbers[index1]):
index1 = i
if (index1 == 1):
index2 = 2
else:
index2=1
for i in range(1,n):
if(numbers[i]!=numbers[index1] and numbers[i]>numbers[index2]):
index2 = i
return (numbers[index1]*numbers[index2])
if __name__ == '__main__':
input_n = int(input())
input_numbers = [int(x) for x in input().split()]
print(max_pairwise_product_fast(input_numbers))
Traceback (most recent call last):
File "C:/Users/Tevin/.PyCharmCE2018.3/config/scratches/scratch_1.py", line 31, in <module>
print(max_pairwise_product_fast(input_numbers))
File "C:/Users/Tevin/.PyCharmCE2018.3/config/scratches/scratch_1.py", line 27, in max_pairwise_product_fast
return (numbers[index1]*numbers[index2])
IndexError: list index out of range
why dont you find the 2 max numbers in your list and multiply them to get the max product. find the max of list then save it in some variable. remove it from the list and find the max again. then multiply this with your saved variable.
as for your code, what is this line for?
input_n = int(input())
you are not using the input_n variable anywhere.
and the line:
input_numbers = [int(x) for x in input().split()]
your code will ask you for 2 inputs. when you first enter your input, it is saved in the input_n variable. then your second input is saved as input_numbers. something is wrong with the type of input you are giving the program.
If I understand your max_pairwise_product_fast correctly, you are trying to find the largest and second largest number and multiply them. The problem is that you initialize index1 as 1, and index2 with 1 or 2, but array-indexes start with 0. Thus, your code will fail for a list with only two elements, e.g. [1,2]. Change the starting indices to 0, and change the range in the loops accordingly, and it will work.
You can also remove some of the checks, e.g. the if/else, as that's redundant with the check you have in your second loop. Also, by comparing number[index1] and number[index2] you could miss the highest product if the highest number appears twice, e.g. [1,2,2].
Staying close to your original code, you can try this:
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = 0
for i in range(n):
if numbers[i] > numbers[index1]:
index1 = i
index2 = 0
for i in range(n):
if index2 != index1 and numbers[i] > numbers[index2]:
index2 = i
return numbers[index1] * numbers[index2]
But you could also use max instead of those two loops:
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = max(range(n), key=lambda i: numbers[i])
index2 = max((i for i in range(n) if i != index1), key=lambda i: numbers[i])
return numbers[index1] * numbers[index2]
Or sort the entire array and pick the highest two:
def max_pairwise_product_fast(numbers):
second, first = sorted(numbers)[-2:]
return first * second
Note, however, that this might still fail if the list includes negative numbers, e.g. [1, 2, -3, -4]. For this, you could call the same function again with all the numbers in the list negated and pick the higher of the two results.
Related
This is what I have so far.
def f(n):
my_list=[]
while n not in my_list:
my_list.append(n)
if n % 2 == 0:
n = n / 2
else:
n = 3 * n + 1
my_list.append(n)
return my_list
The above code takes any input n and outputs a list e.g. f(2) -> [2, 1, 4, 2]
Now I want to look at any range and output just the highest element in said list.
def f_2(i):
for i in range (1,101):
set_f = set(f(i))
print(max(set_f))
So I converted the list to a set and applied the max command to it. All of this has worked as I had intended it so far.
My problem is with the following issue:
I want to output all the indexes of all the highest Elements in all generated lists.
E.g. for i in range (1,101): The highest Element is 9232. I tried doing it in the above way, but a set does not have any indexes. However max() does not seem to work on a list of generated lists.
My try was:
def f_3(i):
for i in range (1,101):
set_f = set(f(i))
if max(set_f) == 9232:
print(set_f.index(9232))
else:
pass
Here I get the error that set has no index attribute.
def f_3(i):
for i in range (1,101):
if max(f(i)) == 9232:
print(f.index(9232))
else:
pass
Here I get the error that function has no index attribute.
Only the range of 1 to 100 is of interest to me. So I can use 9232 as a value.
Any help would be greatly appreciated, I feel a bit stuck on this one.
There's several things to unpack here, and I feel like the Code Review community would be a better fit.
First of all, why does f_2 have the parameter i? You're just using the i from the loop.
Second, why are you converting the list into a set at all? max works just fine on lists too.
set doesn't support indexing, and that's why you were getting that mistake.
At the other attempt with f_3, you've called index on the function f instead of f(i).
Function f_2 can be rewritten as such.
def f_2():
for i in range (1,101):
lst = f(i)
mx = max(lst)
print(lst.index(mx))
Function f_3 is inefficient, but it too can be fixed like this:
def f_3():
for i in range (1,101):
if max(f(i)) == 9232:
print(f(i).index(9232))
I am learning Python and using it to work thru a challenge found in Project Euler. Unfortunately, I cannot seem to get around this problem.
The problem:
Even Fibonacci numbers
Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will
be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.
I created a for loop that adds the second to last element and the last element from the list x:
x = [1,2]
for i in x:
second_to_last = x[-2]
running_sum = i + second_to_last
If you run the above, you get 3. I am looking to add this new element back to the original list, x, and repeat the process. However, each time I try to use the append() function, the program crashes and keeps on running without stopping. I tried to use a while loop to stop this, but that was a complete failure. Why am I not able to add or append() the new element (running_sum) back to the original list (x)?
UPDATE:
I did arrive at the solution (4613732), but I the work to getting there did not seem efficient. Here is my solution:
while len(x) in range(1,32):
for i in x:
second_to_last = x[-2]
running_sum = i + second_to_last
x.append(running_sum)
print(x)
new_x = []
for i in x:
if i%2 == 0:
new_x.append(i)
sum(new_x)
I did have to check the range to see visually whether I did not exceed 4 million. But as I said, the process I took was not efficient.
If you keep adding elements to a list while iterating over that list, the iteration will never finish.
You will need some other criterion to abort the loop - for example, in this case
if running_sum > 4000000:
break
would work.
(Note that you don't strictly speaking need a list at all here; I'd suggest experimenting a bit with it.)
Here are two different ways to solve this. One of them builds the whole list, then sums the even elements. The other one only keeps the last two elements, without making the whole list.
fib = [1,2]
while fib[-1] < 4000000:
fib.append(fib[-2]+fib[-1])
# Get rid of the last one, since it was over the limit.
fib.pop(-1)
print( sum(i for i in fib if i % 2 == 0) )
fib = (1,2)
sumx = 2
while True:
nxt = fib[0]+fib[1]
if nxt >= 4000000:
break
if nxt % 2 == 0:
sumx += nxt
fib = (fib[1],nxt)
print(sumx)
I don't answer your question about list modification but the solution for your problem:
def sum_even_number_fibonacci(limit):
n0 = 0 # Since we don't care about index (n-th), we can use n0 = 0 or 1
n1 = 1
even_number_sum = 0
while n1 <= limit:
if n1 % 2 == 0:
even_number_sum += n1
n2 = n0 + n1
# Only store the last two number of the Fibonacci sequence to calculate the next one
n0 = n1
n1 = n2
return even_number_sum
sum_even_number_fibonacci(4_000_000)
recently I was trying out some past year AIO questions, and I couldn't solve this one.
The problem is as follows:
Safe Cracking
Input File: safein.txt
Output File: safeout.txt
Time Limit: 1 second
Over the centuries many wars have been won, not through a battle of strength but a battle of wits. Your sources have recently informed you that your mother has purchased a pre-release copy of the latest computer game, WheeZork, and is hiding it in the safe at home. To open the safe, one must enter a long sequence of numbers by rotating the circular dial to each number in the correct order.
If the correct sequence of numbers is entered into the safe, the safe opens and you can sneak your Christmas present out early. If you get the sequence wrong the alarm system is activated and you will be grounded for life! Luckily, you know that your mother has written the code down on a sheet of paper in her bedside drawer, which she likes to call the "code sheet".
She often boasts about how clever she is and explains to you that the numbers on the sheet are indeed the code to the safe, however each number in the sequence has been increased by a constant non-negative integer, k, which only she knows. Without this value the sheet is useless, and thus only she can open the safe ... or so she thinks!
In order to determine the correct code, you have spied on your mother when she unlocks the safe and you have managed to remember part of the code that she entered. You are not sure which part of the code this corresponds to, but it is definitely a consecutive sequence of numbers in the code. Armed with this knowledge, you set out to determine the full code to the safe.
Your task is, given the full list of numbers your mother has written down on her code sheet, and the shorter sequence that you know appears in the actual code, determine the entire sequence to unlock the safe.
For example, if the code to the safe was 7, 9, 4, 6, 8, 12, and your mother had incremented all numbers by 4, her code sheet would read 11, 13, 8, 10, 12, 16. This is because 7 + 4 = 11, giving the first number 11. The second number is obtained by adding 9 + 4 = 13. The third number is obtained by adding 4 + 4 = 8, and so forth. You may have caught a glimpse of her entering the numbers 4, 6, 8, in order. With this knowledge, you can determine the entire code.
Input
The first line of the input file will contain two integers, a b, separated by a space. The integer a is the length of the sequence written on your mother's code sheet ( 2 <= a <= 100000). The integer b is the length of the sequence that you know is contained within the code to the safe ( 2 <= b <= 30).
Following this will be a lines, each containing a single integer between 1 and 1000000. These lines are the sequence written on your mother's code sheet, in the order they are entered into the safe.
Following this will be b lines, each containing a single integer, also between 1 and 1000000. These lines describe the glimpse of the actual code to the safe.
You are guaranteed that there will only be one possible solution for any given input scenario.
Output
Your output file should consist of a lines. Each of these lines should contain a single integer, representing the full sequence of numbers required to open the safe.
My code (that passes most test cases) is as follows:
'''program implements a function diff which is returns a list that is the difference of the current elements in the list
to solve the problem, the subset list is reduced until it consists of a single integer
the index of this integer in the original list is then found, before determining the non-negative integer
which was used to encode the numbers'''
def diff(lst):
lst2=[]
for i in range(len(lst)-1):
lst2.append(lst[i+1]-lst[i])
return lst2
infile = open("safein.txt", "r")
outfile = open("safeout.txt", "w")
a, b = map(int, infile.readline().split())
lst, sub = [], []
for i in range(a):
lst.append(int(infile.readline()))
for j in range(b):
sub.append(int(infile.readline()))
temp_sub=sub
temp_lst=lst
k = 0
while len(temp_sub) != 1:
temp_sub=diff(temp_sub)
k+=1
for x in range(k):
temp_lst=diff(temp_lst)
n = temp_lst.index(temp_sub[0])
m = lst[n]-sub[0]
lst=[x-m for x in lst]
for i in lst:
outfile.write(str(i) + "\n")
As this code passes most test cases, with the exception of some cases that give an error (I do not know what error it is), I was wondering if anyone could suggest some corner cases that would lead to this algorithm creating an error. So far all the cases that I have thought of have passed.
EDIT:
as niemmi has pointed out below, there are some side cases which my above algorithm cannot handle. As such, I have rewritten another algorithm to solve it. This algorithm passes most test cases, and there are no errors, except that the execution takes longer than 1s. Could anyone help reduce the time complexity of this solution?
def subset(lst1, lst2):
if lst2[0] in lst1:
idx = lst1.index(lst2[0])
for i in range(len(lst2)):
if lst2[i]==lst1[idx+i]:
continue
else:
return False
else:
return False
return True
infile = open("safein.txt", "r")
outfile = open("safeout.txt", "w")
a, b = map(int, infile.readline().split())
lst, sub = [], []
for x in range(a):
lst.append(int(infile.readline()))
for y in range(b):
sub.append(int(infile.readline()))
if subset(lst, sub):
for i in range(a):
outfile.write(str(int(lst[i])) + "\n")
infile.close()
outfile.close()
exit()
i=1
while True:
temp_sub = [x+i for x in sub]
if subset(lst, temp_sub):
lst = [x-i for x in lst]
for j in range(a):
outfile.write(str(int(lst[j])) + "\n")
infile.close()
outfile.close()
exit()
i+=1
EDIT:
Thanks to niemmi, who provided a solution below that I edited slightly to pass a test case returning an error.
def diff(seq):
return (seq[i - 1] - seq[i] for i in range(1, len(seq)))
with open('safein.txt') as in_file:
a, b = (int(x) for x in in_file.readline().split())
code = [int(in_file.readline()) for _ in range(a)]
plain = [int(in_file.readline()) for _ in range(b)]
code_diff = tuple(diff(code))
plain_diff = tuple(diff(plain))
k = 0
def index(plain_diff, code_diff, plain, code, a, b, k):
for i in range(k, a - b):
for j, x in enumerate(plain_diff, i):
if code_diff[j] != x:
break
else:
k = code[i] - plain[0]
break # found match, break outer loop
return k
k = index(plain_diff, code_diff, plain, code, a, b, k)
with open('safeout.txt', 'w') as out_file:
out_file.write('\n'.join(str(x - k) for x in code))
Thanks!
The above implementation calculates repeatedly the differences of consecutive elements on following lines:
while len(temp_sub) != 1:
temp_sub=diff(temp_sub)
k+=1
When run against the example input after first round temp_sub is [2, 2] and after second and final round it is [0]. Then the implementation proceeds to do the same kind of reduction for temp_lst that contains the incremented code which results to [-7, 7, 0, 2].
Then index is used to find the index with 0 value from temp_lst which is then used to deduce k. This approach obviously won't work if there's another 0 value on temp_lst before the index you're trying to find. We can easily craft an input where this might be the case, for example adding 11 twice at the beginning of the code sheet so the full sheet would be [11, 11, 11, 13, 8, 10, 12, 16].
EDIT Why not just use the initial approach of differences of subsequent numbers to find k? Code below loops over code sheet and for each position checks if plain sequence can start from there i.e. if the number is equal or greater than first number in plain sequence since k was defined to be non-negative integer. Then it loops over next b - 1 numbers both on code sheet and plain sequence to see if differences match or not.
Worst case time complexity is O(ab), if that's not good enough you could utilize KMP for faster matching.
with open('safein.txt') as in_file:
a, b = (int(x) for x in in_file.readline().split())
code = [int(in_file.readline()) for _ in range(a)]
plain = [int(in_file.readline()) for _ in range(b)]
for i in range(a):
k = code[i] - plain[0]
if k < 0:
continue
for j in range(1, b):
if code[i] - code[i + j] != plain[0] - plain[j]:
break
else:
break # found match, break outer loop
with open('safeout.txt', 'w') as out_file:
out_file.write('\n'.join(str(x - k) for x in code))
lst = [3, 4, 3, 5, 3]
def lstmaker(lst):
lst1 = []
x = 0
while x < len(lst):
if lst[x] == lst[x+1]:
lst1.append(lst[x])
else:
pass
x+=1
print lst1
lstmaker(lst)
I tried to make this simple program to find the the mode of list, but it just throws the index of out range error.
Thanks
For the last value of x, lst[x+1] x+1 is out of range. The while loop should be while x < len(lst) -1.
As a side note, to calculate the mode, you can simply do: max(set(lst), key=lst.count) as shown here.
The logic is incorrect.
For starters, the reason you're getting an index out of range issue is because of the line
if lst[x] == lst[x+1]
x is correctly incremented throughout your loop, but when x is at the last index, that +1 bit accesses an index that isn't in the list (e.g. index 5 of a list of size 5).
Additionally, what you were actually doing within the loop doesn't appear to be getting you towards a value for the mode. The mode is the element(s) in a list that occurs the most. One approach to tackling this problem could be using a dictionary (dict()) where the "keys" are the elements in your list, and the "values" are the amount of times each element occurs.
Try something like this:
# lst defined up here
occurrences = dict()
for x in lst:
if x in occurrences:
occurrences[x] += 1
else:
occurrences[x] = 1
mode = occurrences.keys()[0]
for k in occurrences:
if occurrences[k] >= mode:
mode = k
print(mode) # or return, etc.
This is perhaps not the most "Pythonic" solution, though it is an intuitive break-down of the logic involved in finding the mode, at least as if you were to do it by hand on paper.
I am doing some homework and I am stuck. I supposed to write a code in Python 3, that reads a text file that is like a bill with an amount of numbers. I am supposed to write the code so it will calculate the total amount.
I figured that a bill(simple example) will contain a number and the a prise. like:
2 10$
1 10 $
and so on
So I figured that I create a list with all numbers in it and then I want to multiply the first with the second element in the list and then jump in the list so the tird and the fourth element get multiply and so on, until there is no more numbers in my list. During this happens I want the sums of every multiplication in a new list called sums there they later will be summed.
my code looks like this so far:
file = open('bill.txt')
s = file.read()
file.close()
numbers = []
garbage = []
for x in s.split():
try:
numbers.append(float(x))
except ValueEror:
garbage.append()
print(numbers)
for n in numbers:
sums = []
start = 0
nxt = start + 1
t = numbers[start]*numbers[nxt]
if n <= len(numbers):
start += 2
nxt += 2
summor.append(t)
if n == len(numbers):
print(sum(sums))
The problem in your code is likely that you keep resetting sums for every number in the list. So you basically keep forgetting the sums you previously collected. The same applies to start and nxt. If you move these definition outside of the loop, and also fix the summor.append(t) to sums.append(t) it should almost work. Also note that the loop variable n does not iterate over indexes of numbers but over the actual items (i.e. the numbers). So the check at the end n == len(numbers) is unlikely to do what you expect. Instead, you can just put the print after the loop because you know that when you reached that point the loop is over and all numbers have been looked at.
A common idiom is to use zip to combine two elements with each other. Usually, you use zip on two different iterators or sequences, but you can also use zip on the same iterator for a single list:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> it = iter(numbers)
>>> for a, b in zip(it, it):
print(a, b)
1 2
3 4
5 6
7 8
As you can see, this will group the numbers automatically while iterating through the list. So now you just need to collect those sums:
>>> sums = []
>>> it = iter(numbers)
>>> for a, b in zip(it, it):
sums.append(a * b)
>>> sum(sums)
100
And finally, you can shorten that a bit more using generator expressions:
>>> it = iter(numbers)
>>> sum(a * b for a, b in zip(it, it))
100
This may be a typo when you entered it but on your 2nd line of data there is a space between the amount and $ and no space on the line above. This will cause some problems when striping out the $.
Try this:
total = 0
with open('data.txt', 'r') as f:
lines = f.readlines()
amounts = []
garbage = []
for line in lines:
try:
multiples = line.split()
multiplier = multiples[0]
amount = multiples[1].strip('$\n')
amounts.append(int(multiplier)*float(amount))
except:
garbage.append(line)
total = sum(amounts)
print(total)
With some minor formatting on output or the text data you should be able to get the result you want. Here is the txt data I used:
2 10$
1 10$
3 20.00$
and the output is:
90.0
Also, you may want to get away from file = open('data.txt', 'r') which requires you to explicitly close your file. Use with open('data.txt', 'r') as f: and your file will implicitly be closed.
Firstly, I would say, quite a good attempt. If you don't want to be spoiled, you should not read the code I have written unless you try out the corrections/improvements yourself. (I am not a pro)
Well, like you said every line contains 2 numbers that need be multiplied, you should start by reading line by line & not individual numbers as that might get troublesome.
file = open('bill.txt')
s = file.readlines()
file.close()
numbers = []
garbage = []
for line in s:
try:
line.strip('$') # removes the trailing $ sign for easy number extraction
numbers.append(map(int, line.split()))
except ValueEror:
garbage.append(line)
print(numbers)
Later, when summing up the multiplication of the number & the bills, you probably won't require a list for that, instead a sum integer variable should be enough.
sum = 0
for num, bill in numbers:
sum += num * bill
print("The total amount is", sum)
Several things:
sums = [] is inside the loop for n in numbers. This means you're resetting the sums list every time. You should move this outside the loop.
The same applies to start = 0 and nxt = start + 1. These values now keep being reset to 0 and 1 respectively for each number in the list.
You are comparing if n <= len(numbers): but what is n? It's an actual value in your list of numbers, it doesn't represent the position in the list. You should replace this with while start < len(numbers): - as long as the starting position is still within the list we should keep going. This also means you can remove n from your code.
The code now becomes:
sums = []
start = 0
nxt = start + 1
while start < len(numbers):
t = numbers[start]*numbers[nxt]
start += 2
nxt += 2
sums.append(t)
print(sum(sums))