Trying to write a solution to re-order an array without using sort() - arrays

I feel like I'm close but not quite sure why my while loop stops executing, I want it to run/ increase the counter then the conditions are true, then when it runs into numbers out of order, swap them, then decrease the counter, then run the while loop again until all the numbers are in order. So like it slides the number that's out of order backwards until it's higher than the number before it but lower than then number after it. If that makes sense.Probably an easy one for most of you but I'm just new to python. Here is my code so far;
arr = [7, 14, 21, 32, 17, 48, 69, 78, 72]
count = 0
while (count < len(arr) - 1) and (arr[count] < arr[count+1]):
count += 1
if (arr[count] > arr[count+1]):
arr[count], arr[count+1] = arr[count+1], arr[count]
count -= 1
continue
print(count)
print(arr)
below my code with some pseudocode to make it clearer.
# list of numbers out of order
arr = [7, 14, 21, 32, 17, 48, 69, 78, 72]
# first position in index
count = 0
# loop to check first if value of index position is less than length of array -1 (9-1 = 8)
# or if value of index position is less than index position + 1 (next index position)
while (count < len(arr) - 1) and (arr[count] < arr[count+1]):
# if true loop should continue + 1 on the next index
count += 1
# if the value of number in the current index position is greater than the next number it swaps them.
if (arr[count] > arr[count+1]):
arr[count], arr[count+1] = arr[count+1], arr[count]
count -= 1
continue
print(count)
print(arr)
I've tried various different things, I think I'm just stuck on how while loops actually work and I need to get the loop to run again after it hits it's first false statement.

This would work in the way that is required in the question:
finds the first two numbers that are out of order.
switched those numbers only and exit.
arr = [7, 14, 21, 32, 17, 48, 69, 78, 72]
for i, v in enumerate(arr):
if i == len(arr) -1:
print('reached the end')
break
if v > arr[i+1]:
print('out of order index', i, 'value:',v)
# do the switch
arr[i], arr[i+1] = arr[i+1], v
break
print(arr)
the result is this:
out of order index 3 value: 32
[7, 14, 21, 17, 32, 48, 69, 78, 72]
You could also achieve the same with a while loop so long as a break condition existed.

Related

how can i multiply each index of a list by the next?

So, I have this array:
numbers = [5, 9, 3, 19, 70, 8, 100, 2, 35, 27]
What I want to do is to create another array from this one, but now each value of this new array must be equal to the corresponding value
in the numbers array multiplied by the following.
For example: the first value of the new array should be 45, as it is the multiplication
of 5 (first value) and 9 (next value). The second value of the new array should be 27, as it is the multiplication of 9 (second
value) and 3 (next value), and so on. If there is no next value, the multiplication must be done by 2.
So, this array numbers should result in this other array: [45, 27, 57 ,1330, 560, 800, 200, 70, 945, 54]
I only managed to get to this code, but I'm having problems with index:
numbers = [5,9,3,19,70,8,100,2,35,27]
new_array = []
x = 0
while x <= 8: # Only got it to work until 8 and not the entire index of the array
new_array.append(numbers[x] * numbers[x + 1])
x += 1
print(new_array)
How can I make it work no matter what is index of the array and then if there's no next number, multiply it by 2? I've tried everything but this was the closest I could get.
Try:
numbers = [5, 9, 3, 19, 70, 8, 100, 2, 35, 27]
out = [a * b for a, b in zip(numbers, numbers[1:] + [2])]
print(out)
Prints:
[45, 27, 57, 1330, 560, 800, 200, 70, 945, 54]
Andrej Kesely's approach is totally fine and would be the way to go for an experienced python developer.
But I assume you are kind of new to python, so here is a more simple approach if you are a bit familiar with other programming languages:
#function called multiply, taking an int[], returns int[]
def multiply(values):
newData = []
valuesLength = len(values) - 1
for i in range(valuesLength):
newData.append(values[i] * values[i+1])
newData.append(values[valuesLength] * 2)
return newData
#init int[], calling multiply-function and printing the data
numbers = [5,9,3,19,70,8,100,2,35,27]
newData = multiply(numbers)
print(newData)
The multiply-Function basically initiates an empty array, then loops over the passed values, multiplying them with the following value, leaves the loop one value too early and finally adds the last value by multiplying it with 2.
With the same approach as you did, making use of len(numbers):
numbers = [5,9,3,19,70,8,100,2,35,27]
new_array = []
x = 0
while x < len(numbers):
nxt = 2 if x+1 >= len(numbers) else numbers[x+1]
new_array.append(numbers[x] * nxt)
x += 1
print(new_array)
NOTE: The shorthand for nxt = 2.... is explained in the first comment of this answer: https://stackoverflow.com/a/14461963/724039

How to make sum of each value of list

