Selecting values below a threshold and anchored at the left or right using Ruby NArray - ruby

Using NArray, is there some nifty way to create masks of arrays with values below e.g. 5, but only for runs of values anchored a the left or right side, E.g. this 1-D array:
[3, 4, 5, 7, 1, 7, 8]
would result in:
[1, 1, 0, 0, 0, 0, 0]
And this 2-D array:
[[2, 4, 5, 7, 1, 2, 3],
[3, 4, 5, 7, 1, 7, 8],
[8, 1, 1, 7, 1, 7, 1]]
would result in:
[[1, 1, 0, 0, 1, 1, 1],
[1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1]]

require "narray"
def anchor_mask(mask)
idx = (mask.not).where
y = idx/mask.shape[0]
u = (y[0..-2].ne y[1..-1]).where
t = [0] + (u+1).to_a + [idx.size]
s = (0..u.size).map{|i| idx[t[i]]..idx[t[i+1]-1]}
mask[s] = 0
return mask
end
a = NArray[3, 4, 5, 7, 1, 7, 8]
p anchor_mask a.lt(5)
#=> NArray.byte(7):
# [ 1, 1, 0, 0, 0, 0, 0 ]
a = NArray[[2, 4, 5, 7, 1, 2, 3],
[3, 4, 5, 7, 1, 7, 8],
[8, 1, 1, 7, 1, 7, 1]]
p anchor_mask a.lt(5)
#=> NArray.byte(7,3):
# [ [ 1, 1, 0, 0, 1, 1, 1 ],
# [ 1, 1, 0, 0, 0, 0, 0 ],
# [ 0, 0, 0, 0, 0, 0, 1 ] ]

Related

Select/4 on a list of lists

On prolog i'm trying to solve the following exercise for connect 4
?- generate_move(2,[[1, 0, 1, 0],[0, 1, 1, 0],[0, 0, 1, 1],[1, 0, 0, 1]],BP).
BP = [[1, 2, 1, 0], [0, 1, 1, 0], [0, 0, 1, 1], [1, 0, 0, 1]] ;
BP = [[1, 0, 1, 2], [0, 1, 1, 0], [0, 0, 1, 1], [1, 0, 0, 1]] ;
BP = [[1, 0, 1, 0], [2, 1, 1, 0], [0, 0, 1, 1], [1, 0, 0, 1]] ;
BP = [[1, 0, 1, 0], [0, 1, 1, 2], [0, 0, 1, 1], [1, 0, 0, 1]] ;
BP = [[1, 0, 1, 0], [0, 1, 1, 0], [2, 0, 1, 1], [1, 0, 0, 1]] ;
BP = [[1, 0, 1, 0], [0, 1, 1, 0], [0, 2, 1, 1], [1, 0, 0, 1]] ;
Where the rule is that is returns every possible move left for a player provided (in this case 2)
I was thinking of using select/4 to find every result possible for each list in the list of lists, then join it. But i'm failing to "condense" results and my second iteration of findall fails:
generate_move(_,[],[]).
generate_move(Player,[H|T],[FinalLine|FinalBoard]) :-
findall(X0,(select(0, H, Player, X0)),FinalLine),
join_results(FinalLine,T,FinalBoard),
generate_move(Player,T,FinalBoard).
join_results([],[],[]).
join_results([H|T],LeftOvers,FinalBoard) :-
append([H],LeftOvers,FinalBoard),
join_results(T,LeftOvers,FinalBoard).
Any tips? My join_results returns false at the second call and so does my findall.

Convert string to list of integers

This is the input string: 1,1,1,1,1,1,1,1,1,1,-9\n1,1,1,1,1,1,1,1,1,1,1\n2,1,2,1,2,1,2,1,2,1,2\n1,0,1,0,1,0\n3,1,2,-2,1,-2
I need to convert this string to lists of integers, so the output should be: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -9], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2], [1, 0, 1, 0, 1, 0], [3, 1, 2, -2, 1, -2]]
My solution is:
text.split("\n").map do |row|
row.split(",").map(&:to_i)
end
Is there a better, more efficient way?
Refactored as a One-Liner
I often find that when people say "more efficient" or "more elegant" they just mean shorter or more compact. There's nothing wrong with your code, and unless you're performing actions on tens of thousands of arrays I doubt efficiency is anything other than a premature optimization. That said, you can write a one-liner for this if you want.
For example, using Ruby 2.7.1 and str as your input string:
str.split.map { _1.split(?,).map &:to_i }
#=> [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -9], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2], [1, 0, 1, 0, 1, 0], [3, 1, 2, -2, 1, -2]]
If you pretty-print the result with Kernel#pp, you'll get the results you expect.
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -9],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
[1, 0, 1, 0, 1, 0],
[3, 1, 2, -2, 1, -2]]
This isn't better than your existing code in any meaningful way, and I won't even claim it's faster. About all I can really say is that it's more compact and uses fewer lines, so please use your own judgment about its readability and utility value.

Iterating over integer arrays with fixed sum in Julia

