Check if an Integer Array can be Equalized using Recursion in Python - python

Given an integer array of size 5 with arbitrary positive values and m, I am tasked to create a program that will check if it is possible to equalize this array (all integers are equal) with the following process:
With m being the current position, it will jump to another integer, and by jumping, the integer in that position gets reduced based of the distance from this integer's position from m.
Example: [2, 2, 4, 2, 2] with m = 0 (first position)
we jump to the third position to equalize the integer array, that means 4 minus (distance from current position to 4)
v (m = 0)
[2, 2, 4, 2, 2]
v jump to index 2 (3rd position)
[2, 2, (4 - abs(2-0)), 2, 2]
= [2, 2, 2, 2, 2] (all integer is equal)
since there is a way to equalize the array, return True.
Integers in the array must only be positive. If there is no possible way to equalize the array, return False.
I managed to make a code but it's not working for the hidden cases (this is a problem from our school).
def canEqual(array, m):
if min(array) == max(array): return True # Array can be Equalized, Return True
for integer in array:
if integer < 1: return False # If there is an integer in the array
# less than 1, then return False since
# it cannot be.
for index, integer in enumerate(array): # Treats the min value in the array as the
if integer > min(array) and index != m: # basis for equalizing. If an element is greater
temp = array[:] # than the minimum, the program will jump to this position
temp[index] = integer-abs(m-index) # and the cycle continues until either the array
# is equalized or there exists a non positive integer.
if canEqual(temp, index): return canEqual(temp, index)
I'm not really sure if my approach to this problem is correct.

Take a look at that (and try to understand it better by investigate it), uncomment the two prints to understand better the process, and ask for clarifications if something not make sense to you.
def canEqual(cur_arr, m):
if min(cur_arr) < 0:
return False
if min(cur_arr) == max(cur_arr):
return True
else:
for iter, item in enumerate(cur_arr):
if iter!=m:
cur_arr[iter] = cur_arr[iter]-abs(m-iter)
# print(iter)
# print(cur_arr)
if canEqual(cur_arr, iter):
return True
else:
cur_arr[iter] = cur_arr[iter]+abs(m-iter)
return False
print(canEqual([2, 2, 4, 2, 2], 2))
output:
True

Related

How to use recursion to sum up a list of numbers up until a certain index

I have to write a code that makes use of recursion to sum numbers in a list up until the index is equal to a pre-determined integer value. i.e.
list = [1,4,8,9]
int = 2
sum = 1 + 4 (index 0 and 1)
below is my code so far, but I am struggling with the logic with my first if statement and hence it isn't working. I get the error 'int' object has no attribute 'index' Any help would be greatly appreciated (PS very new to coding - so sorry if my code isn't the best)!
# Sum Recursion
def Arecursion(Alist,index):
if index > 0: # if the index point in the list matches the integer return the sum
return Alist[index] + Arecursion(Alist,index-1)
else:
return 0
list_test = [1,4,6,7,10]
int_test = 2
print(Arecursion(list_test,int_test))
You are making it more complex that you need to. You just need a base case — the current index is too big, and the recursion — the value at the current index plus the rest:
def sum_rec(l,max_index, i=0):
if i >= max_index or i >= len(l): # base case
return 0
return l[i] + sum_rec(l, max_index, i+1) # recursion
sum_rec([1, 2, 3, 4], 0)
# 0
sum_rec([1, 2, 3, 4], 1)
# 1
sum_rec([1, 2, 3, 4], 2)
# 3
sum_rec([1, 2, 3, 4], 3)
#6

Finding the minimum difference between two elements with recursion

