Is there a common name for a function that maps by an index? - algorithm

Names such as map, filter or sum are generally understood by every resonably good programmer.
I wonder whether the following function f also has such a standard name:
def f(data, idx): return [data[i] for i in idx]
Example usages:
r = f(['world', '!', 'hello'], [2, 0, 1, 1, 1])
piecePrice = [100, 50, 20, 180]
pieceIdx = [0, 2, 3, 0, 0]
total Price = sum(f(piecePrice, pieceIdx))
I started with map, but map is generally understood as a function that applies a function on each element of a list.

Related

CountMultiplicativePairs in Python using optimized way

The complete problem is given below for which I wrote a Python code and wanted to know the complexity of it or whether it can be optimised more. The solutions are available in C# but the logics are quiet complex.
http://www.whatsjs.com/2018/01/codility-countmultiplicativepairs.html
Here is the solution to the problem:
How to find pairs with product greater than sum
Below the code I wrote in Python. Is there any other way or someone who has tried this problem in python as the C# code explained above doesn't have proper explanation
def solution(A,B):
"""
Count the number of pairs (x, y) such that x * y >= x + y.
"""
M = 1000*1000
max_count=1000*1000*1000
zero=count=0
if len(A)<=1:
return "Length of array A should be greater than 1"
if len(B)<=1:
return "Length of array B should be greater than 1"
if len(A)!=len(B):
return "Length of both arrays should be equal"
C=[0]*len(A)
for (i, elem) in enumerate(A):
C[i]=float(A[i])+float(B[i]/M)
for (i, elem) in enumerate(C):
if elem==0:
zero+=1
if elem>0 and elem<=1:
pass
if elem>1:
for j in range(i+1,len(C)):
if round(C[i]*C[j],2)>=C[i]+C[j]:
count+=1
zero_pairs=int(zero*(zero-1)/2)
count+=zero_pairs
return min(count,max_count)
#return C
#print(solution([0,1,2,2,3,5], [500000, 500000, 0, 0, 0, 20000]))
print(solution([1, 1, 1, 2, 2, 3, 5, 6],[200000, 250000, 500000, 0, 0, 0, 0, 0]))
# print(solution([0, 0, 2, 2], [0, 0, 0, 0]))
# print(solution([1, 3], [500000, 10000]))
# print(solution([1, 3], [400000, 500000]))
#print(solution([0, 0, 0, 0] , [0, 0, 0, 0]))
#print(solution([0, 0, 0, 0] , [1, 1, 1, 1]))
I wanted a more optimised way to solve this, as I feel the complexity currently is O(n^2)

how do i reverse individual (and specific) columns in a 2d array (RUBY)

