Query on lambda calculus addition - lambda-calculus

How do I add two numbers in lambda calculus using below given arithmetic representation of addition?
m + n = λx.λy.(m x) (n x) y
2 = λa.λb.a (a b)
3 = λa.λb.a (a (a b))

You know what 2 is, what 3 is, and what addition is. Take the values and just stick 'em into the operation!
2 + 3 = (λx.λy.(m x) (n x) y) (λa.λb.a (a b)) (λa.λb.a (a (a b)))
|-------- + --------| |----- 2 -----| |------- 3 -------|
This is an application with a lambda on the left. Such a term is called a redex, and it can be β-reduced. The actual reduction is left as an exercise for the reader.

Related

SICP solution to Fibonacci, set `a + b = a`, why not `a + b = b`?

I am reading Tree Recursion of SICP, where fib was computed by a linear recursion.
We can also formulate an iterative process for computing the
Fibonacci numbers. The idea is to use a pair of integers a and b,
initialized to Fib(1) = 1 and Fib(0) = 0, and to repeatedly apply the
simultaneous transformations
It is not hard to show that, after applying this transformation n
times, a and b will be equal, respectively, to Fib(n + 1) and Fib(n).
Thus, we can compute Fibonacci numbers iteratively using the procedure
(rewrite by Emacs Lisp substitute for Scheme)
#+begin_src emacs-lisp :session sicp
(defun fib-iter (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(defun fib (n)
(fib-iter 1 0 n))
(fib 4)
#+end_src
"Set a + b = a and b = a", it's hard to wrap my mind around it.
The general idea to find a fib is simple:
Suppose a completed Fibonacci number table, search X in the table by jumping step by step from 0 to X.
The solution is barely intuitive.
It's reasonably to set a + b = b, a = b:
(defun fib-iter (a b count)
(if (= count 0)
a
(fib-iter b (+ a b) (- count 1))
)
)
(defun fib(n)
(fib-iter 0 1 n))
So, the authors' setting seems no more than just anti-intuitively placing b in the head with no special purpose.
However, I surely acknowledge that SICP deserves digging deeper and deeper.
What key points am I missing? Why set a + b = a rather than a + b = b?
As far as I can see your problem is that you don't like it that order of the arguments to fib-iter is not what you think it should be. The answer is that the order of arguments to functions is very often simply arbitrary and/or conventional: it's a choice made by the person writing the function. It does not matter to anyone but the person reading or writing the code: it's a stylistic choice. It doesn't particularly seem more intuitive to me to have fib defined as
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter next current n)
(if (zero? n)
current
(fib-iter (+ next current) next (- n 1))))
Rather than
(define (fib n)
(fib-iter 0 1 n))
(define (fib-iter current next n)
(if (zero? n)
current
(fib-iter (+ next current) current (- n 1))))
There are instances where this isn't true. For instance Standard Lisp (warning, PDF link) defined mapcar so that the list being mapped over was the first argument with the function being mapped the second. This means you can't extend it in the way it has been extended for more recent dialects, so that it takes any positive number of lists with the function being applied to the
corresponding elements of all the lists.
Similarly I think it would be extremely unintuitive to define the arguments of - or / the other way around.
but in many, many cases it's just a matter of making a choice and sticking to it.
The recurrence is given in an imperative form. For instance, in Common Lisp, we could use parallel assignment in the body of a loop:
(psetf a (+ a b)
b a)
To reduce confusion, we should think about this functionally and give the old and new variables different names:
a = a' + b'
b = a'
This is no longer an assignment but a pair of equalities; we are justified in using the ordinary "=" operator of mathematics instead of the assignment arrow.
The linear recursion does this implicitly, because it avoids assignment. The value of the expression (+ a b) is passed as the parameter a. But that's a fresh instance of a in new scope which uses the same name, not an assignment; the binding just induces the two to be equivalent.
We can see it also like this with the help of a "Fibonacci slide rule":
1 1 2 3 5 8 13
----------------------------- <-- sliding interface
b' a'
b a
As we calculate the sequence, there is a two-number window whose entries we are calling a and b, which slides along the sequence. You can read the equalities at any position directly off the slide rule: look, b = a' = 5 and a = b' + a' = 8.
You may be confused by a referring to the higher position in the sequence. You might be thinking of this labeling:
1 1 2 3 5 8 13
------------------------
a' b'
a b
Indeed, under this naming arrangement, now we have b = a' + b', as you expect, and a = b'.
It's just a matter of which variable is designated as the leading one farther along the sequence, and which is the trailing one.
The "a is leading" convention comes from the idea that a is before b in the alphabet, and so it receives the newer "updates" from the sequence first, which then pass off to b.
This may seem counterintuitive, but such a pattern appears elsewhere in mathematics, such as convolution of functions.

