Any way to align 2 dimensional arrays in Rubymine - ruby

I'm working on a project where our data setup is similar to this:
data = [
[:col1, :col2, :col3],
[1, 1, 1],
[1, 2, 1],
[2, 1, 1]
]
With enough columns present, it starts to get unreadable.
I'd like it to look similar to this:
data = [
[:col1, :col2, :col3],
[ 1, 1, 1],
[ 1, 2, 1],
[ 2, 1, 1]
]
Is there anyway to make Rubymine's autoformat to format arrays similar to the second example?

Related

Finding duplicate columns in a nested array

0 1 2 3 4 5 6
0{1,2,1,2,1,5,5}
1{5,4,5,4,5,1,1}
2{2,4,2,4,2,1,1}
3{1,2,1,2,1,1,1}
4{4,4,4,4,4,1,1}
5{2,4,2,4,2,2,2}
output: {{0,2,4}, {1,3}, {5,6}} (can use any data structure)
Let's say there is a nested array like above. If we wanted to find column indices that contain the same exact numbers in the same order (for example, column 0, 2, 4 with (1,5,2,1,4,2) and column 1, 3 with (2,4,4,2,4,4), and column 5, 6 with (5,1,1,1,1,2), how can we go about with this efficiently? Will it require dynamic programming?
Thanks in advance.
You can just iterate through the columns, keeping a hashmap of the columns that you've seen so far. Here's an implementation in python:
x = [[1, 2, 1, 2, 1, 5, 5],
[5, 4, 5, 4, 5, 1, 1],
[2, 4, 2, 4, 2, 1, 1],
[1, 2, 1, 2, 1, 1, 1],
[4, 4, 4, 4, 4, 1, 1],
[2, 4, 2, 4, 2, 2, 2]]
seen_before = {}
for v, col in enumerate(zip(*x)):
if tuple(col) not in seen_before:
seen_before[tuple(col)] = [v]
else:
seen_before[tuple(col)].append(v)
This solves the problem in linear time. I hope that's good enough for you.

Understanding the effect of arguments on .flatten method

The ruby doc does a great job of explaining what .flatten does without an argument. But I can't for the life of me understand what is happening when a 1 is passed to flatten
flatten(level) → new_ary
Returns a new array that is a one-dimensional flattening of self (recursively).That is, for every element that is an array, extract its elements into the new array.The optional level argument determines the level of recursion to flatten.
s = [ 1, 2, 3 ] #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1) #=> [1, 2, 3, [4, 5]]
By 'recursion' does it mean that the argument directly effects the number of actions '.flatten' performs to convert the multidimensional array to a regular singular array? Terms that a super-scrub can understand would be greatly appreciated here.
Thank you.
Basically, argument to flatten means how deep should go in attempts to flatten the structure.
a = [ 1, 2, [3, [4, 5] ] ]
# where
[ 1, 2, [3, [4, 5] ] ] # level 0 (original array)
[3, [4, 5] ] # level 1
[4, 5] # level 2
So, if you pass 1, it will go only one level deep and will treat level-2 array as a single element and will not recurse into it. So,
a.flatten(1) #=> [1, 2, 3, [4, 5]]
What #Sergio Tulentsev mentioned in his answer, are correct. But one more thing I would like to add here -
if you don't supply any argument, then flattening will be happened recursively, in all nested level. That is a.flatten will give [1, 2, 3, 4, 5].
Don't think a.flatten is same as a.flatten(0). No, they work differently. If you pass nested level number as 0,1,2, then flattening will be happened as you asked the method to do. But If you don't pass any argument, the method will work, as it is designed to do, i.e it will create a single level array, by breaking all the deeper nested one also.
a = [ 1, 2, [3, [4, [5,[6]]] ] ]
# see no nested level is here, all are flattened.
a.flatten # => [1, 2, 3, 4, 5, 6]

Why is my concatenation messing up when I pass in an array?