RUBY the goal is to get the max value from each of the four zones and get their sum.
UPDATE I came up with a solution, I'm sorry about the mixup. It turned out that the matrix is a 2n x 2n matrix so it could have been greater or smaller than 4x4 in fact it. The solution i wrote below worked on all of the test cases. Here is a link to the problem
I tried doing matrix.transpose then I tried reversing the specific array, that didn't work for all edge cases.
Here is the code for that
def flippingMatrix(matrix)
2.times do
matrix = matrix.transpose
matrix = matrix.map do |array|
if (array[-1] == array.max) || (array[-2] == array.max)
array.reverse
else
array
end
end
end
return matrix[0][0] + matrix[0][1] + matrix[1][0] + matrix[1][1]
end
I gave up and tried the below, which in my mind works, it also works for most edge cases but not all.
But i'm getting an error (undefined method `[]' for nil:NilClass (NoMethodError))
keep in mind when I print the results or spot_1, spot_2, spot_3, or spot_4 I get the correct answer. does anyone have an idea why this is happening?
Here is a matrix that FAILED
[
[517, 37, 380, 3727],
[3049, 1181, 2690, 1587],
[3227, 3500, 2665, 383],
[4041, 2013, 384, 965]
]
**expected output: 12,881 (this fails)**
**because 4041 + 2013 + 3227 + 3500 = 12,881**
Here is a matrix that PASSED
[
[112, 42, 83, 119],
[56, 125, 56, 49],
[15, 78, 101, 43],
[62, 98, 114, 108],
]
**expected output: 414 (this passes)**
Here is the code
def flippingMatrix(matrix)
# Write your code here
spot_1 = [matrix[0][0] , matrix[0][3] , matrix[3][0] , matrix[3][3]].max
spot_2 = [matrix[0][1] , matrix[0][2] , matrix[3][1] , matrix[3][2]].max
spot_3 = [matrix[1][0] , matrix[1][3] , matrix[2][0] , matrix[2][3]].max
spot_4 = [matrix[1][1] , matrix[1][2] , matrix[2][1] , matrix[2][2]].max
return (spot_1 + spot_2 + spot_3 + spot_4)
end
I will answer your question and at the same time suggest two other ways to obtain the desired sum.
Suppose
arr = [
[ 1, 30, 40, 2],
[300, 4000, 1000, 200],
[400, 3000, 2000, 100],
[ 4, 10, 20, 3]
]
First solution
We see that the desired return value is 4444. This corresponds to
A B B A
C D D C
C D D C
A B B A
First create three helper methods.
Compute the largest value among the four inner elements
def mx(arr)
[arr[1][1], arr[1][2], arr[2][1], arr[2][2]].max
end
mx(arr)
#=> 4000
This is the largest of the "D" values.
Reverse the first two and last two rows
def row_flip(arr)
[arr[1], arr[0], arr[3], arr[2]]
end
row_flip(arr)
#=> [[300, 4000, 1000, 200],
# [ 1, 30, 40, 2],
# [ 4, 10, 20, 3],
# [400, 3000, 2000, 100]]
This allows us to use the method mx to obtain the largest of the "B" values.
Reverse the first two and last two columns
def column_flip(arr)
row_flip(arr.transpose).transpose
end
column_flip(arr)
#= [[ 30, 1, 2, 40],
# [4000, 300, 200, 1000],
# [3000, 400, 100, 2000],
# [ 10, 4, 3, 20]]
This allows us to use the method mx to obtain the largest of the "C" values.
Lastly, the maximum of the "A" values can be computed as follows.
t = row_flip(column_flip(arr))
#=> [[4000, 300, 200, 1000],
# [ 30, 1, 2, 40],
# [ 10, 4, 3, 20],
# [3000, 400, 100, 2000]]
mx(column_flip(t))
#=> 4
The sum of the maximum values may therefore be computed as follows.
def sum_max(arr)
t = column_flip(arr)
mx(arr) + mx(row_flip(arr)) + mx(t) + mx(row_flip(t))
end
sum_max(arr)
#=> 4444
Second solution
Another way is the following:
[0, 1].product([0, 1]).sum do |i, j|
[arr[i][j], arr[i][-j-1], arr[-i-1][j], arr[-i-1][-j-1]].max
end
#=> 4444
To see how this works let me break this into two statements add a puts statement. Note that, for each of the groups A, B, C and D, the block variables i and j are the row and column indices of the top-left element of the group.
top_left_indices = [0, 1].product([0, 1])
#=> [[0, 0], [0, 1], [1, 0], [1, 1]]
top_left_indices.sum do |i, j|
a = [arr[i][j], arr[i][-j-1], arr[-i-1][j], arr[-i-1][-j-1]]
puts a
a.max
end
#=> 4444
The prints the following.
[1, 2, 4, 3]
[30, 40, 10, 20]
[300, 200, 400, 100]
[4000, 1000, 3000, 2000]
ahhh I came up with an answer that answers all edge cases. I originally saw something like this in Javascript and kind of turned it into Ruby. Apparently some of the hidden edge cases (that were hidden) weren't all 4 by 4 some were smaller and some larger, that was the cause of the nil error.
Here is the solution:
def flippingMatrix(matrix)
total = []
(0...(matrix.length/2)).each do |idx1|
(0...(matrix.length/2)).each do |idx2|
total << [matrix[idx1][idx2],
matrix[(matrix.length - 1)-idx1][idx2],
matrix[idx1][(matrix.length - 1)-idx2],
matrix[(matrix.length - 1)-idx1][(matrix.length - 1)-idx2]].max
end
end
total.sum
end
Thank you all for your support! I hope this helps someone in the near future.

pure ruby: calculate sparse matrix rank fast(er)