Switch from dyadic to monadic interpretation in a J sentence

I am trying to understand composition in J, after struggling to mix and match different phases. I would like help switching between monadic and dyadic phrases in the same sentence.
I just made a simple dice roller in J, which will serve as an example:
d=.1+[:?[#]
4 d 6
2 3 1 1
8 d 12
10 2 11 11 5 11 1 10
This is a chain: "d is one plus the (capped) roll of x occurrences of y"
But what if I wanted to use >: to increment (and skip the cap [: ), such that it "switched" to monadic interpretation after the first fork?
It would read: "d is the incremented roll of x occurrences of y".
Something like this doesn't work, even though it looks to me to have about the right structure:
d=.>:&?[#]
d
>:&? ([ # ])
(If this approach is against the grain for J and I should stick to capped forks, that is also useful information.)
Let's look at a dyadic fork a(c d f h g)b where c,d,f, g and h are verbs and a and b are arguments, which is evaluated as: (a c b) d (a f b) h (a g b) The arguments are applied dyadically to the verbs in the odd positions (or tines c,f and g) - and those results are fed dyadically right to left into the even tines d and h. Also a fork can be either in the form of (v v v) or (n v v) where v stands for verbs and n stands for nouns. In the case of (n v v) you just get the value of n as the left argument to the middle tine.
If you look at your original definition of d=.1+[:?[#] you might notice it simplifies to a dyadic fork with five tines (1 + [: ? #) where the [ # ] can be replaced by # as it is a dyadic fork (see definition above).
The [: (Cap) verb returns no value to the left argument of ? which means that ? acts monadically on the result of a # b and this becomes the right argument to + which has a left argument of 1.
So, on to the question of how to get rid of the [: and use >: instead of 1 + ...
You can also write ([: f g) as f#:g to get rid of the Cap, which means that ([: ? #) becomes ?#:# and now since you want to feed this result into >: you can do that by either:
d1=.>:#:?#:#
d2=. [: >: ?#:#
4 d1 6
6 6 1 5
4 d2 6
2 3 4 5
8 d1 12
7 6 6 4 6 9 8 7
8 d2 12
2 10 10 9 8 12 4 3
Hope this helps, it is a good fundamental question about how forks are evaluated. It would be your preference of whether you use the ([: f g) or f#:g forms of composition.
To summarize the main simple patterns of verb mixing in J:
(f #: g) y = f (g y) NB. (1) monadic "at"
x (f #: g) y = f (x g y) NB. (2) dyadic "at"
x (f &: g) y = (g x) f (g y) NB. (3) "appose"
(f g h) y = (f y) g (h y) NB. (4) monadic fork
x (f g h) y = (x f y) g (x h y) NB. (5) dyadic fork
(f g) y = y f (g y) NB. (6) monadic hook
x (f g) y = x f (g y) NB. (7) dyadic hook
A nice review of those is here (compositions) and here (trains).
Usually there are many possible forms for a verb. To complicate matters more, you can mix many primitives in different ways to achieve to same result.
Experience, style, performance and other such factors influence the way you'll combine the above to form your verb.
In this particular case, I would use #bob's d1 because I find it clearer to read: increase the roll of x copies of y:
>: # ? # $
For the same reason, I am replacing # with $. When I see # in this context, I automatically read "number of elements of", but maybe that's just me.

Building trees starting from a list of symbols

I have a list of symbols which are organized by well formed parenthesis and I want to generate a tree like this one:
Leaf nodes are the symbols and the non-terminal nodes represent the parenthesis and I want to store in a strucuter both them.
Is there a way to build this tree?
It should be easy to split the whole formula into chunks that are direct descendants, while each chunk is well-formed. Use counting of nesting level for that: an opening parenthesis increases the level, a closing parenthesis decreases the level, and whenever the nesting level is 0, there is a boundary between chunks.
This way, you can convert
((a b) (c d)) e ((f g h) i)
into its constituent parts:
((a b) (c d))
e
((f g h) i)
For each part, if it contains more than one symbol, run the same algorithm recursively.
Certainly. First, if you implement a language in which parentheses are syntactic collecting punctuation (e.g. Python lists), you can likely use a built-in evaluation function to parse your input into a desirable structure.
Failing that ... I believe that the below is merely a more detailed version of the previous answer. The steps are simple (recursion should be simple, neh?):
If the input is atomic, make this a leaf node and return.
Split the given list into elements at every internal 0 in the open parenthesis count.
For each element in this list:
3a. Remove the outermost parentheses;
3b. Reduce the parenthesis counts by 1 each;
3c. Recur on this element.
Now, let's walk through the example you give.I'm ignoring the original root node text, in favor of the structure you show in the tree:
[(A ((B C) (D E)))(F G (H I L))]
At each level, the first thing to do is to strip off the outermost parentheses (actually brackets, in this case. I'm not sure why you have a different symbol on the outside).
(A ((B C) (D E)))(F G (H I L))
Now, start at the front, keeping count of how many open parentheses you have.
(A ((B C) (D E)))(F G (H I L))
1 23 2 3 2101 2 10
Note: If you need to throw syntax errors for an imbalance, you have a
nice check: the final count must be 0, with no following characters.
Wherever you have a 0 in the middle, break the string (marked with ^):
(A ((B C) (D E))) ^ (F G (H I L))
1 23 2 3 210 1 2 10
Now, recur on each element you found. If the element is atomic, it's a leaf node.
If you want to save counting time, carry the count as another argument to the routine. Reduce it by 1 on recursion.
^
A ((B C) (D E)) F G (H I L)
12 1 2 10 1 0
The left side has two elements: a leaf node A, and another expression on which we recur:
((B C) (D E))
12 1 2 10
There is no internal 0, so we trivially recur on the entire list:
(B C) (D E)
1 0 1 0
This break into two lists, (B C) and (D E)
Similarly, the right branch of the root node breaks into three elements: F, G, and (H I L). Handle these the same way.

Iterative tree calculation in scheme

I'm trying to implement a function defined as such:
f(n) = n if n < 4
f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) + 4f(n - 4) if n >= 4
The iterative way to do this would be to start at the bottom until I hit n, so if n = 6:
f(4) = (3) + 2(2) + 3(1) + 4(0) | 10
f(5) = f(4) + 2(3) + 3(2) + 4(1) | 10 + 16 = 26
f(6) = f(5) + 2f(4) + 3(3) + 4(2) | 26 + 2(10) + 17 = 63
Implementation attempt:
; m1...m4 | The results of the previous calculations (eg. f(n-1), f(n-2), etc.)
; result | The result thus far
; counter | The current iteration of the loop--starts at 4 and ends at n
(define (fourf-iter n)
(cond [(< n 4) n]
[else
(define (helper m1 m2 m3 m4 result counter)
(cond [(= counter n) result]
[(helper result m1 m2 m3 (+ result m1 (* 2 m2) (* 3 m3) (* 4 m4)) (+ counter 1))]))
(helper 3 2 1 0 10 4)]))
Several problems:
The returned result is one iteration less than what it's supposed to be, because the actual calculations don't take place until the recursive call
Instead of using the defined algorithm to calculate f(4), I'm just putting it right in there that f(4) = 10
Ideally I want to start result at 0 and counter at 3 so that the calculations are applied to m1 through m4 (and so that f(4) will actually be calculated out instead of being preset), but then 0 gets used for m1 in the next iteration when it should be the result of f(4) instead (10)
tl;dr either the result calculation is delayed, or the result itself is delayed. How can I write this properly?
I think the appropriately "Scheme-ish" way to write a function that's defined recursively like that is to use memoization. If a function f is memoized, then when you call f(4) first it looks up 4 in a key-value table and if it finds it, returns the stored value. Otherwise, it simply calculates normally and then stores whatever it calculates in the table. Therefore, f will never evaluate the same computation twice. This is similar to the pattern of making an array of size n and filling in values starting from 0, building up a solution for n. That method is called dynamic programming, and memoization and dynamic programming are really different ways of looking at the same optimization strategy - avoiding computing the same thing twice. Here's a simple Racket function memo that takes a function and returns a memoized version of it:
(define (memo f)
(let ([table (make-hash)])
(lambda args
(hash-ref! table
args
(thunk (apply f args))))))
Now, we can write your function f recursively without having to worry about the performance problems of ever calculating the same result twice, thus going from an exponential time algorithm down to a linear one while keeping the implementation straightforward:
(define f
(memo
(lambda (n)
(if (< n 4)
n
(+ (f (- n 1))
(* 2 (f (- n 2)))
(* 3 (f (- n 3)))
(* 4 (f (- n 4))))))))
Note that as long as the function f exists, it will keep in memory a table containing the result of every time it's ever been called.
If you want a properly tail-recursive solution, your best approach is probably to use the named let construct. If you do (let name ([id val] ...) body ...) then calling (name val ...) anywhere in body ... will jump back to the beginning of the let with the new values val ... for the bindings. An example:
(define (display-n string n)
(let loop ([i 0])
(when (< i n)
(display string)
(loop (add1 i)))))
Using this makes a tail-recursive solution for your problem much less wordy than defining a helper function and calling it:
(define (f n)
(if (< n 4)
n
(let loop ([a 3] [b 2] [c 1] [d 0] [i 4])
(if (<= i n)
(loop (fn+1 a b c d) a b c (add1 i))
a))))
(define (fn+1 a b c d)
(+ a (* 2 b) (* 3 c) (* 4 d)))
This version of the function keeps track of four values for f, then uses them to compute the next value and ditches the oldest value. This builds up a solution while only keeping four values in memory, and it doesn't keep a huge table stored between calls. The fn+1 helper function is for combining the four previous results of the function into the next result, it's just there for readability. This might be a function to use if you want to optimize for memory usage. Using the memoized version has two advantages however:
The memoized version is much easier to understand, the recursive logic is preserved.
The memoized version stores results between calls, so if you call f(10) and then f(4), the second call will only be a table lookup in constant time because calling f(10) stored all the results for calling f with n from 0 to 10.

How to combine two generators in a non-trivial way

I have a generator which produces all positive integers that are powers of 2, and another which produces all integers that are powers of 3. I now need to use those to produce integers of the form 2^i*3^j where i,j >=0,0 in the increasing order.
The point of using generators is to reduce memory consumption, I think. I have been trying to do this for a while now to no avail. Please help out.
Using a self-reading stream
You can solve this using a self-read stream:
----------- -----------
| pow 2 |------->| |
----------- | |
| merge |-------+------------>
----------- | | |
.->| x 3 |------->| | |
| ----------- ----------- |
\_______________________________________/
The first stream produces the powers of two,
while the second one ensures all the generated numbers
are multiplied by 3 and reinjected into the output.
The merge operator ensures that the output is sorted.
Note that we must "seed" the output stream with 1,
or the first element will try to produce itself when evaluated.
Here is the code:
(require srfi/41)
(define (merge s1 s2)
(stream-match s1 ((x . xs)
(stream-match s2 ((y . ys)
(if (< x y)
(stream-cons x (merge xs s2))
(stream-cons y (merge ys s1))))))))
(define (the-stream)
(letrec ((s
(stream-cons 1 (merge (stream-map (lambda (x) (* 3 x)) s)
(stream-iterate (lambda (x) (* 2 x)) 2)))))
s))
It's quite simple and fast compared to my other proposal,
because it uses arithmetic properties of the problem besides monotonicity.
I'm wrong, it can be generalized just as well (upcoming)
$ mzscheme -f feedback.scm -e '(display (stream->list (stream-take 20 (the-stream))))'
(1 2 3 4 6 8 9 12 16 18 24 27 32 36 48 54 64 72 81 96)
$ time mzscheme -f feedback.scm -e '(display (stream-ref (the-stream) 10000))'
161968247347450370721577384417107686788864605658546176
real 0m1.746s
user 0m1.344s
sys 0m0.156s
Using generators and a queue
We can also implement this with python's generators,
but we need to use a queue to store the numbers waiting in the feedback loop:
# Merge the output of two generators
def merge(g1, g2):
v1 = g1.next()
v2 = g2.next()
while 1:
if v1 < v2:
yield v1
v1 = g1.next()
else:
yield v2
v2 = g2.next()
# Generates the powers of 2, starting with n
def pow2(n):
while 1: yield n; n *= 2
# Generates values shifted from the given 'q' and multiplied by 3
def mul3(q):
while 1: yield q.pop(0) * 3
# The generator we want
def pow23():
q = []
v = 1
g = merge(pow2(2), mul3(q))
while 1:
yield v
q.append(v)
v = g.next()
g23 = pow23()
for i in range(10000): g23.next()
print g23.next()
This is somewhat less elegant (IMHO),
but the generators are much more lightweight:
$ time python feedback.py
161968247347450370721577384417107686788864605658546176
real 0m0.150s
user 0m0.112s
sys 0m0.012s
For what is worth, I have done a scheme implementation
(using closures as generators)
which shows roughly the same performance.
I don't know much about generators,
however I can propose a solution based on streams (lazily constructed,
possibly infinite lists), which are somewhat similar.
My approach would be to create a stream
whose "state" itself would be a stream of streams.
The individual, inner streams of numbers,
let's call them the 3-streams,
would represent lists of the successive powers of 3, starting with 1,
multiplied by a given power of two.
We can then assemble an infinity of such 3-streams,
one for each successive power of 2, starting with 1.
Let's call this the 2-stream.
The initial state, in ascii-art, is this:
---------------------- --- -- -
| The 2-stream ...
--|----|----|----|---- --- -- -
V V V V
|1| | 2| | 4| | 8|
|3| | 6| |12| |24| ...
|9| |18| |36| |72| The 3-streams
: : : :
Now, we're going to manipulate this so that at any moment,
the 3-streams will be ordered within the 2-stream
with regards to their first elements.
As a consequence the next smallest generated number
will always be the first element of the first 3-stream.
So, to get the next number in the sequence you wish to obtain,
we're going to pull out the first 3-stream,
pull out its first element (which is the number we're interested in),
and then re-insert the 3-stream in the 2-stream
at a position determined by its new first element.
The new state after the first number (1) has been extracted would be:
---------------------- --- -- -
| The 2-stream ...
---|----|----|----|---- --- -- -
V V V V
| 2| | 3| | 4| | 8|
| 6| | 9| |12| |24| ...
|18| |27| |36| |72| The 3-streams
: : : :
Note that this method does not depend on 2^i, 3^j or multiplication specifically
(just on 2^i * 3^j being monotonically increasing with i and j).
I have posted another answer which does, and
is much more simple and fast as a result.
don't trust me: it has nothing to do with the math
Below is an example implementation, using SRFI-41 streams:
(require srfi/41)
; Geometric sequence with initial value 'init', and ratio 'r'
(define (make-geoseq init r)
(stream-cons
init
(make-geoseq (* r init) r)))
; Your power generators
(define pow2 (make-geoseq 1 2))
(define pow3 (make-geoseq 1 3))
; Construct a 3-stream from the pow3 sequence
(define (make-3stream mult)
(stream-map (lambda (x) (* mult x)) pow3))
; Construct the (initial) 2-stream from the pow2 sequence
(define initial-2stream
(stream-map make-3stream pow2))
; Insert a modified 3-stream into the given 2-stream, at the right position
(define (insert two-stream three-stream)
(if (< (stream-car three-stream)
(stream-car (stream-car two-stream)))
; we have the smallest 3-stream, put it at the front
(stream-cons
three-stream
two-stream)
; otherwise, recurse
(stream-cons
(stream-car two-stream)
(insert (stream-cdr two-stream) three-stream))))
; Construct a 2^n * 3^p stream with the given 2-stream as its "state"
(define (make-the-stream current-2stream)
(let*
; pull out the first 3-stream
((first-3s (stream-car current-2stream))
(other-3s (stream-cdr current-2stream))
; use its first element as our next value
(next-val (stream-car first-3s))
; reinsert its tail into the 2-stream's tail
(next-2s (insert other-3s (stream-cdr first-3s))))
; and use the resulting 2-stream to construct the (outer) stream's tail
(stream-cons
next-val
(make-the-stream next-2s))))
; Now, we can construct the stream we want
(define the-stream (make-the-stream initial-2stream))
Using plt-scheme (on my rather crappy hardware):
$ mzscheme -f pow23.scm -e '(display (stream->list (stream-take 20 the-stream)))'
(1 2 3 4 6 8 9 12 16 18 24 27 32 36 48 54 64 72 81 96)
$ time mzscheme -f pow23.scm -e '(display (stream-ref the-stream 10000))'
161968247347450370721577384417107686788864605658546176
real 0m12.550s
user 0m11.005s
sys 0m0.340s
Implementing this with generators could be done I guess,
but the tricky part would be implementing (insert).
You could do so by composing generators,
but you would end up adding one "layer" every time a number is pulled,
whereas a stream created with (insert) shares its tail with the original one
(the "layers" eventually merge).
Just merge the two ordered lists a la
(define merge
(lambda (pred ls1 ls2)
(cond
[(null? ls1) ls2]
[(null? ls2) ls1]
[(pred (car ls1) (car ls2))
(cons (car ls1) (merge pred (cdr ls1) ls2))]
[else (cons (car ls2) (merge pred ls1 (cdr ls2)))])))
lifted from here.
The simple solution w/o any examples is creating a new one.
for (i = 0; i < X; i++)
{
if (i%2 or i%3)
{
cout << i
}
}
edit: X is how long you want to run it say you want output 0-100 put 100.
int counter = 1000;
bool done = false;
while(!done)
{
if (i%2 or i%3)
{
cout << i;
counter--;
if(counter <= 1)
{
done = true;
}
}
i++;
}
It's a little messy but should work.
edit: The counter should end at 1 or it will give you 1001 items.
At least if I understand your question, you just need to merge the results from the two generators:
Generate an output from each generator
Produce the smaller of the two as the next output
Generate the next output from that generator
Go back to Step 2
If the two generators produce equal values, produce that as the output, and generate the next value from each generator.
Note that although it's typically used for sorting existing data instead of generating new data, this is similar to the merge used in a normal merge sort, with the exception that I've assumed you don't want duplicates, where a merge sort normally retains duplicates.
Edit: Thanks to lpthnc, I've reread the question, and I think he's right -- I misread the original question. To get the correct output, you'd need to create a third generator and produces the multiples of (in this case) six, and use a three-way merge between that result set and those from the other two generators.
I haven't played with it much, but I believe the Lazy language level (or lazy module) in recent iterations of PLT Scheme would let you write your code to generate the entire infinite sequence, which would theoretically use infinite time and memory, but only evaluate a finite subset of that as needed.
This is pretty easy in Haskell:
merge as bs =
case (as, bs) of
([], _) -> bs
(_, []) -> as
((a:as'), (b:bs')) ->
if a <= b
then a : (merge as' bs)
else b : (merge as bs')
rmDups as =
case as of
[] -> []
[a] -> [a]
(a:bs#(b:_)) ->
if a == b
then rmDups bs
else a:(rmDups bs)
take 25 $ rmDups $ merge (map (2^) [1..]) (map (3^) [1..])
yields the following:
[2,3,4,8,9,16,27,32,64,81,128,243,256,512,729,1024,2048,2187,4096,6561,8192,16384,19683,32768,59049]
though I imagine there's a more elegant way to do it...
Redacted. The more I look at this, the more I think I've got it all wrong - and others appear to have better answers, already.
Sorry, none of this is in scheme, just pseudocode...
The following code matches the thought process I garner from your question:
EDIT: revised pseudocode now that I realize it's "2^i*3^j", not "2^i, 3^j"
// If i got close, this time,
// inputs min-i=0, max-i=2, min-j=0, max-j=2
// should get output like
// 2^0 * 3^0 = 1
// 2^0 * 3^1 = 3
// 2^0 * 3^2 = 6
// 2^1 * 3^0 = 2
// 2^1 * 3^1 = 6
// 2^1 * 3^2 = 12
// 2^2 * 3^0 = 4
// 2^2 * 3^1 = 12
// 2^2 * 3^2 = 24
LET min-i, max-i, min-j, max-j be input
LET current-value = 1
FOR i = min-i to max-i
FOR j = min-j to max-j DO
PRINT "2^" . i . " * j^" . j . " = " . current-value
current-value *= 3;
DONE // end j loop
current-value *= 2
DONE // end i loop

Resources