Inner String array swap - arrays

I try to swap inner string array value with none additional array, stack...etc.
Example:
s = [1,2,3,4,5,6,7,8]
output= [1,5,2,6,3,7,4,8]
My solution shows as below, but I think isn't the best solution. Can someone correct my code efficiency?
[python3]
class Solution:
def inner_number(self, s):
i=len(s)//2
index=1
while i < len(s):
for j in range(i,index,-1):
s[j-1],s[j]=s[j],s[j-1]
i+=1
index+=2
return s

s = [1,2,3,4,5,6,7,8,9]
h = len(s)//2
res= []
if len(s)%2==1:
res = [j for i in zip(s[:h],s[h:]) for j in i] + [s[-1]]
else:
res = [j for i in zip(s[:h],s[h:]) for j in i]
print(res)
# output [1, 5, 2, 6, 3, 7, 4, 8, 9]

def inner_swap(input):
req_length = int(len(input)/2) if len(input) % 2 == 0 else int(len(input)/2)+1
s1 = input[:req_length]
s2 = input[req_length:]
result = [None]*len(input)
result[::2] = s1
result[1::2] = s2
return result
assert inner_swap([1, 2, 3, 4]) == [1, 3, 2, 4]
assert inner_swap([1, 2, 3, 4, 5]) == [1, 4, 2, 5, 3]

Related

Merge Two Sorted Arrays in Python

I have two sorted arrays
array1 = [0, 3, 4, 31]
array2 = [4, 6, 30]
I try to sort these arrays by using the code below:
def mergeSortedArray(array1, array2):
if not len(array1):
return array2
if not len(array2):
return array1
mergedArray = []
array1Item = array1[0]
array2Item = array2[0]
i = 0
j = 0
while (i < len(array1)) and (j < len(array2)):
if array1Item < array2Item:
mergedArray.append(array1Item)
array1Item = array1[i + 1]
i += 1
else:
mergedArray.append(array2Item)
print(j)
array2Item = array2[j + 1]
j += 1
return mergedArray
print(mergeSortedArray([0, 3, 4, 31], [4, 6, 30]))
But the terminal keep telling me that:
line 26, in mergeSortedArray
array2Item = array2[j + 1]
IndexError: list index out of range
I wonder which part I did wrong! Can someone explain to me? plz~
BTW, what is the syntactically cleanest way to accomplish this?
Make use of Python's features, such as merging two lists with the + operator. Then, simply sort the new list.
>>> array1 = [0, 3, 4, 31]
>>> array2 = [4, 6, 30]
>>> merged_array = array1 + array2
>>> merged_array.sort()
>>> merged_array
[0, 3, 4, 4, 6, 30, 31]

how to shrink an array if two consecutive numbers in an array are equal then remove one and increment other

How to shrink an array if two consecutive numbers in an array are equal then remove one and increment other
Example 1:
int a[6]={2,2,3,4,4,4};
// Output: 6
Example 2:
int b[7]={1,2,2,2,4,2,4};
// Output: {1,3,2,4,2,4}
lst = [2,2,3,4,4,4]
def shrink(lst):
idx = 0
while len(lst) > idx+1:
a, b = lst.pop(idx), lst.pop(idx)
if a == b:
lst.insert(idx, a+1)
idx = 0
else:
lst.insert(idx, b)
lst.insert(idx, a)
idx += 1
shrink(lst)
print(lst)
Prints:
[6]
For [5, 5, 5, 1] prints [6, 5, 1]
This can be done in near-linear time like so:
a = [2, 2, 3, 4, 4, 4]
b = [1, 2, 2, 2, 4, 2, 4]
c = [5, 5, 5, 1]
def shrink_array(a):
res = []
for i in range(1, len(a)+1):
if i < len(a) and a[i] == a[i-1]: # if equal to previous
a[i] += 1 # increment and move on
else:
if len(res) > 0 and res[-1] == a[i-1]: # if equal to last in res
res[-1] += 1 # increment last in res
else:
res.append(a[i-1]) # add to res
while len(res) > 1 and res[-1] == res[-2]: # shrink possible duplicates
res[-2] += 1
del res[-1]
return(res)
for arr in [a, b, c]:
print(shrink_array(arr))
Output:
[6]
[1, 3, 2, 4, 2, 4]
[6, 5, 1]

Merge two ordered arrays into one ordered array

