├── latex.template ├── [frwk] google_web_toolkit.md ├── src ├── programming_languages │ ├── ps5_p1.png │ ├── ps2_gem1.py │ ├── ps1_p2.py │ ├── unit5_l9 │ │ ├── unit5_l9.py │ │ └── graphics.py │ ├── ps6 │ │ ├── htmlinterp.py │ │ ├── htmltokens.py │ │ ├── htmlgrammar.py │ │ ├── ps6_p6.py │ │ ├── jstokens.py │ │ ├── parsetabhtml.py │ │ ├── ps6_p4.py │ │ ├── jsgrammar.py │ │ ├── ps6_challenge.py │ │ ├── ps6_p2.py │ │ ├── ps6_p3.py │ │ └── graphics.py │ ├── ps2_p5.js │ ├── ps1_p3.py │ ├── ps4_p2.py │ ├── ps1_p5.py │ ├── ps5_p5.py │ ├── ps5_p2.py │ ├── final │ │ ├── final_4.py │ │ ├── final_5.py │ │ ├── final_9.py │ │ ├── final_1.py │ │ └── final_2.py │ ├── ps2_p4.py │ ├── parsetabhtml.py │ ├── ps2_p2.py │ ├── ps5_p1.py │ ├── ps1_p6.py │ ├── ps4_p3.py │ ├── jstokens.py │ ├── ps3_p5_actual_answer.py │ ├── ps4_parser.py │ ├── ps2_p1.py │ ├── ps2_p3.py │ └── graphics.py ├── machine_learning_in_action │ ├── ch02 │ │ └── kNN.py │ └── ch03 │ │ ├── trees.py │ │ └── treePlotter.py └── software_testing │ └── ps1.py ├── html ├── _header.html ├── _footer.html └── _pandoc.css ├── README.md ├── articles └── going_faster_with_python │ └── html │ ├── _header.html │ ├── _footer.html │ └── _pandoc.css ├── [admn] transmission_cli.md ├── .gitignore ├── [lang] erlang.md ├── [course] algorithms_cs-215.md ├── [app] openfire_xmpp.md ├── [site] architecture_notes.md ├── [book] tapworthy.md ├── [notes] GRE.md ├── travelbot_locations.txt ├── [presentation] hci_resources.md ├── [book] head first object-oriented design and analysis.md ├── [post] monty_hall_problem.md ├── [book] html5 and javascript web apps (oreilly).md └── [admn] commands.md /latex.template: -------------------------------------------------------------------------------- 1 | \usepackage{marvosym} 2 | 3 | -------------------------------------------------------------------------------- /[frwk] google_web_toolkit.md: -------------------------------------------------------------------------------- 1 | # Google Web Toolkit 2 | 3 | ## Tutorials 4 | 5 | ## General notes 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/programming_languages/ps5_p1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asimihsan/notes/HEAD/src/programming_languages/ps5_p1.png -------------------------------------------------------------------------------- /html/_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # notes 2 | 3 | There are just notes I've made when reading up on languages, frameworks, sites, or books. 4 | 5 | After starting a few Coursera courses I realised I needed both Markdown and LaTeX support. To that end I've created a simple script that uses `pandoc` to do the necessary conversion, i.e. 6 | 7 | pandoc -o tex/ 8 | 9 | Conversion to TeX leaves LaTeX statements bounded by `$$ .. $$` intact; super! Open the TeX file in TexShop, which should handle regeneration to PDF for you. -------------------------------------------------------------------------------- /articles/going_faster_with_python/html/_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[admn] transmission_cli.md: -------------------------------------------------------------------------------- 1 | # transmission-cli 2 | 3 | - Build transmission from source. 4 | 5 | ``` 6 | sudo apt-get install build-essential automake autoconf libtool pkg-config intltool libcurl4-openssl-dev libglib2.0-dev libevent-dev libminiupnpc-dev libminiupnpc5 libappindicator-dev 7 | 8 | wget http://download.transmissionbt.com/files/transmission-2.61.tar.bz2 9 | bunzip2 transmission-2.61.tar.bz2 10 | tar -xvf transmission-2.61.tar 11 | rm -f transmission-2.61.tar 12 | cd transmission-2.61/ 13 | 14 | ./configure --disable-gtk --disable-mac --enable-lightweight 15 | make 16 | sudo make install 17 | 18 | cd .. 19 | rm -rf transmission-2.61/ 20 | ``` 21 | 22 | - Copy on relevant `settings.json` and `transmission.sh` file into e.g. `~/transmission`. 23 | - Run `./transmission.sh`. 24 | 25 | -------------------------------------------------------------------------------- /src/machine_learning_in_action/ch02/kNN.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | import operator 3 | 4 | def createDataSet(): 5 | group = numpy.array([[1.0,1.1], [1.0,1.0], [0,0], [0,0.1]]) 6 | labels = ['A', 'A', 'B', 'B'] 7 | return group, labels 8 | 9 | def classify0(inX, dataSet, labels, k): 10 | dataSetSize = dataSet.shape[0] 11 | diffMat = numpy.tile(inX, (dataSetSize, 1)) - dataSet 12 | sqDiffMat = diffMat ** 2 13 | sqDistances = sqDiffMat.sum(axis=1) 14 | distances = sqDistances ** 0.5 15 | sortedDistIndices = distances.argsort() 16 | 17 | classCount={} 18 | for i in xrange(k): 19 | voteIlabel = labels[sortedDistIndices[i]] 20 | classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 21 | sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) 22 | return sortedClassCount[0][0] 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tex/ 2 | pdf/ 3 | output/ 4 | 5 | *.pyc 6 | src/programming_languages/parser.out 7 | src/programming_languages/parsetab.py 8 | src/programming_languages/unit5_l9/student.aux 9 | src/programming_languages/unit5_l9/student.log 10 | src/programming_languages/unit5_l9/student.out 11 | src/programming_languages/unit5_l9/student.pdf 12 | src/programming_languages/unit5_l9/student.png 13 | src/programming_languages/unit5_l9/student.taglog 14 | src/programming_languages/unit5_l9/student.tex 15 | src/programming_languages/ps6/student.aux 16 | src/programming_languages/ps6/student.log 17 | src/programming_languages/ps6/student.out 18 | src/programming_languages/ps6/student.pdf 19 | src/programming_languages/ps6/student.png 20 | src/programming_languages/ps6/student.taglog 21 | src/programming_languages/ps6/student.tex 22 | src/programming_languages/final/parser.out 23 | src/programming_languages/final/parsetab.py 24 | src/programming_languages/final/test.py 25 | -------------------------------------------------------------------------------- /src/programming_languages/ps2_gem1.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def maximize(l, f): 4 | # ------------------------------------------------------------------------- 5 | # Assumptions 6 | # ------------------------------------------------------------------------- 7 | assert(len(l) > 0) 8 | # ------------------------------------------------------------------------- 9 | 10 | (maximum, maximum_result) = (l[0], f(l[0])) 11 | maximum_result = f(maximum) 12 | for elem in l: 13 | result = f(elem) 14 | if result > maximum_result: 15 | (maximum, maximum_result) = (elem, result) 16 | return maximum 17 | 18 | if __name__ == "__main__": 19 | l = ['Barbara', 'kingsolver', 'wrote', 'The', 'Poisonwood','Bible'] 20 | f = len 21 | print maximize(l, f) 22 | 23 | l = [5, 6, 7, 8, 9, 10, 11, 12, 15, 0] 24 | f = math.sqrt 25 | print maximize(l, f) 26 | 27 | l = [1, 2, 3, 4] 28 | f = math.sqrt 29 | print maximize(l, f) 30 | 31 | l = [4, 3, 2, 1] 32 | f = math.sqrt 33 | print maximize(l, f) 34 | -------------------------------------------------------------------------------- /[lang] erlang.md: -------------------------------------------------------------------------------- 1 | # erlang notes 2 | 3 | ## using rebar 4 | 5 | - References: 6 | - Erlang application management with rebar: [http://alancastro.org/2010/05/01/erlang-application-management-with-rebar.html](http://alancastro.org/2010/05/01/erlang-application-management-with-rebar.html) 7 | - http://www.slideshare.net/konstantinvsorokin/kostis-sagonas-cool-tools-for-modern-erlang-program-developmen 8 | - _Dialyzer_: Automatically identifies bugs 9 | - _Typer_: Displays/adds type information 10 | - _Tidier_: Cleans up Erlang code. 11 | - _Proper_: Performs semi-automatic property based testing. 12 | - _CED_: Auto test suite, concurrency issues. 13 | 14 | - Install: 15 | 16 | wget https://github.com/basho/rebar/wiki/rebar -O rebar 17 | chmod u+x rebar 18 | 19 | - To get list of commands: 20 | 21 | ./rebar -c 22 | 23 | - Create application: 24 | 25 | ./rebar create-app appid=tcpproxy 26 | 27 | - Use a Makefile as shown in the `tcpproxy` app in `travelbot`. 28 | - Add dependencies to a `rebar.config` file inside the root, again consult app as reference. 29 | - Run `make`. 30 | - `tcpproxy` has other good tidbits in it. 31 | 32 | - Display function specs: 33 | 34 | typer --plt .dialyzer.plt --show-exported src/ -------------------------------------------------------------------------------- /src/programming_languages/ps1_p2.py: -------------------------------------------------------------------------------- 1 | # Title: Summing Numbers 2 | 3 | # Write a procedure called sumnums(). Your procedure must accept as input a 4 | # single string. Your procedure must output an integer equal to the sum of 5 | # all integer numbers (one or more digits in sequence) within that string. 6 | # If there are no decimal numbers in the input string, your procedure must 7 | # return the integer 0. The input string will not contain any negative integers. 8 | # 9 | # Example Input: "hello 2 all of you 44" 10 | # Example Output: 46 11 | # 12 | # Hint: int("44") == 44 13 | 14 | import re 15 | 16 | def sumnums(sentence): 17 | result = 0 18 | integers = re.findall(r'[0-9]+', sentence) 19 | if len(integers) > 0: 20 | result += sum(int(integer) for integer in integers) 21 | return result 22 | 23 | # This problem includes an example test case to help you tell if you are on 24 | # the right track. You may want to make your own additional tests as well. 25 | 26 | test_case_input = """The Act of Independence of Lithuania was signed 27 | on February 16, 1918, by 20 council members.""" 28 | 29 | test_case_output = 1954 30 | 31 | if sumnums(test_case_input) == test_case_output: 32 | print "Test case passed." 33 | else: 34 | print "Test case failed:" 35 | print sumnums(test_case_input) 36 | 37 | -------------------------------------------------------------------------------- /html/_footer.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 20 | 21 | 22 | 37 | -------------------------------------------------------------------------------- /articles/going_faster_with_python/html/_footer.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 20 | 21 | 22 | 37 | -------------------------------------------------------------------------------- /src/programming_languages/unit5_l9/unit5_l9.py: -------------------------------------------------------------------------------- 1 | # Your function should display HTML according to a given parse tree. 2 | 3 | # graphics.warning(msg) displays an error message. Upon encountering mismatched 4 | # tags, use graphics.warning to display the error message: "mismatched tag". 5 | 6 | # To display a tag, use graphics.begintag(tag,args) at the start and 7 | # graphics.endtag() at the end of the tag. 8 | 9 | import graphics 10 | 11 | def interpret(trees): # Hello, friend 12 | for tree in trees: # Hello, 13 | # ("word-element","Hello") 14 | nodetype=tree[0] # "word-element" 15 | if nodetype == "word-element": 16 | graphics.word(tree[1]) 17 | elif nodetype == "tag-element": 18 | # Strong text 19 | tagname = tree[1] # b 20 | tagargs = tree[2] # [] 21 | subtrees = tree[3] # ...Strong Text!... 22 | closetagname = tree[4] # b 23 | # QUIZ: (1) check that the tags match 24 | # if not use graphics.warning() 25 | if tagname != closetagname: 26 | graphics.warning("Mismatched tag. start: '%s', end: '%s'" % (tagname, closetagname)) 27 | else: 28 | # (2): Interpret the subtree 29 | # HINT: Call interpret recursively 30 | graphics.begintag(tagname, {}) 31 | interpret(subtrees) 32 | graphics.endtag() 33 | 34 | # Note that graphics.initialize and finalize will only work surrounding a call 35 | # to interpret 36 | 37 | graphics.initialize() # Enables display of output. 38 | 39 | tree = [('tag-element', 'body', [], 40 | [('tag-element', 'b', [], 41 | [('word-element', 'Hello World')], 42 | 'b')], 43 | 'body')] 44 | 45 | interpret(tree) 46 | graphics.finalize() # Enables display of output. 47 | 48 | 49 | -------------------------------------------------------------------------------- /html/_pandoc.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: auto; 3 | padding-right: 1em; 4 | padding-left: 1em; 5 | max-width: 50em; 6 | border-left: 1px solid black; 7 | border-right: 1px solid black; 8 | color: black; 9 | font-family: 'Noticia Text', Verdana, sans-serif; 10 | font-size: 100%; 11 | line-height: 1.8em; 12 | color: #333; 13 | } 14 | sup { 15 | line-height: 0; 16 | } 17 | 18 | pre { 19 | border: 1px dotted gray; 20 | background-color: #ececec; 21 | color: #1111111; 22 | padding: 0.5em; 23 | } 24 | code { 25 | font-family: 'Inconsolata',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif; 26 | } 27 | h1 a, h2 a, h3 a, h4 a, h5 a { 28 | text-decoration: none; 29 | color: #7a5ada; 30 | } 31 | h1, h2, h3, h4, h5 { font-family: 'Source Sans Pro', Verdana, sans-serif; 32 | font-weight: bold; 33 | border-bottom: 1px dotted black; 34 | color: #7a5ada; } 35 | h1 { 36 | font-size: 150%; 37 | } 38 | 39 | h2 { 40 | font-size: 130%; 41 | } 42 | 43 | h3 { 44 | font-size: 115%; 45 | } 46 | 47 | h4 { 48 | font-size: 110%; 49 | font-style: italic; 50 | } 51 | 52 | h5 { 53 | font-size: 110%; 54 | font-style: italic; 55 | } 56 | 57 | h1.title { 58 | font-size: 220%; 59 | font-weight: bold; 60 | padding-top: 0.2em; 61 | padding-bottom: 0.2em; 62 | text-align: left; 63 | border: none; 64 | } 65 | 66 | dt code { 67 | font-weight: bold; 68 | } 69 | dd p { 70 | margin-top: 0; 71 | } 72 | 73 | #footer { 74 | padding-top: 1em; 75 | font-size: 70%; 76 | color: gray; 77 | text-align: center; 78 | } 79 | 80 | blockquote { 81 | margin-top: 10px; 82 | margin-bottom: 10px; 83 | margin-left: 50px; 84 | padding-left: 15px; 85 | border-left: 3px solid #ccc; 86 | font-style: italic; 87 | } 88 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/htmlinterp.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # -- INSTRUCTOR PROVIDES this file 3 | # 4 | # This is an interpreter for a simple subset of HTML. The interpretation is 5 | # that a graphics library is called on the text and tags of the HTML. This 6 | # is basically just an AST tree walk. 7 | # 8 | # It is likely that this would be explained by the professor in class and 9 | # provided to students. 10 | import ply.lex as lex 11 | import ply.yacc as yacc 12 | import jstokens 13 | import jsgrammar 14 | import graphics as graphics 15 | import jsinterp 16 | 17 | # Recursively Interpret an HTML AST 18 | def interpret(ast): # AST 19 | for node in ast: 20 | nodetype = node[0] 21 | if nodetype == "word-element": 22 | graphics.word(node[1]) 23 | elif nodetype == "tag-element": 24 | tagname = node[1]; 25 | tagargs = node[2]; 26 | subast = node[3]; 27 | closetagname = node[4]; 28 | if (tagname <> closetagname): 29 | graphics.warning("(mistmatched " + tagname + " " + closetagname + ")") 30 | else: 31 | graphics.begintag(tagname,tagargs); 32 | interpret(subast) 33 | graphics.endtag(); 34 | elif nodetype == "javascript-element": 35 | jstext = node[1]; 36 | jslexer = lex.lex(module=jstokens) 37 | 38 | if False: # JavaScript lexer/parser debugging 39 | print jstext 40 | jslexer.input(jstext) 41 | while True: 42 | tok = jslexer.token() 43 | if not tok: break 44 | print tok 45 | 46 | jsparser = yacc.yacc(module=jsgrammar,tabmodule="parsetabjs") 47 | jsast = jsparser.parse(jstext,lexer=jslexer) 48 | result = jsinterp.interpret(jsast) 49 | graphics.word(result) 50 | -------------------------------------------------------------------------------- /articles/going_faster_with_python/html/_pandoc.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: auto; 3 | padding-right: 1em; 4 | padding-left: 1em; 5 | max-width: 50em; 6 | border-left: 1px solid black; 7 | border-right: 1px solid black; 8 | color: black; 9 | font-family: 'Noticia Text', Verdana, sans-serif; 10 | font-size: 100%; 11 | line-height: 1.8em; 12 | color: #333; 13 | } 14 | sup { 15 | line-height: 0; 16 | } 17 | 18 | pre { 19 | border: 1px dotted gray; 20 | background-color: #ececec; 21 | color: #1111111; 22 | padding: 0.5em; 23 | } 24 | code { 25 | font-family: 'Inconsolata',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif; 26 | } 27 | h1 a, h2 a, h3 a, h4 a, h5 a { 28 | text-decoration: none; 29 | color: #7a5ada; 30 | } 31 | h1, h2, h3, h4, h5 { font-family: 'Source Sans Pro', Verdana, sans-serif; 32 | font-weight: bold; 33 | border-bottom: 1px dotted black; 34 | color: #7a5ada; } 35 | h1 { 36 | font-size: 150%; 37 | } 38 | 39 | h2 { 40 | font-size: 130%; 41 | } 42 | 43 | h3 { 44 | font-size: 115%; 45 | } 46 | 47 | h4 { 48 | font-size: 110%; 49 | font-style: italic; 50 | } 51 | 52 | h5 { 53 | font-size: 110%; 54 | font-style: italic; 55 | } 56 | 57 | h1.title { 58 | font-size: 220%; 59 | font-weight: bold; 60 | padding-top: 0.2em; 61 | padding-bottom: 0.2em; 62 | text-align: left; 63 | border: none; 64 | } 65 | 66 | dt code { 67 | font-weight: bold; 68 | } 69 | dd p { 70 | margin-top: 0; 71 | } 72 | 73 | #footer { 74 | padding-top: 1em; 75 | font-size: 70%; 76 | color: gray; 77 | text-align: center; 78 | } 79 | 80 | blockquote { 81 | margin-top: 10px; 82 | margin-bottom: 10px; 83 | margin-left: 50px; 84 | padding-left: 15px; 85 | border-left: 3px solid #ccc; 86 | font-style: italic; 87 | } 88 | -------------------------------------------------------------------------------- /src/software_testing/ps1.py: -------------------------------------------------------------------------------- 1 | # CORRECT SPECIFICATION: 2 | # 3 | # the Queue class provides a fixed-size FIFO queue of integers 4 | # 5 | # the constructor takes a single parameter: an integer > 0 that 6 | # is the maximum number of elements the queue can hold. 7 | # 8 | # empty() returns True if and only if the queue currently 9 | # holds no elements, and False otherwise. 10 | # 11 | # full() returns True if and only if the queue cannot hold 12 | # any more elements, and False otherwise. 13 | # 14 | # enqueue(i) attempts to put the integer i into the queue; it returns 15 | # True if successful and False if the queue is full. 16 | # 17 | # dequeue() removes an integer from the queue and returns it, 18 | # or else returns None if the queue is empty. 19 | # 20 | # Example: 21 | # q = Queue(1) 22 | # is_empty = q.empty() 23 | # succeeded = q.enqueue(10) 24 | # is_full = q.full() 25 | # value = q.dequeue() 26 | # 27 | # 1. Should create a Queue q that can only hold 1 element 28 | # 2. Should then check whether q is empty, which should return True 29 | # 3. Should attempt to put 10 into the queue, and return True 30 | # 4. Should check whether q is now full, which should return True 31 | # 5. Should attempt to dequeue and put the result into value, which 32 | # should be 10 33 | # 34 | # Your test function should run assertion checks and throw an 35 | # AssertionError for each of the 5 incorrect Queues. Pressing 36 | # submit will tell you how many you successfully catch so far. 37 | 38 | 39 | from queue_test import * 40 | 41 | def test(): 42 | q = Queue(2) 43 | assert q.empty() == True 44 | assert q.enqueue(2 ** 16 + 1) == True 45 | assert q.empty() == False 46 | assert q.enqueue(11) == True 47 | assert q.enqueue(12) == False 48 | assert q.dequeue() == 2 ** 16 + 1 49 | assert q.dequeue() == 11 50 | assert q.empty() == True 51 | assert q.dequeue() is None 52 | 53 | size = 50000 54 | q = Queue(size) 55 | cnt = 1 56 | while cnt < size: 57 | assert q.enqueue(cnt) == True 58 | cnt += 1 59 | cnt = 1 60 | while cnt < size: 61 | assert q.dequeue() == cnt 62 | cnt += 1 63 | 64 | -------------------------------------------------------------------------------- /src/programming_languages/ps2_p5.js: -------------------------------------------------------------------------------- 1 | // Euclid's Algorithm 2 | // 3 | // Format: Submit JavaScript Code 4 | // 5 | // In mathematics, because 8 divides 24 evenly, we say that 8 is a 6 | // *divisor* of 24. When computing, it is often useful to find the 7 | // largest divisor that two numbers have in common. For example, 36 8 | // and 24 are both divisible by 2, 3, 4, and 12: the greatest 9 | // divisor that they have in common is 12. It turns out that finding 10 | // common divisors for numbers is critical for modern cryptography, 11 | // including public-key crypto systems such as RSA: a backbone of internet 12 | // commerce. 13 | // 14 | // Perhaps the oldest algorithm known -- ever! -- is for computing the 15 | // greatest common divisor of two positive numbers. It is attributed to the 16 | // Greek mathematician Euclid around 300 BCE. Here's how it goes: 17 | // 18 | // You are computing the greatest common divisor ("gcd") of two positive 19 | // integers called "a" and "b". The gcd can be computed recursively (or 20 | // iteratively) using the following three rules: 21 | // 22 | // gcd(a,b) = a if a == b 23 | // gcd(a,b) = gcd(a-b,b) if a > b 24 | // gcd(a,b) = gcd(a,b-a) if a < b 25 | // 26 | // print a JavaScript (_not_ Python) program that declares a function called gcd 27 | // that accepts two positive integer arguments a and b and returns their greatest 28 | // common divisor. Store your function in a variable called javascriptcode. 29 | // 30 | // We will return anything printed out when you hit submit as we execute the 31 | // JavaScript behind the scenes. 32 | // 33 | // !!AI I altered the file to be able to be executable using Mozilla Rhino, i.e. 34 | // 35 | // rhino ps2_p5.js 36 | // 37 | // Changed the comments from # to //, and write() with print(). 38 | 39 | function gcd(a,b) { 40 | if (a == b) return a; 41 | if (a > b) return gcd(a-b, b); 42 | return gcd(a, b-a); 43 | } 44 | 45 | print( gcd(24,8) == 8 ); 46 | print(" "); 47 | print( gcd(1362, 1407) ); // Empress Xu (Ming Dynasty) wrote biographies 48 | print(" "); 49 | print( gcd(1875, 1907) ); // Qiu Jin, feminist, revolutionary, and writer 50 | print(" "); 51 | print( gcd(45,116) ); // Ban Zhao, first known female Chinese historian 52 | 53 | -------------------------------------------------------------------------------- /[course] algorithms_cs-215.md: -------------------------------------------------------------------------------- 1 | # Algorithms (CS-215) on Udacity 2 | 3 | ## Student 4 | 5 | [Asim Ihsan](http://www.asimihsan.com) 6 | 7 | ## Unit 1: A Social Network Magic Trick 8 | 9 | ### 1.3: Eulerian Path 10 | 11 | - **Eulerian path**: Path that traverses through all edges once in a connected graph. 12 | - **Eulerian tour**: Eulerian path that starts and ends at the same node. 13 | 14 | ### 1.4: Algorithms are Cool 15 | 16 | def algorithm_Development(problem_spec): 17 | correct = False 18 | while not correct or not fast_enough: 19 | algorithm = devise_algorithm(problem_spec) 20 | correct = analyze_correctness(algorithm) 21 | running_time = analyse_efficiency(algorithm) 22 | return algorithm 23 | 24 | ### 1.6: Correctness 25 | 26 | - e.g. naive(a,b) = a*b. 27 | - *Claim*: Before or after "while" loop 28 | 29 | ab = xy + z 30 | 31 | - *Base case*: First time through, x=a, y=b, z=0 32 | 33 | ab = ab + 0 34 | 35 | - *Inductive step* 36 | - If ab = xy + z before 37 | - Then ab = x'y' + z' after. 38 | 39 | x' = x - 1 40 | y' = y 41 | z' = z + y 42 | 43 | x'y' + z' = (x-1)(y) + (z+y) 44 | = xy-y + z + y 45 | = xy + z 46 | = ab 47 | 48 | - So we know that the claim is true. So? 49 | - What happens when x = 0 at the end? 50 | - ab = z, the return value. 51 | - QED. 52 | 53 | ### 1.8: Russian Peasant's Algorithm 54 | 55 | - aka Ancient Egyptian multiplication 56 | 57 | def russian(a, b): 58 | x = a 59 | y = b 60 | z = 0 61 | while x > 0: 62 | if x % 2 == 1: 63 | z = z + y 64 | y = y << 1 65 | x = x >> 1 66 | return z 67 | 68 | e.g. russian(14, 11), should = 154 69 | 70 | x y z 71 | 14 11 0 72 | 7 22 22 73 | 3 44 66 74 | 1 88 154 75 | 0 176 154 76 | 77 | ### 1.10: Correctness 78 | 79 | - Claim: 80 | 81 | ab = xy + z 82 | 83 | - Base case: true, same as naive. 84 | - Inductive step: if ab = xy + z holds at start then ab = x'y' + z'. 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /[app] openfire_xmpp.md: -------------------------------------------------------------------------------- 1 | # Openfire XMPP setup 2 | 3 | This document goes over my experience attempting to set up the Openfire XMPP server. It wasn't easy, pay attention. 4 | 5 | ## Initial steps 6 | 7 | - Download the RPM for the latest version of Java, or yum/apt-get it, as you wish. [RPMs here](https://www.java.com/en/download/manual.jsp). 8 | - Download the RPM for Openfire and install here. [RPM here](http://www.igniterealtime.org/projects/openfire/). 9 | - Install PostgreSQL, follow [Linode's excellent instructions](https://library.linode.com/databases/postgresql). 10 | - Create a database called `openfire` use `\l /usr/local/openfire/resources/database/openfire_postgresql.sql` to create the necessary tables. 11 | - Make sure you enable PostgreSQL to allow connections over IP. Create a new user, grant it password access to this box over IP. 12 | - Actual use this IP connection, check it works. 13 | - Go to `http://localhost:9090`, this is the Openfire admin panel. By default when you start off you get a setup wizard. If you mess up and want to go back through the wizard add `true` to `/usr/local/openfire/conf/openfire.xml`. 14 | - TODO Oddly enough Openfire will claim the PostgreSQL connection works but then revert to the embedded database. I need to figure this out. 15 | 16 | ## More! 17 | 18 | - Admin panel default username is `admin`, password `admin`. 19 | - Add a user via the admin panel, log in via a client like [Ignite Spark](http://www.igniterealtime.org/projects/spark/). This should work. 20 | - At this point you'll notice your user's domain name is "127.0.0.1". This is annoying, and will really upset programming APIs that expect the domain name to be usable over a remote socket. To change this, go to the Openfire admin panel, -> Server -> Server Manager -> Server Properties, set `xmpp.domain` to `domain.fqdn`. 21 | - Use a library like [Python Wokkel](http://wokkel.ik.nu/documentation/current/client.html) and explicitly confirm that you can log in as `username@domain.fqdn`. 22 | - an API for adding/removing users is available via the "User Service" plugin. Easiest way to install it is via the admin page, Plugins -> Plugin Admin -> Available Plugins. The gotcha is that you need to enable it afterwards in Server -> Server Settings -> User Service. API thereafter is according to README file, e.g. 23 | 24 | `http://example.com:9090/plugins/userService/userservice?type=add&secret=bigsecret&username=kafka&password=drowssap&name=franz&email=franz@kafka.com` 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/htmltokens.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # 3 | # This is a set of regular expressions defining a lexer for HTML with 4 | # embedded JavaScript fragments. 5 | # 6 | 7 | import ply.lex as lex 8 | 9 | tokens = ( 10 | 'LANGLE', # < 11 | 'LANGLESLASH', # 13 | 'SLASHRANGLE', # /> 14 | 'EQUAL', # = 15 | 'STRING', # "144" 16 | 'WORD', # 'Welcome' in "Welcome to my webpage." 17 | 'JAVASCRIPT', # embedded JavaScript Fragment 18 | ) 19 | 20 | states = ( 21 | ('javascript', 'exclusive'), # ' 46 | t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos-9] 47 | t.type = "JAVASCRIPT" 48 | t.lexer.lineno += t.value.count('\n') 49 | t.lexer.begin('INITIAL') 50 | return t 51 | 52 | def t_javascript_error(t): 53 | t.lexer.skip(1) 54 | 55 | def t_LANGLESLASH(t): 56 | r'' 65 | return t 66 | 67 | def t_RANGLE(t): 68 | r'>' 69 | return t 70 | 71 | def t_EQUAL(t): 72 | r'=' 73 | return t 74 | 75 | def t_STRING(t): 76 | r'(?:"[^"]*"|\'[^\']*\')' 77 | t.value = t.value[1:-1] # drop "surrounding quotes" 78 | return t 79 | 80 | def t_WORD(t): 81 | r'[^ \t\v\r\n<>=]+' 82 | return t 83 | 84 | t_ignore = ' \t\v\r' 85 | t_htmlcomment_ignore = ' \t\v\r' 86 | t_javascript_ignore = ' \t\v\r' 87 | 88 | def t_newline(t): 89 | r'\n' 90 | t.lexer.lineno += 1 91 | 92 | def t_error(t): 93 | print "HTML Lexer: Illegal character " + t.value[0] 94 | t.lexer.skip(1) 95 | -------------------------------------------------------------------------------- /[site] architecture_notes.md: -------------------------------------------------------------------------------- 1 | # Architecture notes 2 | 3 | ## Main lessons 4 | 5 | - Keep it **simple**. 6 | 7 | ## Other 8 | 9 | - Use [Amazon CloudFront](http://aws.amazon.com/cloudfront/) to push content to the edges of a CDN close to consumers; "intelligent" S3. 10 | - [Celery with Kombu](http://docs.celeryproject.org/en/latest/tutorials/clickcounter.html) fits well with Django, worth learning and deploying with. 11 | 12 | ## High Scalability 13 | 14 | - iDoneThis 15 | - Python, Django, PostgreSQL. 16 | - Django hosts both HTML view for browsers and JSON view for Backbone.js and iPhone apps. 17 | - **Lucene, Solr** for full-text search. 18 | - One instance. Amazon EC2 extra large. 19 | - [Celery](http://celeryproject.org/) to aynchronously sending emails (probably with RabbitMQ backend). 20 | 21 | - Instagram 22 | - Amazon ELB -> nginx -> Django. 23 | - [Gunicorn](http://gunicorn.org/) as WSGI server. 24 | - [Fabric](http://fabric.readthedocs.org/en/1.3.3/index.html) for deployment. 25 | - PostgreSQL running as master-replica using [streaming replication](https://github.com/greg2ndQuadrant/repmgr). EBS used for snapshotting. 26 | - EBS deployed with software RAID using [mdadm](http://en.wikipedia.org/wiki/Mdadm). 27 | - [Vmtouch](http://hoytech.com/vmtouch/vmtouch.c) for managing data in memory. 28 | - XFS as file system, for consistent snapshots on RAID arrays. 29 | - [Pgbouncer](http://pgfoundry.org/projects/pgbouncer/) for pooling PostgreSQL connections. 30 | - Amazon S3 for photos, Amazon Cloudfront as CDN. 31 | - redis for feeds, sessions, other mappings. Many large instances in master-replica setup. EBS snapshots of replicas. 32 | - Amazon Solr for geo-search API. 33 | - memcached for caching. 34 | - [Gearman](http://gearman.org/#introduction) as a job dispatcher. Asynchronously sharing photos, notifying real-time subscribers, feed fan-out. 35 | - [Pyapns](https://github.com/samuraisam/pyapns) for Apple push notifications. 36 | - [Munin](http://munin-monitoring.org/) for graphing metrics, alerts on problems with custom plugins. 37 | - [Pingdom](http://pingdom.com/) for external monitoring. 38 | - [PagerDuty](http://pagerduty.com/) of handling notifications of incidents. 39 | - [Sentry](http://pypi.python.org/pypi/django-sentry) for Python error reporting. 40 | 41 | - Google and latency 42 | - Prioritize request queues and network traffic. 43 | - Reduce head-of-line blocking by breaking large requests into smaller requests. 44 | - Rate limit activity. 45 | - Defer expensive activity if you can. -------------------------------------------------------------------------------- /src/programming_languages/ps1_p3.py: -------------------------------------------------------------------------------- 1 | # Singly-Hyphenated Words 2 | 3 | # We examined hyphenated words in a quiz in class. In this problem you 4 | # will get a chance to handle them correctly. 5 | # 6 | # Assign to the variable regexp a Python regular expression that matches 7 | # both words (with letters a-z) and also singly-hyphenated words. If you 8 | # use grouping, you must use (?: and ) as your regular expression 9 | # parentheses. 10 | # 11 | # Examples: 12 | # 13 | # regexp exactly matches "astronomy" 14 | # regexp exactly matches "near-infrared" 15 | # regexp exactly matches "x-ray" 16 | # regexp does not exactly match "-tricky" 17 | # regexp does not exactly match "tricky-" 18 | # regexp does not exactly match "large - scale" 19 | # regexp does not exactly match "gamma-ray-burst" 20 | # regexp does not exactly match "" 21 | 22 | # Your regular expression only needs to handle lowercase strings. 23 | 24 | # In Python regular expressions, r"A|B" checks A first and then B - it 25 | # does not follow the maximal munch rule. Thus, you may want to check 26 | # for doubly-hyphenated words first and then non-hyphenated words. 27 | 28 | import re 29 | 30 | regexp = r"[a-z]+(?:-[a-z]+)?" # you should replace this with your regular expression 31 | 32 | # This problem includes an example test case to help you tell if you are on 33 | # the right track. You may want to make your own additional tests as well. 34 | 35 | test_case_input = """the wide-field infrared survey explorer is a nasa 36 | infrared-wavelength space telescope in an earth-orbiting satellite which 37 | performed an all-sky astronomical survey. be careful of -tricky tricky- 38 | hyphens --- be precise.""" 39 | 40 | test_case_output = ['the', 'wide-field', 'infrared', 'survey', 'explorer', 41 | 'is', 'a', 'nasa', 'infrared-wavelength', 'space', 'telescope', 'in', 'an', 42 | 'earth-orbiting', 'satellite', 'which', 'performed', 'an', 'all-sky', 43 | 'astronomical', 'survey', 'be', 'careful', 'of', 'tricky', 'tricky', 44 | 'hyphens', 'be', 'precise'] 45 | 46 | if re.findall(regexp, test_case_input) == test_case_output: 47 | print "Test case 1 passed." 48 | else: 49 | print "Test case 1 failed:" 50 | print re.findall(regexp, test_case_input) 51 | 52 | for successful_match in ["astronomy", "near-infrared", "x-ray"]: 53 | print "%s - %s" % (successful_match, re.findall(regexp, successful_match) == [successful_match]) 54 | 55 | for unsuccessful_match in ["-tricky-", "tricky-", "large - scale", "gamme-ray-burst"]: 56 | print "%s - %s" % (unsuccessful_match, re.findall(regexp, unsuccessful_match) != [unsuccessful_match]) 57 | 58 | -------------------------------------------------------------------------------- /src/programming_languages/ps4_p2.py: -------------------------------------------------------------------------------- 1 | # Bank Heist 2 | # 3 | # Suppose you are a daring thief who has infiltrated the palace of an evil 4 | # dictator. You need to be quick when making your escape, so you can only 5 | # carry 20 kilograms of unbroken goods out with you. Despite this, you want 6 | # to escape with items worth as much money as possible. Suppose further 7 | # that there are three artifacts available: 8 | # 9 | # a 1502 ACE Incan statue massing 15 kilograms, valued at $30000 10 | # a 1499 ACE Aztec jade mask massing 9 kilograms, valued at $16000 11 | # a 300 ACE Mayan urn massing 8 kilograms, valued at $15000 12 | # 13 | # It is not possible to take all three, and even though the Incan statue 14 | # has the highest value-to-mass ratio, given a 20 kilogram limit the best 15 | # choice is to take the Aztec mask and the Mayan urn. 16 | # 17 | # This is the setup for the "0-1 Knapsack Problem", an important task in 18 | # theoretical computer science. In general, deciding what to take given a 19 | # list of items and a mass limit is believed to be very difficult. This 20 | # question does not ask you to come up with a solution, however -- instead, 21 | # you will evaluate solutions. 22 | # 23 | # We can encode a problem instance as follows. We'll use a dictionary 24 | # mapping item names to (mass,value) pairs. 25 | # 26 | available = { 27 | "statue" : (15, 30000) , 28 | "mask" : (9, 16000) , 29 | "urn" : (8, 15000) , 30 | } 31 | # 32 | # Then the mass limit and the taken objects are just a number and a 33 | # string list respectively: 34 | limit = 20 35 | taken = [ "mask", "urn" ] 36 | # 37 | # Write a Python procedure heistvalid(available,limit,taken) that returns 38 | # True (the boolean value True, not the string "True") if the objects 39 | # in the list `taken' have a total mass less than or equal to the limit. 40 | # 41 | # In addition, write a Python procedure heisttotal(available,limit,taken) 42 | # that returns the total value (as a number) of the objects in the list 43 | # `taken'. 44 | # 45 | # This problem is meant to provide practice for *list comprehensions*. Make 46 | # the body each of your procedures *at most one line long*. 47 | # 48 | # Hint: sum([1,2,3]) == 6 49 | 50 | def heistvalid(available, limit, taken): 51 | return sum([available[name][0] for name in taken]) <= limit 52 | 53 | def heisttotal(available, limit, taken): 54 | return sum([available[name][1] for name in taken]) 55 | 56 | # We have provided some test cases. You will likely want to make others. 57 | print heistvalid(available, limit, taken) == True 58 | print heisttotal(available, limit, taken) == 31000 59 | allthree = ["statue", "mask", "urn"] 60 | print heistvalid(available, limit, allthree) == False 61 | print heisttotal(available, limit, allthree) == 61000 62 | 63 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/htmlgrammar.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # 3 | # This is a grammar definition file for a simple subset of HTML with 4 | # embedded JavaScript. 5 | # 6 | 7 | import ply.yacc as yacc 8 | from htmltokens import tokens 9 | 10 | start = 'html' 11 | 12 | tag_stack = [] # for error reporting 13 | 14 | def p_html(p): 15 | 'html : element html' 16 | p[0] = [p[1]] + p[2] 17 | def p_html_empty(p): 18 | 'html : ' 19 | p[0] = [ ] 20 | 21 | def p_element_word(p): 22 | 'element : WORD' 23 | p[0] = ('word-element',p[1]) 24 | 25 | def p_element_word_eq(p): 26 | 'element : EQUAL' 27 | p[0] = ('word-element',p[1]) 28 | 29 | def p_element_word_string(p): 30 | 'element : STRING' 31 | p[0] = ('word-element',"``" + p[1] + "''") 32 | 33 | def p_tagname(p): 34 | 'tagname : WORD' 35 | global tag_stack 36 | tag_stack = [(p[1],p.lineno(1))] + tag_stack 37 | p[0] = p[1] 38 | 39 | def p_tagnameend(p): 40 | 'tagnameend : WORD' 41 | global tag_stack 42 | if (tag_stack[0])[0] != p[1]: 43 | print "HTML Syntax Error: <" + tag_stack[0][0] + "> on line " + str(tag_stack[0][1]) + " closed by on line " + str(p.lineno(1)) 44 | exit(1) 45 | tag_stack = tag_stack[1:] 46 | p[0] = p[1] 47 | 48 | def p_element_tag_empty(p): 49 | #
50 | 'element : LANGLE tagname tag_arguments SLASHRANGLE' 51 | global tag_stack 52 | tag_stack = tag_stack[1:] 53 | p[0] = ('tag-element',p[2],p[3],[],p[2]) 54 | 55 | def p_element_tag(p): 56 | # Important text! 57 | 'element : LANGLE tagname tag_arguments RANGLE html LANGLESLASH tagnameend RANGLE' 58 | p[0] = ('tag-element',p[2],p[3],p[5],p[7]) 59 | 60 | def p_tag_arguments(p): 61 | 'tag_arguments : tag_argument tag_arguments' 62 | p[0] = dict(p[1].items() + p[2].items()) 63 | 64 | def p_tag_arguments_empty(p): 65 | 'tag_arguments : ' 66 | p[0] = { } 67 | 68 | def p_tag_argument_word(p): 69 | 'tag_argument : WORD EQUAL WORD' 70 | p[0] = { p[1].lower() : p[3] } 71 | 72 | def p_tag_argument_string(p): 73 | 'tag_argument : WORD EQUAL STRING' 74 | p[0] = { p[1].lower() : p[3] } 75 | 76 | def p_element_javascript(p): 77 | 'element : JAVASCRIPT' 78 | p[0] = ("javascript-element",p[1]) 79 | 80 | def p_error(t): 81 | if tag_stack[0] != []: 82 | print "HTML Syntax Error: <" + tag_stack[0][0] + "> on line " + str(tag_stack[0][1]) + " never closed" 83 | else: 84 | tok = yacc.token() 85 | print "HTML Syntax Error: Near Token " + str(tok) 86 | exit(1) 87 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/ps6_p6.py: -------------------------------------------------------------------------------- 1 | # A Web Browser For HTML + JavaScript 2 | # 3 | # Congratulations! You have written: 4 | # 5 | # regular expressions defining HTML tokens 6 | # and thus an HTML lexical analyzer 7 | # 8 | # regular expressions defining JavaScript tokens 9 | # and thus a JavaScript lexical analyzer 10 | # 11 | # a context-free grammar defining well-formed HTML 12 | # and an HTML parser that makes abstract syntax trees 13 | # 14 | # a context-free grammar defining well-formed JavaScript 15 | # and an HTML parser than makes abstract syntax trees 16 | # 17 | # a recursive tree-walking interpreter for HTML 18 | # that calls a graphics library and a JavaScript interpreter 19 | # 20 | # a recursive tree-walking interpreter for JavaScript 21 | # that handles statements, expressions, variables, 22 | # environments and functions 23 | # 24 | # an optional interpreter for simplifying JavaScript 25 | # 26 | # glue code that follows software design decisions to link them all 27 | # together 28 | # 29 | # Those are the major components of our web browser. This class did not 30 | # support all of JavaScript, and you did not write the graphics library, 31 | # but those are minor concerns. We could easily imagine adding "for loops" 32 | # or other JavaScript syntax as needed, now that you have the base 33 | # language. 34 | # 35 | # For this problem, you must submit "your favorite" webpage text that our 36 | # web browser can handle. 37 | # 38 | # The only official requirement is that your webpage text contain 39 | # correctly-nested tags, start with , and contain 15 | # 16 | # 17 | # Does not output the literal string "Tags in my output should be 18 | # processed." Instead, the tags are lexed, parsed and interpreted 19 | # again, and the web page contains "Tags in my output should be processed." 20 | # with the word "my" drawn in italics. 21 | # 22 | # This sort of recursive dependence -- in which intepreted HTML contains 23 | # JavaScript which runs and creates new HTML which is then interpreted, 24 | # and so on, is the heart of JavaScript's power. You can visualize it like 25 | # a snake eating its own tail: http://en.wikipedia.org/wiki/Ouroboros 26 | # 27 | # In this assignment you will extend our web browser so that the string 28 | # produced by JavaScript is not merely passed to the graphics library as a 29 | # word, but is instead lexed, parsed and interpreted as HTML. (For the 30 | # purposes of this assignment, if JavaScript creates HTML, it must created 31 | # only well-balanced tags.) 32 | # 33 | # Below is the top-level HTML Interpreter code for the web browser. You 34 | # will not need to change any lexer definitions, token definitions, or 35 | # anything about the JavaScript interpreter. 36 | # 37 | # Hint: The required extension can be made by changin as few as three lines 38 | # (because you already know so much about this topic)! It does require you 39 | # to understand how lexers, parser and interpreters all fit together. 40 | 41 | import ply.lex as lex 42 | import ply.yacc as yacc 43 | import graphics as graphics 44 | import jstokens 45 | import jsgrammar 46 | import jsinterp 47 | import htmltokens 48 | import htmlgrammar 49 | 50 | # Load up the lexers and parsers that you have already written in 51 | # previous assignments. Do not worry about the "module" or 52 | # "tabmodule" arguments -- they handle storing the JavaScript 53 | # and HTML rules separately. 54 | htmllexer = lex.lex(module=htmltokens) 55 | htmlparser = yacc.yacc(module=htmlgrammar,tabmodule="parsetabhtml") 56 | jslexer = lex.lex(module=jstokens) 57 | jsparser = yacc.yacc(module=jsgrammar,tabmodule="parsetabjs") 58 | 59 | # The heart of our browser: recursively interpret an HTML abstract 60 | # syntax tree. 61 | def interpret(ast): 62 | for node in ast: 63 | nodetype = node[0] 64 | if nodetype == "word-element": 65 | graphics.word(node[1]) 66 | elif nodetype == "tag-element": 67 | tagname = node[1]; 68 | tagargs = node[2]; 69 | subast = node[3]; 70 | closetagname = node[4]; 71 | if (tagname <> closetagname): 72 | graphics.warning("(mistmatched " + tagname + " " + closetagname + ")") 73 | else: 74 | graphics.begintag(tagname,tagargs); 75 | interpret(subast) 76 | graphics.endtag(); 77 | elif nodetype == "javascript-element": 78 | jstext = node[1]; 79 | jsast = jsparser.parse(jstext,lexer=jslexer) 80 | result = jsinterp.interpret(jsast) 81 | 82 | # rather than just call graphics we re-interpret here. 83 | # graphics.word(result) 84 | htmlast = htmlparser.parse(result,lexer=htmllexer) 85 | interpret(htmlast) 86 | 87 | # Here is an example webpage that includes JavaScript that generates HTML. 88 | # You can use it for testing. 89 | webpage = """ 90 |

