I've been implementing an exercise on bubbling sorting.
So far, managed to bubble sort through an array.
Let's say, we have our array = ([5,6,7], [2,3,4])
How can I bubble sort through this without modifying the original array or using sort?
The exercise requires that I do not copy/duplicate/clone/edit or use a sort method.
My code to bubble sort through a regular array:
def bubble_sort(array)
is_sorted = false
until is_sorted
is_sorted = true
(array.count - 1).times do |i|
if array[i] > array[i + 1]
array[i], array[i + 1] = array[i + 1], array[i]
is_sorted = false
end
end
end
end
arr
As usual I learned quite a lot solving the OPs homework :-)
Firstly "do not copy/duplicate/clone/edit or use a sort method" just means that you have to implement your own algorithm. It does not mean you shouldn't copy the array passed to your function. You must copy your original array to avoid the side effect of modifying the original array.
However! if you simply copy the array new_array = array ruby will copy by reference.
That means that both variables will still point to the same data structure. Your sort will happily sort the numbers and the array passed as a parameter will be modified.
To fix this you need to copy the array using the dup function.
new_array = array.dup
Then the bubble sort function ends up looking like this:
def bubble_sort(array)
result = array.dup
begin
sorted = true
(0..result.length - 2).each do |i|
if result[i] > result[i + 1]
result[i], result[i+1] = result[i+1], result[i]
sorted = false
end
end
end while !sorted
result
end
Some test code:
a = [9,8,7,6,5,5,9,]
puts "array before sorting:"
puts a.inspect
puts "sorted array returned by function"
puts bubble_sort(a).inspect
puts "original array after sorting:"
puts a.inspect
Resulting output:
>ruby mysort.rb
array before sorting:
[9, 8, 7, 6, 5, 5, 9]
sorted array returned by function
[5, 5, 6, 7, 8, 9, 9]
original array after sorting:
[9, 8, 7, 6, 5, 5, 9]
Create a new array that is a copy of the original and sort that. That will let you keep the original array and have the sorted array.
Can you just combine the two arrays into a single array and then run a typical bubble sort?
def combine_arrays(arr1,arr2)
final = arr1 + arr2
sorted = true
while sorted do
sorted = false
(0..final.length - 2).each do |x|
if final[x] > final[x+1]
final[x], final[x+1] = final[x+1], final[x]
sorted = true
end
end
end
final
end
p combine_arrays([1,3,5],[2,4,6]) => [1, 2, 3, 4, 5, 6]
i think the simplest way for Bubble Sorting multi Dimensional Arrays is:
int main()
{
const size_t row = 4,col=6;
int temp;
int arr[row][col] = { { 6, 5, 4, 3, 2, 1 }, { 12, 11, 10, 9, 8, 7 }, {18, 17, 16, 15, 14, 13 }, { 24,23,22,21,20,1 } };
for (auto &row : arr)
{
for (int i = 0; i != col; ++i)
{
int flag = 0;
for (int j = 0; j != col-i - 1; ++j)
{
if (row[j]>row[j+1])
{
temp = row[j];
row[j] = row[j + 1];
row[j + 1] = temp;
flag = 1;
}
}
if (!flag)break;
}
}
for (auto &row : arr)
{
for (auto col : row)
cout << col << " ";
cout << endl;
}
return 0;
}
Related
I am given a string S (of integers) and a number N. I want to insert arbitrary number of '+' in S so that the sum becomes equal to N.
Ex:<br>
S = 15112 and N = 28<br>
Ans is : 15+11+2<br>
S = 120012 and N = 33<br>
Ans is : 1+20+012<br>
S = 123 and N = 123<br>
Ans is : 123
given : |S| <= 120 and N <= 10^6
It is guarenteed that S and N are given such that it is always possible to form valid expression. Is there any algorithm which can solve this? I tried to think on it but couldn't come up with solution.
There may be more efficient ways to do this, but since you have nothing so far…
You can simply find all combinations of a boolean array that indicates whether a plus should exist between the numbers or not.
For example: with an input of 112134, 1 + 12 + 13 + 4 can be represented with the boolean array [true, false, true, false, true] indicating that there is a plus after the 1st, 3rd, and 5th numbers. The problem then reduces to finding which combinations add to your number. There are lot of ways to find combinations. Recursive backtracking is a classic.
In javascript/node this might look like this:
function splitOnIndexes(arr, a) {
// split the array into numbers based on the booleans
let current = "" + arr[0]
let output = []
for (let i = 0; i < a.length; i++) {
if (!a[i]) {
current += arr[i + 1]
} else {
output.push(current)
current = "" + arr[i + 1]
}
}
output.push(current)
return output
}
function findSum(input, total) {
function backtrack(n, k = 0, a = []) {
const sum = (arr) => arr.reduce((a, c) => a + parseInt(c), 0)
if (k === n) {
let ans = splitOnIndexes(input, a)
if (sum(ans) === total) {
console.log(ans.join(' + '))
}
} else {
k = k + 1
let c = [true, false]
for (let i = 0; i < 2; i++) {
a[k - 1] = c[i]
backtrack(n, k, a)
}
}
}
backtrack(input.length - 1)
}
findSum('15112', 28)
findSum('120012', 33)
findSum('123', 123)
As you can see, more than one answer is possible. Your first example is solved with both 15+1+12 and 15+11+2. If you only need one, you can of course stop early.
The idea is to use dynamic programming, you only care about sums between 0 and 10^6 and only have 120 possible indexes. if dp[i][j] = x, it means that from index x of the string, we went to index i (so we added a + before i) and we got a sum of j. This leads to a O(|S| * N) solution:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string s;
long n;
long dp[123][1000001];
void solve (int index, long sum) {//index = what index of s still remains to scan. sum = the sum we have accumulated till now
if (sum >= n or index >= s.length()) return;
if (dp[index][sum] != -1) return;
if (index == n and sum == n) return;
long num = 0;
for (int i = 0; i < 7 && index + i < s.length(); i++) { //N has 6 digits at most
num = stoi(s.substr(index, i + 1));
solve(index + i + 1, sum + num);
if (sum + num <= n) {
dp[index + i + 1][sum + num] = index;
}
}
}
int main () {
cin >> s;
cin >> n;
for (int i = 0; i < 121; i++) {
for (int j = 0; j < 1000001; j++) {
dp[i][j] = -1;
}
}
solve(0, 0);
int sum = n;
int idx = s.length();
vector<string> nums;
//reconstruct solution
while (idx != 0) {
nums.push_back(s.substr(dp[idx][sum], idx - dp[idx][sum]));
idx = dp[idx][sum];
sum -= stoi(nums[nums.size() - 1]);
}
for (int i = nums.size() -1; i >= 0; i--) {
cout << nums[i];
if (i != 0) cout << "+";
}
}
This is a Ruby version with step by step explanation of the algorithm, so you can easily code in C++ (or I'll try later).
# Let's consider that we extracted the values from text, so we already have the string of int and the result as integer:
string_of_int = "15112"
result = 28
# The basic idea is to find a map (array) that tells how to group digits, for example
sum_map = [2, 1, 2]
# This means that string_of_int is mapped into the following numbers
# 15, 1, 12
# then sum the numbers, in this case 15+1+12 = 28
# For finding a the solution we need to map
# all the possible combinations of addition given the n digits of the string_of_int then check if the sum is equal to the result
# We call k the number of digits of string_of_int
# in ruby we can build an array called sum_maps
# containing all the possible permutations like this:
k = string_of_int.length # => 5
sum_maps = []
k.times do |length|
(1..k).to_a.repeated_permutation(length).each {|e| sum_maps << e if e.inject(:+) == k}
end
sum_maps
# => [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1], [1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 4, 1], [2, 1, 3], [2, 2, 2], [2, 3, 1], [3, 1, 2], [3, 2, 1], [4, 1, 1]]
# Now must check which of of the sum_map is giving us the required result.
#
# First, to keep the code short and DRY,
# better to define a couple of useful methods for the String class to use then:
class String
def group_digits_by(sum_map)
string_of_int_splitted = self.split("")
grouped_digits = []
sum_map.each { |n| grouped_digits << string_of_int_splitted.shift(n).join.to_i}
grouped_digits.reject { |element| element == 0 }
end
def sum_grouped_of_digits_by(sum_map)
group_digits_by(sum_map).inject(:+)
end
end
# So we can call the methods directly on the string
# for example, in ruby:
string_of_int.group_digits_by sum_map #=> [15, 1, 12]
string_of_int.sum_grouped_of_digits_by sum_map #=> 28
# Now that we have this metods, we just iterate through the sum_maps array
# and apply it for printing out the sm_map if the sum of grouped digits is equal to the result
# coded in ruby it is:
combinations = []
sum_maps.each { |sum_map| combinations << string_of_int.group_digits_by(sum_map) if string_of_int.sum_grouped_of_digits_by(sum_map) == result }
p combinations.uniq
# => [[15, 1, 12], [15, 11, 2]]
In short, written as a Ruby module it becomes:
module GuessAddition
class ::String
def group_digits_by(sum_map)
string_of_int_splitted = self.split("")
grouped_digits = []
sum_map.each { |n| grouped_digits << string_of_int_splitted.shift(n).join.to_i}
grouped_digits.reject { |element| element == 0 }
end
def sum_grouped_of_digits_by(sum_map)
group_digits_by(sum_map).inject(:+)
end
end
def self.guess_this(string_of_int, result)
k = string_of_int.length
sum_maps = []
k.times { |length| (1..k).to_a.repeated_permutation(length).each {|e| sum_maps << e if e.inject(:+) == k} }
combinations = []
sum_maps.each { |sum_map| combinations << string_of_int.group_digits_by(sum_map) if string_of_int.sum_grouped_of_digits_by(sum_map) == result }
combinations.uniq
end
end
p GuessAddition::guess_this("15112", 28) # => [[15, 1, 12], [15, 11, 2]]
Why does this block of code output [1, 2, 3, 4, 5] and not [2, 3, 4, 5, 6]?
x = [1, 2, 3, 4, 5]
x.each do |a|
a + 1
end
I viewed the source of each at https://ruby-doc.org/core-2.2.0/Array.html#method-i-each. Something like this is written there.
VALUE
rb_ary_each(VALUE array)
{
long i;
volatile VALUE ary = array;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
Can someone please explain?
It outputs the object, you're calling each on, because this is the return value of each.
If you want to just print the a + 1, you should actually make it being output:
x.each do |a|
puts a + 1
end
Or, if your desired result is [2, 3, 4, 5, 6] - you want Enumerable#map, not each.
x.map { |a| a + 1 }
#=> [2, 3, 4, 5, 6]
Let me go through the key lines.
From this one it follows 'ary' is logically equal to array. Note the line is absent from newer versions of Ruby such as 2.4.0!
volatile VALUE ary = array;
I skip RETURN_SIZED_ENUMERATOR since a block is given. Refer to its source in at include/ruby/intern.h.
Next, we go into a 'for' for each element of 'ary' array.
Next is the line that puzzles you, I believe. First, it take i-th element from 'ary' array via RARRAY_AREF macro. Second, it passed the element's value to the block given (i.e 'a + 1') via rb_yield. Thus, it does not store anything.
rb_yield(RARRAY_AREF(ary, i));
Since nothing was written at rb_yield, the function return the 'ary' array which is [see above] is input 'array'.
Comparing it to 'map!' may help you further:
static VALUE rb_ary_collect_bang(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
}
return ary;
}
Note 'rb_ary_store' function call inside the 'for' loop. It is the thing! It rb_yield-s just like in 'each' variant, but it does not throw away the result returned. The result is stored at i-th element of our [beloved] 'ary' array.
The answer might be obvious to the trained eye, but I've been hitting the books for a few hours now, my eyes are straining, and I can't seem to see the bug.
Below are two implementations of selection sort I wrote, and neither is sorting the input correctly. You can play with this code on an online interpreter.
def selection_sort_enum(array)
n = array.length - 1
0.upto(n - 1) do |i|
smallest = i
(i + 1).upto(n) do |j|
smallest = j if array[j] < array[i]
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
end
end
def selection_sort_loop(array)
n = array.length - 1
i = 0
while i <= n - 1
smallest = i
j = i + 1
while j <= n
smallest = j if array[j] < array[i]
j += 1
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
i += 1
end
end
Here's the test of the first implementation, selection_sort_enum:
puts "Using enum:"
a1 = [*1..10].shuffle
puts "Before sort: #{a1.inspect}"
selection_sort_enum(a1)
puts "After sort: #{a1.inspect}"
Here's the test of the second implementation, selection_sort_loop:
puts "Using while:"
a2 = [*1..10].shuffle
puts "Before sort: #{a2.inspect}"
selection_sort_enum(a2)
puts "After sort: #{a2.inspect}"
Here's the output of the first implementation, selection_sort_enum:
Using enum:
Before sort: [7, 5, 2, 10, 6, 1, 3, 4, 8, 9]
After sort: [4, 3, 1, 9, 5, 2, 6, 7, 8, 10]
Here's the output of the second implementation, selection_sort_loop:
Using while:
Before sort: [1, 10, 5, 3, 7, 4, 8, 9, 6, 2]
After sort: [1, 2, 4, 3, 6, 5, 7, 8, 9, 10]
In both the code snippets you are comparing with index i instead of index smallest.
This should work :
def selection_sort_enum(array)
n = array.length - 1
0.upto(n - 1) do |i|
smallest = i
(i + 1).upto(n) do |j|
smallest = j if array[j] < array[smallest]
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
end
end
def selection_sort_loop(array)
n = array.length - 1
i = 0
while i <= n - 1
smallest = i
j = i + 1
while j <= n
smallest = j if array[j] < array[smallest]
j += 1
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
i += 1
end
end
Output :
Using enum:
Before sort: [5, 6, 7, 9, 2, 4, 8, 1, 10, 3]
After sort: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Using while:
Before sort: [6, 5, 9, 2, 1, 3, 10, 4, 7, 8]
After sort: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Link to solution : http://ideone.com/pKLriY
def selection_sort_enum(array)
n = array.length - 1
0.upto(n) do |i| # n instead of (n - 1)
smallest_index = i
(i + 1).upto(n) do |j|
smallest_index = j if array[j] < array[i]
end
puts "#{array}", smallest_index
array[i], array[smallest_index] = array[smallest_index], array[i] if i != smallest_index
end
end
You might be interested in this:
def selection_sort_enum(array)
n = array.length - 1
0.upto(n - 1) do |i|
smallest = i
(i + 1).upto(n) do |j|
smallest = j if array[j] < array[i]
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
end
array # <-- added to return the modified array
end
def selection_sort_loop(array)
n = array.length - 1
i = 0
while i <= n - 1
smallest = i
j = i + 1
while j <= n
smallest = j if array[j] < array[i]
j += 1
end
array[i], array[smallest] = array[smallest], array[i] if i != smallest
i += 1
end
array # <-- added to return the modified array
end
require 'fruity'
ARY = (1 .. 100).to_a.shuffle
compare do
_enum { selection_sort_enum(ARY.dup) }
_loop { selection_sort_loop(ARY.dup) }
end
Which results in:
# >> Running each test once. Test will take about 1 second.
# >> _enum is faster than _loop by 3x ± 1.0
I would like to write a program in ruby 1.9.3 ver. which collects unique value ranges and then calculates amount of numbers in these ranges.
For example lets use 3 ranges (1..3), (6..8) and (2..4). It will return array with two ranges (1..4), (6..8) and amount of numbers - 7.
I wrote the following code:
z= []
def value_ranges(start, finish, z)
range = (start..finish)
arr = z
point = nil
if arr.empty?
point = nil
else
arr.each { |uniq|
if overlap?(uniq,range) == true
point = arr.index(uniq)
break
else
point = nil
end
}
end
if point != nil
if arr[point].first >= start && arr[point].end <= finish
range = (start..finish)
elsif arr[point].first >= start
range = (start..arr[point].end)
elsif arr[point].end <= finish
range = (arr[point].first..finish)
else
range = (arr[point].first..arr[point].end)
end
arr[point] = range
else
arr << range
end
print arr
end
def overlap?(x,y)
(x.first - y.end) * (y.first - x.end) >= 0
end
Problem comes when program meets a range which overlaps two already collected ranges.
For example (1..5) (7..9) (11..19) and the next given range is (8..11).
It should link both ranges and return the following result - (1..5),(7..19).
I don't have an idea how to recheck whole array without creating infinite loop. Also what is the best way to calculate amount of numbers in ranges?
Here are two Ruby-like ways of doing it.
arr = [1..3, 6..8, 2..4]
#1 Efficient approach
First calculate the amalgamated ranges:
a = arr[1..-1].sort_by(&:first).each_with_object([arr.first]) do |r,ar|
if r.first <= ar.last.last
ar[-1] = ar.last.first..[ar.last.last,r.last].max
else
ar << r
end
end
#=> [1..4, 6..8]
Then compute the total number of elements in those ranges:
a.reduce(0) { |tot,r| tot + r.size }
#=> [1..4, 6..8].reduce(0) { |tot,r| tot + r.size }
#=> 7
Explanation
b = arr[1..-1]
#=> [6..8, 2..4]
c = b.sort_by(&:first)
#=> [2..4, 6..8]
enum = c.each_with_object([1..3])
#=> #<Enumerator: [2..4, 6..8]:each_with_object([1..3])>
The contents of the enumerator enum will be passed into the block and assigned to the block variables by Enumerator#each, which will call Array#each. We can see the contents of the enumerator by converting it to an array:
enum.to_a
#=> [[2..4, [1..3]], [6..8, [1..3]]]
and we can use Enumerator#next to step through the enumerator. The first element of the enumerator passed to the block by each is [2..4, [1..3]]. This is assigned to the block variables as follows:
r, ar = enum.next
#=> [2..4, [1..3]]
r #=> 2..4
ar #=> [1..3]
We now perform the block calculation
if r.first <= ar.last.last
#=> 2 <= (1..3).last
#=> 2 <= 3
#=> true
ar[-1] = ar.last.first..[ar.last.last,r.last].max
#=> ar[-1] = 1..[3,4].max
#=> ar[-1] = 1..4
#=> 1..4
else # not executed this time
ar << r
end
This is not so mysterious. So I don't have to keep saying "the last range of ar", let me define:
ar_last = ar.last
#=> 1..3
First of all, because we began by sorting the ranges by the beginning of each range, we know that when each element of enum is passed into the block:
ar_last.first <= r.first
For each element of enum passed into the block for which:
r.first <= ar_last.last
we compare r.last with ar_last.last. There are two possibilities to consider:
r.last <= ar_last.last, in which case the two ranges overlap and therefore ar_last would not change; and
r.last > ar_last.last, in which case the upper end of ar_last must be increased to r.last.
Here,
2 = r.first <= ar_last.last = 3
4 = r.last > ar_last.last = 3
so ar_last is changed from 1..3 to 1..4.
each now passes the last element of enum into the block:
r, ar = enum.next
#=> [6..8, [1..4]]
r #=> 6..8
ar #=> [1..4]
if r.first <= ar.last.last
#=> (6 <= 4) => false this time
...
else # executed this time
ar << r
#=> ar << (6..8)
#=> [1..4, 6..8]
end
and
a = ar #=> [1..4, 6..8]
This time, r.first > ar_last.last, meaning the range r does not overlap ar_last, so we append r to ar, and ar_last now equals r.
Lastly:
a.reduce(0) { |tot,r| tot + r.size }
#=> [1..4, 6..8].reduce(0) { |tot,r| tot + r.size }
#=> 7
which we could alternatively write:
a.map(&:size).reduce(:+)
#2 Easy but inefficient
Here is an easy, but not especially efficient, method that uses Enumerable#slice_when, newly-minted in v2.2.
arr = [(1..3), (6..8), (2..4)]
To calculate the amagamated ranges:
a = arr.flat_map(&:to_a)
.uniq
.sort
.slice_when { |i,j| i+1 != j }
.map { |ar| (ar.first..ar.last) }
#=> [1..4, 6..8]
The total number of elements in those ranges is calculated as in #1
Explanation
Here are the steps:
b = arr.flat_map(&:to_a)
#=> [1, 2, 3, 6, 7, 8, 2, 3, 4]
c = b.uniq
#=> [1, 2, 3, 6, 7, 8, 4]
d = c.sort
#=> [1, 2, 3, 4, 6, 7, 8]
e = d.slice_when { |i,j| i+1 != j }
#=> #<Enumerator: #<Enumerator::Generator:0x007f81629584f0>:each>
a = e.map { |ar| (ar.first..ar.last) }
#=> [1..4, 6..8]
We can see the contents of the enumerator e by converting it to an array:
e.to_a
#=> [[1, 2, 3, 4], [6, 7, 8]]
Details of the problem: To find if any combination of the array adds to the largest number found in the array.
Here are the steps I am trying to implement:
Extract the largest number from the array
Create a new array of
all the potential combinations that could be added by using
.combination
Test to see if any of these combinations equals the largest number in the original array.
Status: So far, I am just receiving an unexpected end error for the last end in the code. (I have found different answers online on how to solve the subset sums problem in Ruby, but would like to figure out how to solve it using the logic I have used so far.)
Any help would be great!
def subset_sum(sums)
largest_number = subset_sum.sort.reverse[0]
array_without_largest = subset_sum.sort.reverse[1..-1]
full_combination = []
i = 0
while i <= array_without_largest.length
full_combination = full_combination + array_without_largest.combination(i).to_a.to_s
i += 1
end
j = 0
while j <= full_combination.length
return true if full_combination[j].inject { |sum, x| sum + x} == largest_number
j += 1
end
end
return false
end
puts subset_sum(1,2,3,4,10)
puts subset_sum(-1,-3,3,9,8)
Consider this:
def any_subset_adds_to_max?(array)
sub_array = array - [array.max]
every_combination = (1..sub_array.length).flat_map { |n| sub_array.combination(n).to_a }
every_combination.any? { |combination| combination.reduce(:+) == array.max }
end
[
[1, 2, 3, 4, 10],
[-1, -3, 3, 9, 8]
].map { |test_array| any_subset_adds_to_max? test_array } # => [true, false]
Here is the closest example of the code that I could do while maintaining the originality. It works and I appreciate the help!
def subset_sum(sums)
largest_number = sums.max
array_without_largest = sums - [largest_number]
full_combination = []
array_without_largest.size.times do |i|
full_combination << array_without_largest.combination(i+1).to_a
end
full_combination.flatten!(1)
full_combination.size.times do |i|
return true if full_combination[i].inject(:+) == largest_number
end
false
end