Created
October 17, 2016 19:36
-
-
Save BenderV/ef6ebded1da3b0145fe3e9c7e6e3d782 to your computer and use it in GitHub Desktop.
Note on Design of Computer Program by Peter Norvig - https://in.udacity.com/course/design-of-computer-programs--cs212/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""I didn't finish the class, and the notes are only partial and really not cleaned/organized, | |
but they represent at the time what I found interesting to remember. | |
@ben_derv | |
""" | |
?? --->understand---> problem --->specify---> design --->code | |
sum(**2 for x in nums) | |
max(list) | |
max(list, key=function) => return the value witch it have max value with the function | |
max(iter, key=function) => IMPORTANT !!!! | |
list = "val1 val2".split() | |
assert x == True #=> error if not true | |
assert y == True #=> error if not true | |
return "test pass" | |
[sf] + 99*[fk] #=> [sf, fk, fk, ...] | |
tuples (7,9,4) > (7,2,5) | |
cards = ["6A", "5B", "2A"] | |
ranks = [r for r,s in cards] | |
ranks.sort(reverse=True) | |
ranks = ['--23456789TJQKA'.index(r) for r,s in hand] | |
to check if every item in a list is identical | |
len(set(list)) == 1 | |
if condition: #boolean | |
return True | |
else: | |
return False | |
# This is useless, simply do: | |
return condition | |
map(math.sqrt, [5, 2, 10]) === [sqrt(x) for x in [5, 2, 10]] | |
map(pow, [5, -2, 10], [2, 2, 2]) === [pow(x, 2) for x in [5, -2, 10]] | |
[5, 3, 3, 1, 3] => (5, 1), (3, 3), (1, 1) | |
set() // count() | |
if a and b != c: #=> =?= (a and b) != c | |
the amount of change should be proportionnal with the amount of change in the conceptualisation | |
sometime, the better way to code a special case is to write.... | |
if (ranks == [14, 5, 4, 3, 2])... | |
def allmax(iterable, key=None): | |
"Return a list of all items equal to the max of the iterable." | |
key = key or (lambda x: x) # key is a parameter that take a function | |
hands_rank = map(key, iterable) | |
liste = [] | |
for hand_rank, hand in zip(hands_rank, iterable): | |
if hand_rank == max(hands_rank): | |
liste.append(hand) | |
return liste | |
mydeck = [r+s for r in '23456789TJQKA' for s in 'SHDC'] # it's a kind of magiiiiiiiiiiiic | |
deck[n*i:n*(i+1)] for i in nrage(numhands) # 0 à n ou de n à 2n, ect | |
counts = [0]*9 => counts = [0, 0, 0, 0, 0, 0, 0, 0, 0] | |
reversed(range(9)) #=> 8 7 6 5 4 3 2 1 0 | |
sinon, il faut faire : | |
a = range(9) | |
a.reverse() | |
correctness, efficiency (fast enough), features, elegance "elegance is not optionel" | |
"The best is the enemy of the good" | |
groups = [(items.count(x), x) for x in set(items)] | |
return sorted(groups, reverse=True) | |
foo.reverse() actually reverses the elements in the container. reversed() doesn't actually reverse anything, it merely returns an object that can be used to iterate over the container's elements in reverse order. This is often faster than actually reversing the elements. | |
def unzip(pairs): return zip(*pairs) | |
#=> list of pair => pair of list ? | |
Lesson 1 : lessons learned | |
understand, define pieces, reuse, test, explore design space (correctioness, efficiency, elegance, features) | |
counts = defaultdict(int) #=> dico qui initialise pour chaque definition, la valeur par defaut de int (soit 0) | |
all((0.9<=counts[item]/e<=1.1) for item in counts) => nice ! all boolean == True | |
function | |
computing (pure fonction) => easier to test --- sorted([3,2,1]) = [1,2,3] | |
doing (impure fonction/subroutine) --- input = [3,2,1] ; input.sort() ; input==[1,2,3] | |
## write a function to test impure fonction => testImpute(function, [1,2,3]) | |
hands = itertools.combinations(hand,5) | |
maxHand = None | |
for hand in hands: | |
if hand_rank(maxHand)<hand_rank(hand) : maxHand = hand | |
return maxHand | |
itertools.product([1, 2, 3],[100, 200]) => [(1,100), (1,200), (2,100), ...] | |
info : our computer can do about a billion instruction per sec | |
calcul the time : (_number of instruction_ (guess) * number of iteration) / 1 billion per sec | |
if you don't know what design implement, take the simplest and try with it | |
x is y #=> object x is identical to y | |
x == y #=> x has the same value as y | |
houses = first, _, middle, _, _ = [1, 2, 3, 4, 5] #=> crée la list houses et assigne first à 1 et middle à 3 | |
return next((c, c2)) | |
for(a, b, c) in list | |
for(a2, b2, c2) in list | |
if (a == a2) | |
if (b == b2) | |
if (c == c2) | |
) | |
list comprehensions | |
[s for r,s in cards for/if r in "JQK" ... for/if] | |
term...for..........(for/if)*.... | |
same as : | |
result = [] | |
for r,s in cards: | |
if r in "JQK": | |
result.append(s) | |
generator expression (unlike list comprehension, can stop if true) | |
g = (term for-clause opption(for/ifs)) => return a promise to calcul | |
(to iterate) | |
next(g) | |
next(g) | |
==> raise an error if ended | |
put that in a loop or create a list of result | |
for x2 in (sq(x) for x in range(10) if x%2==0):pass | |
list((sq(x) for x in range(10) if x%2==0 )) | |
def timedcall(fn, *args): | |
"Call function with args; return the time in seconds and result." | |
t0 = time.clock() | |
result = fn(*args) | |
t1 = time.clock() | |
return t1-t0, result | |
*args => bundle the rest of args in a tuple | |
#=> def something(f, *args) | |
#=> fn(*args) => unpack the tuple | |
#=> something(f, 1, 2, 3) => *args = (1,2,3) | |
#=> timedcall(zebra_puzzle()) => would compute zebra puzzle and after run the clocks | |
#=> timedcall(zebra_puzzble) => pass the function (an object) as the argument. run the clock before the calculation | |
liste = [something(fn, *args) for _ in range(n)] #=> we don't take the index, so "_" is great | |
something(fn, *args)[0] => to take only the first result of a function | |
isinstance(n, int) | |
aspects oriented programs : seperate the differents aspects => correct, efficient, debug | |
generator functions | |
def ints(start, end=None): | |
i = start | |
while i <= end or end is None: | |
yield i | |
i = i+1 | |
L = ints(0, 100000) | |
L = <generator> | |
next(L) #=> 0 | |
for i in L: print i #=> 0 1 2 3 4 .... 100000 | |
FOR statements : the whole truth | |
# for x in items: print x | |
it = iter(items) # iterable | |
try: | |
while True: | |
x = next(it) | |
return x | |
except StopIteration: | |
pass | |
Summary | |
Concept inventory | |
Eefine ideas | |
Simple implementation | |
Back enveloppe | |
Refine code | |
tools | |
timing | |
counts | |
aspects | |
CLEAN | |
// Cryptoarithmetic | |
eval("2+2") #=> 4 | |
eval("1+1 == 3") #=> false | |
import string | |
table = string.maketrans("ABC", "123") | |
f = "A+B == C" | |
eval(f.translate(table)) #=> eval("1+2==3") #=> True | |
return None is useless; just don't return anything... | |
Profiling : where ? time ? | |
python -m cProfile test.py | |
or | |
import cProfile | |
cProfile.run('test()') | |
takes the fonction that take the longest time | |
feawer calls | |
or | |
easier calls | |
# A revoir l'intérêt | |
def F(Y,O,U,M,E): return blabla ------------ | |
=> | |
lambda Y,O,U,M,E : blabla ----------- | |
# compile_word('YOU') => '(1*U+10*O+100*Y)' | |
liste = ['%s*%s' % (10**index, letter) for (index, letter) in enumerate(reversed(word))] #=> enumerate to pass the index | |
return "("+"+".join(liste)+")" | |
Recap | |
Python | |
list comprehensions [x for x in list in ] | |
generator expression (---- for -----in ----) | |
generator yield x | |
handling types "polymorphism" timedcalls(n, ...) # n= int/float # isinstance | |
eval # str=>object or function | |
Intrumentation | |
timing time.clock() timedcall(s) | |
counting c # we can use the var name "c" because it's just to debug | |
variable naming | |
# TODO add a function to an object | |
----------- | |
def my_function_with_long_name(text): | |
"Do something" | |
def test | |
f = my_function_with_long_name | |
f("ahaha") | |
Regular Expressions // Regular Pattern | |
find substring string | |
s= "some long sting with words" | |
s.find('word') => 21 (the index) (-1 of nothing) | |
s.find('ba+!') | |
Special char | |
* a* '',a,aa,... | |
? a? '',a | |
. . a,b,c,7,!,... # not the empty string(obvious) | |
^ ^b ba,bb,b7,... | |
$ a$ ba,oa,!a,6a | |
'' '' '' | |
a a a | |
ba ba ba | |
python re | |
search(parttern, text) => True, if patterns appears anywhere in text | |
match(parttern, text) => True, if pattern appears at the start of the text | |
API = Appicatin Programming Interface | |
re.search => return the biggest result | |
re.match => return the result if it appear at the start | |
dis.dis(lambda x, y: sqrt(x ** 2 + y ** 2)) | |
/!\ if '' => False | |
def seq(x,y) return lambda set().union(*map(y, x(text)) | |
def lit(s): | |
set_s = set([s]) # Computed once | |
return lambda Ns: set_s if len(s) in Ns else null | |
backward compatible != internal (logic of func) /external (call of the function) | |
@decorator | |
def function() <==> function = decorator(function) | |
memoization | |
# | |
try/except: ask forgivness later (contraty to if/else). Good if already a except planned | |
why list are mutable : https://www.udacity.com/course/viewer#!/c-cs212/l-48738183/e-48713825/m-48713627 (cache management) | |
Tools | |
Debugging | |
countcall | |
trace | |
timeit | |
Perf | |
memo | |
expr | |
n_ary |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it was remembering, thank you