I am writing a method that takes two sorted arrays and I want it to return a merged array with all the values sorted. Given the two arrays below:
array_one = [3, 4, 8]
array_two = [1, 5, 7]
I want my merge_arrays method to return:
[1, 3, 4, 5, 7, 8]
My current algorithm is below:
def merge_arrays(array_one, array_two)
merged_array_size = array_one.length + array_two.length
merged_array = []
current_index_on_one = 0
current_index_on_two = 0
current_merged_index = 0
for i in (0..merged_array_size - 1)
if array_one[current_index_on_one] < array_two[current_index_on_two]
merged_array[current_merged_index] = array_one[current_index_on_one]
current_index_on_one += 1
current_merged_index += 1
else
merged_array[current_merged_index] = array_two[current_index_on_two]
current_index_on_two += 1
current_merged_index += 1
end
end
return merged_array
end
I am getting an error 'undefined method `<' for nil:NilClass'. I don't understand how the conditional is receiving this. I debugged the variables in the conditionals and they are giving true or false values. I'm not sure what is causing this error.
Maybe I am missing the point but you can do:
(array_one + array_two).sort
=> [1, 3, 4, 5, 7, 8]
I am getting an error 'undefined method `<' for nil:NilClass'. I don't understand how the conditional is receiving this.
You start by comparing index 0 to index 0:
[3, 4, 8] [1, 5, 7]
0-----------0 #=> 3 < 1
Then you increment the lower value's index by 1:
[3, 4, 8] [1, 5, 7]
0--------------1 #=> 3 < 5
And so on:
[3, 4, 8] [1, 5, 7]
1-----------1 #=> 4 < 5
[3, 4, 8] [1, 5, 7]
2--------1 #=> 8 < 5
[3, 4, 8] [1, 5, 7]
2-----------2 #=> 8 < 7
At that point you get:
[3, 4, 8] [1, 5, 7]
2--------------3 #=> 8 < nil
Index 3 is outside the array's bounds, so array_two[current_index_on_two] returns nil and:
if array_one[current_index_on_one] < array_two[current_index_on_two]
# ...
end
becomes
if 8 < nil
# ...
end
resulting in ArgumentError(comparison of Integer with nil failed). If nil is on the left hand side, you'd get NoMethodError (undefined method `<' for nil:NilClass).
Here's one way you can write merge using recursion. Note, as you specified, both inputs must already be sorted otherwise the output will be invalid. The inputs can vary in size.
def merge (xs, ys)
if xs.empty?
ys
elsif ys.empty?
xs
else
x, *_xs = xs
y, *_ys = ys
if x < y
[x] + (merge _xs, ys)
else
[y] + (merge xs, _ys)
end
end
end
merge [ 1, 3, 4, 6, 8, 9 ], [ 0, 2, 5, 7 ]
# => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Assuming you have two sorted arrays. You need to create pipeline using recursion going to crunch through each array. checking at each iteration to see
which value at index 0 of either array is lower, removing that from the array and appending that value to the result array.
def merge_arrays(a, b)
# build a holder array that is the size of both input arrays O(n) space
result = []
# get lower head value
if a[0] < b[0]
result << a.shift
else
result << b.shift
end
# check to see if either array is empty
if a.length == 0
return result + b
elsif b.length == 0
return result + a
else
return result + merge_arrays(a, b)
end
end
> a = [3, 4, 6, 10, 11, 15]
> b = [1, 5, 8, 12, 14, 19]
> merge_arrays(a, b)
#=> [1, 3, 4, 5, 6, 8, 10, 11, 12, 14, 15, 19]
I made slight changes to your code in order to make it work. See the comments inside.
array_one = [2, 3, 4, 8, 10, 11, 12, 13, 15]
array_two = [1, 5, 6, 7, 9, 14]
def merge_arrays(array_one, array_two)
array_one, array_two = array_two, array_one if array_one.length > array_two.length # (1) swap arrays to make satement (3) work, need array_two always be the longest
merged_array_size = array_one.length + array_two.length
merged_array = []
current_index_on_one = 0
current_index_on_two = 0
current_merged_index = 0
for i in (0...merged_array_size-1) # (2) three points to avoid the error
if (!array_one[current_index_on_one].nil? && array_one[current_index_on_one] < array_two[current_index_on_two]) # (3) check also if array_one is nil
merged_array[current_merged_index] = array_one[current_index_on_one]
current_index_on_one += 1
current_merged_index += 1
else
merged_array[current_merged_index] = array_two[current_index_on_two]
current_index_on_two += 1
current_merged_index += 1
end
end
merged_array[current_merged_index] = array_one[current_index_on_one] || array_two[current_index_on_two] # (4) add the missing element at the end of the loop, looks what happen if you comment out this line
return merged_array
end
p merge_arrays(array_one, array_two)
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
The error was coming because the loop was making one step over. The solution is to stop before and insert the missing element at the end of the loop.
It works also with:
# for i in (1...merged_array_size)
# and
# for i in (1..merged_array_size-1)
# and
# (merged_array_size-1).times do
arr1 = [3, 4, 8, 9, 12]
arr2 = [1, 5, 7, 8, 13]
arr = [arr1, arr2]
idx = [0, 0]
(arr1.size + arr2.size).times.with_object([]) do |_,a|
imin = [0, 1].min_by { |i| arr[i][idx[i]] || Float::INFINITY }
a << arr[imin][idx[imin]]
idx[imin] += 1
end
#=> [1, 3, 4, 5, 7, 8, 8, 9, 12, 13]

