Sum of ruby arrays in a loop - arrays

I want to find sum of arrays from 1 to 100.Each number is converted to array containing its own digits eg 97 will be [9,7].Here is what i have tried
(1..100).to_a.each do |i|
i.to_s.split("").map(&:to_i).inject(0) { |sum, number| sum + number }
end
But the sum of arrays are not displayed correctly!
For example;We first create an array of the digits and then return sum
[1]=1
[5]=5
[1, 0]=1
[1, 1]=2
[1, 2]=3
[1, 3]=4
[1, 4]=5
So sum of individual arrays is to be returned.

each will iterate the array, but not create a new array with the result of the block. If you want the results at the end, you need to use map:
result = (1..100).to_a.map do |i|
i.to_s.split("").map(&:to_i).inject(0) { |sum, number| sum + number }
end
result
#=> [1, 2, 3, 4, ...]
For summing an array you can also simply write
array.inject(:+)
# instead of
array.inject(0) { |sum, number| sum + number }
Also, the to_a is not necessary, you can directly call each and/or map on a range. So the simplified code would be
result = (1..100).map do |i|
i.to_s.split("").map(&:to_i).inject(:+)
end
result
#=> [1, 2, 3, 4, ...]

For your codes, you just need to change each method to map.
(1..100).to_a.map do |i|
i.to_s.split("").map(&:to_i).inject(0) { |sum, number| sum + number }
end
more simplicity way:
result = (1..100).to_a.map{ |e| e.to_s.split('').map(&:to_i).reduce(:+) }
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1]
if you want to get the sum of result, just do like this:
result.reduce(:+)

If I understand your question correctly you want the sum of these new arrays, right? This should solve your problem:
(1..100).map { |i| i.to_s.split("").map(&:to_i).inject(:+) }.inject(:+)

digits and sum are newer methods, simplifying this to
(1..100).sum{|i| i.digits.sum}

Another alternative for modern newer versions of Ruby:
(1..100).flat_map(&:digits).sum

Related

Sort a numpy array using multiple index and different order

I have an array of size 300x5 and I am trying to sort the array in such a way that column with index 4 is my primary index and in ascending order, index 1 is secondary index and in descending order, index 3 is tertiary index and in ascending order.
I have tried this using following code,
idx = np.lexsort((arr[:,3],arr[:,1][::-1],arr[:,4]))
arr= arr[idx]
where arr --> array of size 300x5
On executing this the secondary index also gets sorted in ascending order instead of descending order. Can anyone help me with this
I think you want -arr[:,1] and not arr[:,1][::-1] as the secondary index.
>>> import numpy as np
>>> arr = np.random.randint(0, 21, (300, 5))
>>> arr
array([[ 0, 19, 6, 19, 17],
[16, 2, 14, 17, 0],
[ 8, 17, 3, 17, 12],
...,
[ 4, 18, 18, 3, 8],
[10, 15, 4, 12, 4],
[ 9, 16, 12, 0, 12]])
>>> idx = np.lexsort((arr[:,3],-arr[:,1],arr[:,4]))
>>> arr = arr[idx]
>>> arr
array([[11, 20, 11, 18, 0],
[11, 16, 12, 2, 0],
[ 9, 16, 4, 8, 0],
...,
[20, 4, 5, 11, 20],
[ 9, 4, 0, 19, 20],
[ 9, 2, 4, 10, 20]])

Select & display odd numbered indexes from the list of numbers in python

I am trying to achieve the indexes in the following manner:
[1,3,5,7,9,11...],
[2,4,6,8,10,12,...],
[3,5,7,9,11,13...],
[4,6,8,10,12,14,..],
So far I've achieved the format as:
[1,2,3,4,5,...],
2,3,4,5,6,7...]
3,4,5,6,7,8...],
using the CODE LINE
indexer = np.arange(3)[None,:] + np.arange(8)[:,None]
I am not sure how to achieve desired results.
Kindly help me with this!
Thanks
You can define a step size for np.arange in the following way np.arange(start, stop, step):
>>> np.arange(1, 12, 2)[None,:] + np.arange(4)[:,None]
array([[ 1, 3, 5, 7, 9, 11],
[ 2, 4, 6, 8, 10, 12],
[ 3, 5, 7, 9, 11, 13],
[ 4, 6, 8, 10, 12, 14]])