I wrote a method to permute an array (I realize Ruby comes with a permutation function, but I wanted to practice algorithms). I'm encountering a really weird error and have no idea why this is happening.
Here's my code:
def permute(arr)
permutation(arr.sort)
end
def permutation(arr, result=[])
k = nil
result += [arr]
(arr.length-1).times do |i|
if arr[i] < arr[i+1]
k = i
end
end
if k.nil?
return result
else
l = -1
arr.length.times do |i|
if arr[k] < arr[i]
l = i
end
l = nil if l == -1
end
arr[k], arr[l] = arr[l], arr[k]
arr = arr[0..k] + arr[k+1..-1].reverse
return permutation(arr, result)
end
end
The method is recursive, and on each successive call I concatenate arr to my result variable with result += [arr] because I want the method to return a nested array, e.g. [[1, 2, 3], [1, 3, 2]..]
However, when I call this method it gives me a completely weird result.
permute([1,2,3])
=> [[1, 3, 2], [2, 3, 1], [2, 3, 1], [3, 2, 1], [3, 2, 1], [3, 2, 1]]
Why are last three results all [3,2,1]? And the other arrays aren't correct either. The really strange thing is that I can fix this by changing my concatenation to result += arr. With this change, I get the following:
permute([1,2,3])
=> [1, 2, 3, 1, 3, 2, 2, 1, 3, 2, 3, 1, 3, 1, 2, 3, 2, 1]
#I know that I can get my desired nested array like so, but that's beside the point
[1, 2, 3, 1, 3, 2, 2, 1, 3, 2, 3, 1, 3, 1, 2, 3, 2, 1].each_slice(3).to_a
=> [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
I don't get the nested arrays that I want, but the output gives me the correct permutation. Why is it working correctly now, but not which I was using result += [arr]? Is this a Ruby bug, or am I missing something here?
You're being bit by a common ruby mistake - you're modifying the original array since the 'arr' argument to permutation() is a reference to the array
Try changing:
result += [arr]
to:
result += [arr.dup]
And then presto!
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
(Incidentally, you're still monkeying with the original 'arr' values with this solution and should probably clean that up)

"Pyramidizing" an array/list (in Ruby, but general solutions could probably be implemented)

I'm not sure what the best word to use here. By "pyramidizing", I mean:
[1,2,3,4].pyramidize # => [1,1,1,1,2,2,2,3,3,4]
["a","b","c","d"].pyramidize # => ["a","a","a","a","b","b","b","c","c","d"]
To represent visually, it could be thought of as:
[ 1,1,1,1,
2,2,2,
3,3,
4 ]
Is there a way to do this that maximizes elegance? A most ruby-like way?
I came across the "need" to do this in a project of mine. After thinking about it, I gave up and decided to work around the problem in an ugly way. I was wondering if there was a pretty way to do this. So far, to do it directly, I've ended up making a separate array for each index and stretching out each array the appropriate length and combining them together. But I don't know how to do this so it looks pretty; my solution is pretty ugly.
Added code golf tag because any solution in one line would probably make my day, but it doesn't have to be.
It doesn't really matter if your solution makes the first index the "base" of the pyramid, or the last index, because I could just reverse the array before running it.
Requires the new iterator fanciness in Ruby 1.9.
class Array
def pyramidize
reverse.map.with_index do |object, index|
[object] * (index + 1)
end.flatten.reverse
end
end
[1,2,3,4].pyramidize
=> [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]
["a","b","c","d"].pyramidize
=> ["a", "a", "a", "a", "b", "b", "b", "c", "c", "d"]
irb(main):001:0> [2,1,3,5].flat_map.with_index{|i,j|[i]*(j+1)}
=> [2, 1, 1, 3, 3, 3, 5, 5, 5, 5]
irb(main):002:0> [1,2,3,4].flat_map{|i|[i]*i}
=> [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
I'm not sure if you want to use the value of the list or the index to determine how much the list should repeat, but a simple solution in python that can probably transfer to ruby easily:
>>> import operator
>>> input = range(6)
>>> reduce(operator.add, [[i]*idx for idx, i in enumerate(input)])
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
Update
Oh and to invert the counts:
>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])
[1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5]
And of course you reversed the list in one of your examples:
>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])[::-1]
[ 5,
4, 4,
3, 3, 3,
2, 2, 2, 2,
1, 1, 1, 1, 1]
FWIW, this is a mathy way of doing it:
>>> A = [1, 2, 3, 4]
>>> [ A[int((sqrt(8*k+1)-1) / 2)] for k in range(len(A)*(len(A)+1) / 2) ]
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
Admittedly, the use of sqrt is pretty ugly.
Here is another way to do it in Python
>>> A=[1,2,3,4]
>>> [y for i,x in enumerate(A) for y in [x]*(len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]
But it's nicer not to create all those temporary lists
>>> from itertools import repeat
>>> [y for i,x in enumerate(A) for y in repeat(x, len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]

Populate array from vector

I would like to populate an 2 dimensional array, from a vector.
I think the best way to explain myself is to put some examples (with a array of [3,5] length).
When vector is: [1, 0]
[
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0]
]
When vector is: [-1, 0]
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
]
When vector is: [-2, 0]
[
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2]
]
When vector is: [1, 1]
[
[2, 2, 2, 1, 0],
[1, 1, 1, 1, 0],
[0, 0, 0, 0, 0]
]
When vector is: [0, 1]
[
[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1],
[0, 0, 0, 0, 0]
]
Have you got any ideas, a good library or a plan?
Any comments are welcome. Thanks.
Note: I consulted Ruby "Matrix" and "Vector" classes, but I don't see any way to use it in my way...
Edit: In fact, each value is the number of cells (from the current cell to the last cell) according to the given vector.
If we take the example where the vector is [-2, 0], with the value *1* (at array[2, 3]):
array = [
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, *1*, <2>]
]
... we could think such as:
The vector [-2, 0] means that -2 is
for cols and 0 is for rows. So if we
are in array[2, 3], we can move 1 time
on the left (left because 2 is
negative) with 2 length (because
-2.abs == 2). And we don't move on the top or bottom, because of 0 for
rows.
It's quite easy to achieve this:
require 'matrix'
def build(rows, cols, vector)
Matrix.build(rows, cols){|i, j| vector.inner_product([cols-j-1, rows-i-1]) }
end
build(3, 5, Vector[1, 0]) # => your first example
# ...
build(3, 5, Vector[0, 1]) # => your last example
You will need the latest Matrix library which introduces Matrix.build.
Note: I find your examples a bit odd, and the third one even stranger. Looks like we have to divide by the vector you give, unless it's 0? Anyways, just adapt the block to the formula you need.
ok i am a little confused but i am going to take a shot in the dark
What you want is to run through every point in the array and call a function that would calculate the value at that position
so we have
loop i
loop j
array[i,j]=Vectorfunction(i,j,vector);
next j
next i
function(i,j,vector)
Here i am guessing you somehow use the position in the array, and the slope of the line defined by the vector. What that is i can't extract from the data, but i am sure such a function exists.
Most likely this involves arccos to get the angle. and then return i*arcsin+j+arccos

Resources