I'm trying to make a "shortest distance algorithm for 1D".
However, I'm confused on the recursive case. I don't know how to get the value back after the recursive calls (lines 14 and 15). How can I fix the following code?
def recCPairDist(points):
if len(points) == 1:
return 0
elif len(points)== 2:
abs(points[1]-points[0])
#how do i assign the result final value back to "leftDist rightDist"
#since its a recurisive, the result can be more than 1, should i store all the result in a list first?
#then get the min(list)?
else:
mid = len(points) // 2
first_half = points[:mid]
second_half = points[mid:]
leftDist = recCPairDist(first_half)
rightDist = recCPairDist(second_half)
midDist = abs(second_half[0] - first_half[1]) #i dont think this is correct since i didnt consider the recursion
return min(leftDist,rightDist,midDist)
def cPairDist(points):
points.sort()
return recCPairDist(points)
P1 = [7, 4, 12, 14, 2, 10, 16, 6]
cPairDist(P1)
The expected result for P1 should be 1, since the shortest distance would be between 7 and 6.
You're really close! There's three things you have to do:
For the case where there's only one point to consider, you should not return 0. For example, for the array [3, 6, 9], the answer is 3, but your given base case will return 0. This is because one of the resulting subarrays will be of length 1 for odd-length arrays, and the zero return value will propagate when you return from each recursive call.
You need to return the value abs(points[1]-points[0]) in the len == 2 base case explicitly using the return keyword.
For your recursive case, the minimum difference must be between two consecutive elements in the left half, two consecutive elements in the right half, or between the last element of the first half and the first element of the second half (two consecutive elements in the original array, but not covered in the two recursive cases). So, your midDist should compute this value.
Here is a code snippet that resolves all three of these issues:
def recCPairDist(points):
if len(points) == 1:
return float('inf')
elif len(points)== 2:
return abs(points[1]-points[0])
else:
mid = len(points) // 2
first_half = points[:mid]
second_half = points[mid:]
leftDist = recCPairDist(first_half)
rightDist = recCPairDist(second_half)
midDist = abs(first_half[-1] - second_half[0])
return min(leftDist,rightDist,midDist)

How to calculate numbers of "uninterrupted" repeats in an array in python?