JavaScript That Produces HTML

91 |

92 | This paragraph starts in HTML ... 93 | 96 | ... and this paragraph finishes in HTML. 97 |

98 |
99 |

100 | Now we will use JavaScript to display even numbers in italics and 101 | odd numbers in bold.

102 | 120 |

121 | """ 122 | 123 | htmlast = htmlparser.parse(webpage,lexer=htmllexer) 124 | graphics.initialize() # let's start rendering a webpage 125 | interpret(htmlast) 126 | graphics.finalize() # we're done rendering this webpage 127 | 128 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/ps6_p3.py: -------------------------------------------------------------------------------- 1 | # Debugging Environments 2 | # 3 | # Debugging is critical to making high-quality software. In this problem I 4 | # have inserted a bug into our JavaScript interpreter and you will have to 5 | # fix it. In particular, we will focus on function call expressions. 6 | # 7 | # Suppose our code for eval_exp(), evaluating JavaScript expressions, looks 8 | # like this : 9 | 10 | # def eval_exp(exp,env): 11 | # etype = exp[0] 12 | # if etype == "identifier": 13 | # vname = exp[1] 14 | # value = env_lookup(vname,env) 15 | # if value == None: 16 | # print "ERROR: unbound variable " + vname 17 | # else: 18 | # return value 19 | # elif etype == "number": 20 | # return float(exp[1]) 21 | # elif etype == "string": 22 | # return exp[1] 23 | # elif etype == "true": 24 | # return True 25 | # # ... 26 | # elif etype == "call": 27 | # return eval_call(exp,env) 28 | # 29 | # Then the function eval_call() is responsible for handling function call 30 | # expressions. I have written a buggy version of it below. You must find 31 | # and fix the bug. 32 | # 33 | # To test your eval_call() and localize the bug, you may define the 34 | # variable webpage to hold any webpage text (presumably including 35 | # JavaScript) that you like. 36 | # 37 | # Hint: Pay careful attention to environments. Remember that a function is 38 | # defined in one environment but called in another. 39 | 40 | import ply.lex as lex 41 | import ply.yacc as yacc 42 | import graphics as graphics 43 | import jstokens 44 | import jsgrammar 45 | import jsinterp 46 | import htmltokens 47 | import htmlgrammar 48 | import htmlinterp 49 | 50 | htmllexer = lex.lex(module=htmltokens) 51 | htmlparser = yacc.yacc(module=htmlgrammar,tabmodule="parsetabhtml") 52 | jslexer = lex.lex(module=jstokens) 53 | jsparser = yacc.yacc(module=jsgrammar,tabmodule="parsetabjs") 54 | env_lookup = jsinterp.env_lookup 55 | eval_exp = jsinterp.eval_exp 56 | JSReturn = jsinterp.JSReturn 57 | eval_stmts = jsinterp.eval_stmts 58 | env_update = jsinterp.env_update 59 | 60 | def eval_call(exp,env): 61 | # Recall: exp = (fname, args, body, fenv) 62 | fname = exp[1] 63 | args = exp[2] 64 | fvalue = env_lookup(fname,env) 65 | if fname == "write": 66 | argval = eval_exp(args[0],env) 67 | output_sofar = env_lookup("javascript output",env) 68 | env_update("javascript output",output_sofar + str(argval),env) 69 | elif fvalue[0] == "function": 70 | fparams = fvalue[1] 71 | fbody = fvalue[2] 72 | fenv = fvalue[3] 73 | if len(fparams) <> len(args): 74 | print "ERROR: wrong number arguments to " + fname 75 | else: 76 | # make a new environment frame 77 | # !!AI the error was here. Yes, we need to make a new 78 | # environment frame for this function call, but the parent 79 | # must be the **environment frame when the function was 80 | # initialized**, not the current calling environment frame 81 | newenv = (fenv,{ }) 82 | 83 | for i in range(len(args)): 84 | argval = eval_exp(args[i],env) 85 | (newenv[1])[fparams[i]] = argval 86 | # evaluate the body in the new frame 87 | try: 88 | eval_stmts(fbody,newenv) 89 | return None 90 | except JSReturn as r: 91 | return r.retval 92 | else: 93 | print "ERROR: call to non-function " + fname 94 | 95 | jsinterp.eval_call = eval_call 96 | 97 | # This example webpage already demonstrates the error, but you may want 98 | # to change or refine it to localize the bug. 99 | 100 | # Another webpage, trying to localize. 101 | webpage2 = """ 102 |

