3.1 Exhaustive Enumeration

What is decrementing function in a loop program block?

The decrementing function in a loop has four properties:

  1. It maps a set of program variables into an integer.
  2. When the loop is entered, its value is nonnegative.
  3. When its value is ≤ 0, the loop terminates.
  4. Its value is decreased every time through the loop.

Can we look down the exhaustive enumeration algorithms?

The algorithmic technique used in this program is a variant of guess and check called exhaustive enumeration. We enumerate all possibilities until we get to the right answer or exhaust the space of possibilities. At first blush[^ At first blush], this may seem like an incredibly stupid way to solve a problem. Surprisingly, however, exhaustive enumeration algorithms are often the most practical way to solve a problem. They are typically easy to implement and easy to understand. And, in many cases, they run fast enough for all practical purposes.

[^ At first blush]: At first blush , or At the first blush , at the first appearance or view. “At the first blush, we thought they had been ships come from France.” Hakluyt. This phrase is used now more of ideas, opinions, etc., than of material things.

3.2 For Loops

What is the relationship of for loop mechanism and while loop?

The while loops we have used so far are highly stylized [^ stylized]. Each iterates over a sequence of integers. Python provides a language mechanism, the for loop, that can be used to simplify programs containing this kind of iteration.

[^ stylized]: stylized: depicted or treated in a mannered and nonrealistic style.

3.4 A Few Words About Using Floats

Why not call it real number in computer system?

In almost modern programming languages non-integer numbers are implemented using a representation called floating point.

How to represent digital number in binary float point?

Modern computers use binary, not decimal, representations. We represent the significant digits and exponents in binary rather than decimal and raise 2 rather than 10 to the exponent. For example, the number 0.625 (5/8) would be represented as the pair (101, -11); because 5/8 is 0.101 in binary and -11 is the binary representation of -3, the pair (101, -11) stands for 5*2-3 = 5/8 = 0.625.

What is the representation of 0.1 in Python floating point?

What about the decimal fraction 1/10, which we write in Python as 0.1? The best we can do with four significant binary digits is (0011, -101). This is equivalent to 3/32, i.e., 0.09375. If we had five significant binary digits, we would represent 0.1 as (11001, -1000), which is equivalent to 25/256, i.e., 0.09765625. How many significant digits would we need to get an exact floating point representation of 0.1? An infinite number of digits! There do not exist integers sig and exp such that sig * 2-exp equals 0.1.

In most Python implementations, there are 53 bits of precision available for floating point numbers, so the significant digits stored for the decimal number 0.1 will be

11001100110011001100110011001100110011001100110011001

This is equivalent to the decimal number

0.1000000000000000055511151231257827021181583404541015625

Does the difference between real and floating point numbers really matter?

As we have seen, using == to compare two floating point values can produce a surprising result. It is almost always more appropriate to ask whether two floating point values are close enough to each other, not whether they are identical. So, for example, it is better to write abs(x-y) < 0.0001 rather than x == y.

3.5 Newton-Raphson

How to define finding the square root problem in the polynomial formulation?

A polynomial with one variable (by convention, we will write the variable as x) is either 0 or the sum of a finite number of nonzero terms, e.g., 3x2 + 2x + 3. Each term, e.g., 3x2, consists of a constant (the coefficient of the term, 3 in this case) multiplied by the variable (x in this case) raised to a nonnegative integer exponent (2 in this case). The exponent on a variable in a term is called the degree of that term. The degree of a polynomial is the largest degree of any single term. Some examples are, 3 (degree 0), 2.5x + 12 (degree 1), and 3x2 (degree 2). In contrast, 2/x and x0.5 are not polynomials.

If p is a polynomial and r a real number, we will write p(r) to stand for the value of the polynomial when x = r. A root of the polynomial p is a solution to the equation p = 0, i.e., an r such that p(r) = 0. So, for example, the problem of finding an approximation to the square root of 24 can be formulated as finding an x such that x2 – 24 ≈ 0.

What is successive approximation?

Newton proved a theorem that implies that if a value, call it guess, is an ap- proximation to a root of a polynomial, then guess – p(guess)/p’(guess), where p’ is the first derivative of p, is a better approximation.20

