I am having trouble understanding this lambda calculus from Understanding Computation - ruby

In Tom Stuart's book Understanding Computation, there is a chapter devoted to rebuilding FizzBuzz through Procs/Lambdas. He begins by talking about how to define numbers through procs, and shows that a 'number' could be represented by a proc that is run x number of times for the number it represents (i.e., 1 is proc[x], 2 is proc[proc[x]], etc). That makes sense. However, the next bit he defines a to_integer method as such:
def to_integer(proc)
proc[-> n { n + 1 }][0]
end
This has broken my brain. I cannot make sense of what this means. I have admittedly not worked with procs much, other than lambdas in scope while working with rails.
I can simplify it to
def to_integer(proc)
proc[Proc.new(n){ n + 1 }][0]
end
...but that is as far as I can seem to get. Can anyone explain or simplify this in a way that is easier to understand? What is going on here? I'm confused by the proc[x][0] style, where n is coming from. I am just having a very tough time understanding this.
In the book, the procs being passed to this method are like so:
ZERO = -> p { -> x { x } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }

The code in to_integer chains 2 proc calls using Ruby's [] shorthand for calling a proc.
It's helpful to walk through it by hand in IRB. Lets start by defining ZERO(a lambda):
ZERO = -> p { -> x { x } }
=> #<Proc:0x007ff86a147930#(irb):103 (lambda)>
You will see different numbers here but the important part is that ZERO is a lambda, which is a proc.
Let's give the anonymous lambda in to_integer a name to make it clear what's going on there. Using the "stabby lambda" syntax:
INCR = -> n { n + 1 }
INCR[2]
=> 3
INCR[3]
=> 4
We send in a number, it returns that number plus 1.
We then pass ZERO into to_integer and it starts things off by calling the lambda ZERO and sending in INCR:
ZERO[INCR]
=> #<Proc:0x007ff86a0decf0#(irb):103 (lambda)>
As you can see this returns another lambda(the one defined in ZERO where p is set to INCR). We can now start the ball rolling by calling this lambda and sending in 0:
ZERO[INCR][0]
=> 0

A proc literal has the syntax "-> parameters { body }". An concrete example of a proc literal to increment a number is "-> n { n + 1 }". For readability, a proc literal can be assigned to a variable, e.g. "INCREMENT = -> n { n + 1 }".
A proc literal can be called by using square brackets "-> parameters { body }[arguments]". Using the previous example, here's how to increment 9 to give you 10 "-> n { n + 1 }[9]". The passed in argument "9" is represented by the parameter "n" in the body, and 1 is added to "n" to give the result. Again, for readability, "INCREMENT[9]" can be used to give the same result.
Now let's look at "ZERO = -> p { -> x { x } }". When "ZERO[INCREMENT][0]" is executed, the "ZERO[INCREMENT]" part is executed first. The result is "-> x { x }" and, by substitution, the original statement becomes "-> x { x }[0]". When that is executed, it returns a 0.
Now let's look at "ONE = -> p { -> x { p[x] } }". When "ONE[INCREMENT][0]" is executed, the "ONE[INCREMENT]" part is executed first. The result is "-> x { p[x] }" where p is "INCREMENT". By substitution, the original statement becomes "-> x { INCREMENT[x] }[0]". When that is executed, basically INCREMENT is called with 0, i.e. "INCREMENT[0]", and the result is 1.
Finally, let's look at:
def to_integer(proc)
proc[-> n { n + 1 }][0]
end
"to_integer(ZERO)" executes "ZERO[-> n { n + 1 }][0]". Note that "-> n { n + 1}" is the same as INCREMENT, so that execution is the same as ZERO[INCREMENT][0]. And as stated above, that produces 0.
"to_integer(ONE)" executes "ONE[-> n { n + 1 }][0]". Note that "-> n { n + 1}" is the same as INCREMENT, so that execution is the same as ONE[INCREMENT][0]. And as stated above, that produces 1.
The same process can be applied to TWO, etc.