103 | 117 |

118 | 119 | """ 120 | 121 | # Original webpage 122 | webpage = """ 123 |

124 | The correct answer is 3.0 4.0: 125 | 144 |

145 |
146 | 147 | 148 | """ 149 | 150 | 151 | htmlast = htmlparser.parse(webpage,lexer=htmllexer) 152 | graphics.initialize() # let's start rendering a webpage 153 | htmlinterp.interpret(htmlast) 154 | graphics.finalize() # we're done rendering this webpage 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /src/programming_languages/ps3_p5_actual_answer.py: -------------------------------------------------------------------------------- 1 | # Detecting Ambiguity 2 | # 3 | # A grammar is ambiguous if there exists a string in the language of that 4 | # grammar that has two (or more) parse trees. Equivalently, a grammar is 5 | # ambiguous if there are two (or more) different sequences of rewrite rules 6 | # that arrive at the same final string. 7 | # 8 | # Ambiguity is a critical concept in natural languages and in programming 9 | # languages. If we are not careful, our formal grammars for languages like 10 | # JavaScript will have ambiguity. 11 | # 12 | # In this problem you will write a procedure isambig(grammar,start,tokens) 13 | # that takes as input a grammar with a finite number of possible 14 | # derivations and a string and returns True (the value True, not the string 15 | # "True") if those tokens demonstrate that the grammar is ambiguous 16 | # starting from that start symbol (i.e., because two different sequences of 17 | # rewrite rules can arrive at those tokens). 18 | # 19 | # For example: 20 | # 21 | # grammar1 = [ # Rule Number 22 | # ("S", [ "P", ] ), # 0 23 | # ("S", [ "a", "Q", ]) , # 1 24 | # ("P", [ "a", "T"]), # 2 25 | # ("P", [ "c" ]), # 3 26 | # ("Q", [ "b" ]), # 4 27 | # ("T", [ "b" ]), # 5 28 | # ] 29 | # 30 | # In this grammar, the tokens ["a", "b"] do demonstrate that the 31 | # grammar is ambiguous because there are two difference sequences of 32 | # rewrite rules to obtain them: 33 | # 34 | # S --0-> P --2-> a T --5-> a b 35 | # 36 | # S --1-> a Q --4-> a b 37 | # 38 | # (I have written the number of the rule used inside the arrow for 39 | # clarity.) The two sequences are [0,2,5] and [1,4]. 40 | # 41 | # However, the tokens ["c"] do _not_ demonstrate that the grammar is 42 | # ambiguous, because there is only one derivation for it: 43 | # 44 | # S --0-> P --3-> c 45 | # 46 | # So even though the grammar is ambiguous, the tokens ["c"] do not 47 | # demonstrate that: there is only one sequence [0,3]. 48 | # 49 | # Important Assumption: In this problem the grammar given to you will 50 | # always have a finite number of possible derivations. So only a 51 | # finite set of strings will be in the language of the grammar. (You could 52 | # test this with something like cfginfinite, so we'll just assume it.) 53 | # 54 | # Hint 1: Consider something like "expand" from the end of the Unit, but 55 | # instead of just enumerating utterances, enumerate (utterance,derivation) 56 | # pairs. For a derivation, you might use a list of the rule indexes as we 57 | # did in the example above. 58 | # 59 | # Hint 2: Because the grammar has only a finite number of derivations, you 60 | # can just keep enumerating new (utterance,derivation) pairs until you 61 | # cannot find any that are not already enumerated. 62 | 63 | def expand(tokens_and_derivation, grammar): 64 | (tokens, derivation) = tokens_and_derivation 65 | for token_pos in range(len(tokens)): # for each token 66 | for rule_index in range(len(grammar)): # for each rule 67 | rule = grammar[rule_index] 68 | if tokens[token_pos] == rule[0]: # token is on LHS of rule 69 | yield ((tokens[:token_pos] + rule[1] + tokens[token_pos+1:]), derivation + [rule_index]) 70 | 71 | def isambig(grammar, start, utterance): 72 | enumerated = [ ([start], []) ] 73 | while True: 74 | new_enumerated = enumerated 75 | 76 | # ENUMERATE 77 | for u in enumerated: 78 | for i in expand(u, grammar): 79 | if not i in new_enumerated: 80 | new_enumerated = new_enumerated + [i] 81 | 82 | if new_enumerated != enumerated: 83 | enumerated = new_enumerated 84 | else: 85 | break 86 | 87 | return len([x for x in enumerated if x[0] == utterance]) + 1 88 | 89 | # We have provided a few test cases. You will likely want to add your own. 90 | 91 | grammar1 = [ 92 | ("S", [ "P", ]), 93 | ("S", [ "a", "Q", ]) , 94 | ("P", [ "a", "T"]), 95 | ("P", [ "c" ]), 96 | ("Q", [ "b" ]), 97 | ("T", [ "b" ]), 98 | ] 99 | print '-' * 20 + ' 1 ' + '-' * 20 100 | print isambig(grammar1, "S", ["a", "b"]) == True 101 | print isambig(grammar1, "S", ["c"]) == False 102 | 103 | grammar2 = [ 104 | ("A", [ "B", ]), 105 | ("B", [ "C", ]), 106 | ("C", [ "D", ]), 107 | ("D", [ "E", ]), 108 | ("E", [ "F", ]), 109 | ("E", [ "G", ]), 110 | ("E", [ "x", "H", ]), 111 | ("F", [ "x", "H"]), 112 | ("G", [ "x", "H"]), 113 | ("H", [ "y", ]), 114 | ] 115 | print '-' * 20 + ' 2 ' + '-' * 20 116 | print isambig(grammar2, "A", ["x", "y"]) == True 117 | print isambig(grammar2, "E", ["y"]) == False 118 | 119 | grammar3 = [ # Rivers in Kenya 120 | ("A", [ "B", "C"]), 121 | ("A", [ "D", ]), 122 | ("B", [ "Dawa", ]), 123 | ("C", [ "Gucha", ]), 124 | ("D", [ "B", "Gucha"]), 125 | ("A", [ "E", "Mbagathi"]), 126 | ("A", [ "F", "Nairobi"]), 127 | ("E", [ "Tsavo" ]), 128 | ("F", [ "Dawa", "Gucha" ]) 129 | ] 130 | print '-' * 20 + ' 3 ' + '-' * 20 131 | print isambig(grammar3, "A", ["Dawa", "Gucha"]) == True 132 | print isambig(grammar3, "A", ["Dawa", "Gucha", "Nairobi"]) == False 133 | print isambig(grammar3, "A", ["Tsavo"]) == False 134 | -------------------------------------------------------------------------------- /src/programming_languages/ps4_parser.py: -------------------------------------------------------------------------------- 1 | work_count = 0 # track one notion of "time taken" 2 | 3 | def addtoset(theset,index,elt): 4 | if not (elt in theset[index]): 5 | theset[index] = [elt] + theset[index] 6 | return True 7 | return False 8 | 9 | def parse(tokens,grammar): 10 | global work_count 11 | work_count = 0 12 | tokens = tokens + [ "end_of_input_marker" ] 13 | chart = {} 14 | start_rule = grammar[0] 15 | for i in xrange(len(tokens)+1): 16 | chart[i] = [] 17 | start_state = (start_rule[0], [], start_rule[1], 0) 18 | chart[0] = [start_state] 19 | for i in xrange(len(tokens)): 20 | while True: 21 | changes = False 22 | for state in chart[i]: 23 | # State === x -> a b . c d , j 24 | (x, ab, cd, j) = state 25 | 26 | # Current State == x -> a b . c d , j 27 | # Option 1: For each grammar rule c -> p q r 28 | # (where the c's match) 29 | # make a next state c -> . p q r , i 30 | # English: We're about to start parsing a "c", but 31 | # "c" may be something like "exp" with its own 32 | # production rules. We'll bring those production rules in. 33 | next_states = [ (rule[0], [], rule[1], i) 34 | for rule in grammar 35 | if cd <> [] and cd[0] == rule[0] ] 36 | work_count = work_count + len(grammar) 37 | for next_state in next_states: 38 | changes = addtoset(chart,i,next_state) or changes 39 | 40 | # Current State == x -> a b . c d , j 41 | # Option 2: If tokens[i] == c, 42 | # make a next state x -> a b c . d , j 43 | # in chart[i+1] 44 | # English: We're looking for to parse token c next 45 | # and the current token is exactly c! Aren't we lucky! 46 | # So we can parse over it and move to j+1. 47 | if cd <> [] and tokens[i] == cd[0]: 48 | next_state = (x, ab + [cd[0]], cd[1:], j) 49 | changes = addtoset(chart,i+1,next_state) or changes 50 | 51 | # Current State == x -> a b . c d , j 52 | # Option 3: If cd is [], the state is just x -> a b . , j 53 | # for each p -> q . x r , l in chart[j] 54 | # make a new state p -> q x . r , l 55 | # in chart[i] 56 | # English: We just finished parsing an "x" with this token, 57 | # but that may have been a sub-step (like matching "exp -> 2" 58 | # in "2+3"). We should update the higher-level rules as well. 59 | next_states = [ (jstate[0], jstate[1] + [x], (jstate[2])[1:], 60 | jstate[3] ) 61 | for jstate in chart[j] 62 | if cd == [] and 63 | jstate[2] <> [] and 64 | (jstate[2])[0] == x ] 65 | 66 | work_count = work_count + len(chart[j]) 67 | for next_state in next_states: 68 | changes = addtoset(chart,i,next_state) or changes 69 | 70 | # We're done if nothing changed! 71 | if not changes: 72 | break 73 | 74 | ## Uncomment this block if you'd like to see the chart printed. 75 | # 76 | for i in range(len(tokens)): 77 | print "== chart " + str(i) 78 | for state in chart[i]: 79 | x, ab, cd, j = state 80 | print " " + x + " ->", 81 | for sym in ab: 82 | print " " + sym, 83 | print " .", 84 | for sym in cd: 85 | print " " + sym, 86 | print " from " + str(j) 87 | 88 | # Uncomment this block if you'd like to see the chart printed 89 | # in cases where it's important to see quotes in the grammar 90 | # for i in range(len(tokens)): 91 | # print "== chart " + str(i) 92 | # for state in chart[i]: 93 | # x = state[0] 94 | # ab = state[1] 95 | # cd = state[2] 96 | # j = state[3] 97 | # print " " + x.__repr__() + " ->", 98 | # for sym in ab: 99 | # print " " + sym.__repr__(), 100 | # print " .", 101 | # for sym in cd: 102 | # print " " + sym.__repr__(), 103 | # print " from " + str(j) 104 | 105 | accepting_state = (start_rule[0], start_rule[1], [], 0) 106 | return accepting_state in chart[len(tokens)-1] 107 | 108 | def parentheses(): 109 | grammar = [ 110 | ("S", ["P" ]) , 111 | ("P", ["(" , "P", ")" ]), 112 | ("P", [ ]) , 113 | ] 114 | tokens = [ "(", "(", ")", ")"] 115 | #tokens = [ "(", "(", "(", ")"] 116 | result=parse(tokens, grammar) 117 | print result 118 | 119 | def ps4_p1(): 120 | grammar = [ 121 | ("S", ["id", "(", "OPTARGS", ")"]), 122 | ("OPTARGS", []), 123 | ("OPTARGS", ["ARGS"]), 124 | ("ARGS", ["exp", ",", "ARGS"]), 125 | ("ARGS", ["exp"]), 126 | ] 127 | tokens = ["id", "(", "exp", ",", "exp", ")"] 128 | result = parse(tokens, grammar) 129 | print result 130 | 131 | if __name__ == "__main__": 132 | ps4_p1() 133 | 134 | -------------------------------------------------------------------------------- /src/programming_languages/ps2_p1.py: -------------------------------------------------------------------------------- 1 | # Hexadecimal Numbers 2 | # 3 | # In this exercise you will write a lexical analyzer that breaks strings up 4 | # into whitespace-separated identifiers and numbers. An identifier is a 5 | # sequence of one or more upper- or lower-case letters. In this exercise, 6 | # however, there are two types of numbers: decimal numbers, and 7 | # _hexadecimal_ numbers. 8 | # 9 | # Humans usually write numbers using "decimal" or "base 10" notation. The 10 | # number# 234 means 2*10^2 + 3*10 + 4*1. 11 | # 12 | # It is also possible to write numbers using other "bases", like "base 16" 13 | # or "hexadecimal". Computers often use base 16 because 16 is a convenient 14 | # power of two (i.e., it is a closer fit to the "binary" system that 15 | # computers use internally). A hexadecimal number always starts with the 16 | # two-character prefix "0x" so that you know not to mistake it for a binary 17 | # number. The number 0x234 means 18 | # 2 * 16^2 19 | # + 3 * 16^1 20 | # + 4 * 16^0 21 | # = 564 decimal. 22 | # 23 | # Because base 16 is larger than base 10, the letters 'a' through 'f' are 24 | # used to represent the numbers '10' through '15'. So the hexadecimal 25 | # number 0xb is the same as the decimal number 11. When read out loud, the 26 | # "0x" is often pronounced like "hex". "0x" must always be followed by at 27 | # least one hexadecimal digit to count as a hexadecimal number. 28 | # 29 | # Modern programming languages like Python can understand hexadecimal 30 | # numbers natively! Try it: 31 | # 32 | # print 0x234 # uncomment me to see 564 printed 33 | # print 0xb # uncomment me to see 11 printed 34 | # 35 | # This provides an easy way to test your knowledge of hexadecimal. 36 | # 37 | # For this assignment you must write token definition rules (e.g., t_ID, 38 | # t_NUM_hex) that will break up a string of whitespace-separated 39 | # identifiers and numbers (either decimal or hexadecimal) into ID and NUM 40 | # tokens. If the token is an ID, you should store its text in the 41 | # token.value field. If the token is a NUM, you must store its numerical 42 | # value (NOT a string) in the token.value field. This means that if a 43 | # hexadecimal string is found, you must convert it to a decimal value. 44 | # 45 | # Hint 1: When presented with a hexadecimal string like "0x2b4", you can 46 | # convert it to a decimal number in stages, reading it from left to right: 47 | # number = 0 # '0x' 48 | # number = number * 16 49 | # number = number + 2 # '2' 50 | # number = number * 16 51 | # number = number + 11 # 'b' 52 | # number = number * 16 53 | # number = number + 4 # '4' 54 | # Of course, since you don't know the number of digits in advance, you'll 55 | # probably want some sort of loop. There are other ways to convert a 56 | # hexadecimal string to a number. You may use any way that works. 57 | # 58 | # Hint 2: The Python function ord() will convert a single letter into 59 | # an ordered internal numerical representation. This allows you to perform 60 | # simple arithmetic on numbers: 61 | # 62 | # print ord('c') - ord('a') == 2 63 | 64 | import ply.lex as lex 65 | 66 | tokens = ('NUM', 'ID') 67 | 68 | #### 69 | # Fill in your code here. 70 | #### 71 | 72 | def t_ID(token): 73 | r'[A-Za-z]+' 74 | return token 75 | 76 | def t_NUM_hex(token): 77 | r'0x[0-9a-f]+' 78 | token.value = int(eval(token.value)) # cheeky! 79 | token.type = 'NUM' 80 | return token 81 | 82 | def t_NUM_decimal(token): 83 | r'[0-9]+' 84 | token.value = int(token.value) # won't work on hex numbers! 85 | token.type = 'NUM' 86 | return token 87 | 88 | t_ignore = ' \t\v\r' 89 | 90 | def t_error(t): 91 | print "Lexer: unexpected character " + t.value[0] 92 | t.lexer.skip(1) 93 | 94 | # We have included some testing code to help you check your work. You will 95 | # probably want to add your own additional tests. 96 | lexer = lex.lex() 97 | 98 | def test_lexer(input_string): 99 | lexer.input(input_string) 100 | result = [ ] 101 | while True: 102 | tok = lexer.token() 103 | if not tok: break 104 | result = result + [(tok.type, tok.value)] 105 | return result 106 | 107 | question1 = "0x19 equals 25" # 0x19 = (1*16) + 9 108 | answer1 = [('NUM', 25), ('ID', 'equals'), ('NUM', 25) ] 109 | 110 | print '---' 111 | print "question1" 112 | print test_lexer(question1) 113 | print test_lexer(question1) == answer1 114 | print '---' 115 | 116 | question2 = "0xfeed MY 0xface" 117 | answer2 = [('NUM', 65261), ('ID', 'MY'), ('NUM', 64206) ] 118 | 119 | print '---' 120 | print "question2" 121 | print test_lexer(question2) 122 | print test_lexer(question2) == answer2 123 | print '---' 124 | 125 | question3 = "tricky 0x0x0x" 126 | answer3 = [('ID', 'tricky'), ('NUM', 0), ('ID', 'x'), ('NUM', 0), ('ID', 'x')] 127 | print '---' 128 | print "question3" 129 | print test_lexer(question3) 130 | print test_lexer(question3) == answer3 131 | print '---' 132 | 133 | question4 = "in 0xdeed" 134 | print test_lexer(question4) 135 | 136 | question5 = "where is the 0xbeef" 137 | print test_lexer(question5) 138 | 139 | question6 = "5 is 0x5" 140 | print '---' 141 | print test_lexer(question6) 142 | print test_lexer(question6) == [('NUM', 5), ('ID', 'is'), ('NUM', 5)] 143 | print '---' 144 | 145 | question7 = "0 is 0x0" 146 | print '---' 147 | print test_lexer(question7) 148 | print test_lexer(question7) == [('NUM', 0), ('ID', 'is'), ('NUM', 0)] 149 | print '---' 150 | 151 | question8 = "tricky 0xabc0x" 152 | print '---' 153 | print test_lexer(question8) 154 | print test_lexer(question8) == [('ID', 'tricky'), ('NUM', 43968), ('ID', 'x')] 155 | print '---' 156 | -------------------------------------------------------------------------------- /[post] monty_hall_problem.md: -------------------------------------------------------------------------------- 1 | I was **extremely** disappointed that a unit that went into an extraordinary level of detail of Bayes nets, inference, sampling, etc., referred to the Monty Hall problem as an obligatory curiosity and then answered it by saying "I'm so, so very clever, bite me Monty." 2 | 3 | Rather than just moan, this is my process of applying Bayes nets to the Monty Hall problem. I've marked this as a community wiki; please feel free to edit, update, append, etc. Also, I might be completely wrong about much of my reasoning; tell me! 4 | 5 | - - - 6 | 7 | I want to draw a Bayes net representing the Monty Hall problem. Nodes are random variables, so what are the random variables? 8 | 9 | - Before I make a choice the prize exists behind some door. Let's call this `Prize (P)`, which is discrete and may have values `[Door1, Door2, Door3]` 10 | - I choose a door at the beginning. Let's call this `First selection (F)`, which is discrete and may have values `[Door1, Door2, Door3]`. 11 | - Monty, the host, opens a door. Let's call this `Monty opens (M)`, which is discrete and may have values `[Door1, Door2, Door3]`. 12 | 13 | What are the edges? 14 | 15 | - Where the `Prize` is will affect which door `Monty opens`; he'll never open the door the `Prize` is behind! Hence `P -> M`. 16 | - Which door I open will affect which door Monty opens. He can't re-open the door I've just opened! Hence `F -> M`. 17 | 18 | Interesting...this looks familiar. This looks like a particular triplet covered in the "D Separation (3.35)" unit! This triplet tells us: 19 | 20 | 1. `P` and `F` are **absolutely independent**. In the absence of other information they do not provide information about one another. (This makes sense!) 21 | 2. `P` and `F` are **conditionally dependent on M**. Given M there is a link between `P` and `F`. 22 | 23 | For me, point 2 is mind-blowing! There is a connection between `P` and `F` in the Bayes net, whereas every ounce of intution in my mind asserts that there is absolutely no connection between the two. *Without even doing any calculations* we've just discovered something totally unintuitive about the Monty Hall problem. 24 | 25 | I think we're going to need four tables, drawn out below: 26 | 27 | +---------+ +---------+ 28 | | P(F) | | P(P) | 29 | +---------+ +---------+ 30 | | D1 | 1/3| | D1 | 1/3| 31 | |----|----| |----|----| 32 | | D2 | 1/3| | D2 | 1/3| 33 | |---------| |---------| 34 | | D3 | 1/3| | D3 | 1/3| 35 | +----v----+ +----v----+ 36 | 37 | +--------------+ +--------------+ 38 | | P(M|F) | | P(M|P) | 39 | |---+---+------+ |---+---+------+ 40 | | M | F | | | M | P | | 41 | |---|---|------| |---|---|------| 42 | | D1| D1| 0 | | D1| D1| 0 | 43 | |--------------| |--------------| 44 | | D1| D2| 1/2 | | D1| D2| 1/2 | 45 | |--------------| |--------------| 46 | | D1| D3| 1/2 | | D1| D3| 1/2 | 47 | |--------------| |--------------| 48 | | D2| D1| 1/2 | | D2| D1| 1/2 | 49 | |--------------| |--------------| 50 | | D2| D2| 0 | | D2| D2| 0 | 51 | |--------------| |--------------| 52 | | D2| D3| 1/2 | | D2| D3| 1/2 | 53 | |--------------| |--------------| 54 | | D3| D1| 1/2 | | D3| D1| 1/2 | 55 | |--------------| |--------------| 56 | | D3| D2| 1/2 | | D3| D2| 1/2 | 57 | |--------------| |--------------| 58 | | D3| D3| 0 | | D3| D3| 0 | 59 | +--------------+ +--------------+ 60 | 61 | Keep in mind the constraints of the problem: Monty cannot re-open the door I opened, and Monty will never open the door with the prize behind it. 62 | 63 | Also, I think, given that M has two incident edges, we actually need a `P(M | F,P)` table, but to save space I've excluded it and used intuition in its place. 64 | 65 | Suppose I've chosen D1, then Monty chooses D3 - just like the lecture video. Should we switch? Well: 66 | 67 | $$\alpha \buildrel\triangle\over = P(P = D1 | F = D1, M = D3)$$ 68 | $$\beta \buildrel\triangle\over = P(P = D2 | F = D1, M = D3)$$ 69 | 70 | If $$\beta \gt \alpha$$ then we should switch. Else we should not switch. In English, beta is "If I chose D1, and Monty chose D3, is the prize behind D2?". 71 | 72 | Rather than go to the trouble of calculating alpha, we just note that: 73 | 74 | $$\alpha + \beta = 1$$ 75 | 76 | This is true because of the contraints of the problem; Monty will never reveal the door containing the prize, hence the prize may only be behind doors D1 or D2. 77 | 78 | Hence, we are actually trying to determine if: 79 | 80 | $$\beta \gt \frac{1}{2}$$ 81 | 82 | Using conditional probability: 83 | 84 | $$\beta = \frac{P(P=D2, F=D1, M=D3)}{P(F=D1, M=D3)}$$ 85 | 86 | Using material from Section 4.2 (Enumeration): 87 | 88 | $$\beta = \frac{P(P=D2) \times P(F=D1) \times P(M=D3 | P=D2, F=D1)}{P(F=D1) \times P(M=D3 | F=D1)}$$ 89 | 90 | $$\beta = \frac{\frac{1}{3} \times \frac{1}{3} \times P(M=D3 | P=D2, F=D1)}{\frac{1}{3} \times P(M=D3 | F=D1)}$$ 91 | 92 | The conditional in the denominator can be read straight out of the `P(M|F)` table: 93 | 94 | $$\beta = \frac{\frac{1}{3} \times \frac{1}{3} \times P(M=D3 | P=D2, F=D1)}{\frac{1}{3} \times \frac{1}{2}}$$ 95 | 96 | $$\beta = \frac{2}{3} \times P(M=D3 | P=D2, F=D1)$$ 97 | 98 | That leaves the conditional: 99 | 100 | $$\gamma \buildrel\triangle\over = P(M=D3 | P=D2, F=D1)$$ 101 | 102 | $$\beta = \frac{2}{3} \times \gamma$$ 103 | 104 | Pause and consider what gamma actually is. If I choose D1, and the prize is behind D2...what door will Monty choose? 105 | 106 | - D1? No! It's already open. 107 | - D2? No! The prize is behind there. 108 | - D3? Yes. 109 | 110 | **Monty will always choose D3**! 111 | 112 | $$\gamma = 1$$ 113 | 114 | $$\beta = \frac{2}{3}$$ 115 | 116 | QED. -------------------------------------------------------------------------------- /src/programming_languages/final/final_1.py: -------------------------------------------------------------------------------- 1 | # Underscoring the Magnitude 2 | # 3 | # Focus: Units 1 and 2, Regular Expressions and Lexical Analysis 4 | # 5 | # In this problem you will use regular expressions to specify tokens for a 6 | # part of a new programming language. You must handle seven types of 7 | # tokens: 8 | # 9 | # 10 | # PLUS + 11 | # MINUS - 12 | # TIMES * 13 | # DIVIDE / 14 | # IDENT my_variable Caps_Are_OK 15 | # STRING 'yes' "also this" 16 | # NUMBER 123 123_456_789 17 | # 18 | # The last three merit a more detailed explanation. 19 | # 20 | # An IDENT token is a non-empty sequence of lower- and/or upper-case 21 | # letters and underscores, but the first character cannot be an underscore. 22 | # (Letters are a-z and A-Z only.) The value of an IDENT token is the string 23 | # matched. 24 | # 25 | # A STRING token is zero or more of any character surrounded by 'single 26 | # quotes' or "double quotes". In this language, there are no escape 27 | # sequences, so "this\" is a string containing five characters. The value 28 | # of a STRING token is the string matched with the quotes removed. 29 | # 30 | # A NUMBER is a a non-empty sequence of digits (0-9) and/or underscores, 31 | # except that the first character cannot be an underscore. Many real-world 32 | # languages actually support this, to make large number easier to read. 33 | # All NUMBERs in this language are positive integers; negative signs and/or 34 | # periods are not part of NUMBERs. The value of a NUMBER is the integer 35 | # value of its digits with all of the underscores removed: the value of 36 | # "12_34" is 1234 (the integer). 37 | # 38 | # For this problem we do *not* care about line number information. Only the 39 | # types and values of tokens matter. Whitespace characters are ' \t\v\r' 40 | # (and we have already filled them in for you below). 41 | # 42 | # Complete the lexer below. 43 | 44 | import ply.lex as lex 45 | 46 | tokens = ('PLUS', 'MINUS', 'TIMES', 'DIVIDE', 47 | 'IDENT', 'STRING', 'NUMBER') 48 | 49 | ##### 50 | # 51 | 52 | # Place your token definition rules here. 53 | 54 | # 55 | ##### 56 | 57 | t_ignore = ' \t\v\r' 58 | 59 | def t_error(t): 60 | print "Lexer: unexpected character " + t.value[0] 61 | t.lexer.skip(1) 62 | 63 | # PLUS + 64 | # MINUS - 65 | # TIMES * 66 | # DIVIDE / 67 | t_PLUS = r'\+' 68 | t_MINUS = r'\-' 69 | t_TIMES = r'\*' 70 | t_DIVIDE = r'\/' 71 | 72 | # An IDENT token is a non-empty sequence of lower- and/or upper-case 73 | # letters and underscores, but the first character cannot be an underscore. 74 | # (Letters are a-z and A-Z only.) The value of an IDENT token is the string 75 | # matched. 76 | t_IDENT = r'[a-zA-Z][a-zA-Z_]*' 77 | 78 | # A STRING token is zero or more of any character surrounded by 'single 79 | # quotes' or "double quotes". In this language, there are no escape 80 | # sequences, so "this\" is a string containing five characters. The value 81 | # of a STRING token is the string matched with the quotes removed. 82 | def t_STRING(token): 83 | #r'\'.*?\'|\".*?\"' !!AI my answer, don't need non-greedy operator. 84 | r'\'[^\']*\'|\"[^\"]*\"' 85 | token.value = token.value[1:-1] 86 | return token 87 | 88 | # A NUMBER is a a non-empty sequence of digits (0-9) and/or underscores, 89 | # except that the first character cannot be an underscore. Many real-world 90 | # languages actually support this, to make large number easier to read. 91 | # All NUMBERs in this language are positive integers; negative signs and/or 92 | # periods are not part of NUMBERs. The value of a NUMBER is the integer 93 | # value of its digits with all of the underscores removed: the value of 94 | # "12_34" is 1234 (the integer). 95 | # 96 | def t_NUMBER(token): 97 | r'[0-9][0-9_]*' 98 | integer = token.value.replace("_","") 99 | token.value = int(integer) 100 | return token 101 | 102 | # We have included some testing code to help you check your work. Since 103 | # this is the final exam, you will definitely want to add your own tests. 104 | lexer = lex.lex() 105 | 106 | def test_lexer(input_string): 107 | lexer.input(input_string) 108 | result = [ ] 109 | while True: 110 | tok = lexer.token() 111 | if not tok: break 112 | result.append((tok.type,tok.value)) 113 | return result 114 | 115 | question1 = " + - / * " 116 | answer1 = [('PLUS', '+'), ('MINUS', '-'), ('DIVIDE', '/'), ('TIMES', '*')] 117 | 118 | print "test 1" 119 | print test_lexer(question1) == answer1 120 | 121 | question2 = """ 'string "nested" \' "inverse 'nested'" """ 122 | answer2 = [('STRING', 'string "nested" '), ('STRING', "inverse 'nested'")] 123 | print "test 2" 124 | print test_lexer(question2) == answer2 125 | 126 | question3 = """ 12_34 5_6_7_8 0______1 1234 """ 127 | answer3 = [('NUMBER', 1234), ('NUMBER', 5678), ('NUMBER', 1), ('NUMBER', 1234)] 128 | print "test 3" 129 | print test_lexer(question3) == answer3 130 | 131 | question4 = """ 'he'llo w0rld 33k """ 132 | answer4 = [('STRING', 'he'), ('IDENT', 'llo'), ('IDENT', 'w'), ('NUMBER', 133 | 0), ('IDENT', 'rld'), ('NUMBER', 33), ('IDENT', 'k')] 134 | print "test 4" 135 | print test_lexer(question4) == answer4 136 | 137 | question5 = """hello world""" 138 | answer5 = [('IDENT','hello'), ('IDENT','world')] 139 | print "test 5" 140 | print test_lexer(question5) == answer5 141 | 142 | question6 = """'hello' "world" """ 143 | answer6 = [('STRING','hello'), ('STRING','world')] 144 | print "test 6" 145 | print test_lexer(question6) == answer6 146 | 147 | question7 = """ 'string "nested" \' """ 148 | answer7 = [('STRING', 'string "nested" ')] 149 | print "test 7" 150 | print test_lexer(question7) == answer7 151 | 152 | question8 = """ "inverse 'nested'" """ 153 | answer8 = [('STRING', "inverse 'nested'")] 154 | print "test 8" 155 | print test_lexer(question8) == answer8 156 | 157 | -------------------------------------------------------------------------------- /src/programming_languages/ps2_p3.py: -------------------------------------------------------------------------------- 1 | # JavaScript: Comments & Keywords 2 | # 3 | # In this exercise you will write token definition rules for all of the 4 | # tokens in our subset of JavaScript *except* IDENTIFIER, NUMBER and 5 | # STRING. In addition, you will handle // end of line comments 6 | # as well as /* delimited comments */. 7 | # 8 | # We will assume that JavaScript is case sensitive and that keywords like 9 | # 'if' and 'true' must be written in lowercase. There are 26 possible 10 | # tokens that you must handle. The 'tokens' variable below has been 11 | # initialized below, listing each token's formal name (i.e., the value of 12 | # token.type). In addition, each token has its associated textual string 13 | # listed in a comment. For example, your lexer must convert && to a token 14 | # with token.type 'ANDAND' (unless the && is found inside a comment). 15 | # 16 | # Hint 1: Use an exclusive state for /* comments */. You may want to define 17 | # t_comment_ignore and t_comment_error as well. 18 | 19 | import ply.lex as lex 20 | 21 | def test_lexer(lexer,input_string): 22 | lexer.input(input_string) 23 | result = [ ] 24 | while True: 25 | tok = lexer.token() 26 | if not tok: break 27 | result = result + [tok.type] 28 | return result 29 | 30 | tokens = ( 31 | 'ANDAND', # && 32 | 'COMMA', # , 33 | 'DIVIDE', # / 34 | 'ELSE', # else 35 | 'EQUAL', # = 36 | 'EQUALEQUAL', # == 37 | 'FALSE', # false 38 | 'FUNCTION', # function 39 | 'GE', # >= 40 | 'GT', # > 41 | # 'IDENTIFIER', #### Not used in this problem. 42 | 'IF', # if 43 | 'LBRACE', # { 44 | 'LE', # <= 45 | 'LPAREN', # ( 46 | 'LT', # < 47 | 'MINUS', # - 48 | 'NOT', # ! 49 | # 'NUMBER', #### Not used in this problem. 50 | 'OROR', # || 51 | 'PLUS', # + 52 | 'RBRACE', # } 53 | 'RETURN', # return 54 | 'RPAREN', # ) 55 | 'SEMICOLON', # ; 56 | # 'STRING', #### Not used in this problem. 57 | 'TIMES', # * 58 | 'TRUE', # true 59 | 'VAR', # var 60 | ) 61 | 62 | states = ( 63 | ('javascriptmultilinecomment', 'exclusive'), 64 | ) 65 | 66 | t_ignore = ' \t\r\f\v' # whitespace 67 | 68 | reserved = { 69 | 'else': 'ELSE', 70 | 'false': 'FALSE', 71 | 'function': 'FUNCTION', 72 | 'if': 'IF', 73 | 'return': 'RETURN', 74 | 'true': 'TRUE', 75 | 'var': 'VAR', 76 | } 77 | 78 | def t_eolcomment(token): 79 | r'//[^\n]*' 80 | pass 81 | 82 | t_ANDAND = r'&&' 83 | t_COMMA = r',' 84 | t_DIVIDE = r'/' 85 | t_ELSE = r'else' 86 | t_EQUALEQUAL = r'==' 87 | t_EQUAL = r'=' 88 | t_GE = r'>=' 89 | t_GT = r'>' 90 | t_LBRACE = r'\{' 91 | t_LE = r'<=' 92 | t_LPAREN = r'\(' 93 | t_LT = r'<' 94 | t_MINUS = r'-' 95 | t_NOT = r'!' 96 | t_OROR = r'\|\|' 97 | t_PLUS = r'\+' 98 | t_RBRACE = r'\}' 99 | t_RPAREN = r'\)' 100 | t_SEMICOLON = r';' 101 | t_TIMES = r'\*' 102 | 103 | # ----------------------------------------------------------------------------- 104 | # We are _not_ going to return an IDENTIFIER from here. Hence we expect 105 | # any matching string to be in the 'reserved' dictionary. 106 | # ----------------------------------------------------------------------------- 107 | def t_IDENTIFIER(token): 108 | r'[a-z]+' 109 | token.type = reserved[token.value] 110 | return token 111 | # ----------------------------------------------------------------------------- 112 | 113 | def t_newline(t): 114 | r'\n' 115 | t.lexer.lineno += 1 116 | 117 | def t_error(t): 118 | print "JavaScript Lexer: Illegal character line %s: %s" % (t.lexer.lineno, t.value[0]) 119 | t.lexer.skip(1) 120 | 121 | # ----------------------------------------------------------------------------- 122 | # 'javascriptmultilinecomment' state. 123 | # ----------------------------------------------------------------------------- 124 | t_javascriptmultilinecomment_ignore = ' \t\r\f\v' 125 | 126 | def t_javascriptmultilinecomment(token): 127 | r'\/\*' 128 | token.lexer.begin('javascriptmultilinecomment') 129 | 130 | def t_javascriptmultilinecomment_end(token): 131 | r'\*\/' 132 | token.lexer.lineno += token.value.count('\n') 133 | token.lexer.begin('INITIAL') 134 | 135 | def t_javascriptmultilinecomment_error(token): 136 | token.lexer.skip(1) 137 | # ----------------------------------------------------------------------------- 138 | 139 | # We have included two test cases to help you debug your lexer. You will 140 | # probably want to write some of your own. 141 | 142 | lexer = lex.lex() 143 | 144 | def test_lexer(input_string): 145 | lexer.input(input_string) 146 | result = [] 147 | while True: 148 | tok = lexer.token() 149 | if not tok: break 150 | result.append(tok.type) 151 | return result 152 | 153 | input1 = """ - ! && () * , / ; { || } + < <= = == > >= else false function 154 | if return true var """ 155 | 156 | output1 = ['MINUS', 'NOT', 'ANDAND', 'LPAREN', 'RPAREN', 'TIMES', 'COMMA', 157 | 'DIVIDE', 'SEMICOLON', 'LBRACE', 'OROR', 'RBRACE', 'PLUS', 'LT', 'LE', 158 | 'EQUAL', 'EQUALEQUAL', 'GT', 'GE', 'ELSE', 'FALSE', 'FUNCTION', 'IF', 159 | 'RETURN', 'TRUE', 'VAR'] 160 | 161 | print test_lexer(input1) == output1 162 | 163 | input2 = """ 164 | if // else mystery 165 | =/*=*/= 166 | true /* false 167 | */ return""" 168 | 169 | output2 = ['IF', 'EQUAL', 'EQUAL', 'TRUE', 'RETURN'] 170 | 171 | print test_lexer(input2) == output2 172 | 173 | input3 = """ 174 | if /* true // else 175 | */ 176 | """ 177 | output3 = ['IF'] 178 | print test_lexer(input3) == output3 179 | 180 | -------------------------------------------------------------------------------- /src/programming_languages/final/final_2.py: -------------------------------------------------------------------------------- 1 | # Terrible Tuples 2 | # 3 | # Focus: Units 3 and 4, Grammars and Parsing 4 | # 5 | # In this problem you will use context-free grammars to specify some 6 | # expression for part of a new programming language. We will specify tuples 7 | # and lists, as in Python. We will consider four types of expressions. 8 | # 9 | # 1. An expression can be a single NUMBER token. In this case, your parser 10 | # should return ("number",XYZ) where XYZ is the value of the NUMBER 11 | # token. 12 | # 13 | # 2. An expression can be LPAREN expression RPAREN . In this case, your 14 | # parser should return the value of the expression inside the parentheses. 15 | # 16 | # 3. An expression can be LPAREN "a list of more than one comma-separated 17 | # expressions" RPAREN. This should remind you of tuples in Python: 18 | # 19 | # (1,2,3) 20 | # 21 | # The inner expressions are 1 2 and 3, and they are separated by commas. 22 | # In this case, your parser should return ("tuple", ...) where ... is a 23 | # list of the child expression values. For example, for (1,2) you should 24 | # return ("tuple",[("number",2),("number",3)]). 25 | # 26 | # 4. An expression can be LBRACKET "a list of one or more comma-separated 27 | # expressions" RBRACKET. This should remind you of lists in Python: 28 | # 29 | # [7,8,9] 30 | # 31 | # These parse exactly like tuples, except that they use square brackets 32 | # instead of parentheses, and singleton lists like [7] are valid. Your 33 | # parser should return ("list", ...) as above, so [7,8] would return 34 | # ("list",[("number",7),("number",8)]). 35 | # 36 | # Complete the parser below. 37 | 38 | import ply.lex as lex 39 | import ply.yacc as yacc 40 | 41 | start = 'exp' # the start symbol in our grammar 42 | 43 | ##### 44 | # 45 | 46 | # Place your grammar definition rules here. 47 | 48 | # 49 | ##### 50 | 51 | # 1. An expression can be a single NUMBER token. In this case, your parser 52 | # should return ("number",XYZ) where XYZ is the value of the NUMBER 53 | # token. 54 | def p_exp_number(p): 55 | r'exp : NUMBER' 56 | p[0] = ("number", p[1]) 57 | 58 | # 2. An expression can be LPAREN expression RPAREN . In this case, your 59 | # parser should return the value of the expression inside the parentheses. 60 | def p_exp_paren(p): 61 | r'exp : LPAREN exp RPAREN' 62 | p[0] = p[2] 63 | 64 | # 3. An expression can be LPAREN "a list of more than one comma-separated 65 | # expressions" RPAREN. This should remind you of tuples in Python: 66 | # 67 | # (1,2,3) 68 | # 69 | # The inner expressions are 1 2 and 3, and they are separated by commas. 70 | # In this case, your parser should return ("tuple", ...) where ... is a 71 | # list of the child expression values. For example, for (1,2) you should 72 | # return ("tuple",[("number",2),("number",3)]). 73 | # 74 | # !!AI this is unusually tricky because e.g. (4) is not a tuple, it's 75 | # a number, so we can't re-use the nonterminal tuplelements to terminate 76 | # the parse. Odd! 77 | def p_exp_tuple(p): 78 | r'exp : LPAREN tupleelements RPAREN' 79 | p[0] = ("tuple", p[2]) 80 | 81 | def p_tupleelements(p): 82 | r'tupleelements : exp COMMA tupleelements_end' 83 | p[0] = [p[1]] + p[3] 84 | 85 | def p_tupleelements_end_more(p): 86 | r'tupleelements_end : tupleelements' 87 | p[0] = p[1] 88 | 89 | def p_tupleelements_end_finished(p): 90 | r'tupleelements_end : exp' 91 | p[0] = [p[1]] 92 | 93 | # 4. An expression can be LBRACKET "a list of one or more comma-separated 94 | # expressions" RBRACKET. This should remind you of lists in Python: 95 | # 96 | # [7,8,9] 97 | # 98 | # These parse exactly like tuples, except that they use square brackets 99 | # instead of parentheses, and singleton lists like [7] are valid. Your 100 | # parser should return ("list", ...) as above, so [7,8] would return 101 | # ("list",[("number",7),("number",8)]). 102 | # 103 | # !!AI this is much easier than tuples, as e.g. [4] is a list. 104 | def p_exp_list(p): 105 | 'exp : LBRACKET listelements RBRACKET' 106 | p[0] = ("list", p[2]) 107 | 108 | def p_listelements_single(p): 109 | 'listelements : exp' 110 | p[0] = [p[1]] 111 | 112 | def p_listelements_morethanone(p): 113 | 'listelements : exp COMMA listelements' 114 | p[0] = [p[1]] + p[3] 115 | 116 | def p_error(p): 117 | raise SyntaxError 118 | 119 | # We have provided a lexer for you. You should not change it. 120 | 121 | tokens = ('LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'NUMBER', 'COMMA') 122 | 123 | def t_NUMBER(token): 124 | r"[0-9]+" 125 | token.value = int(token.value) 126 | return token 127 | 128 | t_ignore = ' \t\v\r' 129 | t_COMMA = r',' 130 | t_LPAREN = r'\(' 131 | t_RPAREN = r'\)' 132 | t_LBRACKET = r'\[' 133 | t_RBRACKET = r'\]' 134 | 135 | def t_error(t): 136 | print "Lexer: unexpected character " + t.value[0] 137 | t.lexer.skip(1) 138 | 139 | # We have included some testing code to help you check your work. Since 140 | # this is the final exam, you will definitely want to add your own tests. 141 | lexer = lex.lex() 142 | 143 | def test(input_string): 144 | lexer.input(input_string) 145 | parser = yacc.yacc() 146 | try: 147 | parse_tree = parser.parse(input_string, lexer=lexer) 148 | return parse_tree 149 | except: 150 | return "error" 151 | 152 | question1 = " 123 " 153 | answer1 = ('number', 123) 154 | print "test 1" 155 | print test(question1) == answer1 156 | 157 | question2 = " (123) " 158 | print "test 2" 159 | print test(question2) == answer1 160 | 161 | question3 = " (1,2,3) " 162 | answer3 = ('tuple', [('number', 1), ('number', 2), ('number', 3)]) 163 | print "test 3" 164 | print test(question3) == answer3 165 | 166 | question4 = " [123] " 167 | answer4 = ('list', [('number', 123)]) 168 | print "test 4" 169 | print test(question4) == answer4 170 | 171 | question5 = " [1,2,3] " 172 | answer5 = ('list', [('number', 1), ('number', 2), ('number', 3)]) 173 | print "test 5" 174 | print test(question5) == answer5 175 | 176 | question6 = " [(1,2),[3,[4]]] " 177 | answer6 = ('list', [('tuple', [('number', 1), ('number', 2)]), ('list', [('number', 3), ('list', [('number', 4)])])]) 178 | print "test 6" 179 | print test(question6) == answer6 180 | 181 | question7 = " (1,2) [3,4) " 182 | answer7 = "error" 183 | print "test 7" 184 | print test(question7) == answer7 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /[book] html5 and javascript web apps (oreilly).md: -------------------------------------------------------------------------------- 1 | # HTML5 and JavaScript Web Apps 2 | 3 | O'Reilly, 2012 4 | 5 | ## Ch1 - Client-Side Architecture 6 | 7 | - Fat clients are back. 8 | - Before HTML5, server-side templating and JS for nicities. 9 | - Browsers are becoming application platforms. 10 | - Cross-browser DOM libraries like jQuery are not enough, do not give a client-side architecture. 11 | - Architecture of heavy, HTML5-driven UI still in its infancy, but this is the topic of the book. 12 | 13 | ## Ch2 - The Mobile Web 14 | 15 | - Support mobile first, then desktop. 16 | - Why? 17 | - You think about constrained resolutions, flexible layouts. 18 | - Device sensors. 19 | - Code-quality, battery life. 20 | - Bleeding edge. 21 | - WebKit on iOS and Android 22 | - Android moving to Dolphin. 23 | - Opera Mobile. 24 | - Internet Explorer Mobile. 25 | - QA 26 | - Preferable to use actual devices. 27 | - Emulators available at [mobilexweb](http://www.mobilexweb.com/emulators). 28 | 29 | ## Ch3 - Building for the Mobile Web 30 | 31 | - Success dependent on design and performance. 32 | - Consistent across all platforms. 33 | - Constrained by CPU/GPU and network throughput/latency. 34 | - Reference: Mobile Design Pattern Gallery (O'Reilly), for UI patterns for native apps. 35 | - Want to use hardware acceleration where possible. 36 | - Functions like `translate3d`, `scale3d`, `translateZ`. 37 | - CSS features like `gradient`, `box-shadow`, `borders`, `background-repeat` cause many repaints, taxing on GPU and battery life. 38 | - p36: use JavaScript to swap class names, and let CSS handle animation. 39 | - Decouples JavaScript from CSS. 40 | - Sliding, flipping, and rotating animations. 41 | - How to debug frames per second and hardware acceleration in Safari. 42 | - p50: fetching and caching 43 | - Code for looking for pages with a `fetch` class name and then using `ajax()` to pre-fetch and then insert into `localStorage`. 44 | - p53: write AJAX response text into a sandboxed `iframe`. 45 | - Browser does DOM parsing and sanitisation for you. 46 | - Just as fast, sometimes faster, than usual `innerHTML` approach. 47 | - p56: network detection. online? slow? 48 | - p61: *single page* approach 49 | - All content in one page. Each subpage wrapped in a div. 50 | - **jQuery Mobile.** 51 | - p61: example. 52 | - **jQTouch** 53 | - Basic widgets and animations. 54 | - Lacks support for multiple platforms. 55 | - p63: example 56 | - In jQuery Mobile and jQTouch you write specially structures HTML. When loaded library reconfigured pages and turns regular links into AJAX-based animated ones. 57 | - p64: *no page structure* approach 58 | - Light markup, not tied to specific DOM structure. 59 | - **[xui](http://xuijs.com/)** 60 | - Comes from PhoneGap. 61 | - DOM manipulation for mobile environment. 62 | - Very light. 63 | - p65: *100% JavaScript Driven* approach 64 | - **Sencha Touch** 65 | - Don't write HTML. UI and app in JavaScript. 66 | - p66: example 67 | - **Wink Toolkit** 68 | - Small following. 69 | - JavaScript helpers, UI via JavaScript. 70 | - p68: example 71 | - **The-M-Project** 72 | - On top of jQuery and jQuery Mobile. 73 | - MVC, Content Binding, Dynamic Value Computing, Event Handling. 74 | - Much more than just fancy UI. 75 | - p70: example. 76 | - Other frameworks: SproutCore, Jo, Zepto, LungoJS, …, but not fit-for-purpose. 77 | - Mobile debugging 78 | - **[weinre](http://people.apache.org/~pmuellr/weinre/)** 79 | - Like a remote Firebug. 80 | - **Adobe Shadow.** 81 | - Again like remote Firebug. 82 | - **Opera Dragonfly** 83 | - For Opera Mobile Emulator. 84 | 85 | ## Ch4 - The Desktop Web 86 | 87 | - Moving towards client-side generation of view. Backend delivers just data over JSON / XML. 88 | - Pros: better UX, less bandwidth, offline capable. 89 | - Cons: security of locally stored data, speed. 90 | - Feature detection 91 | - **modernizr.js** or simple JavaScript to detect client-side capabilities. 92 | - **FormFactor.js** for detecting resolution. 93 | - Sometimes, however, you unfortunately need to parse `userAgent` string, especially for bugs. 94 | - **ua-parser** for parsing useragent. 95 | - **Platform.js** is another userAgent detection method. 96 | - **MobileESP** for server-side userAgent detection. 97 | - Compression. 98 | - GZIP resources and JSON/XML responses. 99 | - Minification, p90 100 | - **JSLint** then **JSMin** 101 | - **Packer**, popular and advanced. 102 | - **Dojo ShrinkSafe**, popular. 103 | - **YUI Compressor**, safety of JSMin with high compression of ShrinkSafe. 104 | - p91, **CompressorRater** to compare. 105 | - p91, **grunt**. 106 | - Command-line build tool for frontend projects. 107 | - node.js package. 108 | - **Jawr**, tunable JavaScript/CSS packager. 109 | - **Ziproxy**, forwarding, noncaching, compressing HTTP proxy. 110 | - MVC 111 | - TodoMVC for comparing many MVC frameworks with a simple Todo app. 112 | - **Backbone** 113 | - Framework of choice. 114 | - Uses **Undescore.js** heavily. 115 | - Data is models. Created, validated, destroyed, saved to server. 116 | - Any UI action change to model triggers `change` event. Views notified and update themselves. 117 | - p99: `Model` and `Collection` example. 118 | - RESTful URI endpoints for models. 119 | - **Ember**, p101 120 | - Formerly Amber.js and SproutCore 2.0. 121 | - Made by Apple 122 | - less wiring than Backbone. 123 | - p101: example 124 | - **Angular**, p102 125 | - Made by Google. 126 | - p103: example. 127 | - Dependency injection. 128 | - **Batman** 129 | - Created by Shopify. 130 | - Similar to Knockout and Angular 131 | - p104: model, server synch. 132 | - **Knockout** 133 | - Three core features 134 | - Observable and dependency tracking. 135 | - Declarative bindings. 136 | - Templating. -------------------------------------------------------------------------------- /src/programming_languages/graphics.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # 3 | # This allows students with minimal knowledge to produce pretty pictures of 4 | # HTML webpages. 5 | # 6 | import sys 7 | import subprocess 8 | import os 9 | 10 | # If you want the output filenames to be different (e.g., based on 11 | # environment variables), just change them here. 12 | output_latex_filename = "./student" 13 | 14 | # If you want to put the static images elsewhere, just change this. 15 | image_directory = "images/" # make "" for current directory 16 | 17 | # The example image output requires these packages: 18 | # 19 | # pdflatex (aka "pdftex") 20 | # imagemagick (for "convert") 21 | # ghostscript (called by "convert") 22 | 23 | outfile = None 24 | logfile = None 25 | 26 | import base64 27 | import json 28 | import sys 29 | 30 | 31 | def word(x): 32 | global outfile 33 | for i in range(len(x)): 34 | if x[i] == '_': 35 | outfile.write("\_") 36 | elif x[i] != '\\': 37 | outfile.write(x[i]) 38 | outfile.write (" ") 39 | 40 | def warning(x): 41 | global outfile 42 | outfile.write("{\\color{red}{\\bf{" + x + "}}}") 43 | 44 | closetags = [] 45 | 46 | def pushclosing(x): 47 | global closetags 48 | closetags = [x] + closetags 49 | def begintag(tag,args): 50 | global outfile 51 | global logfile 52 | tag = tag.lower() 53 | # need "IMG" 54 | logfile.write("TAG + " + tag + "\n") 55 | if tag == "a": 56 | if "href" in args: 57 | target = args["href"] 58 | outfile.write("\\href{" + target + "}{\underline{") 59 | pushclosing("}}") 60 | else: 61 | warning("invalid 'a' tag: no 'href' argument") 62 | pushclosing("") 63 | elif tag == "img": 64 | if "src" in args: 65 | target = args["src"] 66 | filename = image_directory + target 67 | if os.path.isfile(filename): 68 | if "height" in args and "width" in args: 69 | h = args["height"] 70 | w = args["width"] 71 | outfile.write("\\includegraphics[height=" + h + "px, width=" + w + "px]{" + filename + "}") 72 | pushclosing("") 73 | else: 74 | outfile.write("\\includegraphics{" + filename + "}") 75 | pushclosing("") 76 | else: 77 | warning("'img' " + target + " not found (predefined local images only, sorry)") 78 | pushclosing("") 79 | else: 80 | warning("invalid 'img' tag: no 'src' argument") 81 | pushclosing("") 82 | elif tag == "b" or tag == "strong": 83 | outfile.write("\\textbf{") 84 | pushclosing("}") 85 | elif tag == "ul": 86 | outfile.write("\\begin{itemize}") 87 | pushclosing("\\end{itemize}") 88 | elif tag == "ol": 89 | outfile.write("\\begin{enumerate}") 90 | pushclosing("\\end{enumerate}") 91 | elif tag == "li": 92 | outfile.write("\\item{") 93 | pushclosing("}") 94 | elif tag == "big": 95 | outfile.write("{\\Large ") 96 | pushclosing("}") 97 | elif tag == "tt" or tag == "code": 98 | outfile.write("{\\tt ") 99 | pushclosing("}") 100 | elif tag == "small": 101 | outfile.write("{\\footnotesize ") 102 | pushclosing("}") 103 | elif tag == "i" or tag == "em": 104 | outfile.write("\\emph{") 105 | pushclosing("}") 106 | elif tag == "hr": 107 | outfile.write("{\\begin{center} \\line(1,0){400} \\end{center}}") 108 | pushclosing("") 109 | elif tag == "h1": 110 | outfile.write("\\section*{") 111 | pushclosing("}") 112 | elif tag == "h2": 113 | outfile.write("\\subsection*{") 114 | pushclosing("}") 115 | elif tag == "h3": 116 | outfile.write("\\subsubsection*{") 117 | pushclosing("}") 118 | elif tag == "p" or tag == "br": 119 | outfile.write("\n~\n\n\\noindent ") 120 | pushclosing("\n") 121 | else: 122 | pushclosing("") 123 | 124 | def endtag(): 125 | global outfile 126 | global logfile 127 | global closetags 128 | if closetags == []: 129 | raise IndexError 130 | tag = closetags[0] 131 | closetags = closetags[1:] 132 | logfile.write("TAG -\n") 133 | outfile.write(tag) 134 | 135 | def initialize(): 136 | global outfile 137 | global logfile 138 | global output_latex_filename 139 | outfile = open(output_latex_filename + ".tex",'w+') 140 | logfile = open(output_latex_filename + ".taglog",'w+') 141 | outfile.write(""" 142 | \\documentclass{article} 143 | \\usepackage{fullpage} 144 | \\usepackage{hyperref} 145 | \\hypersetup{ 146 | colorlinks,% 147 | citecolor=blue,% 148 | filecolor=blue,% 149 | linkcolor=blue,% 150 | urlcolor=blue 151 | } 152 | \\usepackage{graphicx} 153 | \\usepackage{color} 154 | \\usepackage{url} 155 | \\usepackage{geometry} 156 | \\pagestyle{empty} 157 | \\begin{document} 158 | \\mag 1440 159 | """) 160 | 161 | def finalize(): 162 | global outfile 163 | global logfile 164 | logfile.close() 165 | outfile.write(""" 166 | \\end{document} 167 | """) 168 | #print "Writing TEX Output: " + output_latex_filename + ".tex" 169 | outfile.close() 170 | #print "Rendering PDF Graphics: " + output_latex_filename + ".pdf" 171 | cmd = "pdflatex " + output_latex_filename + ".tex > /dev/null < /dev/null" 172 | subprocess.call(cmd,shell=True) 173 | #print "Rendering PNG Graphics: " + output_latex_filename + ".png" 174 | cmd = "convert " + output_latex_filename + ".pdf " + \ 175 | output_latex_filename + ".png" 176 | subprocess.call(cmd,shell=True) 177 | 178 | 179 | -------------------------------------------------------------------------------- /src/programming_languages/unit5_l9/graphics.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # 3 | # This allows students with minimal knowledge to produce pretty pictures of 4 | # HTML webpages. 5 | # 6 | import sys 7 | import subprocess 8 | import os 9 | 10 | # If you want the output filenames to be different (e.g., based on 11 | # environment variables), just change them here. 12 | output_latex_filename = "./student" 13 | 14 | # If you want to put the static images elsewhere, just change this. 15 | image_directory = "images/" # make "" for current directory 16 | 17 | # The example image output requires these packages: 18 | # 19 | # pdflatex (aka "pdftex") 20 | # imagemagick (for "convert") 21 | # ghostscript (called by "convert") 22 | 23 | outfile = None 24 | logfile = None 25 | 26 | import base64 27 | import json 28 | import sys 29 | 30 | 31 | def word(x): 32 | global outfile 33 | for i in range(len(x)): 34 | if x[i] == '_': 35 | outfile.write("\_") 36 | elif x[i] != '\\': 37 | outfile.write(x[i]) 38 | outfile.write (" ") 39 | 40 | def warning(x): 41 | global outfile 42 | outfile.write("{\\color{red}{\\bf{" + x + "}}}") 43 | 44 | closetags = [] 45 | 46 | def pushclosing(x): 47 | global closetags 48 | closetags = [x] + closetags 49 | def begintag(tag,args): 50 | global outfile 51 | global logfile 52 | tag = tag.lower() 53 | # need "IMG" 54 | logfile.write("TAG + " + tag + "\n") 55 | if tag == "a": 56 | if "href" in args: 57 | target = args["href"] 58 | outfile.write("\\href{" + target + "}{\underline{") 59 | pushclosing("}}") 60 | else: 61 | warning("invalid 'a' tag: no 'href' argument") 62 | pushclosing("") 63 | elif tag == "img": 64 | if "src" in args: 65 | target = args["src"] 66 | filename = image_directory + target 67 | if os.path.isfile(filename): 68 | if "height" in args and "width" in args: 69 | h = args["height"] 70 | w = args["width"] 71 | outfile.write("\\includegraphics[height=" + h + "px, width=" + w + "px]{" + filename + "}") 72 | pushclosing("") 73 | else: 74 | outfile.write("\\includegraphics{" + filename + "}") 75 | pushclosing("") 76 | else: 77 | warning("'img' " + target + " not found (predefined local images only, sorry)") 78 | pushclosing("") 79 | else: 80 | warning("invalid 'img' tag: no 'src' argument") 81 | pushclosing("") 82 | elif tag == "b" or tag == "strong": 83 | outfile.write("\\textbf{") 84 | pushclosing("}") 85 | elif tag == "ul": 86 | outfile.write("\\begin{itemize}") 87 | pushclosing("\\end{itemize}") 88 | elif tag == "ol": 89 | outfile.write("\\begin{enumerate}") 90 | pushclosing("\\end{enumerate}") 91 | elif tag == "li": 92 | outfile.write("\\item{") 93 | pushclosing("}") 94 | elif tag == "big": 95 | outfile.write("{\\Large ") 96 | pushclosing("}") 97 | elif tag == "tt" or tag == "code": 98 | outfile.write("{\\tt ") 99 | pushclosing("}") 100 | elif tag == "small": 101 | outfile.write("{\\footnotesize ") 102 | pushclosing("}") 103 | elif tag == "i" or tag == "em": 104 | outfile.write("\\emph{") 105 | pushclosing("}") 106 | elif tag == "hr": 107 | outfile.write("{\\begin{center} \\line(1,0){400} \\end{center}}") 108 | pushclosing("") 109 | elif tag == "h1": 110 | outfile.write("\\section*{") 111 | pushclosing("}") 112 | elif tag == "h2": 113 | outfile.write("\\subsection*{") 114 | pushclosing("}") 115 | elif tag == "h3": 116 | outfile.write("\\subsubsection*{") 117 | pushclosing("}") 118 | elif tag == "p" or tag == "br": 119 | outfile.write("\n~\n\n\\noindent ") 120 | pushclosing("\n") 121 | else: 122 | pushclosing("") 123 | 124 | def endtag(): 125 | global outfile 126 | global logfile 127 | global closetags 128 | if closetags == []: 129 | raise IndexError 130 | tag = closetags[0] 131 | closetags = closetags[1:] 132 | logfile.write("TAG -\n") 133 | outfile.write(tag) 134 | 135 | def initialize(): 136 | global outfile 137 | global logfile 138 | global output_latex_filename 139 | outfile = open(output_latex_filename + ".tex",'w+') 140 | logfile = open(output_latex_filename + ".taglog",'w+') 141 | outfile.write(""" 142 | \\documentclass{article} 143 | \\usepackage{fullpage} 144 | \\usepackage{hyperref} 145 | \\hypersetup{ 146 | colorlinks,% 147 | citecolor=blue,% 148 | filecolor=blue,% 149 | linkcolor=blue,% 150 | urlcolor=blue 151 | } 152 | \\usepackage{graphicx} 153 | \\usepackage{color} 154 | \\usepackage{url} 155 | \\usepackage{geometry} 156 | \\pagestyle{empty} 157 | \\begin{document} 158 | \\mag 1440 159 | """) 160 | 161 | def finalize(): 162 | global outfile 163 | global logfile 164 | logfile.close() 165 | outfile.write(""" 166 | \\end{document} 167 | """) 168 | #print "Writing TEX Output: " + output_latex_filename + ".tex" 169 | outfile.close() 170 | #print "Rendering PDF Graphics: " + output_latex_filename + ".pdf" 171 | cmd = "pdflatex " + output_latex_filename + ".tex > /dev/null < /dev/null" 172 | subprocess.call(cmd,shell=True) 173 | #print "Rendering PNG Graphics: " + output_latex_filename + ".png" 174 | cmd = "convert " + output_latex_filename + ".pdf " + \ 175 | output_latex_filename + ".png" 176 | subprocess.call(cmd,shell=True) 177 | 178 | 179 | -------------------------------------------------------------------------------- /src/programming_languages/ps6/graphics.py: -------------------------------------------------------------------------------- 1 | # Wes Weimer 2 | # 3 | # This allows students with minimal knowledge to produce pretty pictures of 4 | # HTML webpages. 5 | # 6 | import sys 7 | import subprocess 8 | import os 9 | 10 | # If you want the output filenames to be different (e.g., based on 11 | # environment variables), just change them here. 12 | output_latex_filename = "./student" 13 | 14 | # If you want to put the static images elsewhere, just change this. 15 | image_directory = "images/" # make "" for current directory 16 | 17 | # The example image output requires these packages: 18 | # 19 | # pdflatex (aka "pdftex") 20 | # imagemagick (for "convert") 21 | # ghostscript (called by "convert") 22 | 23 | outfile = None 24 | logfile = None 25 | 26 | import base64 27 | import json 28 | import sys 29 | 30 | 31 | def word(x): 32 | global outfile 33 | for i in range(len(x)): 34 | if x[i] == '_': 35 | outfile.write("\_") 36 | elif x[i] != '\\': 37 | outfile.write(x[i]) 38 | outfile.write (" ") 39 | 40 | def warning(x): 41 | global outfile 42 | outfile.write("{\\color{red}{\\bf{" + x + "}}}") 43 | 44 | closetags = [] 45 | 46 | def pushclosing(x): 47 | global closetags 48 | closetags = [x] + closetags 49 | def begintag(tag,args): 50 | global outfile 51 | global logfile 52 | tag = tag.lower() 53 | # need "IMG" 54 | logfile.write("TAG + " + tag + "\n") 55 | if tag == "a": 56 | if "href" in args: 57 | target = args["href"] 58 | outfile.write("\\href{" + target + "}{\underline{") 59 | pushclosing("}}") 60 | else: 61 | warning("invalid 'a' tag: no 'href' argument") 62 | pushclosing("") 63 | elif tag == "img": 64 | if "src" in args: 65 | target = args["src"] 66 | filename = image_directory + target 67 | if os.path.isfile(filename): 68 | if "height" in args and "width" in args: 69 | h = args["height"] 70 | w = args["width"] 71 | outfile.write("\\includegraphics[height=" + h + "px, width=" + w + "px]{" + filename + "}") 72 | pushclosing("") 73 | else: 74 | outfile.write("\\includegraphics{" + filename + "}") 75 | pushclosing("") 76 | else: 77 | warning("'img' " + target + " not found (predefined local images only, sorry)") 78 | pushclosing("") 79 | else: 80 | warning("invalid 'img' tag: no 'src' argument") 81 | pushclosing("") 82 | elif tag == "b" or tag == "strong": 83 | outfile.write("\\textbf{") 84 | pushclosing("}") 85 | elif tag == "ul": 86 | outfile.write("\\begin{itemize}") 87 | pushclosing("\\end{itemize}") 88 | elif tag == "ol": 89 | outfile.write("\\begin{enumerate}") 90 | pushclosing("\\end{enumerate}") 91 | elif tag == "li": 92 | outfile.write("\\item{") 93 | pushclosing("}") 94 | elif tag == "big": 95 | outfile.write("{\\Large ") 96 | pushclosing("}") 97 | elif tag == "tt" or tag == "code": 98 | outfile.write("{\\tt ") 99 | pushclosing("}") 100 | elif tag == "small": 101 | outfile.write("{\\footnotesize ") 102 | pushclosing("}") 103 | elif tag == "i" or tag == "em": 104 | outfile.write("\\emph{") 105 | pushclosing("}") 106 | elif tag == "hr": 107 | outfile.write("{\\begin{center} \\line(1,0){400} \\end{center}}") 108 | pushclosing("") 109 | elif tag == "h1": 110 | outfile.write("\\section*{") 111 | pushclosing("}") 112 | elif tag == "h2": 113 | outfile.write("\\subsection*{") 114 | pushclosing("}") 115 | elif tag == "h3": 116 | outfile.write("\\subsubsection*{") 117 | pushclosing("}") 118 | elif tag == "p" or tag == "br": 119 | outfile.write("\n~\n\n\\noindent ") 120 | pushclosing("\n") 121 | else: 122 | pushclosing("") 123 | 124 | def endtag(): 125 | global outfile 126 | global logfile 127 | global closetags 128 | if closetags == []: 129 | raise IndexError 130 | tag = closetags[0] 131 | closetags = closetags[1:] 132 | logfile.write("TAG -\n") 133 | outfile.write(tag) 134 | 135 | def initialize(): 136 | global outfile 137 | global logfile 138 | global output_latex_filename 139 | outfile = open(output_latex_filename + ".tex",'w+') 140 | logfile = open(output_latex_filename + ".taglog",'w+') 141 | outfile.write(""" 142 | \\documentclass{article} 143 | \\usepackage{fullpage} 144 | \\usepackage{hyperref} 145 | \\hypersetup{ 146 | colorlinks,% 147 | citecolor=blue,% 148 | filecolor=blue,% 149 | linkcolor=blue,% 150 | urlcolor=blue 151 | } 152 | \\usepackage{graphicx} 153 | \\usepackage{color} 154 | \\usepackage{url} 155 | \\usepackage{geometry} 156 | \\pagestyle{empty} 157 | \\begin{document} 158 | \\mag 1440 159 | """) 160 | 161 | def finalize(): 162 | global outfile 163 | global logfile 164 | logfile.close() 165 | outfile.write(""" 166 | \\end{document} 167 | """) 168 | #print "Writing TEX Output: " + output_latex_filename + ".tex" 169 | outfile.close() 170 | #print "Rendering PDF Graphics: " + output_latex_filename + ".pdf" 171 | cmd = "pdflatex " + output_latex_filename + ".tex > /dev/null < /dev/null" 172 | subprocess.call(cmd,shell=True) 173 | #print "Rendering PNG Graphics: " + output_latex_filename + ".png" 174 | cmd = "convert " + output_latex_filename + ".pdf " + \ 175 | output_latex_filename + ".png" 176 | subprocess.call(cmd,shell=True) 177 | 178 | -------------------------------------------------------------------------------- /[admn] commands.md: -------------------------------------------------------------------------------- 1 | ## Commands 2 | 3 | - `tshark` HTTP traffic on loopback port 8000: 4 | 5 | sudo tshark -i lo -V -T text -f "tcp port 8000" -d "tcp.port==8000,http" -R "http.request" 6 | 7 | - `ffmpeg` conversion for iPad: 8 | 9 | ffmpeg -i ${input_file} -acodec libfaac -ac 2 -ab 192k -s 1024x768 -vcodec libx264 -vprofile baseline -tune film -preset slower -b:v 1200k -f mp4 -threads 0 ${output_file} 10 | 11 | - sort `du -h` output 12 | 13 | du | sort -nr | cut -f2- | xargs du -hs 14 | 15 | - streaming tcpdump directly to a Windows Wireshark instance (untested) 16 | 17 | tcpdump -w - -v -i eth0 http | "c:\program files\wireshark\wireshark.exe" -k -i -" 18 | 19 | - Python profiling 20 | 21 | # Execute command with profiling 22 | python -u -m cProfile -o profile.stats script.py arg1 arg2 --hostname blah 23 | 24 | # Sort stats by total time spent in function 25 | python -c "import pstats; p = pstats.Stats(\"profile.stats\"); p.sort_stats('time').print_stats(20)" 26 | 27 | - How to run Wireshark on Mac OS X 28 | 29 | # Install XQuartz, install Wireshark. 30 | # Run XQuartz via Spotlight 31 | # Open a new Terminal, run: 32 | 33 | open /Applications/Wireshark.app/ 34 | 35 | # A new xterm instance opens, but Wireshark isn't visible. In the xterm instance run: 36 | 37 | export DISPLAY:=0 38 | 39 | # Wireshark should now be visible. 40 | 41 | - Useful httrack one-liner to index a site and all 'near' non-HTML resources and all first-links away in useful directory structure. 42 | 43 | httrack http://www.cs.columbia.edu/~smaskey/CS6998/ -W -O "/Users/ai/websites/smaskey" --extended-parsing --mirrorlinks --structure=4 +*.pdf 44 | 45 | - Another httrack one liner. 46 | 47 | httrack "http://www.bradblock.com.s3-website-us-west-1.amazonaws.com/mll.html" --mirror-wizard --path "/home/ubuntu/websites" --near --structure=4 --sockets=1 --priority=7 48 | 49 | - Setting up SAMBA on RedHat 50 | - `yum install samba samba-client` 51 | - Replace `/etc/samba/smb.conf` contents with the following, replacing `${ip_address}` with local IP address: 52 | 53 | [global] 54 | 55 | workgroup = DCL 56 | local master = no 57 | preferred master = no 58 | server string = %L Samba %v 59 | interfaces = 127.0.0.1 ${ip_address} 60 | socket address = ${ip_address} 61 | log file = /var/log/samba/log.%m 62 | max log size = 50 63 | security = share 64 | passdb backend = tdbsam 65 | load printers = no 66 | cups options = raw 67 | 68 | [root] 69 | 70 | comment = Root Directory 71 | path = / 72 | read only = no 73 | writable = yes 74 | printable = no 75 | public = yes 76 | force user = root 77 | 78 | - Add a root user to SAMBA by executing 79 | 80 | smbpasswd -a root 81 | 82 | - Set SAMBA to load on startup by executing: 83 | 84 | chkconfig smb on && chkconfig nmb on 85 | 86 | - Enable SAMBA by executing: 87 | 88 | service smb start && service nmb start 89 | 90 | - Browse to `\\${hostname}` 91 | 92 | - Setting up IP connectivity on a fresh RedHat install 93 | - Edit `/etc/sysconfig/network-scripts/ifcfg-eth0` and make sure at least the following lines are present (adjust values as appropriate): 94 | 95 | DEVICE=eth0 96 | BOOTPROTO=none 97 | DNS1=172.19.1.83 98 | DNS2=172.18.10.55 99 | DOMAIN=datcon.co.uk 100 | GATEWAY=10.224.0.1 101 | IPADDR=10.224.104.2 102 | NETMASK=255.255.0.0 103 | ONBOOT=yes 104 | DEFROUTE=yes 105 | 106 | - Assign the IP address to the Ethernet interface: 107 | 108 | ip addr add 10.224.104.2/16 broadcast 10.224.255.255 gateway 10.224.0.1 dev eth0 109 | 110 | - Add a default IP route to the default gateway: 111 | 112 | route add default gw 10.224.0.1 eth0 113 | 114 | - Turn up the Ethernet interface: 115 | 116 | ifconfig eth0 up 117 | 118 | - Set IP connectivity to enable in startup: 119 | 120 | chkconfig network on 121 | 122 | - Install latest GCC on Mac OS X 123 | 124 | # Install homebrew. 125 | brew update 126 | brew tap homebrew/dupes 127 | brew install gcc --use-llvm --enable-all-languages --enable-profiled-build 128 | 129 | - To get GCC 4.7 working on Mac we have to force distutils to give up using `-Qunused-arguments`. It's painful, so we hack it real hard: 130 | 131 | import distutils.sysconfig 132 | for key in distutils.sysconfig._config_vars: 133 | if key in ['CONFIG_ARGS', 'PY_CFLAGS', 'CFLAGS']: 134 | distutils.sysconfig._config_vars[key] = distutils.sysconfig._config_vars[key].replace("-Qunused-arguments ", "") 135 | 136 | - GPG symmetric encryption and compression 137 | 138 | gpg --symmetric --cipher-algo "AES256" --digest-algo "SHA512" --compress-algo "BZIP2" --passphrase "password" -o test.svg.gpg test.svg 139 | 140 | - GPG symmetric decryption and decompression 141 | 142 | gpg --passphrase "password" test.svg.gpg 143 | 144 | - OpenSSL symmetric encryption and compression 145 | 146 | bzip2 --stdout -- test.svg | /usr/local/Cellar/openssl/1.0.1e/bin/openssl enc -aes-256-ctr -salt -k "password" > test.svg.openssl 147 | 148 | - OpenSSL symmetric decryption and decompression 149 | 150 | /usr/local/Cellar/openssl/1.0.1e/bin/openssl enc -aes-256-ctr -d -salt -k "password" -in test.svg.openssl | bunzip2 > test.svg.2 151 | 152 | - With OpenSSL 1.0.1e, AES-CBC-HMAC-SHA1 segfaults and AES-GCM always fails; they are not intended for command-line usage. 153 | 154 | - OpenSSL encrypt and HMAC simultaneously (`pigz` is a parallel gzip implementation) 155 | 156 | cat test.svg | pigz --best -c | /usr/local/Cellar/openssl/1.0.1e/bin/openssl enc -aes-256-ctr -salt -k "password" | tee test.svg.2 | /usr/local/Cellar/openssl/1.0.1e/bin/openssl sha256 -hmac "password" 157 | 158 | - - - 159 | 160 | ### CentOS initial setup 161 | 162 | - Install with "Software development workstation" selected. 163 | - Set up Solarized theme for gnome-terminal 164 | 165 | git clone git://github.com/sigurdga/gnome-terminal-colors-solarized.git 166 | cd gnome-terminal-colors-solarized 167 | 168 | # make it light 169 | ./solarize 170 | 171 | # make it dark 172 | ./solarize 173 | 174 | # then restart terminal 175 | 176 | - Set up "Oh My ZSH" with my custom theme 177 | 178 | curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh 179 | 180 | 181 | - Set up gvim --------------------------------------------------------------------------------