For any constant k and any coefficient c, the first derivative of the polynomial cx2 + k is 2cx. For example, the first derivative of x2 – k is 2x. Therefore, we know that we can improve on the current guess, call it y, by choosing as our next guess y - (y2 - k)/2y. This is called successive approximation.

What is Newton-Raphson method code for finding square root?

#Newton-Raphson for square root
#Find x such that x**2 - 24 is within epsilon of 0 epsilon = 0.01
k = 24.0
guess = k/2.0
while abs(guess*guess - k) >= epsilon:
    guess = guess - (((guess**2) - k)/(2*guess)) 
print('Square root of', k, 'is about', guess)

Compare the efficiency of Newton-Raphson and bisection search method?

Square root of 54.0 is about 7.348469483546109
LS0tCnRpdGxlOiAwMyBTT01FIFNJTVBMRSBOVU1FUklDQUwgUFJPR1JBTVMKc3VidGl0bGU6IAphdXRob3I6IOabsuaUvwpkYXRlOiAyMDIwLTA1LTI1CnNsdWc6IHNvbWUtc2ltcGxlLW51bWVyaWNhbC1wcm9ncmFtcwp0YWdzOgotIApjYXRlZ29yaWVzOgotIG1pdDYwMDAKLSBJQ1BQCnR5cG9yYS1yb290LXVybDogLi4vLi4vc3RhdGljCnNob3dfdG9jOiB5ZXMKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgMy4xIEV4aGF1c3RpdmUgRW51bWVyYXRpb24KCiMjIyBXaGF0IGlzIGRlY3JlbWVudGluZyBmdW5jdGlvbiBpbiBhIGxvb3AgcHJvZ3JhbSBibG9jaz8KClRoZSBkZWNyZW1lbnRpbmcgZnVuY3Rpb24gaW4gYSBsb29wIGhhcyBmb3VyIHByb3BlcnRpZXM6CgoxLiBJdCBtYXBzIGEgc2V0IG9mIHByb2dyYW0gdmFyaWFibGVzIGludG8gYW4gaW50ZWdlci4KMS4gV2hlbiB0aGUgbG9vcCBpcyBlbnRlcmVkLCBpdHMgdmFsdWUgaXMgbm9ubmVnYXRpdmUuCjEuIFdoZW4gaXRzIHZhbHVlIGlzIGDiiaQgMGAsIHRoZSBsb29wIHRlcm1pbmF0ZXMuIAoxLiBJdHMgdmFsdWUgaXMgZGVjcmVhc2VkIGV2ZXJ5IHRpbWUgdGhyb3VnaCB0aGUgbG9vcC4KCiMjIyBDYW4gd2UgbG9vayBkb3duIHRoZSBleGhhdXN0aXZlIGVudW1lcmF0aW9uIGFsZ29yaXRobXM/CgpUaGUgYWxnb3JpdGhtaWMgdGVjaG5pcXVlIHVzZWQgaW4gdGhpcyBwcm9ncmFtIGlzIGEgdmFyaWFudCBvZiBndWVzcyBhbmQgY2hlY2sgY2FsbGVkIGV4aGF1c3RpdmUgZW51bWVyYXRpb24uIFdlIGVudW1lcmF0ZSBhbGwgcG9zc2liaWxpdGllcyB1bnRpbCB3ZSBnZXQgdG8gdGhlIHJpZ2h0IGFuc3dlciBvciBleGhhdXN0IHRoZSBzcGFjZSBvZiBwb3NzaWJpbGl0aWVzLiBBdCBmaXJzdCBibHVzaFteIEF0IGZpcnN0IGJsdXNoXSwgdGhpcyBtYXkgc2VlbSBsaWtlIGFuIGluY3JlZGlibHkgc3R1cGlkIHdheSB0byBzb2x2ZSBhIHByb2JsZW0uIFN1cnByaXNpbmdseSwgaG93ZXZlciwgZXhoYXVzdGl2ZSBlbnVtZXJhdGlvbiBhbGdvcml0aG1zIGFyZSBvZnRlbiB0aGUgbW9zdCBwcmFjdGljYWwgd2F5IHRvIHNvbHZlIGEgcHJvYmxlbS4gVGhleSBhcmUgdHlwaWNhbGx5IGVhc3kgdG8gaW1wbGVtZW50IGFuZCBlYXN5IHRvIHVuZGVyc3RhbmQuIEFuZCwgaW4gbWFueSBjYXNlcywgdGhleSBydW4gZmFzdCBlbm91Z2ggZm9yIGFsbCBwcmFjdGljYWwgcHVycG9zZXMuIAoKW14gQXQgZmlyc3QgYmx1c2hdOiAqKkF0IGZpcnN0IGJsdXNoKiogLCBvciAqKkF0IHRoZSBmaXJzdCBibHVzaCoqICwgYXQgdGhlIGZpcnN0IGFwcGVhcmFuY2Ugb3Igdmlldy4gIOKAnCpBdCB0aGUgZmlyc3QgYmx1c2gqLCB3ZSB0aG91Z2h0IHRoZXkgaGFkIGJlZW4gc2hpcHMgY29tZSBmcm9tIEZyYW5jZS7igJ0gSGFrbHV5dC4gVGhpcyBwaHJhc2UgaXMgdXNlZCBub3cgbW9yZSBvZiBpZGVhcywgb3BpbmlvbnMsIGV0Yy4sIHRoYW4gb2YgbWF0ZXJpYWwgdGhpbmdzLgoKIyMgMy4yIEZvciBMb29wcwoKIyMjIFdoYXQgaXMgdGhlIHJlbGF0aW9uc2hpcCBvZiBgZm9yYCBsb29wIG1lY2hhbmlzbSBhbmQgYHdoaWxlYCBsb29wPwoKVGhlIHdoaWxlIGxvb3BzIHdlIGhhdmUgdXNlZCBzbyBmYXIgYXJlIGhpZ2hseSBzdHlsaXplZCBbXiBzdHlsaXplZF0uIEVhY2ggaXRlcmF0ZXMgb3ZlciBhIHNlcXVlbmNlIG9mIGludGVnZXJzLiBQeXRob24gcHJvdmlkZXMgYSBsYW5ndWFnZSBtZWNoYW5pc20sIHRoZSAqKmZvcioqIGxvb3AsIHRoYXQgY2FuIGJlIHVzZWQgdG8gc2ltcGxpZnkgcHJvZ3JhbXMgY29udGFpbmluZyB0aGlzIGtpbmQgb2YgaXRlcmF0aW9uLgoKW14gc3R5bGl6ZWRdOiAqKnN0eWxpemVkKio6IGRlcGljdGVkIG9yIHRyZWF0ZWQgaW4gYSBtYW5uZXJlZCBhbmQgbm9ucmVhbGlzdGljIHN0eWxlLgoKIyMgMy4zIEFwcHJveGltYXRlIFNvbHV0aW9ucyBhbmQgQmlzZWN0aW9uIFNlYXJjaAoKIyMjIFdoYXQgaXMgdGhlIGV4aGF1c3RpdmUgZW51bWVyYXRpb24gbWV0aG9kIGZvciBmaW5kaW5nIHRoZSBzcXVhcmUgcm9vdD8KCmBgYHtweXRob259CiMgeCA9IDI1CnggPSAwLjI1CmVwc2lsb24gPSAwLjAxCnN0ZXAgPSBlcHNpbG9uKioyCm51bUd1ZXNzZXMgPSAwCmFucyA9IDAuMAojIHdoaWxlIGFicyhhbnMqKjIgLSB4KSA+PSBlcHNpbG9uIGFuZCBhbnMgPD0geDoKd2hpbGUgYWJzKGFucyoqMiAtIHgpID49IGVwc2lsb24gYW5kIGFucyphbnMgPD0geDoKICAgIGFucyArPSBzdGVwCiAgICBudW1HdWVzc2VzICs9IDEgCnByaW50KCdudW1HdWVzc2VzID0nLCBudW1HdWVzc2VzKSAKaWYgYWJzKGFucyoqMiAtIHgpID49IGVwc2lsb246CiAgICBwcmludCgnRmFpbGVkIG9uIHNxdWFyZSByb290IG9mJywgeCkgCmVsc2U6CiAgICBwcmludChhbnMsICdpcyBjbG9zZSB0byBzcXVhcmUgcm9vdCBvZicsIHgpCmBgYAoKRXhoYXVzdGl2ZSBlbnVtZXJhdGlvbiBtZXRob2QgZm9yIGZpbmRpbmcgdGhlIHNxdWFyZSByb290IGhhcyBub3RoaW5nIGluIGNvbW1vbiB3aXRoIHRoZSB3YXkgb2YgZmluZGluZyBzcXVhcmUgcm9vdHMgdXNpbmcgYSBwZW5jaWwgdGhhdCB5b3UgbWlnaHQgaGF2ZSBsZWFybmVkIGluIG1pZGRsZSBzY2hvb2wuIEl0IGlzIG9mdGVuIHRoZSBjYXNlIHRoYXQgdGhlIGJlc3Qgd2F5IHRvIHNvbHZlIGEgcHJvYmxlbSB3aXRoIGEgY29tcHV0ZXIgaXMgcXVpdGUgZGlmZmVyZW50IGZyb20gaG93IG9uZSB3b3VsZCBhcHByb2FjaCB0aGUgcHJvYmxlbSBieSBoYW5kLgoKIyMjIFNob3VsZCB3ZSBiZSBkaXNhcHBvaW50ZWQgdGhhdCB0aGUgcHJvZ3JhbSBkaWRu4oCZdCBmaWd1cmUgb3V0IHRoYXQgMjUgaXMgYSBwZXJmZWN0IHNxdWFyZSBhbmQgcHJpbnQgNT8KCk5vLiBUaGUgcHJvZ3JhbSBkaWQgd2hhdCBpdCB3YXMgaW50ZW5kZWQgdG8gZG8uIFRob3VnaCBpdCB3b3VsZCBoYXZlIGJlZW4gT0sgdG8gcHJpbnQgNSwgZG9pbmcgc28gaXMgbm8gYmV0dGVyIHRoYW4gcHJpbnRpbmcgYW55IHZhbHVlIGNsb3NlIGVub3VnaCB0byA1LgoKIyMjIFdoYXQgaXMgdGhlIG9wdGlvbiBCIHdoZW4gZmluZGluZyBleGhhdXN0aXZlIGVudW1lcmF0aW9uIGFsZ29yaXRobSBub3QgZWZmaWNpZW50IGluIHNvbWUgY2FzZT8KCldlIGNvdWxkIHRyeSB0byBzcGVlZCBpdCB1cCBieSBzdGFydGluZyBjbG9zZXIgdG8gdGhlIGFuc3dlciwgYnV0IHRoYXQgcHJlc3VtZXMgdGhhdCB3ZSBrbm93IHRoZSBhbnN3ZXIuIFRoZSB0aW1lIGhhcyBjb21lIHRvIGxvb2sgZm9yIGEgZGlmZmVyZW50IHdheSB0byBhdHRhY2sgdGhlIHByb2JsZW0uIFdlIG5lZWQgdG8gY2hvb3NlIGEgYmV0dGVyIGFsZ29yaXRobSByYXRoZXIgdGhhbiBmaW5lLXR1bmUgdGhlIGN1cnJlbnQgb25lLgoKIyMjIFdoYXQgaXMgdGhlIGJpc2VjdGlvbiBzZWFyY2ggbWV0aG9kIGZvciBmaW5kaW5nIHRoZSBzcXVhcmUgcm9vdD8KCmBgYHtweXRob259CnggPSAyNQplcHNpbG9uID0gMC4wMQpudW1HdWVzc2VzID0gMApsb3cgPSAwLjAKaGlnaCA9IG1heCgxLjAsIHgpCmFucyA9IChoaWdoICsgbG93KS8yLjAKd2hpbGUgYWJzKGFucyoqMiAtIHgpID49IGVwc2lsb246CiAgICBwcmludCgnbG93ID0nLCBsb3csICdoaWdoID0nLCBoaWdoLCAnYW5zID0nLCBhbnMpIAogICAgbnVtR3Vlc3NlcyArPSAxCiAgICBpZiBhbnMqKjIgPCB4OgogICAgICAgIGxvdyA9IGFucyAKICAgIGVsc2U6CiAgICAgICAgaGlnaCA9IGFucwogICAgYW5zID0gKGhpZ2ggKyBsb3cpLzIuMApwcmludCgnbnVtR3Vlc3NlcyA9JywgbnVtR3Vlc3NlcykgCnByaW50KGFucywgJ2lzIGNsb3NlIHRvIHNxdWFyZSByb290IG9mJywgeCkKYGBgCgpNb3JlIGltcG9ydGFudCwgbm90aWNlIHRoYXQgYXQgZWFjaCBpdGVyYXRpb24gb2YgdGhlIGxvb3AgdGhlIHNpemUgb2YgdGhlIHNwYWNlIHRvIGJlIHNlYXJjaGVkIGlzIGN1dCBpbiBoYWxmLiBCZWNhdXNlIGl0IGRpdmlkZXMgdGhlIHNlYXJjaCBzcGFjZSBpbiBoYWxmIGF0IGVhY2ggc3RlcCwgaXQgaXMgY2FsbGVkIGEgYmlzZWN0aW9uIHNlYXJjaC4gQmlzZWN0aW9uIHNlYXJjaCBpcyBhIGh1Z2UgaW1wcm92ZW1lbnQgb3ZlciBvdXIgZWFybGllciBhbGdvcml0aG0sIHdoaWNoIHJlZHVjZWQgdGhlIHNlYXJjaCBzcGFjZSBieSBvbmx5IGEgc21hbGwgYW1vdW50IGF0IGVhY2ggaXRlcmF0aW9uLgoKIyMgMy40IEEgRmV3IFdvcmRzIEFib3V0IFVzaW5nIEZsb2F0cwoKIyMjIFdoeSBub3QgY2FsbCBpdCByZWFsIG51bWJlciBpbiBjb21wdXRlciBzeXN0ZW0/CgpJbiBhbG1vc3QgbW9kZXJuIHByb2dyYW1taW5nIGxhbmd1YWdlcyBub24taW50ZWdlciBudW1iZXJzIGFyZSBpbXBsZW1lbnRlZCB1c2luZyBhIHJlcHJlc2VudGF0aW9uIGNhbGxlZCAqKmZsb2F0aW5nIHBvaW50KiouCgojIyMgSG93IHRvIHJlcHJlc2VudCBkaWdpdGFsIG51bWJlciBpbiBiaW5hcnkgZmxvYXQgcG9pbnQ/CgpNb2Rlcm4gY29tcHV0ZXJzIHVzZSBiaW5hcnksIG5vdCBkZWNpbWFsLCByZXByZXNlbnRhdGlvbnMuIFdlIHJlcHJlc2VudCB0aGUgc2lnbmlmaWNhbnQgZGlnaXRzIGFuZCBleHBvbmVudHMgaW4gYmluYXJ5IHJhdGhlciB0aGFuIGRlY2ltYWwgYW5kIHJhaXNlIDIgcmF0aGVyIHRoYW4gMTAgdG8gdGhlIGV4cG9uZW50LiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciAwLjYyNSAoNS84KSB3b3VsZCBiZSByZXByZXNlbnRlZCBhcyB0aGUgcGFpciAoMTAxLCAtMTEpOyBiZWNhdXNlIDUvOCBpcyAwLjEwMSBpbiBiaW5hcnkgYW5kIC0xMSBpcyB0aGUgYmluYXJ5IHJlcHJlc2VudGF0aW9uIG9mIC0zLCB0aGUgcGFpciAoMTAxLCAtMTEpIHN0YW5kcyBmb3IgNSoyLTMgPSA1LzggPSAwLjYyNS4KCiMjIyBXaGF0IGlzIHRoZSByZXByZXNlbnRhdGlvbiBvZiAwLjEgaW4gUHl0aG9uIGZsb2F0aW5nIHBvaW50PwoKV2hhdCBhYm91dCB0aGUgZGVjaW1hbCBmcmFjdGlvbiAxLzEwLCB3aGljaCB3ZSB3cml0ZSBpbiBQeXRob24gYXMgMC4xPyBUaGUgYmVzdCB3ZSBjYW4gZG8gd2l0aCBmb3VyIHNpZ25pZmljYW50IGJpbmFyeSBkaWdpdHMgaXMgKDAwMTEsIC0xMDEpLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gMy8zMiwgaS5lLiwgMC4wOTM3NS4gSWYgd2UgaGFkIGZpdmUgc2lnbmlmaWNhbnQgYmluYXJ5IGRpZ2l0cywgd2Ugd291bGQgcmVwcmVzZW50IDAuMSBhcyAoMTEwMDEsIC0xMDAwKSwgd2hpY2ggaXMgZXF1aXZhbGVudCB0byAyNS8yNTYsIGkuZS4sIDAuMDk3NjU2MjUuIEhvdyBtYW55IHNpZ25pZmljYW50IGRpZ2l0cyB3b3VsZCB3ZSBuZWVkIHRvIGdldCBhbiBleGFjdCBmbG9hdGluZyBwb2ludCByZXByZXNlbnRhdGlvbiBvZiAwLjE/IEFuIGluZmluaXRlIG51bWJlciBvZiBkaWdpdHMhIFRoZXJlIGRvIG5vdCBleGlzdCBpbnRlZ2VycyBgc2lnYCBhbmQgYGV4cGAgc3VjaCB0aGF0IHNpZyAqIDJeLWV4cF4gZXF1YWxzIDAuMS4KCkluIG1vc3QgUHl0aG9uIGltcGxlbWVudGF0aW9ucywgdGhlcmUgYXJlIDUzIGJpdHMgb2YgcHJlY2lzaW9uIGF2YWlsYWJsZSBmb3IgZmxvYXRpbmcgcG9pbnQgbnVtYmVycywgc28gdGhlIHNpZ25pZmljYW50IGRpZ2l0cyBzdG9yZWQgZm9yIHRoZSBkZWNpbWFsIG51bWJlciAwLjEgd2lsbCBiZQoKYDExMDAxMTAwMTEwMDExMDAxMTAwMTEwMDExMDAxMTAwMTEwMDExMDAxMTAwMTEwMDExMDAxYAoKVGhpcyBpcyBlcXVpdmFsZW50IHRvIHRoZSBkZWNpbWFsIG51bWJlcgoKYDAuMTAwMDAwMDAwMDAwMDAwMDA1NTUxMTE1MTIzMTI1NzgyNzAyMTE4MTU4MzQwNDU0MTAxNTYyNWAKCiMjIyBEb2VzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gcmVhbCBhbmQgZmxvYXRpbmcgcG9pbnQgbnVtYmVycyByZWFsbHkgbWF0dGVyPwoKQXMgd2UgaGF2ZSBzZWVuLCB1c2luZyBgYD09YGAgdG8gY29tcGFyZSB0d28gZmxvYXRpbmcgcG9pbnQgdmFsdWVzIGNhbiBwcm9kdWNlIGEgc3VycHJpc2luZyByZXN1bHQuIEl0IGlzIGFsbW9zdCBhbHdheXMgbW9yZSBhcHByb3ByaWF0ZSB0byBhc2sgd2hldGhlciB0d28gZmxvYXRpbmcgcG9pbnQgdmFsdWVzIGFyZSBjbG9zZSBlbm91Z2ggdG8gZWFjaCBvdGhlciwgbm90IHdoZXRoZXIgdGhleSBhcmUgaWRlbnRpY2FsLiBTbywgZm9yIGV4YW1wbGUsIGl0IGlzIGJldHRlciB0byB3cml0ZSBgYWJzKHgteSkgPCAwLjAwMDFgIHJhdGhlciB0aGFuIGB4ID09IHlgLgoKIyMgMy41IE5ld3Rvbi1SYXBoc29uCgojIyMgSG93IHRvIGRlZmluZSBmaW5kaW5nIHRoZSBzcXVhcmUgcm9vdCBwcm9ibGVtIGluIHRoZSBwb2x5bm9taWFsIGZvcm11bGF0aW9uPwoKQSBwb2x5bm9taWFsIHdpdGggb25lIHZhcmlhYmxlIChieSBjb252ZW50aW9uLCB3ZSB3aWxsIHdyaXRlIHRoZSB2YXJpYWJsZSBhcyB4KSBpcyBlaXRoZXIgMCBvciB0aGUgc3VtIG9mIGEgZmluaXRlIG51bWJlciBvZiBub256ZXJvIHRlcm1zLCBlLmcuLCAzeDIgKyAyeCArIDMuIEVhY2ggdGVybSwgZS5nLiwgM3gyLCBjb25zaXN0cyBvZiBhIGNvbnN0YW50ICh0aGUgY29lZmZpY2llbnQgb2YgdGhlIHRlcm0sIDMgaW4gdGhpcyBjYXNlKSBtdWx0aXBsaWVkIGJ5IHRoZSB2YXJpYWJsZSAoeCBpbiB0aGlzIGNhc2UpIHJhaXNlZCB0byBhIG5vbm5lZ2F0aXZlIGludGVnZXIgZXhwb25lbnQgKDIgaW4gdGhpcyBjYXNlKS4gVGhlIGV4cG9uZW50IG9uIGEgdmFyaWFibGUgaW4gYSB0ZXJtIGlzIGNhbGxlZCB0aGUgZGVncmVlIG9mIHRoYXQgdGVybS4gVGhlIGRlZ3JlZSBvZiBhIHBvbHlub21pYWwgaXMgdGhlIGxhcmdlc3QgZGVncmVlIG9mIGFueSBzaW5nbGUgdGVybS4gU29tZSBleGFtcGxlcyBhcmUsIDMgKGRlZ3JlZSAwKSwgMi41eCArIDEyIChkZWdyZWUgMSksIGFuZCAzeDIgKGRlZ3JlZSAyKS4gSW4gY29udHJhc3QsIDIveCBhbmQgeDAuNSBhcmUgbm90IHBvbHlub21pYWxzLgoKSWYgcCBpcyBhIHBvbHlub21pYWwgYW5kIHIgYSByZWFsIG51bWJlciwgd2Ugd2lsbCB3cml0ZSBwKHIpIHRvIHN0YW5kIGZvciB0aGUgdmFsdWUgb2YgdGhlIHBvbHlub21pYWwgd2hlbiB4ID0gci4gQSByb290IG9mIHRoZSBwb2x5bm9taWFsIHAgaXMgYSBzb2x1dGlvbiB0byB0aGUgZXF1YXRpb24gcCA9IDAsIGkuZS4sIGFuIHIgc3VjaCB0aGF0IHAocikgPSAwLiBTbywgZm9yIGV4YW1wbGUsIHRoZSBwcm9ibGVtIG9mIGZpbmRpbmcgYW4gYXBwcm94aW1hdGlvbiB0byB0aGUgc3F1YXJlIHJvb3Qgb2YgMjQgY2FuIGJlIGZvcm11bGF0ZWQgYXMgZmluZGluZyBhbiB4IHN1Y2ggdGhhdCB4MiDigJMgMjQg4omIIDAuCgojIyMgV2hhdCBpcyBzdWNjZXNzaXZlIGFwcHJveGltYXRpb24/CgpOZXd0b24gcHJvdmVkIGEgdGhlb3JlbSB0aGF0IGltcGxpZXMgdGhhdCBpZiBhIHZhbHVlLCBjYWxsIGl0IGd1ZXNzLCBpcyBhbiBhcC0gcHJveGltYXRpb24gdG8gYSByb290IG9mIGEgcG9seW5vbWlhbCwgdGhlbiBndWVzcyDigJMgcChndWVzcykvcOKAmShndWVzcyksIHdoZXJlIHDigJkgaXMgdGhlIGZpcnN0IGRlcml2YXRpdmUgb2YgcCwgaXMgYSBiZXR0ZXIgYXBwcm94aW1hdGlvbi4yMAoKRm9yIGFueSBjb25zdGFudCBrIGFuZCBhbnkgY29lZmZpY2llbnQgYywgdGhlIGZpcnN0IGRlcml2YXRpdmUgb2YgdGhlIHBvbHlub21pYWwgY3heMl4gKyBrIGlzIDJjeC4gRm9yIGV4YW1wbGUsIHRoZSBmaXJzdCBkZXJpdmF0aXZlIG9mIHheMl4g4oCTIGsgaXMgMnguIFRoZXJlZm9yZSwgd2Uga25vdyB0aGF0IHdlIGNhbiBpbXByb3ZlIG9uIHRoZSBjdXJyZW50IGd1ZXNzLCBjYWxsIGl0IHksIGJ5IGNob29zaW5nIGFzIG91ciBuZXh0IGd1ZXNzIHkgLSAoeV4yXiAtIGspLzJ5LiBUaGlzIGlzIGNhbGxlZCAqKnN1Y2Nlc3NpdmUgYXBwcm94aW1hdGlvbioqLgoKIyMjIFdoYXQgaXMgTmV3dG9uLVJhcGhzb24gbWV0aG9kIGNvZGUgZm9yIGZpbmRpbmcgc3F1YXJlIHJvb3Q/CgpgYGB7cHl0aG9ufQojTmV3dG9uLVJhcGhzb24gZm9yIHNxdWFyZSByb290CiNGaW5kIHggc3VjaCB0aGF0IHgqKjIgLSAyNCBpcyB3aXRoaW4gZXBzaWxvbiBvZiAwIGVwc2lsb24gPSAwLjAxCmsgPSAyNC4wCmd1ZXNzID0gay8yLjAKd2hpbGUgYWJzKGd1ZXNzKmd1ZXNzIC0gaykgPj0gZXBzaWxvbjoKCWd1ZXNzID0gZ3Vlc3MgLSAoKChndWVzcyoqMikgLSBrKS8oMipndWVzcykpIApwcmludCgnU3F1YXJlIHJvb3Qgb2YnLCBrLCAnaXMgYWJvdXQnLCBndWVzcykKYGBgCgojIyMgQ29tcGFyZSB0aGUgZWZmaWNpZW5jeSBvZiBOZXd0b24tUmFwaHNvbiBhbmQgYmlzZWN0aW9uIHNlYXJjaCBtZXRob2Q/CgpgYGB7cHl0aG9ufQp5ID0gNTQuMAplcHNpbG9uID0gMC4wMQoKbnVtR3Vlc3NlcyA9IDAKbG93ID0gMC4wCmhpZ2ggPSB5CmFucyA9IChoaWdoICsgbG93KS8yLjAKCndoaWxlIGFicyAoYW5zKioyIC0geSkgPj0gZXBzaWxvbjoKICAgIHByaW50ICgnbG93ID0gJyArIHN0ciAobG93KSArICcgaGlnaCA9ICcgKyBzdHIgKGhpZ2gpICsgJyBhbnMgPSAnICsgc3RyIChhbnMpKQogICAgbnVtR3Vlc3NlcyArPSAxCiAgICBpZiBhbnMqKjIgPCB5OgogICAgICAgIGxvdyA9IGFucwogICAgZWxzZToKICAgICAgICBoaWdoID0gYW5zCiAgICBhbnMgPSAoaGlnaCArIGxvdykvMi4wCnByaW50ICgnQmlzZWN0aW9uIHNlYXJjaCBudW1HdWVzc2VzID0gJyArIHN0ciAobnVtR3Vlc3NlcykpCnByaW50IChzdHIgKGFucykgKyAnIGlzIGNsb3NlIHRvIHNxdWFyZSByb290IG9mICcgKyBzdHIgKHkpKQoKZ3Vlc3MgPSB5LzIuMApudW1HdWVzc2VzID0gMAoKd2hpbGUgYWJzIChndWVzcypndWVzcyAtIHkpID49IGVwc2lsb246CiAgICBudW1HdWVzc2VzICs9IDEKICAgIHByaW50KCJHdWVzcyBpcyBub3cgYXQiLCBndWVzcykKICAgIGd1ZXNzID0gZ3Vlc3MgLSAoKChndWVzcyoqMikgLSB5KS8oMipndWVzcykpCnByaW50ICgnTmV3dG9uLVJhcGhzb24gbnVtR3Vlc3NlcyA9ICcgKyBzdHIgKG51bUd1ZXNzZXMpKQpwcmludCAoJ1NxdWFyZSByb290IG9mICcgKyBzdHIgKHkpICsgJyBpcyBhYm91dCAnICsgc3RyIChndWVzcykpCmBgYAoK