I am looking for an algorithm to iterate over all arrays of length n whose entries are integers between 0 and d and whose sum is k*d. It would be even better if there is a way to do this with built-in Julia functions and iterators. The algorithm should be non-recursive and memory efficient as I am hoping to use this for reasonable values of n.
For small values of n, d, and k, I've written down all such arrays in lexicographical ordering, but I haven't been able to come up with code for iterating through all such arrays.
I think this should work but it requires Combinatorics.jl and ResumableFunctions.jl
using Combinatorics, ResumableFunctions
#resumable function gen_all(n, k, d)
for x in partitions(k*d + n, n)
x = x .- 1
if all(x .<= d)
ys = Set(permutations(x))
for y in ys
#yield y
end
end
end
end
for ga in gen_all(5, 2, 2)
println(ga)
end
gives
[2, 0, 0, 2, 0]
[2, 0, 0, 0, 2]
[0, 0, 2, 2, 0]
[0, 2, 2, 0, 0]
[2, 0, 2, 0, 0]
[0, 2, 0, 2, 0]
[2, 2, 0, 0, 0]
[0, 0, 0, 2, 2]
[0, 0, 2, 0, 2]
[0, 2, 0, 0, 2]
[0, 2, 0, 1, 1]
[0, 1, 1, 0, 2]
[0, 1, 2, 0, 1]
[0, 1, 1, 2, 0]
[2, 1, 1, 0, 0]
[2, 1, 0, 0, 1]
[0, 0, 1, 1, 2]
[1, 2, 1, 0, 0]
[1, 2, 0, 0, 1]
[0, 1, 2, 1, 0]
[0, 1, 0, 1, 2]
[1, 0, 0, 1, 2]
[0, 2, 1, 1, 0]
[2, 0, 0, 1, 1]
[1, 0, 2, 0, 1]
[1, 2, 0, 1, 0]
[0, 1, 0, 2, 1]
[2, 0, 1, 0, 1]
[0, 2, 1, 0, 1]
[1, 0, 1, 2, 0]
[0, 0, 1, 2, 1]
[1, 0, 0, 2, 1]
[2, 1, 0, 1, 0]
[1, 1, 0, 0, 2]
[1, 0, 2, 1, 0]
[1, 0, 1, 0, 2]
[1, 1, 0, 2, 0]
[0, 0, 2, 1, 1]
[2, 0, 1, 1, 0]
[1, 1, 2, 0, 0]
[1, 1, 1, 0, 1]
[1, 1, 0, 1, 1]
[1, 0, 1, 1, 1]
[1, 1, 1, 1, 0]
[0, 1, 1, 1, 1]

Searching through a matrix with Ruby

I have a matrix like this:
0 1 0 0 1 0
1 0 1 0 1 0
0 1 0 1 0 0
0 0 1 0 1 1
1 1 0 1 0 0
0 0 0 1 0 0
How can I define a matrix in Ruby, and then search through it?
I would like to write a program which searches through all rows and returns rows with the highest sum of "1".
Quick way to define a matrix in Ruby:
Array.new 6, Array.new(6, 0)
# => [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
]
The above code initializes an array with 6 items and defaults their values to the 2nd argument which is another array with 6 items and default values of 0.
In other more imperative languages you would use nested loops:
matrix = []
for x in [0,1,2,3,4,5]
for y in [0,1,2,3,4,5]
matrix[x] ||= [] # create the row as an empty array
matrix[x] << y # push the y value to it
end
end
# matrix is now:
# => [
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]
]
To search through the matrix and find the row with greatest sum:
greatest_sum_row_index = 0
greatest_sum = 0
matrix.each_with_index do |row, i|
# row.inject(:+) is a shortcut to adding each int in the array and returning the sum
sum = row.inject(:+)
if sum > greatest_sum
greatest_sum = sum
greatest_sum_row_index = i
end
end
# highest_row is now the index of the greatest sum row
matrix[greatest_sum_row_index] # returns the row with the greatest sum
If the array were large and memory requirements were a concern, you might do something like this:
def rows_with_most_ones(arr)
arr.each_with_index.with_object([-1, nil]) do |(row,i),best|
tot = row.count(1)
case tot<=>best.first
when 1 then best.replace([tot, [i]])
when 0 then best.last << i
end
end
end
arr = [[0, 1, 0, 0, 1, 0],
[1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 0],
[0, 0, 1, 0, 1, 1],
[1, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0]]
rows_with_most_ones(arr)
#=> [3, [1, 3, 4]]

Understand disaster model in PyMC

I start learning PyMC and strungle to understand the very first tutorial´s example.
disasters_array = \
np.array([ 4, 5, 4, 0, 1, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6,
3, 3, 5, 4, 5, 3, 1, 4, 4, 1, 5, 5, 3, 4, 2, 5,
2, 2, 3, 4, 2, 1, 3, 2, 2, 1, 1, 1, 1, 3, 0, 0,
1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1,
0, 1, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2,
3, 3, 1, 1, 2, 1, 1, 1, 1, 2, 4, 2, 0, 0, 1, 4,
0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1])
switchpoint = DiscreteUniform('switchpoint', lower=0, upper=110, doc='Switchpoint[year]')
early_mean = Exponential('early_mean', beta=1.)
late_mean = Exponential('late_mean', beta=1.)
I don´t understand why early_mean and late_mean is modeled as stochastic variable following exponential distribution with rate = 1. My intuition is that they should be deterministic calculated using disasters_array and switchpoint variable e.g.
#deterministic(plot=False)
def early_mean(s=switchpoint):
return sum(disasters_array[:(s-1)])/(s-1)
#deterministic(plot=False)
def late_mean(s=switchpoint):
return sum(disasters_array[s:])/s
disasters_array are the data generated by a Poisson process, under the assumptions of this model. late_mean and early_mean are the parameters associated with this process, depending on when in the time series they occurred. The true values of the parameters are unknown, so they are specified as stochastic variables. Deterministic objects are only for nodes that are completely determined by the values of their parents.
Think of early_mean and late_mean stochastics as model parameters, and the Exponential as the prior distribution for these parameters. In the version of the model here, the deterministic r and likelihood D lead to posteriors on early_mean and late_mean through MCMC sampling.

Resources