How is a double for loop implemented in Elixir?
I was interested in writing a double for loop to compare a naiveSort to a quickSort implementation.
Then I realized I don't even know how to write a double for loop in elixir!
So, how is a double for loop written in Elixir? Keep in mind I'm trying to do a naiveSort...
An idiomatic way to do this might use list comprehensions like:
defmodule Quick do
def sort([first | rest]) do
sort(for(n <- rest, n < first, do: n)) ++
[first] ++
sort(for(n <- rest, n >= first, do: n))
end
def sort([]) do
[]
end
end
iex(5)> Quick.sort [5,4,3,2,1]
[1, 2, 3, 4, 5]
Of course quick sort lends itself quite nicely to a recursive solution since the algorithm is "sort all the items smaller than me, then add me, then add all the items larger than me". Which is expressed very nearly in Elixir (and Erlang).
The for is a list comprehension. It builds a list based upon a generator (the n <- rest part and a filter (the n < first part).
Related
Suppose that we have a Lua table called t, defined as follows:
t = {4, 5, 6, 7}
Suppose we wish further to know what the product of the numbers in t is. (Aside: the answer is 840.) I can think of two methods.
First, a basic for loop:
answer = 1
for i = 1, #t do
answer = answer * t[i]
end
print ( answer )
Second, an ipairs iterator:
answer = 1
for i, j in ipairs ( t ) do
answer = answer * j
end
print ( answer )
(I suppose one could also use a pairs iterator.)
My questions:
Does either of the two methods shown above suffer from any real drawbacks?
Are there methods for obtaining the desired value of answer that are more efficient and/or robust than the methods shown above?
ipairs involves a function call. This makes generic for-loop slower tiny bit. If the inner task is anything complex, the function call overhead will be negligible, in comparison to a few arithmetic operations it may be notable in some extreme cases. Try it:
a={}
for i=1,2e8 do a[i]=math.random() end
t=os.time()
q=1
for i=1,#a do q=q*a[i] end
print(os.time()-t)
w=1
t=os.time()
for i,v in ipairs(a) do w=w*v end
print(os.time()-t)
For me results were 15 and 18.
It is more impactful when the calculation is repeated multiple times (nested loops):
a={} for i=1,1e4 do a[i]=math.random() end
t=os.time() q=1; for i=1,1e5 do for j=1,1e4 do q=q*a[j] end end print(os.time()-t)
t=os.time() q=1; for i=1,1e5 do for _,v in ipairs(a) do q=q*v end end print(os.time()-t)
But still not a lot.
If you really need to squeeze out even that bit of performance, you probably should take a look at luajit and various numeric frameworks based on it: 1, 2, 3.
Also, there's article on optimization by the language author.
So I'm trying to code something for my class that will output an int list of the first k terms in an n-step fibonacci sequence.
So for those of you that don't know, an n step fibonacci sequence is when you add the n numbers before it to get the next one,
so for n=1 it'd be 1,1,1,1,1,...
n=2, it'd be 1,1,2,3,5,...
n=3 it'd be 1,1,2,4,7...
My approach was to start of with a base case, so
let rec n_step n k=
if k=1 then [1] else
if n=1 then 1::nacci n k-1 else
but now I'm stuck here. I know I need to iterate through and add up the terms in the list, but I'm not sure how to accomplish this.
I made a helper function sum
let rec sum lst =
match lst with
| [] -> 0
| h::t -> h + sum t
I was trying to make it selectively add the last n numbers of the list to get the next value but I got stuck on that as well
Thanks in advance!
This is homework so I'll only suggest some steps, not a complete solution:
if you come from an imperative background, try first an imperative solution such as a loop that prints the result instead of building a list and tying the recursion at once. You can store the required state in a global and gradually change that to pass parameters.
start with n=2, using a tuple instead of a list. It will be considerably easier to do that first, manually extend to fixed n=3 and fixed n=4 before using a list.
Applying these two pieces of advice, a first step might be:
let print_fib_2 () =
let previous_ref = ref (1, 1) in
for i = 0 to 10 do
let (a, b) = !previous_ref in
let next = a + b in
previous_ref := (next, a);
Printf.printf "%d\n" next
done
I'd first generalize to using changing n=2 to n=3: what happens to the pairs (a, b) and (next, a)? what does it mean in terms of lists?
By following baby steps from a working example you should be able to work to a solution.
I've figured it out using many helper functions.
So I've made a sum function that would sum up the values in a list
A gather function that would only take the n values from the entire list
and then in my original function, I used pattern matching for the k's such that if k=1, it would yield one and otherwise it would recurse. If it wasn't one I appended the next value using the helper
I am trying to loop the numbers 1 to 1000 in such a way that I have all possible pairs, e.g., 1 and 1, 1 and 2, 1 and 3, ..., but also 2 and 1, 2 and 2, 2 and 3, et cetera, and so on.
In this case I have a condition (amicable_pair) that returns true if two numbers are an amicable pair. I want to check all numbers from 1 to n against each other and add all amicable pairs to a total total. The first value will be added to the total if it is part of an amicable pair (not the second value of the pair, since we'll find that later in the loop). To do this I wrote the following "Java-like" code:
def add_amicable_pairs(n)
amicable_values = []
for i in 1..n
for j in 1..n
if (amicable_pair?(i,j))
amicable_values.push(i)
puts "added #{i} from amicable pair #{i}, #{j}"
end
end
end
return amicable_values.inject(:+)
end
Two issues with this: (1) it is really slow. (2) In Ruby you should not use for-loops.
This is why I am wondering how this can be accomplished in a faster and more Ruby-like way. Any help would be greatly appreciated.
Your code has O(n^2) runtime, so if n gets moderately large then it will naturally be slow. Brute-force algorithms are always slow if the search space is large. To avoid this, is there some way you can directly find the "amicable pairs" rather than looping through all possible combinations and checking one by one?
As far as how to write the loops in a more elegant way, I would probably rewrite your code as:
(1..n).to_a.product((1..n).to_a).select { |a,b| amicable_pair?(a,b) }.reduce(0, &:+)
(1..1000).to_a.repeated_permutation(2).select{|pair| amicable_pair?(*pair)}
.map(&:first).inject(:+)
Let's say we have a Set S which contains a few subsets:
- [a,b,c]
- [a,b]
- [c]
- [d,e,f]
- [d,f]
- [e]
Let's also say that S contains six unique elements: a, b, c, d, e and f.
How can we find all possible subsets of S that contain each of the unique elements of S exactly once?
The result of the function/method should be something like that:
[[a,b,c], [d,e,f]];
[[a,b,c], [d,f], [e]];
[[a,b], [c], [d,e,f]];
[[a,b], [c], [d,f], [e]].
Is there any best practice or any standard way to achieve that?
I would be grateful for a Pseudo-code, Ruby or Erlang example.
It sounds like what you are looking for are the partitions of a set/array.
One way of doing this is recursively:
a 1 element array [x] has exactly one partition
if x is an array of the form x = [head] + tail, then the partitions of x are generated by taking each partition of tail and adding head to each possible. For example if we were generating the partitions of [3,2,1] then from the partition [[2,1]] of [2,1] we can either add 3 to to [2,1] or as a separate element, which gives us 2 partitions [[3,2,1] or [[2,1], [3]] of the 5 that [1,2,3] has
A ruby implementation looks a little like
def partitions(x)
if x.length == 1
[[x]]
else
head, tail = x[0], x[1, x.length-1]
partitions(tail).inject([]) do |result, tail_partition|
result + partitions_by_adding_element(tail_partition, head)
end
end
end
def partitions_by_adding_element(partition, element)
(0..partition.length).collect do |index_to_add_at|
new_partition = partition.dup
new_partition[index_to_add_at] = (new_partition[index_to_add_at] || []) + [element]
new_partition
end
end
Why not to use the greedy algorithm?
1) sort set S descending using the subsets length
2) let i := 0
3) add S[i] to solution
4) find S[j] where j > i such as it contains of elements which are not in current solution
5) if you can't find element described in 4 then
5.a) clear solution
5.b) increase i
5.c) if i > |S| then break, no solution found ;(
5.d) goto 3
EDIT
Hmm, read again your post and come to conclusion that you need a Best-First search. Your question is not actually a partition problem because what you need is also known as Change-making problem but in the latter situation the very first solution is taken as the best one - you actually want to find all solutions and that's the reason why you should you the best-first search strategy approach.
It seems like a classic "backtrack" excercise.
#1: Order your sets amongst eacother, so the backtrack will not give solutions twice.
#2: current_set = [], set_list=[]
#3: Loop Run through all the set that have lower order mark than the last in the set_list, (or all if the set_list is empty). Let call it set_at_hand
#4: If set_at_hand has no intersection with current_set
#4/true/1: Union it to current_set, also add to set_list.
#4/true/2: current_set complete? true: add set_list to the list of correct solutions. false: recurse to #3
#4/true/3: remove set_at_hand from current_set and set_list
#5: End of loop
#6: return
generate all subsets
def allSubsets set
combs=2**set.length
subsets=[]
for i in (0..combs) do
subset=[]
0.upto(set.length-1){|j| subset<<set[j] if i&(1<<j)!=0}
subsets<<subset
end
subsets
end
take a look here: https://github.com/sagivo/algorithms/blob/master/powerset.rb
this is a simple algorithm i built to find a powerset of an array.
I'm new to Ruby and just started to pick up the language a couple of days back. As an exercise, I tried to implement a simple quicksort
class Sort
def swap(i,j)
#data[i], #data[j] = #data[j], #data[i]
end
def quicksort(lower=0, upper = #data.length - 1)
return nil if lower >= upper
m = lower
i = 0
((lower+1)..upper).each do |i|
swap(++m, i) if #data[i] < #data[lower]
end
swap(m, lower)
quicksort1(lower, m -1)
quicksort1(m+1, upper)
end
end
Calling quicksort on say 10000 integers gives me a stack-level error. After googling, I figured out that tail-recursion isn't supported yet in Ruby (kind of). But then I found the following snippet (from here)
def qs(v)
return v if v.nil? or v.length <= 1
less, more = v[1..-1].partition { |i| i < v[0] }
qs(less) + [v[0]] + qs(more)
end
Running the second snippet works perfectly well even with a million integers. Yet, as far as I can tell, there's tail recursion at the end. So what am I not understanding here?
Neither of the methods you've shown are tail recursive (well technically the first one is half tail-recursive: the second recursive call is a tail call, but the first one is not - the second method is not tail recursive at all).
The reason that the first method overflows the stack, but the second one does not is that the first method recurses much deeper than the second (linearly instead of logarithmically) because of a bug (++m just applies the unary + operator to m twice - it does not actually do anything to m).
When given a large enough array both versions will overflow (and would do so even if ruby did perform TCO), but without the bug 10000 elements is not nearly large enough.