I have a 0,1 numpy array like this:
[0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0]
I want to have a function that tells me number 1 is repeated 3,2,4 times in this array, respectively. Is there a simple numpy function for this?
This is one way to do it to find first the clusters and then get their frequency using Counter. The first part is inspired from this answer for 2d arrays. I added the second Counter part to get the desired answer.
If you find the linked original answer helpful, please visit it and upvote it.
from scipy.ndimage import measurements
from collections import Counter
arr = np.array([0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0])
cluster, freq = measurements.label(arr)
print (list(Counter(cluster).values())[1:])
# [3, 2, 4]
Assume you only have 0s and 1s:
import numpy as np
a = np.array([0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0])
# pad a with 0 at both sides for edge cases when a starts or ends with 1
d = np.diff(np.pad(a, pad_width=1, mode='constant'))
# subtract indices when value changes from 0 to 1 from indices where value changes from 1 to 0
np.flatnonzero(d == -1) - np.flatnonzero(d == 1)
# array([3, 2, 4])
A custom implementation?
def count_consecutives(predicate, iterable):
tmp = []
for e in iterable:
if predicate(e): tmp.append(e)
else:
if len(tmp) > 0: yield(len(tmp)) # > 1 if you want at least two consecutive
tmp = []
if len(tmp) > 0: yield(len(tmp)) # > 1 if you want at least two consecutive
So you can:
array = [0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0]
(count_consecutives(lambda x: x == 0, array)
#=> [3, 2, 4]
And also:
array = [0,0,0,1,2,3,0,0,3,2,1,0,0,1,11,10,10,0,0,100]
count_consecutives(lambda x: x > 1, array)
# => [2, 2, 3, 1]

Function to Create a Zigzag Array in Python

I'm trying to create an array of positive and negative integers, representing distances north and south of a location - I need to see the elements of the array in zigzag order.
This means that the largest member appears first, the smallest member appears second, and the remaining elements alternate between the larger members decreasing from the largest and the smaller members increasing from the smallest.
I.e. the array [1, 3, 6, 9, -3] becomes [9, -3, 6, 1, 3].
I'm trying to complete the function wiggleArrangeArray, which takes one argument, an integer array of n integers.
Required Input Format, Constraints, and Output Format
I'm not sure how to say
"if the item in the array is larger than the other items in the array, display it first."
"if the item is smaller than the other items in the array, display it second."
"then alternate between the next largest numbers, and the next smallest numbers"
def wiggleArrangeArray(intArr):
for i in intArr
#if i > other items in intArr
#display that i at index value 0
#if i < other items in intArr
#display that i at index value 1
#if i < i at index value 0 and > other items in intArr, display it next
#if i > i at index value 1 and < other items in intArr, display it next
#repeat last two lines for continuing values
Please help if possible. Here's a link to the solution in C++ but I need it in Python. Thanks.
Edit: The function needs to work with the following tests:
f = open(os.environ["OUTPUT_PATH"], "w")
_intArr_cnt = int(raw_input())
_intArr_i=0
_intARR = []
while _intArr_i < _intArr_cnt:
_intArr_item = int(raw_input());
_intArr.append(_intArr_item)
_intArr_i+=1
res = wiggleArrangeArray(_intArr);
for res_cur in res:
f.write( str(res_cur) + "\n" )
f.close()
The altered C++ code
Note the algorithm you provided does calculate some sort of zigzag, but it is not the zigzag you are looking for. For future reference I will leave it here.
In the C++ code you provided, they only look for a sequences that satisfies a < b > c < d > e < f, you are looking however for a sequence with the 1-max, 1-min, 2-max, 2-min,...
Your link provides you a solution which you can copy nearly verbatim in Python. You only define a swap function:
def swap(arr,i,j):
t = arr[i]
arr[i] = arr[j]
arr[j] = t
Next you can simply modify the code:
def zigZag(arr):
n = len(arr)
# Flag true indicates relation "<" is expected,
# else ">" is expected. The first expected relation
# is "<"
flag = True
i = 0
while i<= n-2:
if (flag): # "<" relation expected
# If we have a situation like A > B > C,
# we get A > B < C by swapping B and C
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
else: # ">" relation expected
# If we have a situation like A < B < C,
# we get A < C > B by swapping B and C
if arr[i] < arr[i+1]:
swap(arr,i,i+1)
flag = not flag # flip flag
i += 1
Mind that this is rather un-Pythonic, so you can simply improve it like:
def swap(arr,i,j):
arr[i],arr[j] = arr[j],arr[i]
def zigZag(arr):
n = len(arr)
for i in range(len(arr)-1):
if not i&1:
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
elif arr[i] < arr[i+1]:
swap(arr,i,i+1)
return arr
Here tuple assignment is used to swap elements in the list, a range is used to iterate over the indices, we can furthermore use an elif instead of an if in an else, and for I've abandoned the flag by using a modulo check.
Your zigzag function
You can simply solve the problem by sorting the list, and using two pointers that each time emit the most left, the most right and walk towards each other. In other words something like:
def zigZag(arr):
srt = sorted(arr)
left = 0
right = len(srt)-1
result = []
while left < right:
result.append(srt[right])
right -= 1
if left < right:
result.append(srt[left])
left += 1
return result
Here Python implementation example.
Sort your data in reversed order (9, 6, 3, 1, -3)
Split by two lists (9, 6) (3, 1, -3)
Iterate over both (using zip_longest) first one from start, second in reverse order (9, -3), (6, 1) (None, 3)
Unpack tuples created by zip_longest (chain(*zip...)) so you get iterable data (9, -3, 6, 1, None, 3)
Remove None value in case if the list has an odd number of elements (if x is not None)
Example:
from itertools import zip_longest, chain
def zig_zag_array(data):
data = sorted(data)
mid = len(data) // 2
return [
x for x in chain(*zip_longest(data[mid:][::-1], data[:mid])) if x is not None
]
Test:
if __name__ == "__main__":
data = [1, 3, 6, 9, -3]
expected = [9, -3, 6, 1, 3]
output = zig_zag_array(data)
assert output == expected, f"Odd length: {output=}"
data = [1, 3, 6, 9, -3, 0]
expected = [9, -3, 6, 0, 3, 1]
output = zig_zag_array(data)
assert output == expected, f"Even length: {output=}"
print("PASSED")

Numpy: Truth comparison of multidimensional arrays

So I am writing a sudoku solver using a 9x9 array for the grid and a 9x9x9 array for its possibilities. Due to the backtracking algorithm I am using, I have to check whether the Sudoku is still valid, aka:
If there is a field that does not contain a number and has no possibilities left, return False.
So far I implemented that as follows:
for j in range(9):
for i in range(9):
if puzzle[j,i] == 0 and (solving[j,i] == 0).sum() == 9:
return False
return True
If the square at (j,i) contained, for example, the options 2, 3 and 7, the according possibility array would be:
solving[j,i] = array([0, 2, 3, 0, 0, 0, 7, 0, 0], dtype = int8)
I am trying to avoid such loops here and elsewhere in my solver. I tried this as follows:
solving[where(puzzle == 0)]
This returned an n x 9 array, where n is the amount of empty squares in my puzzle. I want the function to return False if any of the n arrays with shape 1x9 is exactly equal to
array([0,0,0,0,0,0,0,0,0], dtype = int8)
However, I did not have any success with various tries including .any() and .all() experiments. This is the latest code I was using:
def is_valid(self, puzzle, solving):
if (solving[py.where(puzzle == 0)].all() == 0).sum() > 0:
return False
return True
... which always returns False. What's the proper way to code this?
I think the following is the check you want to do:
np.all(puzzle | np.any(solving, axis=-1)
This returns True if all cells either have a value assigned (puzzle), or (|) have at least a non-zero entry in solving (np.any(solving, axis=-1)).

Categories

Resources