# List_values = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
# Example :
# 21 = 1+2+3+4+5+6
# 27 = 2+3+4+5+6+7
# 33 = 3+4+5+6+7+8
# 39 = 4+5+6+7+8+9
# Output = [21,27,33,39,45,51,57,63,69,75] # till 10 times
I am trying to make the sum of 0 index value to Nth index and then skip first index value(1) and start making sum from second index value(2) to Nth index value
Do you want this? -
n = 5 # specify the value of n
result = [sum(l[i:(i+n+1)]) for i in range(len(l)-n)][:10]
print(result)
Here, the idea is to evaluate the sum of 5 elements at a time and then take the top 10 elements from the list.
[21, 27, 33, 39, 45, 51, 57, 63, 69, 75]
I think you will need at least one loop for iterating over the list.
Below is my approach to your problem:
# creating a list
list1 = [1, 2, 3, 4, 5]
for i in range(len(list1)):
sm = sum(list1[i:len(list1)]) # Sum of 'a' from 0th index to 4th index. sum(a) == sum(a[0:len(a)]
print(sm)

Swap elements in array if the next is bigger then current

I want change order in arr if the next element is bigger than current.
Hot to modify the code, so it will be work?
arr = [5, 22, 29, 39, 19, 51, 78, 96, 84]
i = 0
while (i < arr.size-1)
if arr[i].to_i < arr[i+1].to_i
arr[i]
elsif arr[i].to_i > arr[i + 1].to_i
arr[i+1], arr[i] = arr[i], arr[i+1]
end
puts arr[i]
i += 1
end
Returns: [5, 22, 29, 39, 19, 51, 78, 96, 84]
Instead: [5, 19, 22, 29, 39, 51, 78, 84, 96]
You can use any of sorting algorithms depending on the size of array (n),
For Bubble Sort, Time Complexity is O(n^2)
For Merge Sort, Time Complexity is O(nlogn)
For Counting Sort, Time Complexity is O(n) but number in array must be 0.upto 10^6
Bubble Sort: It runs pairwise in one iteration and put the maximum element in last, In second iteration, put the second maximum element in second last position and so on till array is sorted.
Iterate (n-1) times [to find (n-1) max numbers]
Iterate (n-idx-1) times to swap pair of numbers if (first number is
greater than next number)
If swapping stopped in inner loop means that array becomes sorted,
so break the outer loop
Ruby Code:
def bubble_sort(arr)
n = arr.size
(n-1).times do |idx|
swapped = false
(n-idx-1).times do |i|
if arr[i] > arr[i+1]
arr[i], arr[i+1] = arr[i+1], arr[i]
swapped = true
end
end
break unless swapped
end
arr
end
p bubble_sort([5, 22, 29, 39, 19, 51, 78, 96, 84])
Merge Sort: It runs on divide and conquer strategy, i.e if you know two halves of array is sorted then you can sort whole array by using two pointer strategy in O(n).
For Instance,
#first half : [4,5,7,9]
#second half : [1,2,10,15]
1. Take two pointer l and r assigned to starting index of both halves i.e 0
2. Iterate over l and r upto their lengths to consume both arrays
if element at first_half[l] < second_half[r]
Put first_half[l] in result_array
Increment l pointer
else
Put second_half[r] in result_array
Increment r pointer
This merge operation will take O(n) to sort whole array.
Now, if we divide whole array into two halves recursively, we will get binary tree of height log(n) and each level will take O(n) to sort the subproblems (halves), resulting in O(nlogn) Time Complexity.
Base case would be : single element array is always sorted
Ruby Code:
def merge(left_sorted, right_sorted)
res = []
left_size, right_size = left_sorted.size, right_sorted.size
l = r = 0
loop do
break if r == right_size and l == left_size # break if both halves processed
if r == right_size or (l < left_size and left_sorted[l] < right_sorted[r])
res << left_sorted[l]; l += 1
else
res << right_sorted[r]; r += 1
end
end
res
end
def merge_sort(arr)
size = arr.size
return arr if size <= 1 # base case
mid = arr.size/2 - 1
left_half, right_half = arr[0..mid], arr[mid+1..-1]
left_sorted = merge_sort(left_half)
right_sorted = merge_sort(right_half)
return merge(left_sorted, right_sorted)
end
p merge_sort([5, 22, 29, 39, 19, 51, 78, 96, 84])
Counting Sort: It works in O(n) by counting numbers appearance in array if numbers in array lies in range(0..10^6)
Keep count of each number of array in count_array.
Iterate from min_element to max_element of array, and put element in
sorted_array if appeared i.e its count > 0
Ruby Code:
def counting_sort(arr)
min, max = arr.min, arr.max
count_arr = [0] * (max - min + 1) # initialize count_array with all 0s
arr.each do |num|
count_arr[num - min] += 1
end
res = []
size = count_arr.size
size.times do |i|
count_arr[i].times do
res << i + min
end
end
res
end
p counting_sort([5, 22, 29, 39, 19, 51, 78, 96, 84])
Notice that as you sort you are rearranging the array. Don't modify it, use it as a reference and place the sorted items in a new array.
If you want to study algotirthms use C or C++.
def bubble_sort(array)
sorted = array.dup
i = 0
l = sorted.length
while i < (l - 1)
j = 0
while j < l - i - 1
if sorted[j] > sorted[j + 1]
tmp = sorted[j]
sorted[j] = sorted[j + 1]
sorted[j + 1] = tmp
end
j += 1
end
i += 1
end
sorted
end
puts bubble_sort([5, 22, 29, 39, 19, 51, 78, 96, 84])

