Create an array of another array subelements in one line [closed] - ruby

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Like this
oldArray = [[a, b, c, d],[e, f, g, h]]
I need one line of code that will return a new array of, say, element 2 in each element of oldArray
newArray = coolLine(oldArray, 2)
newArray -> [c, g]

This does element number 2:
oldArray.map { |a| a[2] }

Smells a little like homework, but you're looking for the map function.
http://www.ruby-doc.org/core-2.0/Array.html
Have fun!

2nd element in each element of oldArray
oldArray = [[a, b, c, d],[e, f, g, h]]
newArray = coolLine(oldArray, 2)
newArray -> [c, g]
The thing you want can be achieved in many ways. Most common would be the map and zip.
The map function allows you to process the sequence and re-calculate any of its items to a new value:
arr = [ [ 1,2,3 ], %w{ a b c }, [ 10,20,30] ]
# proc will be called twice
# 'item' will first be [ 1,2,3 ] then %w{ a b c } and so on
result = arr.map{|item|
item[1]
}
result -> 2, then 'b', then 20
So, creating your "coolLine" seems pretty straightforward.
However, depending on other things, the zip may turn out to be even better. Zip takes N sequences and enumerates them sequentially returning Nth element from all at once. Why, that's almost exactly what you asked for:
arr = [ [ 1,2,3 ], %w{ a b c }, [ 10,20,30] ]
zipped = arr[0].zip(*arr[1..-1)
zipped -> [ [1,'a',10], [2,'b',20], [3,'c',30] ]
Or, of you don't like the [0]/*[1..-1] trick, you can easily write your own 'cleaner zip' like in here https://stackoverflow.com/a/1601250/717732

Related

fast and concurrent algorithm of frequency calculation in elixir

I have two big lists that their item's lengths isn't constant. Each list include millions items.
And I want to count frequency of items of first list in second list!
For example:
a = [[c, d], [a, b, e]]
b = [[a, d, c], [e, a, b], [a, d], [c, d, a]]
# expected result of calculate_frequency(a, b) is %{[c, d] => 2, [a, b, e] => 1} Or [{[c, d], 2}, {[a, b, e], 1}]
Due to the large size of the lists, I would like this process to be done concurrently.
So I wrote this function:
def calculate_frequency(items, data_list) do
items
|> Task.async_stream(
fn item ->
frequency =
data_list
|> Enum.reduce(0, fn data_row, acc ->
if item -- data_row == [] do
acc + 1
else
acc
end
end)
{item, frequency}
end,
ordered: false
)
|> Enum.reduce([], fn {:ok, merged}, merged_list -> [merged | merged_list] end)
end
But this algorithm is slow. What should I do to make it fast?
PS: Please do not consider the type of inputs and outputs, the speed of execution is important.
Not sure if this fast enough and certainly it's not concurrent. It's O(m + n) where m is the size of items and n is the size of data_list. I can't find a faster concurrent way because combining the result of all the sub-processes also takes time.
data_list
|> Enum.reduce(%{}, fn(item, counts)->
Map.update(counts, item, 1, &(&1 + 1))
end)
|> Map.take(items)
FYI, doing things concurrently does not necessarily mean doing things in parallel. If you have only one CPU core, concurrency actually slows things down because one CPU core can only do one thing at a time.
Put one list into a MapSet.
Go through the second list and see whether or not each element is in the MapSet.
This is linear in the lengths of the lists, and both operations should be able to be parallelized.
I would start by normalizing the data you want to compare so a simple equality check can tell if two items are "equal" as you would define it. Based on your code, I would guess Enum.sort/1 would do the trick, though MapSet.new/1 or a function returning a map may compare faster if it matches your use case.
defp normalize(item) do
Enum.sort(item)
end
def calculate_frequency(items, data_list) do
data_list = Enum.map(data_list, &normalize/1)
items = Enum.map(items, &normalize/1)
end
If you're going to get most frequencies from data list, I would then calculate all frequencies for data list. Elixir 1.10 introduced Enum.frequencies/1 and Enum.frequencies_by/2, but you could do this with a reduce if desired.
def calculate_frequency(items, data_list) do
data_frequencies = Enum.frequencies_by(data_list, &normalize/1) # does map for you
Map.new(items, &Map.get(data_frequencies, normalize(&1), 0)) # if you want result as map
end
I haven't done any benchmarks on my code or yours. If you were looking to do more asynchronous stuff, you could replace your mapping with Task.async_stream/3, and you could replace your frequencies call with a combination of Stream.chunk_every/2, Task.async_stream/3 (with Enum.frequencies/1 being the function), and Map.merge/3.

Generating a string of a specific length, then filling with a value [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am attempting to take a value x and generate a string with the length x so that I will have a value like "00000". I want to manipulate those values and return a value such as "22222", "11111", or "00000". I attempted manipulating an array, and I will do an array if necessary, but I prefer to avoid that as that seems to get unnecessarily lengthy.
def string_gen(length.to_i)
chars = %w(a b c d e f g h i j k l m n o p q r s t u w x y z)
random_string = chars.to_a[rand(chars.length)].join
puts random_string
end
string_gen(6)
#<= "jahsyd"
If you want to do it more then one time add a .times loop:
def string_gen(length.to_i)
chars = %w(a b c d e f g h i j k l m n o p q r s t u w x y z)
5.times do
random_string = chars.to_a[rand(chars.length)].join
puts random_string
end
end
This is completely untested.

Sort nested array by content

I have a data structude ST that contains an array of entities of ST.
struct ST {
ST[];
}
I need to sort it by deep-value.
For example i have an array of ST: [A { B, C, D }, B { C, D }, C, D { E }, E, F]
And i want to get result like this: [E, D, C, B, E, F, A]
Can somebody help me?
The solution depends on what language you are using however the basic idea remains the same. The idea is that each struct can have a value assigned which can then be used for sorting.
A similar question was asked here: Sort ArrayList of custom Objects by property
I hope this helps, but generally you should try asking questions in greater detail

fuzzy list of items - shuffled, but in strict order

I have a list of questions and I need to present each question in a different format.
(a list of N items with M possible permutations for each item).
e.g.
questions = [a, b, c]
permutations = [x, y]
permuted_questions = [(a,x), (b,x), (c,x), (a,y), (b,y), (c,y)]
Producing a simple list of permutations like above is straightforward. However,
To make the list more "interesting", I'd like to shuffle it somehow.
The problem is that the list of permutations is strictly ordered. i.e. for given item a, permutation (a,x) should always appear before permutation (a,y).
e.g.
[(a,x), (b,x), (a,y), (c,x), (b,y), (c,y)] is a valid shuffle
[(a,x), (b,y), (a,y), (c,x), (b,x), (c,y)] is invalid, because (b,y) appears before (b,x)
Any suggestions?
You could simply shuffle the questions into any permutation, and then postprocess the list by labelling the first "a" question x, and the second "a" question y, and so on for the other types of question.
e.g.:
Construct shuffle:
(a,x), (b,y), (a,y), (c,x), (b,x), (c,y)
Turn into valid shuffle:
(a,x), (b,x), (a,y), (c,x), (b,y), (c,y)
Example Python code:
from random import shuffle
from itertools import product
from collections import defaultdict
questions = ['a', 'b', 'c']
permutations = ['x', 'y']
Q = list(product(questions,permutations))
shuffle(Q)
D = defaultdict(int) # Keep track of permutation to use for each question
C = []
for q,p in Q:
C.append( (q,permutations[D[q]]) )
D[q] += 1
print C

A Prolog predicate result [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have written a Prolog relation remove(E,L,R) that is true if R is the list which results from removing one instance of E from list L. The relation is false if E isn't a member of L.
I want to know the result of the following query
remove(p(X),[a,p(a),p(p(a)),p(p(p(a)))],R).
So? Just ask. Not us, but ask Prolog. The result should be
?- remove(p(X),[a,p(a),p(p(a)),p(p(p(a)))],R).
X = a,
R = [a, p(p(a)), p(p(p(a)))]
or something along those lines, if you've written it right. If you allow backtracking (in other words, removing an element from your list, starting with the first), you'll get something like
?- remove(p(X),[a,p(a),p(p(a)),p(p(p(a)))],R).
X = a,
R = [a, p(p(a)), p(p(p(a)))] ;
X = p(a),
R = [a, p(a), p(p(p(a)))] ;
X = p(p(a)),
R = [a, p(a), p(p(a))] ;
false.

Resources