Python intersection of 2 arrays without using loops/functions - python

I have some problems with this task:
write in recursive functions which (NOTE: you can't use loops.):
3.1 Will display on the screen the common part of two sorted arrays
3.2 Will write the back of the word/array on the screen
Right now I have rest of the exercise:
firstArray = [1, 2, 3, 4, 5]
secondArray = [4, 5, 6, 7, 8]
#1 function - print first element
def printFirstElement():
firstElemenet = firstArray[0]
print(firstElemenet)
printFirstElement()
#2 function - print all without first element
def printAllWithouthFirstElemenet():
arrayWithoutFirstElement = firstArray[1:]
print(arrayWithoutFirstElement)
printAllWithouthFirstElemenet()
#3 functin - return information if array is empty
def checkArrayEmptiness():
if firstArray:
print("Array has somehting")
else:
print("Array is empty")
checkArrayEmptiness()
##rest code should be here
I really don't have idea what I could write more, someone could help me?
Edit 1
Without ready-made solutions

You can use python set.
Something like:
print(set(firstArray).intersection(secondArray))
In most cases it will be smart to use Python built in solutions, as they are more efficient for the general case.
But, in case you do need it, try looking at this duplicate question: Finding List Intersection using Python List Slices & recursion

Related

Optimizing Python Code for returning the smallest element with highest occurrences in a list

I am trying to solve one of HackerRanks easy rated problems with Python. My code solves 4 out of 5 test cases but for one of the test cases, I get an error message saying time limit exceeded. Please recommend ways to optimize this. I am a beginner at python and still trying to understand itertools but it seems quite complicated.
Problem Statement:
Given an array of bird sightings where every element represents a bird type id, determine the id of the most frequently sighted type. If more than 1 type has been spotted that maximum amount, return the smallest of their ids.
Sample input: arr=[1,2,3,4,5,4,3,2,1,3,4]
Sample output: 3
My current code:
def migratoryBirds(arr):
d={}
arr2=[]
for i in range(len(arr)):
d[arr[i]]=arr.count(arr[i])
for i in d.keys():
if d[i]==max(d.values()):
arr2.append(i)
return(min(arr2))
Your algorithm is slower because you are going through the whole array multiple times with the .count() function. You are also going through your dictionary multiple times in the second loop with the max() function. This results in O(N^2) time complexity.
To achieve O(N) time, you should only add 1 per item in the array and then process the dictionary on the basis of max total / min id:
arr=[1,2,3,4,5,4,3,2,1,3,4]
counts = {}
for bird in arr: counts[bird] = counts.get(bird,0) + 1 # +1 per bird
result,_ = max(counts.items(),key=lambda kv:(kv[1],-kv[0])) # max total / min id
print(result) # 3
def migratoryBirds(arr):
most_common_item = max(arr, key=arr.count)
print(most_common_item)
migratoryBirds([1, 2, 3, 4, 5, 4, 3, 2, 1, 3, 4]) # Testing
I am a new entry too in python!
I solved like that...maybe this was not the scope of the exercise and probably this will be the worst code you have ever seen running...but it runs! :D
arr=[1,2,3,4,5,4,3,2,1,3,4]
import pandas as pd
a=pd.Series(arr)
x=a.value_counts()==a.value_counts().max()
print( x[x].tail(1).index[0] )

Gale-Shapley Algorithm Stability Test

I'm a beginner in python coding and am trying to figure out how to test the stability of the Gale-Shapley Algorithm. I understand that for a stable pairing to be made, this means that there's no situation whereby there's 2 people who prefers each other over their assigned partner.
The data of participants' preferences is as follows:
preference = [["boy1",1,3,2,4], ["boy2",1,2,4,3],["boy3",1,2,3,4],["boy4",2,3,1,4],["girl1",2,1,3,4],["girl2",4,3,2,1],["girl3",1,2,3,4],["girl4",3,4,2,1]]
For example, for preference[0], boy1's ranking for girl1 is 1, girl2 is 3, girl3 is 2, girl 4 is 4. This means that the list goes: ["boy1", (ranking of girl1), (ranking of girl2), (ranking of girl3), (ranking of girl 4)].
An example of a solution of pairings is as follows:
solution1 = [["boy1","girl1"],["boy2","girl3"],["boy3","girl2"],["boy4","girl4"]
I'm trying to come up with a function that produces true if solution is stable and false if the solution isn't stable, given the preference, solution and number of couples.
I've tried using pandas and numpy but I keep getting stuck with many for loops and if and problems with indexing as I'm not very familiar with any of these python libraries. I'm now trying to go back to basic and see if it's possible to do it. However, as I'm doing it, I realize that I kept using for loops and it won't be as efficient. Below is my incomplete code, please do advise on what I should do to improve the efficiency of this incomplete code - and if it's possible to execute my current incomplete code once it's complete. Please do suggest any python libraries that I can use too, any suggestions are greatly appreciated!
def teststability(n, preference, solution):
for i in solution[i]:
fpo = solution[i][1][1]
for j in preference[j]:
if solution[i][0] == preference[j][0]:
rank = preference[j][fpo]
if rank == 1:
continue
else:
for k in pref[j][k]:
if pref[j][k] < rank:
lst.append("girl"+str(k))
else:
continue
You don't Pandas or Numpy for this, as it's a classic algorithmic SAT problem, and not one of data. (If you need to apply a given solution algorithm to a large array of pairs, then Pandas might be useful.)
The algorithm is implemented in the QuantEcon/MatchingMarkets package.
Lastly, I'd note that it's a little confusing that you're using lists made of strings and integers. I'd suggest dict of male-to-female and female-to-male preferences, eg:
female_prefs = {1: [2, 1, 3, 4], 2: [4, 3, 2, 1], 3: [1, 2, 3, 4], 4: [3, 4, 2, 1]}

Given list of integers,remove odd positions of the list(starting from position 1(index 0) until the list contains a single element in minimum time

I'm given a list of numbers,I need to remove the odd positions of the list until my list contains a single number
Given list: (0,1,1,2,3,5,8,3,1)
Explanation:(1,2,5,3)
(2,3)
(3)
Answer:3
Constraint:1 ≤ No. of elements of the list ≤ 10^18
I've tried to find the solution using slicing in loop but as the no. of elements can vary from 1 to 10^18 it will take a lot of time to complete the operation.Therefore I'm searching for an optimized solution.
while(len(R)>1):
R=R[1::2]
print(R[0])
The output was as expected but takes a lot of time to execute when the no. of elements is increased.So searching for an optimized solution.
You can do it without looping.
l = [0, 1, 1, 2, 3, 5, 8, 3, 1,2,3]
import math
i=2**math.floor(math.log(len(l),2))
ans=l[i-1]
print(ans)
This answer was accepted before it was correct, credit goes to #rahul verma for pointing out the answer was a bit more complex. The answer previously gave a solution that only works in specific cases.
If the required answer is only the final element in the last list with a single element, then computing what the index of the element would be in the original list is far more efficient than actually processing the lists.
In this case, the result is the element at the index equal to the largest power of two that's equal to or smaller than the length of the list, minus one (since a list starts at index 0).
import math
l = [0, 1, 1, 2, 3, 5, 8, 3, 1]
result = l[2**math.floor(math.log(len(l), 2))-1]
print(result)
math.log(x, 2) gets you the number you need to raise 2 to to get x, math.floor gets you the integer part of that number, 2**x raises 2 to the power of x and one is subtracted to get the correct element from the list.
If you really need to find the fastest solution using intermediate lists, or if all the lists have to be given as part of the actual answer, then I think you've already found a fairly optimal solution. Except that you're overwriting previous results with each iteration, so it seems you're not really after this.
Possibly, you could improve performance by changing the list into a more efficient type of array (built-in or numpy for example), manipulating that for the intermediate results and returning those. But if you need to return lists, that won't be much better as the conversion to and from that datatype will add cost that will likely eliminate the advantage of a faster selection.

Optimizing generating a list of sums in Python

I am attempting to use Python for the following task: given a set of integers S, produce S + S, the set of integers expressible as s1 + s2 for s1, s2 members of S (not necessarily distinct).
I am using the following code:
def sumList(l):
# generates a list of numbers which are sums of two elements of l
sumL = []
howlong = len(l)
for i in range(howlong):
for j in range(i+1):
if not l[i]+l[j] in sumL:
sumL.append(l[i]+l[j])
return sumL
This works fine for short enough lists, but when handed a longer list (say, 5000 elements between 0 and 20000) goes incredibly slowly (20+ minutes).
Question: what is making this slow? My guess is that asking whether the sum is already a member of the list is taking some time, but I am a relative newcomer to both Python and programming, so I am not sure. I am also looking for suggestions on how to perform the task of producing S + S in a quick fashion.
Python has a built-in type set that has very fast lookups. You can't store duplicates or unhashable objects in a set, but since you want a set of integers, it's perfect for your needs. In the below, I also use itertools.product to generate the pairs.
from itertools import product
def sums(l):
return {x+y for x, y in product(l, repeat=2)}
print(sums([1, 2, 3, 4]))
# {2, 3, 4, 5, 6, 7, 8}
As to why your existing solution is so slow, you might want to look up the term "algorithmic complexity". Basically, it's a way of categorizing algorithms into general groups based on how well they scale to many inputs. Your algorithm is a O(n^3) algorithm (it will do about n^3 comparisons). In comparison, the set solution is O(n^2). It accomplished this by discarding the need to check if a particular sum is already in the set.

Python: graph redundant nodes (without Networkx)

We've been given standard beginner's python problem as a homework exercise, but my research into it shows people always use Networkx to solve these graph type node problems, whereas we're not allowed to use the Networkx built-in to solve it. I'm hoping for advice on a nice way to tackle this please.
There are five nodes (named 1,2,3,4,5) and the order is this:
1 goes nowhere
2 only goes to 1
3 goes to 1 and 5 (but 5 is closer which makes the 3 to 1 path redundant)
4 goes to 1 and 2 (but 2 is closer so 4-1 is redundant)
5 goes to 2
This is the example data to read in (note this is just one data set - it has to work with other pairs too):
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)', 'R(3,1)', 'R(4,1)']
This is the non-redundant pair output:
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)']
My attempt so far has been to split into two lists for start node and end node:
start_value = []
end_value = []
for i in range(len(partial_order)):
start_value.append(int(partial_order[i][2]))
for i in range(len(partial_order)):
end_value.append(int(partial_order[i][4]))
dictionary = dict(zip(start_value, end_value))
Output:
[3, 4, 5, 2, 3, 4]
[5, 2, 2, 1, 1, 1]
{3: 1, 4: 1, 5: 2, 2: 1}
I thought if I put it into a dictionary, I can try something from there, but my dictionary only shows 3:1 instead of 3:[1,5]. It is the 3-5 pair that I need to keep since it is closer, so 3-1 is redundant. Thanks for any tips on how to progress without Networkx.
This is one of pages I was reading - I'm trying to set up graph dictionary like that so I can try out their find_shortest_path function, to see if that gives me a solution.
https://www.python.org/doc/essays/graphs/
UPDATE:
I ended up abandoning the dictionary idea and zipping the two lists together then performed a whole bunch of if statements to get it working.
But I really would like to hear anyone's solution for something more Pythonic (so long as it doesn't use packages like Networkx). Happy coding.

Categories

Resources