I am trying to write a function that will not only determine whether the sum of a subset of a set adds to a desired target number, but also to print the subset that is the solution.
Here is my code for finding whether a subset exists:
def subsetsum(array,num):
if num == 0 or num < 1:
return False
elif len(array) == 0:
return False
else:
if array[0] == num:
return True
else:
return subsetsum(array[1:],(num - array[0])) or subsetsum(array[1:],num)
How can I modify this to record the subset itself so that I can print it? Thanks in advance!
Based on your solution:
def subsetsum(array,num):
if num == 0 or num < 1:
return None
elif len(array) == 0:
return None
else:
if array[0] == num:
return [array[0]]
else:
with_v = subsetsum(array[1:],(num - array[0]))
if with_v:
return [array[0]] + with_v
else:
return subsetsum(array[1:],num)
Modification to also detect duplicates and further solutions when a match happened
def subset(array, num):
result = []
def find(arr, num, path=()):
if not arr:
return
if arr[0] == num:
result.append(path + (arr[0],))
else:
find(arr[1:], num - arr[0], path + (arr[0],))
find(arr[1:], num, path)
find(array, num)
return result
You could change your approach to do that more easily, something like:
def subsetsum(array, num):
if sum(array) == num:
return array
if len(array) > 1:
for subset in (array[:-1], array[1:]):
result = subsetsum(subset, num)
if result is not None:
return result
This will return either a valid subset or None.
Thought I'll throw another solution into the mix.
We can map each selection of a subset of the list to a (0-padded) binary number, where a 0 means not taking the member in the corresponsing position in the list, and 1 means taking it.
So masking [1, 2, 3, 4] with 0101 creates the sub-list [2, 4].
So, by generating all 0-padded binary numbers in the range between 0 and 2^LENGTH_OF_LIST, we can iterate all selections. If we use these sub-list selections as masks and sum the selection - we can know the answer.
This is how it's done:
#!/usr/bin/env python
# use a binary number (represented as string) as a mask
def mask(lst, m):
# pad number to create a valid selection mask
# according to definition in the solution laid out
m = m.zfill(len(lst))
return map(lambda x: x[0], filter(lambda x: x[1] != '0', zip(lst, m)))
def subset_sum(lst, target):
# there are 2^n binary numbers with length of the original list
for i in xrange(2**len(lst)):
# create the pick corresponsing to current number
pick = mask(lst, bin(i)[2:])
if sum(pick) == target:
return pick
return False
print subset_sum([1,2,3,4,5], 7)
Output:
[3, 4]
To return all possibilities we can use a generator instead (the only changes are in subset_sum, using yield instead of return and removing return False guard):
#!/usr/bin/env python
# use a binary number (represented as string) as a mask
def mask(lst, m):
# pad number to create a valid selection mask
# according to definition in the solution laid out
m = m.zfill(len(lst))
return map(lambda x: x[0], filter(lambda x: x[1] != '0', zip(lst, m)))
def subset_sum(lst, target):
# there are 2^n binary numbers with length of the original list
for i in xrange(2**len(lst)):
# create the pick corresponsing to current number
pick = mask(lst, bin(i)[2:])
if sum(pick) == target:
yield pick
# use 'list' to unpack the generator
print list(subset_sum([1,2,3,4,5], 7))
Output:
[[3, 4], [2, 5], [1, 2, 4]]
Note: While not padding the mask with zeros may work as well, as it will simply select members of the original list in a reverse order - I haven't checked it and didn't use it.
I didn't use it since it's less obvious (to me) what's going on with such trenary-like mask (1, 0 or nothing) and I rather have everything well defined.
Slightly updated the below code to return all possible combinations for this problem. Snippet in the thread above will not print all possible combinations when the input is given as subset([4,3,1],4)
def subset(array, num):
result = []
def find(arr, num, path=()):
if not arr:
return
if arr[0] == num:
result.append(path + (arr[0],))
else:
find(arr[1:], num - arr[0], path + (arr[0],))
find(arr[1:], num, path)
find(array, num)
return result
A bit different approach to print all subset through Recursion.
def subsetSumToK(arr,k):
if len(arr)==0:
if k == 0:
return [[]]
else:
return []
output=[]
if arr[0]<=k:
temp2=subsetSumToK(arr[1:],k-arr[0]) #Including the current element
if len(temp2)>0:
for i in range(len(temp2)):
temp2[i].insert(0,arr[0])
output.append(temp2[i])
temp1=subsetSumToK(arr[1:],k) #Excluding the current element
if len(temp1)>0:
for i in range(len(temp1)):
output.append(temp1[i])
return output
arr=[int(i) for i in input().split()]
k=int(input())
sub=subsetSumToK(arr,k)
for i in sub:
for j in range(len(i)):
if j==len(i)-1:
print(i[j])
else:
print(i[j],end=" ")
Rather than using recursion, you could use the iterative approach.
def desiredSum(array, sum):
numberOfItems = len(array)
storage = [[0 for x in range(sum + 1)] for x in range(numberOfItems + 1)]
for i in range(numberOfItems + 1):
for j in range(sum + 1):
value = array[i - 1]
if i is 0: storage[i][j] = 0
if j is 0: storage[i][j] = 1
if value <= j:
noTake = storage[i - 1][j]
take = storage[i - 1][j - value]
storage[i][j] = noTake + take
return storage[numberOfItems][sum]
Related
after I reverse my list list elements are changing not reversing properly
here is my first code
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
print(reverse_fib_series(11))
it returns [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
if I want to reverse it
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x[::-1]
print(reverse_fib_series(11))
it returns [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]. I do not know why?
i am trying to solve the following exercise:
"In Fibonacci Numbers, each number progresses as the sum of the two preceding numbers, such as 0,1,1,2,3,5,8, ... In this question you are given a number (0 <N <20). Accordingly, write the program that prints all Fibonacci numbers backwards from the Nth Fibonacci number."
This is happening because you reverse the list in each recursive call, rather than only reversing it once at the end -- so instead of summing the last two elements of the series to get the next element, you're summing the first two elements, which are always 0 and 1. That's why every element of the series after the first two becomes 1. (The list isn't changing when you reverse it at the end, the computation of the series is broken because you're reversing it each time.)
You could write the function so that it builds the series in-place from back to front, or you could fix this by simplifying the loop body to eliminate the unnecessary recursion, but this is a good opportunity to learn the concept of composing two simple things to produce one more complicated thing. :) Rather than trying to do it all at once, take the working (if sub-optimal) function you already have to produce the Fibonacci series, and then reverse it afterwards:
def fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(fib_series(i)[-2:]))
return x
def reverse_fib_series(num):
return fib_series(num)[::-1]
Note that your fib_series function can be a little simpler than what you wrote; you don't need to recursively call fib_series to get the last two numbers, because you already have them stored in x:
def fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(x[-2:]))
return x
or you could make it a little shorter by writing it as a generator:
def fib_series(num):
x = [0, 1]
x.extend(sum(x[-2::]) for _ in range(num - 2))
return x[:num]
try this code:
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
print(reverse_fib_series(11)[::-1])
reverse the return value because you use recursion in the function
Because you are reversing array inside of a recursive function. It adds one number and reverse. And it keeps repeating the process.
This code will hel
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
reversed = reverse_fib_series(11)[::-1]
print(reversed)
Just another ways, using [].insert(0, sum())
def reverse_fib_loop(n: int):
lx = []
for i in range(n):
if i > 1:
lx.insert(0, sum(lx[:2]))
else:
lx.insert(0, i)
return lx
def reverse_fib_recursion(size: int):
def wrapped(lx: list, sn: int, n: int):
if n > 0:
lx.insert(0, sn)
sn = sum(lx[:2]) if len(lx) >= 2 else 1
return wrapped(lx, sn, n-1)
return lx
return wrapped([], 0, size)
if __name__ == '__main__':
N = int(input('N='))
print(reverse_fib_loop(N))
print(reverse_fib_recursion(N))
Write a function that given an array of A of N int, returns the smallest positive(greater than 0) that does not occur in A.
I decided to approach this problem by iterating through the list after sorting it.
The value of the current element would be compared to the value of the next element. Because the list is sorted, the list should follow sequentially until the end.
However, if there is a skipped number this indicates the smallest number that does not occur in the list.
And if it follows through until the end, then you should just add one to the value of the last element.
def test():
arr = [23,26,25,24,28]
arr.sort()
l = len(arr)
if arr[-1] <= 0:
return 1
for i in range(0,l):
for j in range(1,l):
cur_val = arr[i]
next_val = arr[j]
num = cur_val + 1
if num != next_val:
return num
if num == next_val: //if completes the list with no skips
return arr[j] + 1
print(test())
I suggest that you convert to a set, and you can then efficiently test whether numbers are members of it:
def first_int_not_in_list(lst, starting_value=1):
s = set(lst)
i = starting_value
while i in s:
i += 1
return i
arr = [23,26,25,24,28]
print(first_int_not_in_list(arr)) # prints 1
You can do the following:
def minint(arr):
s=set(range(min(arr),max(arr)))-set(arr)
if len(s)>0:
return min(set(range(min(arr),max(arr)))-set(arr)) #the common case
elif 1 in arr:
return max(arr)+1 #arr is a complete range with no blanks
else:
return 1 #arr is negative numbers only
You can make use of sets to achieve your goal.
set.difference() method is same as relative complement denoted by A – B, is the set of all elements in A that are not in B.
Example:
Let A = {1, 3, 5} and B = {1, 2, 3, 4, 5, 6}. Then A - B = {2, 4, 6}.
Using isNeg() method is used to check whether given set contains any negative integer.
Using min() method on A - B returns the minimum value from set difference.
Here's the code snippet
def retMin(arrList):
min_val = min(arrList) if isNeg(arrList) else 1
seqList=list(range((min_val),abs(max(arrList))+2))
return min(list(set(seqList).difference(arrList)))
def isNeg(arr):
return(all (x > 0 for x in arr))
Input:
print(retMin([1,3,6,4,1,2]))
Output:
5
Input:
print(retMin([-2,-6,-7]))
Output:
1
Input:
print(retMin([23,25,26,28,30]))
Output:
24
Try with the following code and you should be able to solve your problem:
def test():
arr = [3,-1,23,26,25,24,28]
min_val = min(val for val in arr if val > 0)
arr.sort()
l = len(arr)
if arr[-1] <= 0:
return 1
for i in range(0,l):
if arr[i] > 0 and arr[i] <= min_val:
min_val = arr[i] + 1
return min_val
print(test())
EDIT
It seems you're searching for the the value grater than the minimum positive integer in tha array not sequentially.
The code it's just the same as before I only change min_val = 1 to:
min_val = min(val for val in arr if val > 0), so I'm using a lambda expression to get all the positive value of the array and after getting them, using the min function, I'll get the minimum of those.
You can test it here if you want
I am just getting started in Python Programming. I had a problem on checking if a given list contains alternating sequence of primes and perfect squares. The list can start with either a prime or a perfect square. I came up with a solution but it's not efficient as it generates unwanted lists. Is this possible with more efficient Python code?
First I'm creating functions to generate a list of primes as well as perfect squares up to the max value of testing list. Functions squaretest() and primecheck():
def squaretest(num):
sqlist=[]
i=1
while i**2 <= num:
sqlist.append(i**2)
i+=1
return sqlist
def primecheck(num):
primelist=[]
for i in range(2,num + 1):
for p in range(2,i):
if (i % p) == 0:
break
else:
primelist.append(i)
return primelist
Then I am dividing the given list into lists of even index and odd index elements and checking all elements of them against the primelist and the squarelist:
def primesquare(l):
if len(l)==1:
primelist = primecheck(l[0])
sqlist = squaretest(l[0])
return (l[0] in primelist) or (l[0] in sqlist)
else:
ol=[]
el=[]
for i in range(0,len(l),2):
ol.append(l[i])
for p in range (1, len(l),2):
el.append(l[p])
primelist = primecheck(max(l))
sqlist = squaretest (max(l))
return((all(x in primelist for x in el)) == True and (all(y in sqlist for y in ol)) == True) or ((all(x in primelist for x in ol)) == True and (all(y in sqlist for y in el)) == True)
It works.
Any suggestions will be really helpful.
You can use sets to check if all members of a list are in another list.
def primesquare(l):
if len(l) == 0:
return True
primelist = set(primecheck(max(l)))
sqlist = set(squaretest(max(l)))
ol = set(l[::2])
el = set(l[1::2])
odds_are_primes = ol.issubset(primelist)
odds_are_squares = ol.issubset(sqlist)
evens_are_primes = el.issubset(primelist)
evens_are_squares = el.issubset(sqlist)
return (odds_are_primes and evens_are_squares) or (odds_are_squares and evens_are_primes)
I came up with a solution but it's not efficient as it generates
unwanted lists.
Assuming the unwanted lists are the two lists representing the even and odd elements, then we can fix that. (Eliminating the primes and squares list is a whole 'nother problem.) Below is my rework of your code -- we don't create addtional lists but rather with a couple of reusable ranges which are objects that produce integer sequences as needed, but not stored in memory.
Your any() design is efficient in that the arguments are generator expressions, not lists, which are computed as needed. As soon as a flaw is found in the array, the whole thing stops and returns False--it doesn't need to process the rest:
def squares(number):
return {x * x for x in range(int(number ** 0.5) + 1)}
def primes(number):
prime_set = set()
for i in range(2, number + 1):
for p in range(2, int(i ** 0.5) + 1):
if (i % p) == 0:
break
else: # no break
prime_set.add(i)
return prime_set
def primesquare(array):
if not array:
return True # define as the problem demands
length, maximum = len(array), max(array)
odd, even = range(0, length, 2), range(1, length, 2)
prime_set, square_set = primes(maximum), squares(maximum)
return all(array[i] in prime_set for i in even) and all(array[i] in square_set for i in odd) or all(array[i] in prime_set for i in odd) and all(array[i] in square_set for i in even)
I admire #AndreySemakin's set-based solution (+1), and use sets above, but his solution generates the same lists you want to eliminate (just in the form of sets).
I came up with this solution:
def primesquare(lst):
# checking if the first element is either perfect square or a prime
if not lst or (not checksquare(lst[0]) and not checkprime(lst[0])):
return False
length = len(lst)
if length == 1:
return True
if checksquare(lst[0]):
# if first element is square then make s(quare)=2 and p(rime)=1
s, p = 2, 1
else:
# if first element is prime then make s=1 and p=2
s, p = 1, 2
# running perfect square loop from s to len-1 with gap of 2 and checking condition
for i in range(s, length, 2):
if not checksquare(lst[i]):
return False
# running prime loop from p to len-1 with gap of 2
for i in range(p, length, 2):
if not checkprime(lst[i]):
return False
return True
def checksquare(n): # function to check perfect square
if n < 0:
return False
if 0 <= n <= 1:
return True
for i in range(int(n ** 0.5) + 1):
if i * i == n:
return True
return False
def checkprime(n): # function to check prime
if n < 2:
return False
if n % 2 == 0:
return n == 2
for i in range(3, int(n ** 0.5) + 1, 2):
if n % i == 0:
return False
return True
I'm trying to run a program that finds the index of the number that is at least two times larger than all other number in the array.
Here's my code
def dominantIndex(self, nums):
max_num = max(nums)
max_i =nums.index(max_num)
if len(nums) == 1:
return nums.index(max_num)
for num in nums:
if max_num >= 2*num:
return num.index(max_num)
return -1
However , it doesn't work perfectly for all inputs. Could someone please fix it and check for inputs like :
[1,0]
[0,3,4,8]
[0,3,5,2]
This checks for many possible input problems.
Then it sorts the list to get the answer you are looking for. I decided to sort, for simplicity, but you could use other methods as well. I added comments so everything is clear, especially about the input tests, as asked.
def dominantIndex(nums):
# If the array is empty or None or not a list, return -1
if not nums or type(nums) != list:
return -1
# If the array is of length 1, return the only index, 0
elif len(nums) == 1:
return 0
sorted_numbers = sorted(nums)
# If the highest number is twice the second largest, return it's index
if sorted_numbers[-2] * 2 <= sorted_numbers[-1]:
return nums.index(sorted_numbers[-1])
else:
return -1
There actually is a library function nlargest in the heapq module.
>>> L1 = [1, 0]
>>> L2 = [0, 3, 4, 8]
>>> L3 = [0, 4, 5, 2]
>>>
>>> from heapq import nlargest
>>> def dom_ind(nums):
... a, b = nlargest(2, range(len(nums)), key=nums.__getitem__)
... return a if nums[a] >= 2 * nums[b] else -1
...
>>>
>>> dom_ind(L1)
0
>>> dom_ind(L2)
3
>>> dom_ind(L3)
-1
Use below code
def check(nums):
if len(nums) == 1:
return 0
max_num = max(nums)
ind = nums.index(max_num)
updated_array = map(lambda x: x if x != max_num else -1, nums)
if max_num >= 2*max(updated_array):
return ind
return -1
Output:
check([1,0])
0
>>> check([0,3,4,8])
3
>>> check([0,3,5,2])
-1
You can get the second highest as well;:
def dominantIndex(nums):
max_num = max(nums)
secondHighest = max( n for n in nums if n != max_num)
if max_num > 2 * secondHighest:
return nums.index(max_num)
return -1
print(dominantIndex( [1,2,39,7]))
print(dominantIndex( [1,2,3,5]))
Output:
2
-1
I'd iterate over the list and find the two largest elements. Then, if the largest element is at least twice as large as the second largest, you can return its index.
def dominantIndex(nums):
# Assumption - nums has a length of at least 2.
# Bootsrap the rist two indexes
if nums[0] > nums[1]:
max_ind = 0
next_ind = 1
else:
max_ind = 1
next_ind = 0
# Go over the rest
for i in range(2, len(nums)):
if nums[i] > nums[max_ind]:
next_ind = max_ind
max_ind = i
elif nums[i] > nums[next_ind]:
next_ind = i
if nums[max_ind] >= nums[next_ind] * 2:
retrun max_ind
return -1
I think none of the other suggested solutions works if the largest number appears multiple times in nums. This does:
def dominantIndex(self, nums):
s = sorted(nums)
if s[-1] >= 2 * s[-2]:
return nums.index(s[-1])
else:
return -1
In addition, you might want to check if nums has more than one element.
I want to define a recursive function can sort any list of ints:
def sort_l(l):
if l==[]:
return []
else:
if len(l)==1:
return [l[-1]]
elif l[0]<l[1]:
return [l[0]]+sort_l(l[1:])
else:
return sort_l(l[1:])+[l[0]]
Calling this function on a list [3, 1, 2,4,7,5,6,9,8] should give me:
[1,2,3,4,5,6,7,8,9]
But I get:
print(sort_l([3, 1, 2,4,7,5,6,9,8]))--> [1, 2, 4, 5, 6, 8, 9, 7, 3]
Please help me to fix the problem, actual code would be appreciated. Thanks!
The quick sort is recursive and easy to implement in Python:
def quick_sort(l):
if len(l) <= 1:
return l
else:
return quick_sort([e for e in l[1:] if e <= l[0]]) + [l[0]] +\
quick_sort([e for e in l[1:] if e > l[0]])
will give:
>>> quick_sort([3, 1, 2, 4, 7, 5, 6, 9, 8])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
For this you would want to use merge sort. Essentially in a merge sort you recursively split the list in half until you have single elements and than build it back up in the correct order. merge sort on has a complexity of O(n log(n)) and is an extremely stable sorting method.
Here are some good in depth explanations and visuals for merge sorting:
https://www.youtube.com/watch?v=vxENKlcs2Tw
http://www.princeton.edu/~achaney/tmve/wiki100k/docs/Merge_sort.html
def maximum(lis):
if len(lis) == 1:
return lis[0]
return maximum(lis[1:]) if lis[0] < lis[1] else maximum(lis[:1] + lis[2:])
def sorter(lis):
if len(lis) == 1:
return lis
x = maximum(lis)
lis.remove(x)
return sorter(lis) + [x]
with functional programming:
sor = lambda lis: lis if len(lis) == 1 else [lis.pop(lis.index(reduce(lambda x, y: x if x > y else y, lis)))] + sor(lis)
def quicksort(lst):
"Quicksort over a list-like sequence"
if len(lst) == 0:
return lst
pivot = lst[0]
pivots = [x for x in lst if x == pivot]
small = quicksort([x for x in lst if x < pivot])
large = quicksort([x for x in lst if x > pivot])
return small + pivots + large
Above is a more readable recursive implementation of Quick Sort Algorithm. Above piece of code is from book Functional programing in python by O'REILLY.
Above function will produce.
list=[9,8,7,6,5,4]
quicksort(list)
>>[4,5,6,7,8,9]
def sort(array, index = 0, bigNumber = 0):
if len(array) == index:
return array
elif bigNumber > array[index]:
array[index - 1] = array[index]
array[index] = bigNumber
bigNumber = array[0]
index = 0
else:
bigNumber = array[index]
return sort(array, (index + 1), bigNumber)
#sort an int list using recursion
global array
array=[5,3,8,4,2,6,1]
def sort1(array:[])->[]:
if len(array)==1:
return
temp=array[-1]
array.pop()
sort1(array)
sort2(array,temp)
def sort2(array:[],temp):
if len(array)==0 or temp>=array[-1]:
array.append(temp)
return
a=array[-1]
array.pop()
sort2(array,temp)
array.append(a)
sort1(array)
print(array)
Here i am explaining recursive approach to sort a list. we can follow "Induction Base-condition Hypothesis" recursion approach. so basically we consider our hypothesis here sort_l(nums) function which sorts for given list and Base condition will be found when we have singly number list available which is already sorted. Now in induction step, we insert the temp element (last element of list) in the correct position of given list.
example-
sort_l([1,5,0,2]) will make below recursively call
sort_l([1]) <-- 5 (here you need to insert 5 in correct position)
sort_l([1,5]) <-- 0 (here you need to insert 0 in correct position)
sort_l([0,1,5]) <-- 2 (here you need to insert 2 in correct position)
sort_l([0,1,5,2]) Finally it will be in sorted list.
====== Below is working code=======
def insert_element(nums, temp):
if len(nums) == 1:
if nums[0] > temp:
nums.insert(0, temp)
elif nums[0] < temp:
nums.append(temp)
else:
for i in range(len(nums)):
if nums[i] > temp:
nums.insert(i, temp)
break
if nums[-1] < temp:
nums.append(temp)
def sort_l(nums): ## hypothesis
if len(nums)==1: ## base condition
return nums
temp = nums[-1]
nums.pop()
sort_l(nums)
insert_element(nums, temp) ## induction
return nums
This is a complementary answer since both quicksort and complexity are already covered in previous answers. Although, I believe an easy-to-get sort function that covers Python's identity is missing*.
def sort(xs: list) -> list:
if not xs:
return xs
else:
xs.remove(num := min(xs))
return [num] + sort(xs)
[*] Python is a (slow) interpreted language, but it has become famous because of its readability and easiness to learn. It doesn't really "reward" its developers for using immutable objects nor it is a language that should be used for computation intensive applications
This is a recursive solution. For an explanation, refer to this video:
arr = [3,1,2,4,7,5,6,9,8]
def insert_fn(arr, temp): # Hypothesis
if len(arr) == 0 or arr[-1] <= temp: # Base - condition
arr.append(temp)
return arr
# Induction
val = arr[-1]
arr.pop()
insert_fn(arr, temp) # Call function on a smaller input.
arr.append(val) # Induction step
return arr
def sort_fn(arr): # Hypothesis
if len(arr) == 1: # Base - condition
return arr
# Induction
val = arr[-1]
arr.pop()
sort_fn(arr) # Call function on a smaller input.
insert_fn(arr, val) # Induction step
return arr
print(sort_fn(arr))