Removing elements from an array

Problem:
I have two arrays A and B:
A = [0, 1, 2, 3]; %A will always be from 0 to N where N in this case is 3.
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = [3, 4, 5, 6];
I want to compare the first element of A to the first 3 elements of B and the second element of A to the next 4 elements of B. If the elements of A are equal I remove it from B. So in example:
if (A(1) == B(1:3))
remove A(1) from B
Similarly,
I want to compare A(2) to the next 4 elements of B i.e. to B(4:7):
if (A(2) == B(4:7))
remove A(2) from B
I want to compare A(3) to the next 5 elements of B i.e. to B(8:12)
if (A(3) == B(8:12))
remove A(3) from B
I want to compare A(4) to the next 6 elements of B i.e. to B(13:18)
if (A(4) == B(13:18))
remove A(4) from B
Note: The array weights_B determines the number of elements in B that should be respectively compared to A(1), A(2), .. , A(4)
So in the end B should have the following elements:
B = [1, 3, 9, 4, 6, 5, 9, 10, 11, 8, 1, 5, 9, 10];
Needed Solution:
Is there any way I can do this without having to hard-code the indices?
Here's a way without hard-coding:
Bw = mat2cell(B, 1, weights_B); % split into chunks
result = cell(size(Bw)); % initiallize result
for k = 1: numel(A)
result{k} = Bw{k}(Bw{k}~=A(k)); % fill each chunk of the result
end
result = [result{:}]; % concatenate into a row vector
For the sake of diversity, here's a way to do this using splitapply:
function out = q50982235
A = 0:3;
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = [3, 4, 5, 6];
a_ind = 0; % acts as a "global" variable for the inner function
G = repelem( 1:numel(weights_B), weights_B ); % this creates a vector of groups
out = cell2mat( splitapply(#movdif, B, G) );
function out = movdif(B)
a_ind = a_ind + 1;
out = {B(B ~= A(a_ind))};
end
end
The above works because the order of processed groups is predictable.
This solution requires R2015b.
Try this
A = [0, 1, 2, 3];
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = A + A(end);
border_0 = zeros(size(A));
border_1 = zeros(size(A));
border_0(1) = 1;
border_1(end) = length(B);
for i= 2:length(A)
border_0(i) = border_0(i-1) + weights_B(i-1);
border_1(i-1) = border_0(i)-1;
end
C = [];
for i= 1:length(border_0)
shift = 0;
if (i > 1)
shift = border_1(i-1);
end
C = [C B( find(B(border_0(i):border_1(i))~=A(i)) + shift )]
end
A = [0, 1];
B = [0, 1, 3, 1, 4, 5, 6];
% Split B into cells
C{1} = B(1:3) ; % this can be coded if more splits are required
C{2} = B(4:end) ;
% removing the lements
for i = 1:2
C{i}(C{i}==A(i))=[] ; % remove the elements in C{i} present in A(i)
end
cell2mat(C)
Since you want to compare the elements of A with first 3 and then 4 elements of B respectively, you would need to involve indexes.
You could simply use loop for it.
for(int i=0;i<B.length;i++){
if((A[0]==B[i])&&i<3){
B[i]=B[i+1];
}
else if((A[0]==B[i])&&i>3){}
B[i]=B[i+1];
}
Then adjust the updated size of array B.

Ruby - How do you perform an operation on each item of two (maybe more) arrays and populate them in a new array?

a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
each of array a's items are divided by each of array b's items and put into a new array called c.
c = [6, 3, 2, 2, 2]
a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
c = a.zip(b).map { |e| e.reduce :/ }
#⇒ [
# [0] 6,
# [1] 3,
# [2] 2,
# [3] 2,
# [4] 2
# ]
Array#zip zips the arrays together and then each element (array of 2 items zipped) is reduced with Integer#/.
I like mudasobwa's zip/map solution, but here are a couple alternatives:
a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
c = Array.new(a.size) { |i| a[i] / b[i] }
c = a.map.with_index { |x, i| x / b[i] }
In particular, I might prefer the Array.new solution if the arrays aren't guaranteed to be the same length, because you can easily ensure you don't go over bounds:
c = Array.new([a.size, b.size].min) { |i| a[i] / b[i] }

Resources