Ruby search for the same values in multidimensional array

I have an array with many arrays inside (2d) (in this example there are four of them):
[
[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8],
[8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6],
[9, 15, 21, 23, 23, 7, 13, 15, 15, 12, 14, 14, 8, 8],
[2, 8, 14, 16, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]
I need to find if any element on any of these arrays is the same and at the same index as in other array. I need to get all those numbers and their indexes.
For ex. First_array[1] = 15, as well as second_array[1] = 15 and third_array[1] = 15. So I need these, with their indexes.
Also all needed values must come from arrays that are to the left or to the right to the array. For ex. - array_one[3] = 23, array_two[3] = 21 and array_three[3] = 23. I dont need these since array_two has a different value and it separates array_one from array_three.
And What I can get is the length of arrays (they all the same length) and the number of arrays, as variables.
I hope you got my point :)
Looks like I am abit closer to my goal. It seems this checks well for the second array (so only two first arrays being checked, but if this was done, the rest should be much easier). And do not judge me, judge just the code :D I know its ugly, its just a prototype:
array.each do |c|
c.each do |v|
c.each_with_index do |k, i|
next_array = array[i + 1]
if next_array.include? v
its_index = next_array.index(v)
if c.index(v) == its_index
p v
end
end
break
end
end
return
end
arr = [[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8],
[ 8, 15, 19, 21, 23, 12, 16, 18, 19, 11, 13, 13, 6, 8],
[ 9, 15, 21, 23, 16, 12, 13, 15, 15, 12, 14, 14, 8, 8],
[ 2, 8, 14, 21, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]]
I've modified arr in a few places.
arr.transpose.each_with_index.with_object({}) do |(col,j),h|
i = 0
h[j] = col.chunk(&:itself).each_with_object({}) do |(x,arr),g|
count = arr.size
g.update(i=>{ value: x, number: count }) if count > 1
i += count
end
end
#=> {0=>{},
# 1=>{0=>{:value=>15, :number=>3}},
# 2=>{},
# 3=>{},
# 4=>{0=>{:value=>23, :number=>2}, 2=>{:value=>16, :number=>2}},
# 5=>{1=>{:value=>12, :number=>2}}
# 6=>{2=>{:value=>13, :number=>2}},
# 7=>{2=>{:value=>15, :number=>2}},
# 8=>{0=>{:value=>19, :number=>2}, 2=>{:value=>15, :number=>2}},
# 9=>{2=>{:value=>12, :number=>2}},
# 10=>{2=>{:value=>14, :number=>2}},
# 11=>{2=>{:value=>14, :number=>2}},
# 12=>{2=>{:value=> 8, :number=>2}},
# 13=>{0=>{:value=> 8, :number=>4}}}
The keys of this hash are indices of columns of arr. The values are hashes that contain the locations and counts of all vertically-adjacent elements which appear at least twice. The columns at indices 0, 2 and 3, are the only ones that contains no vertically-adjacent duplicate values. The column at index 1 contains 3 15's beginning at row index 0; the column at index 4 contains 2 23's, beginning at row index 0 and 2 16's, beginning at row index 2.
matrix = [
[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8],
[ 8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6],
[ 9, 15, 21, 23, 23, 7, 13, 15, 15, 12, 14, 14, 8, 8],
[ 2, 8, 14, 16, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]
equal_surround = matrix
.each_with_index.map do |v,i|
v.each_with_index.map do |k,j|
if (i-1>=0 && k == matrix[i-1][j])
k
elsif (i+1 < matrix.length && k == matrix[i+1][j])
k
else
nil
end
end
end
=> [
[nil, 15, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
[nil, 15, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
[nil, 15, nil, nil, nil, 7, 13, 15, 15, 12, 14, 14, 8, 8],
[nil, nil, nil, nil, nil, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]
You didn't show any code, so I won't write any either.
I can tell you that array#transpose should make this problem much more manageable, though.
You'll just need to iterate on the rows (former columns) and look for any repeating number.
You can either do it FORTRAN style with a loop or with fancier Enumerable methods, like each_with_index, map or chunk.
test_array = [
[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8],
[8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6],
[9, 15, 21, 23, 23, 7, 13, 15, 15, 12, 14, 14, 8, 8],
[2, 8, 14, 16, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]
final_res = Hash.new {|h,k| h[k] = Array.new }
test_array.each_cons(2).to_a.each_with_index do |(a,b),i|
final_match = Hash.new {|h,k| h[k] = Array.new }
res = a & b
res.each do |ele|
a_index = a.each_index.select{|i| a[i] == ele}
b_index = b.each_index.select{|i| b[i] == ele}
(a_index & b_index).size > 0 ? final_match[ele] << (a_index & b_index) : ''
end
final_match.each_value {|v| v.flatten!}
final_res[:"Match Values Between Array #{i+1} amd Array #{i+2}"] << final_match
end
final_res.each do |a|
puts a
end
OUTPUT:
Match Values Between Array 1 amd Array 2
{15=>[1]}
Match Values Between Array 2 amd Array 3
{15=>[1]}
Match Values Between Array 3 amd Array 4
{15=>[7, 8], 7=>[5], 13=>[6], 12=>[9], 14=>[10, 11], 8=>[12, 13]}

Indexing highest value of numpy matrix

I have a numpy array of shape (4, 7) like this:
array([[ 1, 4, 5, 7, 8, 6, 7]
[ 2, 23, 2, 4, 8, 94, 2],
[ 1, 5, 6, 7, 10, 15, 20],
[ 3, 9, 2, 7, 6, 5, 4]])
I would like to get the index of the highest element, i.e. 94, in a form like: first row fifth column. Thus the output should be a numpy array ([1,5]) (matlab-style).
You get the index of the maximum index using arr.argmax() but to get the actual row and column you must use np.unravel_index as below:
import numpy as np
arr = np.array([[ 1, 4, 5, 7, 8, 6, 7],
[ 2, 23, 2, 4, 8, 94, 2],
[ 1, 5, 6, 7, 10, 15, 20],
[ 3, 9, 2, 7, 6, 5, 4]])
maximum = np.unravel_index(arr.argmax(), arr.shape)
print(maximum)
# (1, 5)
You have to use np.unravel_index as by default np.argmax will return the index from a flattened array (which in your case would be index 12).

Sort BST in O(n) using constant memory

This is not a homework. Just an interesting task :)
Given a complete binary search three represensted by array. Sort the array in O(n) using constant memory.
Example:
Tree:
8
/ \
4 12
/\ / \
2 6 10 14
/\ /\ /\ /\
1 3 5 7 9 11 13 15
Array: 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15
Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
It is possible, people calling it homework probably haven't tried solving it yet.
We use the following as a sub-routine:
Given an array a1 a2 ... an b1 b2 .. bn, convert in O(n) time and O(1) space to
b1 a1 b2 a2 ... bn an
A solution for that can be found here: http://arxiv.org/abs/0805.1598
We use that as follows.
Do the above interleaving for the first 2^(k+1) - 2 elements, starting at k=1 repeating for k=2, 3 etc, till you go past the end of array.
For example in your array we get (interleaving sets identified by brackets)
8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15
[ ][ ]
4, 8, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 (k = 1, interleave 2)
[ ][ ]
2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 (k = 2, interleave 6)
[ ][ ]
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 (k = 3, interleave 14)
So the total time is n + n/2 + n/4 + ... = O(n).
Space used is O(1).
That this works can be proved by induction.
Thinking about the O(1) in-place variant, but for now here's the O(N) solution
An O(N) space solution
If you can use an O(N) output array, then you can simply perform an inorder traversal. Every time you visit a node, add it to the output array.
Here's an implementation in Java:
import java.util.*;
public class Main {
static void inorder(int[] bst, List<Integer> sorted, int node) {
if (node < bst.length) {
inorder(bst, sorted, node * 2 + 1);
sorted.add(bst[node]);
inorder(bst, sorted, node * 2 + 2);
}
}
public static void main(String[] args) {
int[] bst = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
final int N = bst.length;
List<Integer> sorted = new ArrayList<Integer>();
inorder(bst, sorted, 0);
System.out.println(sorted);
// prints "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]"
}
}
Attachment
Source and output on ideone.com

Resources