How do I compare elements of separate arrays at specific indexes?

I have two arrays, I want to return the larger number from the same position in each array.
def get_larger_numbers(a, b)
c = []
count = 0
while count < 10 #assumes there are less than 10 elements in an array, not an ideal solution.
if a[count] > b[count]
c << a[count]
elsif b[count] > a[count]
c << b[count]
else #if numbers are the same
c << a[count]
end
count+= 1
end
return c
end
a = [13, 64, 15, 17, 88]
b = [23, 14, 53, 17, 80]
should return:
c == [23, 64, 53, 17, 88]
Clearly, my code doesn't work, what's the best way to refer to increasing index positions?
Also interested to know simpler ways of doing this.
Your code isn't working because of the static 10 you have as the length. Instead I suggest you make your code more dynamic with regards to how often you loop.
def get_larger_numbers(a,b)
c = []
[a.length, b.length].min.times do |i|
if a[i] > b[i]
c << a[i]
else
c << b[i]
end
end
c
end
a = [13, 64, 15, 17, 88]
b = [23, 14, 53, 17, 80]
get_larger_numbers(a,b)
#=> [23, 64, 53, 17, 88]
This solution assumes that if the arrays are not equal size, you want to throw the rest away.
Okay... Here's what you should do:
def get_larger_numbers(a, b)
c = [] #declare empty array for answer
for i in 0...(a.length < b.length ? a.length : b.length) #see EDIT note
c << (a[i] > b[i] ? a[i] : b[i])
end
c #this is an implicit return
end
a = [13, 64, 15, 17, 88]
b = [23, 14, 53, 17, 80]
puts get_larger_numbers(a,b)
This'll do a for loop that'll run from 0 to the length of a. Yes, it assumes that they're the same length. I figure this is what you want.
Anyway, there's a simple ternary that compares the value of each element in both arrays, one index at a time.
It'll push the bigger value to the c array, leaving you with the greater values in the c array to be returned.
EDIT: Added the ternary expression so that for loops through only the smaller array, because comparing with nil (which is what is at any n index beyond the array, presumably) would raise an error.
A compact solution would be:
def get_larger_numbers(a, b)
return a.zip(b).map{|x, y| (x >= y) ? x : y } # Return optional, added for clarity
end
a = [13, 64, 15, 17, 88]
b = [23, 14, 53, 17, 80]
p get_larger_numbers(a, b)
Note that this assumes the input arrays are of the same length. If arrays are of unequal length, you can truncate to the length of the shorter array, or pad the end with the unpaired elements of the larger array. The current code will throw an error, letting you know you've hit this unspecified case.
As for how it works, the zip pairs the elements of the two arrays, so a.zip(b) becomes:
[[13, 23], [64, 14], [15, 53], [17, 17], [88, 80]]
It then loops over the array with map to produce a new array, passing each pair into the block, which returns the larger of the two elements to fill the output array.
Assuming the two arrays are the same size, simply:
def largest_by_position(a,b)
a.zip(b).map(&:max)
end
largest_by_position([13, 64, 15, 17, 88], [23, 14, 53, 17, 80])
#=> [23, 64, 53, 17, 88]
Alternatively, make the operative line:
[a,b].transpose.map(&:max)
For equal-size arrays a and b, Enumerable#zip and Array#transpose always have this yin and yang relationship:
a.zip(b) == [a,b].transpose #=> true

Calculate number of elements to be evaluated

This is a logical Question which is not bound to any specific language.
Does someone know a way on how to achieve the following?
I do have an array of which I can always evaluate a max of 10 elements.
So if the size of the array grows higher than 10, I need to determine which element I can evaluate - equally distributed.
Example:
[87, 34, 65, 23, 98, 45, 21, 54, 65, 235, 4, 32, 98, 42, 17]
The bold ones could be the ones considered.
And I do want to always evaluate the highest amount of possibles:
If the length of the array is smaller than 10 THEN evaluate every item.
If the length is higher THEN evaluate 10 out of the array.
If length is 20 -> every 2nd item should be evaluated
If length is 100 -> every 10th item should be evaluated
But what if length is 13 or 27?
You can use a function which remaps your index 0..9 to an evenly distributed index form 0..n-1, e.g.
int map_index(int i, // index: 0..9
int n) // no of elements in array
{
return i * (n - 1) / (10 - 1);
}
How about using the ones with the indices floor(k*length/10), where k=1, 2, ... 10?
For length 15 this will result indices 1, 3, 4, 6, 7, 9, 10, 12, 13, 15 - almost matching your example.

Resources