Well the base idea here actually came from constructing natural numbers as in Peano Axioms (http://en.wikipedia.org/wiki/Peano_axioms)
Therefore zero is 0, one is S(0), two is S(S(0)), three is S(S(S(0))) etc (where S is some function).
Secondly this method may be rewritten, substituting [] for call:
def to_integer(proc)
proc.call(Proc.new { |n| n + 1 }).call(0)
end
And we can see now clearly it does reverse computation - when we try to count how many is one (which actually is S(0), or in our notation -> p { -> x { p[x] } } which is equivalent to Proc.new { |p| Proc.new { |x| p.call(x) } }, it stores information about that it needs to S(x), where is something we don't know (argument of our proc)
And now is the tricky part. Here Ruby calls our definition of one (it's a Proc, so it can be called!) passing as argument another Proc - this one is equivalent to S function (n + 1). So before final .call(0) we have sequence of Procs - calling deeper one with argument increased by 1 (because of our integer) - S(x). And by final call(0) we set base of our natural numbers S(0).
Maybe it will be helpful to consider some examples:
What number we will get when we substitute to_integer with:
def to_integer(proc)
proc[-> n { n + 1 }][0]
end
(it may be interesting that this numbers are as good natural numbers as standard one).
What will happen if we change the base in call, from 0 to 1?

Related

How to decide between Global or Local vector for m choose n

Suppose we want to write a code that prints all ways of selecting n out of m options.
I think, the programming language does not matter, but if I should state it, Python.
I put the assignments in a vector A. Do I better define A as a global variable or pass it to the function each time? Why?
def choose(ind, n):
if n == 0:
print(A)
return
elif len(A)<= ind:
return
else:
A[ind] = 1
choose(ind + 1, n - 1)
A[ind] = 0
choose(ind + 1, n)
Always prefer passing over mutating globals whenever feasible.
Say you have the following functions:
def some_fun1 (n):
return n + 1;
m = 1;
def some_fun2 ():
return m + 1
With the first function, you can load up your REPL and throw data at it just by passing it as an argument. Your testing of that pure function has 0 effect on the rest of the program, which makes testing significantly easier.
With the second function, any time you need to test it, you must manually set all the globals the function relies on, which could potentially affect the operation of other functions if they rely on the same globals. This makes testing harder, and for that reason, among others, mutating globals should be avoided.

Corrects sequences of parenthesis

Corrects sequences of parentesis can be defined recursively:
The empty string "" is a correct sequence.
If "X" and "Y" are correct sequences, then "XY" (the concatenation of
X and Y) is a correct sequence.
If "X" is a correct sequence, then "(X)" is a correct sequence.
Each correct parentheses sequence can be derived using the above
rules.
Given two strings s1 and s2. Each character in these strings is a parenthesis, but the strings themselves are not necessarily correct sequences of parentheses.
You would like to interleave the two sequences so that they will form a correct parentheses sequence. Note that sometimes two different ways of interleaving the two sequences will produce the same final sequence of characters. Even if that happens, we count each of the ways separately.
Compute and return the number of different ways to produce a correct parentheses sequence, modulo 10^9 + 7.
Example s1 = (() and s2 = ())
corrects sequences of parentheses, s1 (red) and s2(blue)
I don't understand the recursive algorithm, what does X and Y mean? And modulo 10^9 + 7?
First, I tried defining all permutations of s1 and s2 and then calculate the number of balanced parentheses. But that way is wrong, isn't it?
class InterleavingParenthesis:
def countWays(self, s1, s2):
sequences = list(self.__exchange(list(s1 + s2)))
corrects = 0
for sequence in sequences:
if self.__isCorrect(sequence):
corrects += 1
def __isCorrect(self, sequence):
s = Stack()
balanced = True
i = 0
while i < len(sequence) and balanced:
if '(' == sequence[i]:
s.stack(sequence[i])
elif s.isEmpty():
balanced = False
else: s.remove()
i += 1
if s.isEmpty() and balanced: return True
else: return False
def __exchange(self, s):
if len(s) <= 0: yield s
else:
for i in range(len(s)):
for p in self.__exchange(s[:i] + s[i + 1:]):
yield [s[i]] + p
class Stack:
def __init__(self):
self.items = []
def stack(self, data):
self.items.append(data)
def remove(self):
self.items.pop()
def isEmpty(self):
return self.items == []
Here's an example that shows how this recursive property works:
Start with:
X = "()()(())"
Through property 2, we break this into further X and Y:
X = "()" ; Y = "()(())"
For X, we can look at the insides with property 3.
X = ""
Because of property 1, we know this is valid.
For Y, we use property 2 again:
X = "()"
Y = "(())"
Using the same recursion as before (property 2, then property 1) we know that X is valid. Note that in code, you usually have to go through the same process, I'm just saving time for humans. For Y, you use property 3:
X = "()"
And again.. :
X = ""
And with property 1, you know this is valid.
Because all sub-parts of "()()(())" are valid, "()()(())" is valid. That's an example of recursion: You keep breaking things down into smaller problems until they are solvable. In code, you would have the function call itself with regards to a smaller part of it, in your case, X and Y.
As for the question you were given, there is a bit that doesn't make sense to me. I don't get how there is any room for doubt in any string of parentheses, like in the image you linked. In "((()())())" for example, there is no way these two parentheses do not match up: "((()())())". Therefore my answer would be that there is only one permutation for every valid string of parentheses, but this obviously is wrong somehow.
Could you or anyone else expand on this?

Algorithm to print all valid combations of n pairs of parenthesis

I'm working on the problem stated in the question statement. I know my solution is correct (ran the program) but I'm curious as to whether or not I'm analyzing my code (below) correctly.
def parens(num)
return ["()"] if num == 1
paren_arr = []
parens(num-1).each do |paren|
paren_arr << paren + "()" unless "()#{paren}" == "#{paren}()"
paren_arr << "()#{paren}"
paren_arr << "(#{paren})"
end
paren_arr
end
parens(3), as an example, will output the following:
["()()()", "(()())", "(())()", "()(())", "((()))"]
Here's my analysis:
Every f(n) value is roughly 3 times as many elements as f(n-1). So:
f(n) = 3 * f(n-1) = 3 * 3 * f(n-2) ~ (3^n) time cost.
By a similar analysis, the stack will be occupied by f(1)..f(n) and so the space complexity should be 3^n.
I'm not sure if this analysis for either time or space is correct. On the one hand, the stack only holds n function calls, but each of these calls returns an array ~3 times as big as the call before it. Does this factor into space cost? And is my time analysis correct?
As others have mentioned, your solution is not correct.
My favourite solution to this problem generates all the valid combinations by repeatedly incrementing the current string to the lexically next valid combination.
"Lexically next" breaks down into a few rules that make it pretty easy:
The first difference in the string changes a '(' to a ')'. Otherwise the next string would be lexically before the current one.
The first difference is as far to the right as possible. Otherwise there would be smaller increments.
The part after the first difference is lexically minimal, again because otherwise there would be smaller increments. In this case that means that all the '('s come before all the ')'.
So all you have to do is find the rightmost '(' that can be changed to a ')', flip it, and then append the correct number of '('s and ')'s.
I don't know Ruby, but in Python it looks like this:
current="(((())))"
while True:
print(current)
opens=0
closes=0
pos=0
for i in range(len(current)-1,-1,-1):
if current[i]==')':
closes+=1
else:
opens+=1
if closes > opens:
pos=i
break
if pos<1:
break
current = current[:pos]+ ")" + "("*opens + ")"*(closes-1)
Output:
(((())))
((()()))
((())())
((()))()
(()(()))
(()()())
(()())()
(())(())
(())()()
()((()))
()(()())
()(())()
()()(())
()()()()
Solutions like this turn out to be easy and fast for many types of "generate all the combinations" problems.
Recursive reasoning makes a simple solution. If the number of left parens remaining to emit is positive, emit one and recur. If the number of right parens remaining to emit is greater than the number of left, emit and recur. The base case is when all parens, both left and right, have been emitted. Print.
def parens(l, r = l, s = "")
if l > 0 then parens(l - 1, r, s + "(") end
if r > l then parens(l, r - 1, s + ")") end
if l + r == 0 then print "#{s}\n" end
end
As others have said, the Catalan numbers give the number of strings that will be printed.
While this Ruby implementation doesn't achieve it, a lower level language (like C) would make it easy to use a single string buffer: O(n) space. Due to substring copies, this one is O(n^2). But since the run time and output length are O(n!), O(n) space inefficiency doesn't mean much.
I found Tom Davis' article, "Catalan Numbers," very helpful in explaining one recursive method for defining the Catalan Numbers. I'll try to explain it myself (in part, to see how much of it I've understood) as it may be applied to finding the set of all unique arrangements of N matched parentheses (e.g., 1 (); 2 ()(), (()); etc. ).
For N > 1 let (A)B represent one arrangement of N matched parentheses, where A and B each have only balanced sets of parentheses. Then we know that if A contains k matched sets, B must have the other N - k - 1, where 0 <= k <= N - 1.
In the following example, a dot means the group has zero sets of parentheses:
C_0 => .
C_1 => (.)
To enumerate C_2, we arrange C_1 as AB in all ways and place the second parentheses around A:
. () = AB = C_0C_1 => (.)()
() . = AB = C_1C_0 => (()) .
Now for C_3, we have three partitions for N - 1, each with its own combinations: C_0C_2, C_1C_1, C_2C_0
C_0C_2 = AB = . ()() and . (()) => ()()(), ()(())
C_1C_1 = AB = ()() => (())()
C_2C_0 = AB = ()() . and (()) . => (()()), ((()))
We can code this method by keeping a set for each N and iterating over the combinations for each partition. We'll keep the individual arrangements as bits: 0 for left and 1 for right (this appears backwards when cast as a binary string).
def catalan
Enumerator.new do |y|
# the zero here represents none rather than left
s = [[0],[2]]
y << [0]
y << [2]
i = 2
while true
s[i] = []
(0..i - 1).each do |k|
as = s[k]
bs = s[i - k - 1]
as.each do |a|
bs.each do |b|
if a != 0
s[i] << ((b << (2*k + 2)) | (1 << (2*k + 1)) | (a << 1))
else
s[i] << (2 | (b << 2))
end
end # bs
end # as
end # k
y.yield(s[i])
i = i + 1
end # i
end # enumerator
end
catalan.take(4)
# => [[0], [2], [10, 12], [42, 50, 44, 52, 56]]
The yielder is lazy: although the list is infinite, we can generate as little as we like (using .take for example):
catalan.take(4).last.map{|x| x.to_s(2)}
# => ["101010", "110010", "101100", "110100", "111000"]
The former generation obliges us to keep all previous sets in order to issue the next. Alternatively, we can build a requested set through a more organic type, meandering recursion. This next version yields each arrangement to the block, so we can type:
catalan(4){
|x| (0..7).reduce(""){
|y,i| if x[i] == 0 then y + "(" else y + ")" end
}
}.take(14)
# => ["(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())",
# "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()",
# "()()(())", "()()()()"]
Direct generation:
def catalan(n)
Enumerator.new do |y|
s = [[0,0,0]]
until s.empty?
left,right,result = s.pop
if left + right == 2 * n
y << yield(result)
end
if right < left
s << [left, right + 1, result | 1 << (left + right)]
end
if left < n
s << [left + 1, right, result]
end
end
end
end

I don't understand this method

I'm a beginner in Ruby and I don't understand what this code is doing, could you explain it to me, please?
def a(n)
s = 0
for i in 0..n-1
s += i
end
s
end
def defines a method. Methods can be used to run the same code on different values. For example, lets say you wanted to get the square of a number:
def square(n)
n * n
end
Now I can do that with different values and I don't have to repeat n * n:
square(1) # => 1
square(2) # => 4
square(3) # => 9
= is an assignment.
s = 0 basically says, behind the name s, there is now a zero.
0..n-1 - constructs a range that holds all numbers between 0 and n - 1. For example:
puts (0..3).to_a
# 0
# 1
# 2
# 3
for assigns i each consecutive value of the range. It loops through all values. So first i is 0, then 1, then ... n - 1.
s += i is a shorthand for s = s + i. In other words, increments the existing value of s by i on each iteration.
The s at the end just says that the method (remember the thing we opened with def) will give you back the value of s. In other words - the sum we accumulated so far.
There is your programming lesson in 5 minutes.
This example isn't idiomatic Ruby code even if it is syntactically valid. Ruby hardly ever uses the for construct, iterators are more flexible. This might seem strange if you come from another language background where for is the backbone of many programs.
In any case, the program breaks down to this:
# Define a method called a which takes an argument n
def a(n)
# Assign 0 to the local variable s
s = 0
# For each value i in the range 0 through n minus one...
for i in 0..n-1
# ...add that value to s.
s += i
end
# The result of this method is s, the sum of those values.
s
end
The more Ruby way of expressing this is to use times:
def a(n)
s = 0
# Repeat this block n times, and in each iteration i will represent
# a value in the range 0 to n-1 in order.
n.times do |i|
s += i
end
s
end
That's just addressing the for issue. Already the code is more readable, mind you, where it's n.times do something. The do ... end block represents a chunk of code that's used for each iteration. Ruby blocks might be a little bewildering at first but understanding them is absolutely essential to being effective in Ruby.
Taking this one step further:
def a(n)
# For each element i in the range 0 to n-1...
(0..n-1).reduce |sum, i|
# ...add i to the sum and use that as the sum in the next round.
sum + i
end
end
The reduce method is one of the simple tools in Ruby that's quite potent if used effectively. It allows you to quickly spin through lists of things and compact them down to a single value, hence the name. It's also known as inject which is just an alias for the same thing.
You can also use short-hand for this:
def a(n)
# For each element in the range 0 to n-1, combine them with +
# and return that as the result of this method.
(0..n-1).reduce(&:+)
end
Where here &:+ is shorthand for { |a,b| a + b }, just as &:x would be short for { |a,b| a.x(b) }.
As you are a beginner in Ruby, let's start from the small slices.
0..n-1 => [0, n-1]. E.g. 0..3 => 0, 1, 2, 3 => [0, 3]
for i in 0.. n-1 => this is a for loop. i traverses [0, n-1].
s += i is same as s = s + i
So. Method a(n) initializes s = 0 then in the for loop i traverse [0, n - 1] and s = s + i
At the end of this method there is an s. Ruby omits key words return. so you can see it as return s
def a(n)
s = 0
for i in 0..n-1
s += i
end
s
end
is same as
def a(n)
s = 0
for i in 0..n-1
s = s + i
end
return s
end
a(4) = 0 + 1 + 2 + 3 = 6
Hope this is helpful.
The method a(n) calculates the sums of the first n natural numbers.
Example:
when n=4, then s = 0+1+2+3 = 6
Let's go symbol by symbol!
def a(n)
This is the start of a function definition, and you're defining the function a that takes a single parameter, n - all typical software stuff. Notably, you can define a function on other things, too:
foo = "foo"
def foo.bar
"bar"
end
foo.bar() # "bar"
"foo".bar # NoMethodError
Next line:
s = 0
In this line, you're both declaring the variable s, and setting it's initial value to 0. Also typical programming stuff.
Notably, the value of the entire expression; s = 0, is the value of s after the assignment:
s = 0
r = t = s += 1 # You can think: r = (t = (s += 1) )
# r and t are now 1
Next line:
for i in 0..n-1
This is starting a loop; specifically a for ... in ... loop. This one a little harder to unpack, but the entire statement is basically: "for each integer between 0 and n-1, assign that number to i and then do something". In fact, in Ruby, another way to write this line is:
(0..n-1).each do |i|
This line and your line are exactly the same.
For single line loops, you can use { and } instead of do and end:
(0..n-1).each{|i| s += i }
This line and your for loop are exactly the same.
(0..n-1) is a range. Ranges are super fun! You can use a lot of things to make up a range, particularly, time:
(Time.now..Time.new(2017, 1, 1)) # Now, until Jan 1st in 2017
You can also change the "step size", so that instead of every integer, it's, say, every 1/10:
(0..5).step(0.1).to_a # [0.0, 0.1, 0.2, ...]
Also, you can make the range exclude the last value:
(0..5).to_a # [0, 1, 2, 3, 4, 5]
(0...5).to_a # [0, 1, 2, 3, 4]
Next line!
s += i
Usually read aloud a "plus-equals". It's literally the same as: s = s + 1. AFAIK, almost every operator in Ruby can be paired up this way:
s = 5
s -= 2 # 3
s *= 4 # 12
s /= 2 # 6
s %= 4 # 2
# etc
Final lines (we'll take these as a group):
end
s
end
The "blocks" (groups of code) that are started by def and for need to be ended, that's what you're doing here.
But also!
Everything in Ruby has a value. Every expression has a value (including assignment, as you saw with line 2), and every block of code. The default value of a block is the value of the last expression in that block.
For your function, the last expression is simply s, and so the value of the expression is the value of s, after all is said and done. This is literally the same as:
return s
end
For the loop, it's weirder - it ends up being the evaluated range.
This example may make it clearer:
n = 5
s = 0
x = for i in (0..n-1)
s += i
end
# x is (0..4)
To recap, another way to write you function is:
def a(n)
s = 0
(0..n-1).each{ |i| s = s + i }
return s
end
Questions?

Return values not working as expected in Ruby in a program that solves fibonacci sequence using dynamic programming

I'm new to ruby so I'm probably making a very newbie mistake here but I tried Googling for an answer and couldn't figure out the reason why this code is giving weird behavior. This code is very simple, and uses basic dynamic programming to store intermediate result to a Hash so it is used later to speed up the computation.
$existingSequence = {0 => 1, 1 => 2}
def fib(n)
if $existingSequence.has_key? n
return $existingSequence.values_at n;
end
if n == 0
return 1;
elsif n == 1
return 2;
end
$existingSequence[n] = fib(n - 1) + fib(n - 2)
return $existingSequence[n];
end
n = fib(2)
puts n
I expect this code to output 3 since that makes a call to fib(1) and fib(0) which returns 2 and 1 respectively, and then added to be 3. But the output is 1 and 2.
Hash.values_at returns an array, so when the code does fib(1) + fib(0), it's concatenating the arrays [2] and [1] together, resulting in the answer [2, 1]. Instead of:
return $existingSequence.values_at n;
...you should do this instead:
return $existingSequence[n]
BTW, the Fibonacci sequence traditionally starts with 0 and 1, not 1 and 2.
Slightly off-topic, here's a fun way of doing essentially the same thing, but using the Hash default value mechanism to use the Hash not only for caching, but also for computing the values:
fibs = { 0 => 0, 1 => 1 }.tap do |fibs|
fibs.default_proc = ->(fibs, n) { fibs[n] = fibs[n-1] + fibs[n-2] }
end
fibs[9]
# => 34
Note: I didn't come up with this myself, I stole it from here.
The second line of fib should read:
return $existingSequence[n]
instead of
return $existingSequence.values_at n
Add puts $existingSequence to the end of the file to see the difference.

Resources