How do I speed up the rank calculation of a sparse matrix in pure ruby?
I'm currently calculating the rank of a matrix (std lib) to determine the rigidity of a graph.
That means I have a sparse matrix of about 2 rows * 9 columns to about 300 rows * 300 columns.
That translates to times of several seconds to determine the rank of the matrix, which is very slow for a GUI application.
Because I use Sketchup I am bound to Ruby 2.0.0.
I'd like to avoid the hassle of setting up gcc on windows, so nmatrix is (I think) not a good option.
Edit:
Example matrix:
[[12, -21, 0, -12, 21, 0, 0, 0, 0],
[12, -7, -20, 0, 0, 0, -12, 7, 20],
[0, 0, 0, 0, 14, -20, 0, -14, 20]]
Edit2:
I am using integers instead of floats to speed it up considerably.
I have also added a fail fast mechanism earlier in the code in order to not call the slow rank function at all.
Edit3:
Part of the code
def rigid?(proto_matrix, nodes)
matrix_base = Array.new(proto_matrix.size) { |index|
# initialize the row with 0
arr = Array.new(nodes.size * 3, 0.to_int)
proto_row = proto_matrix[index]
# ids of the nodes in the graph
node_ids = proto_row.map { |hash| hash[:id] }
# set the values of both of the nodes' positions
[0, 1].each { |i|
vertex_index = vertices.find_index(node_ids[i])
# predetermined vector associated to the node
vec = proto_row[i][:vec]
arr[vertex_index * 3] = vec.x.to_int
arr[vertex_index * 3 + 1] = vec.y.to_int
arr[vertex_index * 3 + 2] = vec.z.to_int
}
arr
}
matrix = Matrix::rows(matrix_base, false)
rank = matrix.rank
# graph is rigid if the rank of the matrix is bigger or equal
# to the amount of node coordinates minus the degrees of freedom
# of the whole graph
rank >= nodes.size * 3 - 6
end

Why does my diagonal matrix calculator not return the total?

My method should take an array of subarrays, find the sum of the first value of the first array, the second value of the second array, the third value of the third array, and so on. Some examples of inputs and expected results are as follows:
exampleArray = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
]
diagonalSum(exampleArray) # => 4
exampleArray = [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]
]
diagonalSum(exampleArray) # => 5
I wrote this:
def diagonalSum(matrix)
total = 0
counter = 0
while matrix.length <= counter + 1 do
total += matrix[counter][counter]
counter += 1
end
total
end
and it returns 0.
It's easiest to convert the array to a matrix and apply Matrix#trace.
require 'matrix'
arr = [[1, 0, 0, 7],
[0, 2, 0, 0],
[0, 0, 3, 0],
[8, 0, 0, 4]]
Matrix[*arr].trace
#=> 10
According to the code you provide, in which the input is an array of arrays, the first advice I could give you is that in Ruby you must avoid using for/while loops and make use of iterators such as each/each_with_index instead (based on this Ruby style guide and the suggestions of #tadman and #Yu Hao).
The each with index iterator takes a Ruby block with the current array of the iteration along with its index position, so you don't need to define your own index variable and update it in every iteration.
Applying this to your code will result in the following:
def diagonal_sum(matrix)
total = 0
matrix.each_with_index do |row, index|
total+=row[index]
end
total
end
Also note that the convention in Ruby is to write variable and method names in snake_case (according to the previous style guide).

How to slice a rank 4 tensor in TensorFlow?

I am trying to slice a four-dimensional tensor using the tf.slice() operator, as follows:
x_image = tf.reshape(x, [-1,28,28,1], name='Images_2D')
slice_im = tf.slice(x_image,[0,2,2],[1, 24, 24])
However, when I try to run this code, I get the following exception:
raise ValueError("Shape %s must have rank %d" % (self, rank))
ValueError: Shape TensorShape([Dimension(None), Dimension(28), Dimension(28), Dimension(1)]) must have rank 3
How can I slice this tensor?
The tf.slice(input, begin, size) operator requires that the begin and size vectors—which define the subtensor to be sliced—have the same length as the number of dimensions in input. Therefore, to slice a 4-D tensor, you must pass a vector (or list) of four numbers as the second and third arguments of tf.slice().
For example:
x_image = tf.reshape(x, [-1, 28, 28, 1], name='Images_2D')
slice_im = tf.slice(x_image, [0, 2, 2, 0], [1, 24, 24, 1])
# Or, using the indexing operator:
slice_im = x_image[0:1, 2:26, 2:26, :]
The indexing operator is slightly more powerful, as it can also reduce the rank of the output, if for a dimension you specify a single integer, rather than a range:
slice_im = x_image[0:1, 2:26, 2:26, :]
print slice_im_2d.get_shape() # ==> [1, 24, 24, 1]
slice_im_2d = x_image[0, 2:26, 2:26, 0]
print slice_im_2d.get_shape() # ==> [24, 24]

Resources