├── README.md ├── Listings ├── 3. Basic Data Structures │ ├── snippets.py │ ├── deques.py │ ├── queues.py │ ├── lists.py │ └── stacks.py ├── 6. Trees and Tree Algorithms │ ├── snippets.py │ ├── priority_queue.py │ ├── avltree.py │ ├── bst.py │ └── tree.py ├── 7. Graphs and Graphing Algorithms │ ├── snippets.py │ ├── words_small │ ├── tour.dat │ ├── wordlist.py │ ├── knight.py │ ├── adjacency_list.py │ └── graphics.py ├── 8. Advanced Topics │ ├── dice.png │ ├── bubbles.jpg │ ├── simplequant.py │ ├── stringmatching.py │ ├── arraylist.py │ ├── crypto.py │ ├── skiplist.py │ ├── octreeq.py │ └── octree.py ├── 4. Recursion │ ├── maze.txt │ ├── maze2.txt │ ├── hanoi.py │ ├── sierpinski.py │ ├── maze.py │ └── snippets.py ├── 2. Algorithm Analysis │ ├── dicts.py │ ├── snippets.py │ ├── lists.py │ └── anagrams.py ├── 1. Introduction │ ├── snippets.py │ ├── fraction.py │ └── circuits.py └── 5. Searching and Sorting │ ├── snippets.py │ ├── map.py │ └── sorting.py ├── Figures ├── 4. Recursion │ ├── hanoi.png │ ├── maze.png │ ├── toStr.png │ ├── tree1.png │ ├── tree2.png │ ├── callTree.png │ ├── callstack.png │ ├── gcd-call.png │ ├── recstack.png │ ├── sierpinski.png │ ├── stCallTree.png │ ├── sumlistIn.png │ ├── sumlistOut.png │ ├── toStrBase2.png │ ├── changeTable.png │ ├── elevenCents.png │ ├── newcallstack.png │ ├── sierpinski_colour.png │ └── sierpinski_original.png ├── 1. Introduction │ ├── adt.png │ ├── gates.png │ ├── blackbox.png │ ├── circuit1.png │ ├── connector.png │ ├── fraction1.png │ ├── fraction2.png │ ├── fraction3.png │ ├── assignment1.png │ ├── assignment2.png │ ├── inheritance1.png │ └── truthtable.png ├── 8. Advanced Topics │ ├── dfa.png │ ├── kmp.png │ ├── array.png │ ├── mappic.png │ ├── 8by8image.png │ ├── bubbles.png │ ├── colorcube.png │ ├── datanode.png │ ├── gcd-call.png │ ├── otMerge.png │ ├── steptable.png │ ├── addskiplist.png │ ├── headernode.png │ ├── insertArray.png │ ├── oTreeQuant.jpg │ ├── oTreeQuant.png │ ├── simpleQuant.jpg │ ├── simpleQuant.png │ ├── simplematch.png │ ├── steptable2.png │ ├── OctTreeIndex.png │ ├── addskiplist2.png │ ├── initskiplist.png │ ├── quantizeCube.png │ ├── searchskiplist.png │ ├── simplematch2.png │ ├── vocabskiplist1.png │ ├── vocabskiplist2.png │ └── vocabskiplist3.png ├── 2. Algorithm Analysis │ ├── newplot.png │ ├── newplot2.png │ ├── poptime.png │ ├── tofnplot.png │ └── listvdict.png ├── 3. Basic Data Structures │ ├── idea.png │ ├── idea2.png │ ├── node.png │ ├── node2.png │ ├── stack.png │ ├── dectobin.png │ ├── intopost.png │ ├── listisa.png │ ├── moveleft.png │ ├── prevcurr.png │ ├── remove.png │ ├── remove2.png │ ├── search.png │ ├── addtohead.png │ ├── basicdeque.png │ ├── basicqueue.png │ ├── bookstack.png │ ├── bookstack2.png │ ├── hotpotato.png │ ├── linkedlist.png │ ├── moveright.png │ ├── namequeue.png │ ├── primitive.png │ ├── removeinit.png │ ├── traversal.png │ ├── wrongorder.png │ ├── complexmove.png │ ├── evalpostfix1.png │ ├── evalpostfix2.png │ ├── orderedsearch.png │ ├── initlinkedlist.png │ ├── orderlinkedlist.png │ ├── palindromesetup.png │ ├── simpleparcheck.png │ ├── simplereversal.png │ ├── simplereversal2.png │ ├── simulationsetup.png │ └── linkedlistinsert.png ├── 5. Searching and Sorting │ ├── graph.png │ ├── swap.png │ ├── bubble1.png │ ├── chaining.png │ ├── binsearch.png │ ├── bubblepass.png │ ├── clustering.png │ ├── firstsplit.png │ ├── hashtable.png │ ├── hashtable2.png │ ├── mergesortA.png │ ├── mergesortB.png │ ├── partitionA.png │ ├── partitionB.png │ ├── quadratic.png │ ├── seqsearch.png │ ├── seqsearch2.png │ ├── shellsortA.png │ ├── shellsortB.png │ ├── shellsortC.png │ ├── shellsortD.png │ ├── stringhash.png │ ├── insertionpass.png │ ├── insertionsort.png │ ├── selectionsort.png │ ├── stringhash2.png │ ├── linearprobing1.png │ ├── linearprobing2.png │ └── selectionsortnew.png ├── 6. Trees and Tree Algorithms │ ├── bstput.png │ ├── percUp.png │ ├── badrotate.png │ ├── bfderive.png │ ├── biology.png │ ├── booktree.png │ ├── bstdel1.png │ ├── bstdel2.png │ ├── bstdel3.png │ ├── buildExp.png │ ├── buildExp1.png │ ├── buildExp2.png │ ├── buildExp3.png │ ├── buildExp4.png │ ├── buildExp5.png │ ├── buildExp6.png │ ├── buildExp7.png │ ├── buildExp8.png │ ├── buildheap.png │ ├── compTree.png │ ├── directory.png │ ├── exerTree.png │ ├── heapOrder.png │ ├── htmltree.png │ ├── meParse.png │ ├── meSimple.png │ ├── nlParse.png │ ├── percDown.png │ ├── rotatelr.png │ ├── rotexer1.png │ ├── simpleBST.png │ ├── smalltree.png │ ├── tree_ex.png │ ├── treedef1.png │ ├── treerecs.png │ ├── worstAVL.png │ ├── skewedTree.png │ ├── unbalanced.png │ ├── hardunbalanced.png │ ├── rightrotate1.png │ ├── TreeDefRecursive.png │ └── simpleunbalanced.png └── 7. Graphs and Graphing Algorithms │ ├── bfs1.png │ ├── bfs2.png │ ├── bfs3.png │ ├── mst1.png │ ├── scc1.png │ ├── scc2.png │ ├── adjMat.png │ ├── bcast1.png │ ├── cshome.png │ ├── ktdfsa.png │ ├── ktdfsb.png │ ├── ktdfsc.png │ ├── ktdfsd.png │ ├── ktdfse.png │ ├── ktdfsf.png │ ├── ktdfsg.png │ ├── ktdfsh.png │ ├── prima.png │ ├── primb.png │ ├── primc.png │ ├── primd.png │ ├── prime.png │ ├── primf.png │ ├── primg.png │ ├── scc1a.png │ ├── scc1b.png │ ├── Internet.png │ ├── SimpleMap.png │ ├── adjMatEX.png │ ├── adjlist.png │ ├── bfsDone.png │ ├── bigknight.png │ ├── dfstree.png │ ├── digraph.png │ ├── dijkstraa.png │ ├── dijkstrab.png │ ├── dijkstrac.png │ ├── dijkstrad.png │ ├── dijkstrae.png │ ├── dijkstraf.png │ ├── gendfsa.png │ ├── gendfsb.png │ ├── gendfsc.png │ ├── gendfsd.png │ ├── gendfse.png │ ├── gendfsf.png │ ├── gendfsg.png │ ├── gendfsh.png │ ├── gendfsi.png │ ├── gendfsj.png │ ├── gendfsk.png │ ├── gendfsl.png │ ├── moveCount.png │ ├── pancakes.png │ ├── sccforest.png │ ├── transpose.png │ ├── wordgraph.png │ ├── 8arrayTree.png │ ├── CS-Prereqs.png │ ├── knightmoves.png │ ├── pancakesDFS.png │ ├── pancakesTS.png │ ├── routeGraph.png │ ├── transpose1.png │ ├── transpose2.png │ ├── wordbuckets.png │ ├── completeTour.png │ ├── knightmovesboard.png │ └── knightmovesgraph.png ├── Slides ├── 4. Recursion │ └── 4. Recursion.pptx ├── 1. Introduction │ └── 1. Introduction.pptx ├── 8. Advanced Topics │ └── 8. Advanced Topics.pptx ├── 2. Algorithm Analysis │ └── 2. Algorithm Analysis.pptx ├── 3. Basic Data Structures │ └── 3. Basic Data Structures.pptx ├── 5. Searching and Sorting │ └── 5. Searching and Sorting.pptx ├── 6. Trees and Tree Algorithms │ └── 6. Trees and Tree Algorithms.pptx └── 7. Graphs and Graphing Algorithms │ └── 7. Graphs and Graphing Algorithms.pptx └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Listings/3. Basic Data Structures/snippets.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Listings/6. Trees and Tree Algorithms/snippets.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/snippets.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Figures/4. Recursion/hanoi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/hanoi.png -------------------------------------------------------------------------------- /Figures/4. Recursion/maze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/maze.png -------------------------------------------------------------------------------- /Figures/4. Recursion/toStr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/toStr.png -------------------------------------------------------------------------------- /Figures/4. Recursion/tree1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/tree1.png -------------------------------------------------------------------------------- /Figures/4. Recursion/tree2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/tree2.png -------------------------------------------------------------------------------- /Figures/1. Introduction/adt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/adt.png -------------------------------------------------------------------------------- /Figures/1. Introduction/gates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/gates.png -------------------------------------------------------------------------------- /Figures/4. Recursion/callTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/callTree.png -------------------------------------------------------------------------------- /Figures/4. Recursion/callstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/callstack.png -------------------------------------------------------------------------------- /Figures/4. Recursion/gcd-call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/gcd-call.png -------------------------------------------------------------------------------- /Figures/4. Recursion/recstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/recstack.png -------------------------------------------------------------------------------- /Figures/4. Recursion/sierpinski.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/sierpinski.png -------------------------------------------------------------------------------- /Figures/4. Recursion/stCallTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/stCallTree.png -------------------------------------------------------------------------------- /Figures/4. Recursion/sumlistIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/sumlistIn.png -------------------------------------------------------------------------------- /Figures/4. Recursion/sumlistOut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/sumlistOut.png -------------------------------------------------------------------------------- /Figures/4. Recursion/toStrBase2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/toStrBase2.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/dfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/dfa.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/kmp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/kmp.png -------------------------------------------------------------------------------- /Figures/1. Introduction/blackbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/blackbox.png -------------------------------------------------------------------------------- /Figures/1. Introduction/circuit1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/circuit1.png -------------------------------------------------------------------------------- /Figures/1. Introduction/connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/connector.png -------------------------------------------------------------------------------- /Figures/1. Introduction/fraction1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/fraction1.png -------------------------------------------------------------------------------- /Figures/1. Introduction/fraction2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/fraction2.png -------------------------------------------------------------------------------- /Figures/1. Introduction/fraction3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/fraction3.png -------------------------------------------------------------------------------- /Figures/4. Recursion/changeTable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/changeTable.png -------------------------------------------------------------------------------- /Figures/4. Recursion/elevenCents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/elevenCents.png -------------------------------------------------------------------------------- /Figures/4. Recursion/newcallstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/newcallstack.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/array.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/mappic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/mappic.png -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/dice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Listings/8. Advanced Topics/dice.png -------------------------------------------------------------------------------- /Slides/4. Recursion/4. Recursion.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/4. Recursion/4. Recursion.pptx -------------------------------------------------------------------------------- /Figures/1. Introduction/assignment1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/assignment1.png -------------------------------------------------------------------------------- /Figures/1. Introduction/assignment2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/assignment2.png -------------------------------------------------------------------------------- /Figures/1. Introduction/inheritance1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/inheritance1.png -------------------------------------------------------------------------------- /Figures/1. Introduction/truthtable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/1. Introduction/truthtable.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/8by8image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/8by8image.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/bubbles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/bubbles.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/colorcube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/colorcube.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/datanode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/datanode.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/gcd-call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/gcd-call.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/otMerge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/otMerge.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/steptable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/steptable.png -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/bubbles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Listings/8. Advanced Topics/bubbles.jpg -------------------------------------------------------------------------------- /Figures/2. Algorithm Analysis/newplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/2. Algorithm Analysis/newplot.png -------------------------------------------------------------------------------- /Figures/2. Algorithm Analysis/newplot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/2. Algorithm Analysis/newplot2.png -------------------------------------------------------------------------------- /Figures/2. Algorithm Analysis/poptime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/2. Algorithm Analysis/poptime.png -------------------------------------------------------------------------------- /Figures/2. Algorithm Analysis/tofnplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/2. Algorithm Analysis/tofnplot.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/idea.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/idea2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/idea2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/node.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/node2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/node2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/stack.png -------------------------------------------------------------------------------- /Figures/4. Recursion/sierpinski_colour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/sierpinski_colour.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/graph.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/swap.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/addskiplist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/addskiplist.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/headernode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/headernode.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/insertArray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/insertArray.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/oTreeQuant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/oTreeQuant.jpg -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/oTreeQuant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/oTreeQuant.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/simpleQuant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/simpleQuant.jpg -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/simpleQuant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/simpleQuant.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/simplematch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/simplematch.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/steptable2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/steptable2.png -------------------------------------------------------------------------------- /Figures/2. Algorithm Analysis/listvdict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/2. Algorithm Analysis/listvdict.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/dectobin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/dectobin.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/intopost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/intopost.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/listisa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/listisa.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/moveleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/moveleft.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/prevcurr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/prevcurr.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/remove.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/remove2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/remove2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/search.png -------------------------------------------------------------------------------- /Figures/4. Recursion/sierpinski_original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/4. Recursion/sierpinski_original.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/bubble1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/bubble1.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/chaining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/chaining.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/OctTreeIndex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/OctTreeIndex.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/addskiplist2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/addskiplist2.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/initskiplist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/initskiplist.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/quantizeCube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/quantizeCube.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/searchskiplist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/searchskiplist.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/simplematch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/simplematch2.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/vocabskiplist1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/vocabskiplist1.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/vocabskiplist2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/vocabskiplist2.png -------------------------------------------------------------------------------- /Figures/8. Advanced Topics/vocabskiplist3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/8. Advanced Topics/vocabskiplist3.png -------------------------------------------------------------------------------- /Slides/1. Introduction/1. Introduction.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/1. Introduction/1. Introduction.pptx -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/addtohead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/addtohead.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/basicdeque.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/basicdeque.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/basicqueue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/basicqueue.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/bookstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/bookstack.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/bookstack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/bookstack2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/hotpotato.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/hotpotato.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/linkedlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/linkedlist.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/moveright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/moveright.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/namequeue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/namequeue.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/primitive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/primitive.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/removeinit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/removeinit.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/traversal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/traversal.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/wrongorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/wrongorder.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/binsearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/binsearch.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/bubblepass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/bubblepass.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/clustering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/clustering.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/firstsplit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/firstsplit.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/hashtable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/hashtable.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/hashtable2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/hashtable2.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/mergesortA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/mergesortA.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/mergesortB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/mergesortB.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/partitionA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/partitionA.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/partitionB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/partitionB.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/quadratic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/quadratic.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/seqsearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/seqsearch.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/seqsearch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/seqsearch2.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/shellsortA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/shellsortA.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/shellsortB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/shellsortB.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/shellsortC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/shellsortC.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/shellsortD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/shellsortD.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/stringhash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/stringhash.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/bstput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/bstput.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/percUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/percUp.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/complexmove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/complexmove.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/evalpostfix1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/evalpostfix1.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/evalpostfix2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/evalpostfix2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/orderedsearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/orderedsearch.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/insertionpass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/insertionpass.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/insertionsort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/insertionsort.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/selectionsort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/selectionsort.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/stringhash2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/stringhash2.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/badrotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/badrotate.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/bfderive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/bfderive.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/biology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/biology.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/booktree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/booktree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/bstdel1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/bstdel1.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/bstdel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/bstdel2.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/bstdel3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/bstdel3.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp1.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp2.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp3.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp4.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp5.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp6.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp7.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildExp8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildExp8.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/buildheap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/buildheap.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/compTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/compTree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/directory.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/exerTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/exerTree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/heapOrder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/heapOrder.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/htmltree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/htmltree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/meParse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/meParse.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/meSimple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/meSimple.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/nlParse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/nlParse.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/percDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/percDown.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/rotatelr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/rotatelr.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/rotexer1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/rotexer1.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/simpleBST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/simpleBST.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/smalltree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/smalltree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/tree_ex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/tree_ex.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/treedef1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/treedef1.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/treerecs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/treerecs.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/worstAVL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/worstAVL.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bfs1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bfs1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bfs2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bfs2.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bfs3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bfs3.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/mst1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/mst1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/scc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/scc1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/scc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/scc2.png -------------------------------------------------------------------------------- /Slides/8. Advanced Topics/8. Advanced Topics.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/8. Advanced Topics/8. Advanced Topics.pptx -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/initlinkedlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/initlinkedlist.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/orderlinkedlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/orderlinkedlist.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/palindromesetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/palindromesetup.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/simpleparcheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/simpleparcheck.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/simplereversal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/simplereversal.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/simplereversal2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/simplereversal2.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/simulationsetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/simulationsetup.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/linearprobing1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/linearprobing1.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/linearprobing2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/linearprobing2.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/skewedTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/skewedTree.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/unbalanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/unbalanced.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/adjMat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/adjMat.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bcast1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bcast1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/cshome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/cshome.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsa.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsb.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsc.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsd.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfse.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsf.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsg.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/ktdfsh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/ktdfsh.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/prima.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/prima.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/primb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/primb.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/primc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/primc.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/primd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/primd.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/prime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/prime.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/primf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/primf.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/primg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/primg.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/scc1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/scc1a.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/scc1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/scc1b.png -------------------------------------------------------------------------------- /Figures/3. Basic Data Structures/linkedlistinsert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/3. Basic Data Structures/linkedlistinsert.png -------------------------------------------------------------------------------- /Figures/5. Searching and Sorting/selectionsortnew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/5. Searching and Sorting/selectionsortnew.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/hardunbalanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/hardunbalanced.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/rightrotate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/rightrotate1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/Internet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/Internet.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/SimpleMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/SimpleMap.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/adjMatEX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/adjMatEX.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/adjlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/adjlist.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bfsDone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bfsDone.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/bigknight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/bigknight.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dfstree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dfstree.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/digraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/digraph.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstraa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstraa.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstrab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstrab.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstrac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstrac.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstrad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstrad.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstrae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstrae.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/dijkstraf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/dijkstraf.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsa.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsb.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsc.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsd.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfse.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsf.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsg.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsh.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsi.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsj.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsk.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/gendfsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/gendfsl.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/moveCount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/moveCount.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/pancakes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/pancakes.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/sccforest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/sccforest.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/transpose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/transpose.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/wordgraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/wordgraph.png -------------------------------------------------------------------------------- /Slides/2. Algorithm Analysis/2. Algorithm Analysis.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/2. Algorithm Analysis/2. Algorithm Analysis.pptx -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/TreeDefRecursive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/TreeDefRecursive.png -------------------------------------------------------------------------------- /Figures/6. Trees and Tree Algorithms/simpleunbalanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/6. Trees and Tree Algorithms/simpleunbalanced.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/8arrayTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/8arrayTree.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/CS-Prereqs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/CS-Prereqs.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/knightmoves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/knightmoves.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/pancakesDFS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/pancakesDFS.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/pancakesTS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/pancakesTS.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/routeGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/routeGraph.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/transpose1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/transpose1.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/transpose2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/transpose2.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/wordbuckets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/wordbuckets.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/completeTour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/completeTour.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/knightmovesboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/knightmovesboard.png -------------------------------------------------------------------------------- /Figures/7. Graphs and Graphing Algorithms/knightmovesgraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Figures/7. Graphs and Graphing Algorithms/knightmovesgraph.png -------------------------------------------------------------------------------- /Slides/3. Basic Data Structures/3. Basic Data Structures.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/3. Basic Data Structures/3. Basic Data Structures.pptx -------------------------------------------------------------------------------- /Slides/5. Searching and Sorting/5. Searching and Sorting.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/5. Searching and Sorting/5. Searching and Sorting.pptx -------------------------------------------------------------------------------- /Slides/6. Trees and Tree Algorithms/6. Trees and Tree Algorithms.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/6. Trees and Tree Algorithms/6. Trees and Tree Algorithms.pptx -------------------------------------------------------------------------------- /Slides/7. Graphs and Graphing Algorithms/7. Graphs and Graphing Algorithms.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psads/psadspy-src/HEAD/Slides/7. Graphs and Graphing Algorithms/7. Graphs and Graphing Algorithms.pptx -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/words_small: -------------------------------------------------------------------------------- 1 | bane 2 | bank 3 | bunk 4 | cane 5 | dale 6 | dunk 7 | foil 8 | fool 9 | kale 10 | lane 11 | male 12 | mane 13 | pale 14 | pole 15 | poll 16 | pool 17 | quip 18 | quit 19 | rain 20 | sage 21 | sale 22 | same 23 | tank 24 | vain 25 | wane 26 | -------------------------------------------------------------------------------- /Listings/4. Recursion/maze.txt: -------------------------------------------------------------------------------- 1 | ++++++++++++++++++++++ 2 | + + ++ ++ + 3 | + + + +++ + ++ 4 | + + + ++ ++++ + ++ 5 | +++ ++++++ +++ + + 6 | + ++ ++ + 7 | +++++ ++++++ +++++ + 8 | + + +++++++ + + 9 | + +++++++ S + + 10 | + + +++ 11 | ++++++++++++++++++ +++ 12 | -------------------------------------------------------------------------------- /Listings/4. Recursion/maze2.txt: -------------------------------------------------------------------------------- 1 | ++++++++++++++++++++++ 2 | + + ++ ++ + 3 | + ++++++++++ 4 | + + ++ ++++ +++ ++ 5 | + + + + ++ +++ + 6 | + ++ ++ + + 7 | +++++ + + ++ + + 8 | +++++ +++ + + ++ + 9 | + + + S+ + + 10 | +++++ + + + + + + 11 | ++++++++++++++++++++++ 12 | -------------------------------------------------------------------------------- /Listings/4. Recursion/hanoi.py: -------------------------------------------------------------------------------- 1 | def move_tower(height, from_pole, to_pole, with_pole): 2 | if height >= 1: 3 | move_tower(height - 1, from_pole, with_pole, to_pole) 4 | move_disk(from_pole, to_pole) 5 | move_tower(height - 1, with_pole, to_pole, from_pole) 6 | 7 | 8 | def move_disk(from_p, to_p): 9 | print("moving disk from", from_p, "to", to_p) 10 | 11 | 12 | move_tower(3, "A", "B", "C") 13 | 14 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/tour.dat: -------------------------------------------------------------------------------- 1 | 32 2 | 49 3 | 59 4 | 53 5 | 63 6 | 46 7 | 31 8 | 14 9 | 4 10 | 10 11 | 0 12 | 17 13 | 2 14 | 8 15 | 25 16 | 40 17 | 57 18 | 42 19 | 48 20 | 58 21 | 52 22 | 62 23 | 47 24 | 30 25 | 15 26 | 5 27 | 11 28 | 1 29 | 16 30 | 33 31 | 27 32 | 21 33 | 6 34 | 12 35 | 18 36 | 3 37 | 9 38 | 24 39 | 34 40 | 19 41 | 36 42 | 26 43 | 20 44 | 37 45 | 43 46 | 60 47 | 54 48 | 39 49 | 22 50 | 7 51 | 13 52 | 23 53 | 29 54 | 35 55 | 41 56 | 56 57 | 50 58 | 44 59 | 38 60 | 28 61 | 45 62 | 51 63 | 61 64 | 55 -------------------------------------------------------------------------------- /Listings/2. Algorithm Analysis/dicts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Python dictionary performance""" 3 | 4 | import timeit 5 | import random 6 | 7 | print(f"{'n':10s}{'list':>10s}{'dict':>10s}") 8 | for i in range(10_000, 1_000_001, 20_000): 9 | t = timeit.Timer(f"random.randrange({i}) in x", 10 | "from __main__ import random, x") 11 | x = list(range(i)) 12 | lst_time = t.timeit(number=1000) 13 | x = {j: None for j in range(i)} 14 | dict_time = t.timeit(number=1000) 15 | print(f"{i:<10,}{lst_time:>10.3f}{dict_time:>10.3f}") 16 | -------------------------------------------------------------------------------- /Listings/1. Introduction/snippets.py: -------------------------------------------------------------------------------- 1 | print(2 + 3 * 4) 2 | print((2 + 3) * 4) 3 | print(2 ** 10) 4 | print(6 / 3) 5 | print(7 / 3) 6 | print(7 // 3) 7 | print(7 % 3) 8 | print(3 / 6) 9 | print(3 // 6) 10 | print(3 % 6) 11 | print(2 ** 100) 12 | 13 | my_list = [1, 2, 3, 4] 14 | big_list = [my_list] * 3 15 | print(big_list) 16 | my_list[2] = 45 17 | print(big_list) 18 | 19 | capitals = {"Iowa": "Des Moines", "Wisconsin": "Madison"} 20 | print(capitals["Iowa"]) 21 | capitals["Utah"] = "Salt Lake City" 22 | capitals["California"] = "Sacramento" 23 | print(capitals) 24 | print(len(capitals)) 25 | for k in capitals: 26 | print(capitals[k], "is the capital of", k) 27 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/simplequant.py: -------------------------------------------------------------------------------- 1 | # from PIL import Image 2 | 3 | # im = Image.open('Advanced/simpleQuant.jpg') 4 | # # rgb_im = im.convert('RGB') 5 | # r, g, b = im.getpixel((200, 300)) 6 | # print(r, g, b) 7 | # # (66, 44, 7) 8 | 9 | # im.putpixel((200, 300), (100, 100, 100)) 10 | # r, g, b = im.getpixel((200, 300)) 11 | # print(r, g, b) 12 | 13 | from PIL import Image 14 | 15 | 16 | def simple_quant(): 17 | im = Image.open("Advanced/bubbles.jpg") 18 | w, h = im.size 19 | for row in range(h): 20 | for col in range(w): 21 | r, g, b = im.getpixel((col, row)) 22 | r = r // 36 * 36 23 | g = g // 42 * 42 24 | b = b // 42 * 42 25 | im.putpixel((col, row), (r, g, b)) 26 | im.show() 27 | 28 | 29 | simple_quant() -------------------------------------------------------------------------------- /Listings/1. Introduction/fraction.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Class Fraction""" 3 | 4 | 5 | def gcd(m, n): 6 | while m % n != 0: 7 | m, n = n, m % n 8 | 9 | return n 10 | 11 | 12 | class Fraction: 13 | def __init__(self, top, bottom): 14 | self.num = top 15 | self.den = bottom 16 | 17 | def __str__(self): 18 | return f"{self.num}/{self.den}" 19 | 20 | def __eq__(self, other_fraction): 21 | first_num = self.num * other_fraction.den 22 | second_num = other_fraction.num * self.den 23 | 24 | return first_num == second_num 25 | 26 | def __add__(self, other_fraction): 27 | new_num = self.num * other_fraction.den + self.den * other_fraction.num 28 | new_den = self.den * other_fraction.den 29 | common = gcd(new_num, new_den) 30 | return Fraction(new_num // common, new_den // common) 31 | 32 | def show(self): 33 | print(f"{self.num}/{self.den}") 34 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/stringmatching.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """KMP implementation""" 3 | 4 | 5 | def simple_matcher(pattern, text): 6 | i = j = 0 7 | 8 | while True: 9 | if text[i] == pattern[j]: 10 | j = j + 1 11 | else: 12 | j = 0 13 | i = i + 1 14 | 15 | if i == len(text): 16 | return -1 17 | if j == len(pattern): 18 | return i - j 19 | 20 | 21 | def mismatched_links(pattern): 22 | aug_pattern = "0" + pattern 23 | links = {1: 0} 24 | for k in range(2, len(aug_pattern)): 25 | s = links[k - 1] 26 | while s >= 1: 27 | if aug_pattern[s] == aug_pattern[k - 1]: 28 | break 29 | s = links[s] 30 | links[k] = s + 1 31 | return links 32 | 33 | 34 | assert simple_matcher("ab", "ccabababcab") == 2 35 | assert simple_matcher("xyz", "ccabababcab") == -1 36 | 37 | assert mismatched_links("ACATA") == { 38 | 1: 0, 39 | 2: 1, 40 | 3: 1, 41 | 4: 2, 42 | 5: 1, 43 | } 44 | print("Done") 45 | -------------------------------------------------------------------------------- /Listings/2. Algorithm Analysis/snippets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Snippets of code""" 3 | 4 | def sum_of_n(n): 5 | the_sum = 0 6 | for i in range(1, n + 1): 7 | the_sum = the_sum + i 8 | 9 | return the_sum 10 | 11 | 12 | print(sum_of_n(10)) 13 | 14 | 15 | def foo(tom): 16 | fred = 0 17 | for bill in range(1, tom + 1): 18 | barney = bill 19 | fred = fred + barney 20 | 21 | return fred 22 | 23 | 24 | print(foo(10)) 25 | 26 | 27 | import time 28 | 29 | 30 | def sum_of_n_2(n): 31 | start = time.time() 32 | 33 | the_sum = 0 34 | for i in range(1, n + 1): 35 | the_sum = the_sum + i 36 | 37 | end = time.time() 38 | 39 | return the_sum, end - start 40 | 41 | 42 | for i in range(5): 43 | print("Sum is %d required %10.7f seconds" % sum_of_n_2(1000000)) 44 | 45 | 46 | def sum_of_n_3(n): 47 | return (n * (n + 1)) / 2 48 | 49 | 50 | print(sum_of_n_3(10)) 51 | 52 | n = 10 53 | a = 5 54 | b = 6 55 | c = 10 56 | for i in range(n): 57 | for j in range(n): 58 | x = i * i 59 | y = j * j 60 | z = i * j 61 | for k in range(n): 62 | w = a * k + 45 63 | v = b * b 64 | d = 33 65 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/arraylist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ArrayList implementation""" 3 | 4 | 5 | class ArrayList: 6 | def __init__(self): 7 | self.size_exponent = 0 8 | self.max_size = 0 9 | self.last_index = 0 10 | self.my_array = [] 11 | 12 | def append(self, val): 13 | if self.last_index > self.max_size - 1: 14 | self.__resize() 15 | self.my_array[self.last_index] = val 16 | self.last_index += 1 17 | 18 | def __resize(self): 19 | new_size = 2 ** self.size_exponent 20 | print("new_size = ", new_size) 21 | new_array = [0] * new_size 22 | for i in range(self.max_size): 23 | new_array[i] = self.my_array[i] 24 | 25 | self.max_size = new_size 26 | self.my_array = new_array 27 | self.size_exponent += 1 28 | 29 | def __getitem__(self, idx): 30 | if idx < self.last_index: 31 | return self.my_array[idx] 32 | raise LookupError("index out of bounds") 33 | 34 | def __setitem__(self, idx, val): 35 | if idx < self.last_index: 36 | self.my_array[idx] = val 37 | raise LookupError("index out of bounds") 38 | 39 | def insert(self, idx, val): 40 | if self.last_index > self.max_size - 1: 41 | self.__resize() 42 | for i in range(self.last_index, idx - 1, -1): 43 | self.my_array[i + 1] = self.my_array[i] 44 | self.last_index += 1 45 | self.my_array[idx] = val 46 | 47 | 48 | lst = ArrayList() 49 | for i in range(100): 50 | lst.append(i) 51 | -------------------------------------------------------------------------------- /Listings/2. Algorithm Analysis/lists.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Python list performance""" 3 | 4 | from timeit import Timer 5 | 6 | 7 | def test1(): 8 | l = [] 9 | for i in range(1000): 10 | l = l + [i] 11 | 12 | 13 | def test2(): 14 | l = [] 15 | for i in range(1000): 16 | l.append(i) 17 | 18 | 19 | def test3(): 20 | l = [i for i in range(1000)] 21 | 22 | 23 | def test4(): 24 | l = list(range(1000)) 25 | 26 | 27 | t1 = Timer("test1()", "from __main__ import test1") 28 | print(f"concatenation: {t1.timeit(number=1000):15.2f} milliseconds") 29 | t2 = Timer("test2()", "from __main__ import test2") 30 | print(f"appending: {t2.timeit(number=1000):19.2f} milliseconds") 31 | t3 = Timer("test3()", "from __main__ import test3") 32 | print(f"list comprehension: {t3.timeit(number=1000):10.2f} milliseconds") 33 | t4 = Timer("test4()", "from __main__ import test4") 34 | print(f"list range: {t4.timeit(number=1000):18.2f} milliseconds") 35 | 36 | pop_zero = Timer("x.pop(0)", "from __main__ import x") 37 | pop_end = Timer("x.pop()", "from __main__ import x") 38 | 39 | x = list(range(2000000)) 40 | print(f"pop(0): {pop_zero.timeit(number=1000):10.5f} milliseconds") 41 | 42 | x = list(range(2000000)) 43 | print(f"pop(): {pop_end.timeit(number=1000):11.5f} milliseconds") 44 | 45 | 46 | pop_zero = Timer("x.pop(0)", "from __main__ import x") 47 | pop_end = Timer("x.pop()", "from __main__ import x") 48 | print(f"{'n':10s}{'pop(0)':>15s}{'pop()':>15s}") 49 | for i in range(1_000_000, 100_000_001, 1_000_000): 50 | x = list(range(i)) 51 | pop_zero_t = pop_zero.timeit(number=1000) 52 | x = list(range(i)) 53 | pop_end_t = pop_end.timeit(number=1000) 54 | print(f"{i:<10d}{pop_zero_t:>15.5f}{pop_end_t:>15.5f}") 55 | 56 | -------------------------------------------------------------------------------- /Listings/3. Basic Data Structures/deques.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Deque Usage Example""" 3 | from pythonds3.basic import Deque 4 | 5 | 6 | # class Deque: 7 | # """Queue implementation as a list""" 8 | 9 | # def __init__(self): 10 | # """Create new deque""" 11 | # self._items = [] 12 | 13 | # def is_empty(self): 14 | # """Check if the deque is empty""" 15 | # return not bool(self._items) 16 | 17 | # def add_front(self, item): 18 | # """Add an item to the front of the deque""" 19 | # self._items.append(item) 20 | 21 | # def add_rear(self, item): 22 | # """Add an item to the rear of the deque""" 23 | # self._items.insert(0, item) 24 | 25 | # def remove_front(self): 26 | # """Remove an item from the front of the deque""" 27 | # return self._items.pop() 28 | 29 | # def remove_rear(self): 30 | # """Remove an item from the rear of the deque""" 31 | # return self._items.pop(0) 32 | 33 | # def size(self): 34 | # """Get the number of items in the deque""" 35 | # return len(self._items) 36 | 37 | 38 | # d = Deque() 39 | # print(d.is_empty()) 40 | # d.add_rear(4) 41 | # d.add_rear("dog") 42 | # d.add_front("cat") 43 | # d.add_front(True) 44 | # print(d.size()) 45 | # print(d.is_empty()) 46 | # d.add_rear(8.4) 47 | # print(d.remove_rear()) 48 | # print(d.remove_front()) 49 | 50 | 51 | def pal_checker(a_string): 52 | char_deque = Deque() 53 | 54 | for ch in a_string: 55 | char_deque.add_rear(ch) 56 | 57 | while char_deque.size() > 1: 58 | first = char_deque.remove_front() 59 | last = char_deque.remove_rear() 60 | if first != last: 61 | return False 62 | 63 | return True 64 | 65 | 66 | assert pal_checker("lsdkjfskf") == False 67 | assert pal_checker("radar") == True 68 | -------------------------------------------------------------------------------- /Listings/4. Recursion/sierpinski.py: -------------------------------------------------------------------------------- 1 | import turtle 2 | 3 | 4 | def draw_triangle(points, color, my_turtle): 5 | my_turtle.fillcolor(color) 6 | my_turtle.up() 7 | my_turtle.goto(points[0][0], points[0][1]) 8 | my_turtle.down() 9 | my_turtle.begin_fill() 10 | my_turtle.goto(points[1][0], points[1][1]) 11 | my_turtle.goto(points[2][0], points[2][1]) 12 | my_turtle.goto(points[0][0], points[0][1]) 13 | my_turtle.end_fill() 14 | 15 | 16 | def get_mid(p1, p2): 17 | return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2) 18 | 19 | 20 | def sierpinski(points, degree, my_turtle): 21 | colormap = [ 22 | "blue", 23 | "red", 24 | "green", 25 | "white", 26 | "yellow", 27 | "violet", 28 | "orange", 29 | ] 30 | # colormap = ["violet", "yellow", "white", "green", "red", "blue"] 31 | draw_triangle(points, colormap[degree], my_turtle) 32 | if degree > 0: 33 | sierpinski( 34 | [ 35 | points[0], 36 | get_mid(points[0], points[1]), 37 | get_mid(points[0], points[2]), 38 | ], 39 | degree - 1, 40 | my_turtle, 41 | ) 42 | sierpinski( 43 | [ 44 | points[1], 45 | get_mid(points[0], points[1]), 46 | get_mid(points[1], points[2]), 47 | ], 48 | degree - 1, 49 | my_turtle, 50 | ) 51 | sierpinski( 52 | [ 53 | points[2], 54 | get_mid(points[2], points[1]), 55 | get_mid(points[0], points[2]), 56 | ], 57 | degree - 1, 58 | my_turtle, 59 | ) 60 | 61 | 62 | def main(): 63 | my_turtle = turtle.Turtle() 64 | my_turtle.ht() 65 | my_win = turtle.Screen() 66 | # my_win.setup(600, 500) # book 67 | my_points = [[-100, -50], [0, 100], [100, -50]] 68 | # my_points = [[-290, -230], [-5, 240], [280, -230]] 69 | sierpinski(my_points, 5, my_turtle) 70 | my_win.exitonclick() 71 | 72 | 73 | main() 74 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/wordlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Solving Wordladder problem""" 3 | 4 | import importlib.util 5 | import pathlib 6 | import sys 7 | 8 | try: 9 | importlib.util.find_spec( 10 | ".".join(pathlib.Path(__file__).parts[-3]), 11 | "pythonds3", 12 | ) 13 | except ModuleNotFoundError: 14 | sys.path.append( 15 | f"{pathlib.Path(__file__).parents[1]}/" 16 | ) 17 | finally: 18 | from pythonds3.graphs import Graph 19 | 20 | 21 | def build_graph(filename): 22 | buckets = {} 23 | the_graph = Graph() 24 | with open(filename, "r", encoding="utf8") as file_in: 25 | all_words = file_in.readlines() 26 | # create buckets of words that differ by 1 letter 27 | for line in all_words: 28 | word = line.strip() 29 | for i, _ in enumerate(word): 30 | bucket = f"{word[:i]}_{word[i + 1 :]}" 31 | buckets.setdefault(bucket, set()).add(word) 32 | 33 | # connect different words in the same bucket 34 | for similar_words in buckets.values(): 35 | for word1 in similar_words: 36 | for word2 in similar_words - {word1}: 37 | the_graph.add_edge(word1, word2) 38 | return the_graph 39 | 40 | 41 | g = build_graph("Graphs/words_small") 42 | print(len(g)) 43 | 44 | from pythonds3.basic import Queue 45 | from pythonds3.graphs import Graph 46 | 47 | 48 | def bfs(start): 49 | start.distance = 0 50 | start.previous = None 51 | vert_queue = Queue() 52 | vert_queue.enqueue(start) 53 | while vert_queue.size() > 0: 54 | current = vert_queue.dequeue() 55 | for neighbor in current.get_neighbors(): 56 | if neighbor.color == "white": 57 | neighbor.color = "gray" 58 | neighbor.distance = current.distance + 1 59 | neighbor.previous = current 60 | vert_queue.enqueue(neighbor) 61 | current.color = "black" 62 | 63 | 64 | bfs(g.get_vertex("fool")) 65 | 66 | 67 | def traverse(starting_vertex): 68 | current = starting_vertex 69 | while current: 70 | print(current.key) 71 | current = current.previous 72 | 73 | 74 | traverse(g.get_vertex("sage")) 75 | -------------------------------------------------------------------------------- /Listings/1. Introduction/circuits.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Circuit classes""" 3 | 4 | 5 | class LogicGate: 6 | def __init__(self, lbl): 7 | self.label = lbl 8 | self.output = None 9 | 10 | def get_label(self): 11 | return self.label 12 | 13 | def get_output(self): 14 | self.output = self.perform_gate_logic() 15 | return self.output 16 | 17 | 18 | class BinaryGate(LogicGate): 19 | def __init__(self, lbl): 20 | super().__init__(lbl) 21 | self.pin_a = None 22 | self.pin_b = None 23 | 24 | def get_pin_a(self): 25 | if self.pin_a == None: 26 | return input( 27 | f"Enter pin A input for gate \ 28 | {self.get_label()}: " 29 | ) 30 | else: 31 | return self.pin_a.get_from().get_output() 32 | 33 | def get_pin_b(self): 34 | return int( 35 | input( 36 | f"Enter pin B input for gate \ 37 | {self.get_label()}: " 38 | ) 39 | ) 40 | 41 | def set_next_pin(self, source): 42 | if self.pin_a == None: 43 | self.pin_a = source 44 | else: 45 | if self.pin_b == None: 46 | self.pin_b = source 47 | else: 48 | raise RuntimeError("Error: NO EMPTY PINS") 49 | 50 | 51 | class UnaryGate(LogicGate): 52 | def __init__(self, lbl): 53 | LogicGate.__init__(self, lbl) 54 | super().__init__(lbl) 55 | super(UnaryGate, self).__init__(lbl) 56 | super().__init__("UnaryGate", lbl) 57 | self.pin = None 58 | 59 | def get_pin(self): 60 | return int( 61 | input( 62 | f"Enter pin input for gate \ 63 | {self.get_label()}: " 64 | ) 65 | ) 66 | 67 | 68 | class AndGate(BinaryGate): 69 | def __init__(self, lbl): 70 | super().__init__(lbl) 71 | 72 | def perform_gate_logic(self): 73 | a = self.get_pin_a() 74 | b = self.get_pin_b() 75 | if a == 1 and b == 1: 76 | return 1 77 | else: 78 | return 0 79 | 80 | 81 | class Connector: 82 | def __init__(self, fgate, tgate): 83 | self.from_gate = fgate 84 | self.to_gate = tgate 85 | 86 | tgate.set_next_pin(self) 87 | 88 | def get_from(self): 89 | return self.from_gate 90 | 91 | def get_to(self): 92 | return self.to_gate 93 | -------------------------------------------------------------------------------- /Listings/6. Trees and Tree Algorithms/priority_queue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Priority Queue""" 3 | 4 | # from pythonds3.trees import BinaryHeap 5 | 6 | # my_heap = BinaryHeap() 7 | # my_heap.insert(5) 8 | # my_heap.insert(7) 9 | # my_heap.insert(3) 10 | # my_heap.insert(11) 11 | 12 | # print(my_heap.delete()) 13 | # print(my_heap.delete()) 14 | # print(my_heap.delete()) 15 | # print(my_heap.delete()) 16 | 17 | 18 | class BinaryHeap: 19 | def __init__(self): 20 | self._heap = [] 21 | 22 | def _perc_up(self, i): 23 | while (i - 1) // 2 >= 0: 24 | parent_idx = (i - 1) // 2 25 | if self._heap[i] < self._heap[parent_idx]: 26 | self._heap[i], self._heap[parent_idx] = ( 27 | self._heap[parent_idx], 28 | self._heap[i], 29 | ) 30 | i = parent_idx 31 | 32 | def _perc_down(self, i): 33 | while 2 * i + 1 < len(self._heap): 34 | sm_child = self._get_min_child(i) 35 | if self._heap[i] > self._heap[sm_child]: 36 | self._heap[i], self._heap[sm_child] = ( 37 | self._heap[sm_child], 38 | self._heap[i], 39 | ) 40 | else: 41 | return 42 | i = sm_child 43 | 44 | def _get_min_child(self, i): 45 | if 2 * i + 2 > len(self._heap) - 1: 46 | return 2 * i + 1 47 | if self._heap[2 * i + 1] < self._heap[2 * i + 2]: 48 | return 2 * i + 1 49 | return 2 * i + 2 50 | 51 | def heapify(self, not_a_heap): 52 | self._heap = not_a_heap[:] 53 | cur_idx = len(self._heap) // 2 - 1 54 | while cur_idx >= 0: 55 | self._perc_down(cur_idx) 56 | cur_idx = cur_idx - 1 57 | 58 | def get_min(self): 59 | return self._heap[0] 60 | 61 | def insert(self, item): 62 | self._heap.append(item) 63 | self._perc_up(len(self._heap) - 1) 64 | 65 | def delete(self): 66 | self._heap[0], self._heap[-1] = ( 67 | self._heap[-1], 68 | self._heap[0], 69 | ) 70 | result = self._heap.pop() 71 | self._perc_down(0) 72 | return result 73 | 74 | def is_empty(self): 75 | return not bool(self._heap) 76 | 77 | def __len__(self): 78 | return len(self._heap) 79 | 80 | def __str__(self): 81 | return str(self._heap) 82 | 83 | 84 | a_heap = BinaryHeap() 85 | a_heap.heapify([9, 5, 6, 2, 3]) 86 | 87 | while not a_heap.is_empty(): 88 | print(a_heap.delete()) 89 | -------------------------------------------------------------------------------- /Listings/2. Algorithm Analysis/anagrams.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Anagram Detection Example""" 3 | 4 | 5 | def anagram_solution_1(s1, s2): 6 | still_ok = True 7 | if len(s1) != len(s2): 8 | still_ok = False 9 | 10 | a_list = list(s2) 11 | pos_1 = 0 12 | 13 | while pos_1 < len(s1) and still_ok: 14 | pos_2 = 0 15 | found = False 16 | while pos_2 < len(a_list) and not found: 17 | if s1[pos_1] == a_list[pos_2]: 18 | found = True 19 | else: 20 | pos_2 = pos_2 + 1 21 | 22 | if found: 23 | a_list[pos_2] = None 24 | else: 25 | still_ok = False 26 | 27 | pos_1 = pos_1 + 1 28 | 29 | return still_ok 30 | 31 | 32 | print(anagram_solution_1("apple", "pleap")) # expected: True 33 | print(anagram_solution_1("abcd", "dcba")) # expected: True 34 | print(anagram_solution_1("abcd", "dcda")) # expected: False 35 | 36 | 37 | def anagram_solution_2(s1, s2): 38 | a_list_1 = list(s1) 39 | a_list_2 = list(s2) 40 | 41 | a_list_1.sort() 42 | a_list_2.sort() 43 | 44 | pos = 0 45 | matches = True 46 | 47 | while pos < len(s1) and matches: 48 | if a_list_1[pos] == a_list_2[pos]: 49 | pos = pos + 1 50 | else: 51 | matches = False 52 | 53 | return matches 54 | 55 | 56 | print(anagram_solution_2("apple", "pleap")) # expected: True 57 | print(anagram_solution_2("abcd", "dcba")) # expected: True 58 | print(anagram_solution_2("abcd", "dcda")) # expected: False 59 | 60 | 61 | def anagram_solution_4(s1, s2): 62 | c1 = [0] * 26 63 | c2 = [0] * 26 64 | 65 | for i in range(len(s1)): 66 | pos = ord(s1[i]) - ord("a") 67 | c1[pos] = c1[pos] + 1 68 | 69 | for i in range(len(s2)): 70 | pos = ord(s2[i]) - ord("a") 71 | c2[pos] = c2[pos] + 1 72 | 73 | j = 0 74 | still_ok = True 75 | while j < 26 and still_ok: 76 | if c1[j] == c2[j]: 77 | j = j + 1 78 | else: 79 | still_ok = False 80 | 81 | return still_ok 82 | 83 | 84 | print(anagram_solution_4("apple", "pleap")) # expected: True 85 | print(anagram_solution_4("abcd", "dcba")) # expected: True 86 | print(anagram_solution_4("abcd", "dcda")) # expected: False 87 | 88 | 89 | from collections import Counter 90 | 91 | 92 | def anagram_solution_5(s1, s2): 93 | return Counter(s1) == Counter(s2) 94 | 95 | 96 | print(anagram_solution_5("apple", "pleap")) # expected: True 97 | print(anagram_solution_5("abcd", "dcba")) # expected: True 98 | print(anagram_solution_5("abcd", "dcda")) # expected: False 99 | -------------------------------------------------------------------------------- /Listings/5. Searching and Sorting/snippets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Snippets of code""" 3 | 4 | 5 | def sequential_search(a_list, item): 6 | pos = 0 7 | 8 | while pos < len(a_list): 9 | if a_list[pos] == item: 10 | return True 11 | else: 12 | pos = pos + 1 13 | 14 | return False 15 | 16 | 17 | test_list = [1, 2, 32, 8, 17, 19, 42, 13, 0] 18 | assert not sequential_search(test_list, 3) 19 | assert sequential_search(test_list, 13) 20 | 21 | 22 | def ordered_sequential_search(a_list, item): 23 | pos = 0 24 | while pos < len(a_list): 25 | if a_list[pos] == item: 26 | return True 27 | else: 28 | if a_list[pos] > item: 29 | return False 30 | else: 31 | pos = pos + 1 32 | 33 | return False 34 | 35 | 36 | test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] 37 | assert not ordered_sequential_search(test_list, 3) 38 | assert ordered_sequential_search(test_list, 13) 39 | 40 | 41 | def binary_search(a_list, item): 42 | first = 0 43 | last = len(a_list) - 1 44 | 45 | while first <= last: 46 | midpoint = (first + last) // 2 47 | if a_list[midpoint] == item: 48 | return True 49 | elif item < a_list[midpoint]: 50 | last = midpoint - 1 51 | else: 52 | first = midpoint + 1 53 | 54 | return False 55 | 56 | 57 | test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] 58 | 59 | assert not binary_search(test_list, 3) 60 | assert binary_search(test_list, 13) 61 | 62 | 63 | def binary_search_rec(a_list, item): 64 | if len(a_list) == 0: 65 | return False 66 | else: 67 | midpoint = len(a_list) // 2 68 | if a_list[midpoint] == item: 69 | return True 70 | elif item < a_list[midpoint]: 71 | return binary_search_rec( 72 | a_list[:midpoint], item 73 | ) 74 | else: 75 | return binary_search_rec( 76 | a_list[midpoint + 1 :], item 77 | ) 78 | 79 | 80 | test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] 81 | 82 | assert not binary_search_rec(test_list, 3) 83 | assert binary_search_rec(test_list, 13) 84 | 85 | 86 | def hash_str(a_string, table_size): 87 | current_sum = 0 88 | for pos in range(len(a_string)): 89 | current_sum = current_sum + ord(a_string[pos]) 90 | 91 | return current_sum % table_size 92 | 93 | 94 | def hash_str2(a_string, table_size): 95 | return sum([ord(c) for c in a_string]) % table_size 96 | 97 | 98 | assert hash_str("cat", 11) == hash_str2("cat", 11) 99 | assert hash_str("dog", 13) == hash_str2("dog", 13) 100 | assert hash_str("rabbit", 101) == hash_str2( 101 | "rabbit", 101 102 | ) 103 | 104 | -------------------------------------------------------------------------------- /Listings/5. Searching and Sorting/map.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Map ADT implementation""" 3 | 4 | 5 | class HashTable: 6 | def __init__(self): 7 | self.size = 11 8 | self.slots = [None] * self.size 9 | self.data = [None] * self.size 10 | 11 | def put(self, key, data): 12 | hash_value = self.hash_function(key, len(self.slots)) 13 | 14 | if self.slots[hash_value] is None: 15 | self.slots[hash_value] = key 16 | self.data[hash_value] = data 17 | else: 18 | if self.slots[hash_value] == key: 19 | self.data[hash_value] = data # replace 20 | else: 21 | next_slot = self.rehash(hash_value, len(self.slots)) 22 | while ( 23 | self.slots[next_slot] is not None 24 | and self.slots[next_slot] != key 25 | ): 26 | next_slot = self.rehash(next_slot, len(self.slots)) 27 | 28 | if self.slots[next_slot] is None: 29 | self.slots[next_slot] = key 30 | self.data[next_slot] = data 31 | else: 32 | self.data[next_slot] = data 33 | 34 | def hash_function(self, key, size): 35 | return key % size 36 | 37 | def rehash(self, old_hash, size): 38 | return (old_hash + 1) % size 39 | 40 | def get(self, key): 41 | start_slot = self.hash_function(key, len(self.slots)) 42 | 43 | position = start_slot 44 | while self.slots[position] is not None: 45 | if self.slots[position] == key: 46 | return self.data[position] 47 | else: 48 | position = self.rehash(position, len(self.slots)) 49 | if position == start_slot: 50 | return None 51 | 52 | def __getitem__(self, key): 53 | return self.get(key) 54 | 55 | def __setitem__(self, key, data): 56 | self.put(key, data) 57 | 58 | 59 | def main(): 60 | h = HashTable() 61 | h[54] = "cat" 62 | h[26] = "dog" 63 | h[93] = "lion" 64 | h[17] = "tiger" 65 | h[77] = "bird" 66 | h[31] = "cow" 67 | h[44] = "goat" 68 | h[55] = "pig" 69 | h[20] = "chicken" 70 | assert h.slots == [ 71 | 77, 72 | 44, 73 | 55, 74 | 20, 75 | 26, 76 | 93, 77 | 17, 78 | None, 79 | None, 80 | 31, 81 | 54, 82 | ] 83 | assert h.data == [ 84 | "bird", 85 | "goat", 86 | "pig", 87 | "chicken", 88 | "dog", 89 | "lion", 90 | "tiger", 91 | None, 92 | None, 93 | "cow", 94 | "cat", 95 | ] 96 | 97 | assert h[20] == "chicken" 98 | assert h[17] == "tiger" 99 | h[20] = "duck" 100 | assert h[20] == "duck" 101 | assert h.data == [ 102 | "bird", 103 | "goat", 104 | "pig", 105 | "duck", 106 | "dog", 107 | "lion", 108 | "tiger", 109 | None, 110 | None, 111 | "cow", 112 | "cat", 113 | ] 114 | assert h[99] is None 115 | 116 | 117 | if __name__ == "__main__": 118 | main() 119 | print("Done") 120 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/crypto.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """RSA implementation""" 3 | 4 | # def encrypt(msg): 5 | # s = "abcdefghijklmnopqrstuvwxyz" 6 | # n = "" 7 | # for i in msg: 8 | # j = (s.find(i) + 13) % 26 9 | # n = n + s[j] 10 | # return n 11 | 12 | 13 | # def decrypt(msg, k): 14 | # s = "abcdefghijklmnopqrstuvwxyz" 15 | # n = "" 16 | # for i in msg: 17 | # j = (s.find(i) + 26 - k) % 26 18 | # n = n + s[j] 19 | # return n 20 | 21 | 22 | # print(encrypt("helloworld")) 23 | # print(decrypt("uryybjbeyq", 13)) 24 | 25 | 26 | def modexp(x, n, p): 27 | if n == 0: 28 | return 1 29 | t = (x * x) % p 30 | tmp = modexp(t, n // 2, p) 31 | if n % 2 != 0: 32 | tmp = (tmp * x) % p 33 | return tmp 34 | 35 | 36 | def gcd1(a, b): 37 | if b == 0: 38 | return a 39 | elif a < b: 40 | return gcd(b, a) 41 | return gcd(a - b, b) 42 | 43 | 44 | def gcd(a, b): 45 | if b == 0: 46 | return a 47 | return gcd(b, a % b) 48 | 49 | 50 | def ext_gcd(x, y): 51 | if y == 0: 52 | return (x, 1, 0) 53 | else: 54 | (d, a, b) = ext_gcd(y, x % y) 55 | return (d, b, a - (x // y) * b) 56 | 57 | 58 | import random 59 | 60 | 61 | def str_to_chunks(msg, chunk_size): 62 | msg_bytes = bytes(msg, "utf-8") 63 | hex_str = "".join([f"{b:02x}" for b in msg_bytes]) 64 | num_chunks = len(hex_str) // chunk_size 65 | chunk_list = [] 66 | for i in range( 67 | 0, num_chunks * chunk_size + 1, chunk_size 68 | ): 69 | chunk_list.append(hex_str[i : i + chunk_size]) 70 | chunk_list = [ 71 | eval("0x" + x) for x in chunk_list if x 72 | ] 73 | return chunk_list 74 | 75 | 76 | def chunks_to_str(chunk_list, chunk_size): 77 | hex_list = [] 78 | for chunk in chunk_list: 79 | hex_str = hex(chunk)[2:] 80 | clen = len(hex_str) 81 | hex_list.append( 82 | "0" * ((chunk_size - clen) % 2) + hex_str 83 | ) 84 | 85 | hstring = "".join(hex_list) 86 | msg_array = bytearray.fromhex(hstring) 87 | return msg_array.decode("utf-8") 88 | 89 | 90 | def gen_keys(p, q): 91 | n = p * q 92 | m = (p - 1) * (q - 1) 93 | e = int(random.random() * n) 94 | while gcd(m, e) != 1: 95 | e = int(random.random() * n) 96 | d, a, b = ext_gcd(m, e) 97 | if b < 0: 98 | d = m + b 99 | else: 100 | d = b 101 | return (e, d, n) 102 | 103 | 104 | def encrypt(msg, e, n): 105 | chunk_size = n.bit_length() // 8 106 | all_chunks = str_to_chunks(msg, chunk_size) 107 | return [ 108 | modexp(msg_chunk, e, n) 109 | for msg_chunk in all_chunks 110 | ] 111 | 112 | 113 | def decrypt(cipher_chunks, d, n): 114 | chunk_size = n.bit_length() // 8 115 | plain_chunks = [ 116 | modexp(cipher_chunk, d, n) 117 | for cipher_chunk in cipher_chunks 118 | ] 119 | return chunks_to_str(plain_chunks, chunk_size) 120 | 121 | 122 | msg = "Python" 123 | e, d, n = gen_keys(5563, 8191) 124 | # print(e, d, n) # 2646697 33043453 45566533 125 | c = encrypt(msg, e, n) 126 | # print(c) # [22810070, 18852325, 34390906, 22805081] 127 | m = decrypt(c, d, n) 128 | # print(m) # [1287, 2420, 1670, 3950] 129 | assert m == msg 130 | -------------------------------------------------------------------------------- /Listings/3. Basic Data Structures/queues.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Queue Usage Example""" 3 | import random 4 | from pythonds3.basic import Queue 5 | 6 | 7 | # class Queue: 8 | # """Queue implementation as a list""" 9 | 10 | # def __init__(self): 11 | # """Create new queue""" 12 | # self._items = [] 13 | 14 | # def is_empty(self): 15 | # """Check if the queue is empty""" 16 | # return not bool(self._items) 17 | 18 | # def enqueue(self, item): 19 | # """Add an item to the queue""" 20 | # self._items.insert(0, item) 21 | 22 | # def dequeue(self): 23 | # """Remove an item from the queue""" 24 | # return self._items.pop() 25 | 26 | # def size(self): 27 | # """Get the number of items in the queue""" 28 | # return len(self._items) 29 | 30 | 31 | q = Queue() 32 | q.enqueue(4) 33 | q.enqueue("dog") 34 | q.enqueue(True) 35 | print(q.size()) 36 | 37 | 38 | def hot_potato(name_list, num): 39 | sim_queue = Queue() 40 | for name in name_list: 41 | sim_queue.enqueue(name) 42 | 43 | while sim_queue.size() > 1: 44 | for i in range(num): 45 | sim_queue.enqueue(sim_queue.dequeue()) 46 | 47 | sim_queue.dequeue() 48 | 49 | return sim_queue.dequeue() 50 | 51 | 52 | print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7)) 53 | 54 | 55 | class Printer: 56 | def __init__(self, ppm): 57 | self.page_rate = ppm 58 | self.current_task = None 59 | self.time_remaining = 0 60 | 61 | def tick(self): 62 | if self.current_task is not None: 63 | self.time_remaining = self.time_remaining - 1 64 | if self.time_remaining <= 0: 65 | self.current_task = None 66 | 67 | def busy(self): 68 | return self.current_task is not None 69 | 70 | def start_next(self, new_task): 71 | self.current_task = new_task 72 | self.time_remaining = new_task.get_pages() * 60 / self.page_rate 73 | 74 | 75 | class Task: 76 | def __init__(self, time): 77 | self.timestamp = time 78 | self.pages = random.randrange(1, 21) 79 | 80 | def get_stamp(self): 81 | return self.timestamp 82 | 83 | def get_pages(self): 84 | return self.pages 85 | 86 | def wait_time(self, current_time): 87 | return current_time - self.timestamp 88 | 89 | 90 | def simulation(num_seconds, pages_per_minute): 91 | lab_printer = Printer(pages_per_minute) 92 | print_queue = Queue() 93 | waiting_times = [] 94 | 95 | for current_second in range(num_seconds): 96 | if new_print_task(): 97 | task = Task(current_second) 98 | print_queue.enqueue(task) 99 | 100 | if (not lab_printer.busy()) and (not print_queue.is_empty()): 101 | nexttask = print_queue.dequeue() 102 | waiting_times.append(nexttask.wait_time(current_second)) 103 | lab_printer.start_next(nexttask) 104 | 105 | lab_printer.tick() 106 | 107 | average_wait = sum(waiting_times) / len(waiting_times) 108 | print( 109 | f"Average Wait {average_wait:6.2f} secs" \ 110 | + f"{print_queue.size():3d} tasks remaining." 111 | ) 112 | 113 | 114 | def new_print_task(): 115 | num = random.randrange(1, 181) 116 | return num == 180 117 | 118 | 119 | for i in range(10): 120 | simulation(3600, 5) 121 | 122 | -------------------------------------------------------------------------------- /Listings/6. Trees and Tree Algorithms/avltree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """AVL Tree""" 3 | 4 | # import os 5 | # import sys 6 | 7 | # sys.path.insert( 8 | # 0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) 9 | # ) 10 | 11 | from bst import BinarySearchTree, TreeNode 12 | 13 | 14 | class AVLTreeNode(TreeNode): 15 | def __init__( 16 | self, 17 | key, 18 | val, 19 | balance_factor, 20 | left=None, 21 | right=None, 22 | parent=None, 23 | ): 24 | TreeNode.__init__( 25 | self, key, val, left, right, parent 26 | ) 27 | self.balance_factor = balance_factor 28 | 29 | 30 | class AVLTree(BinarySearchTree): 31 | def __init__(self): 32 | BinarySearchTree.__init__(self) 33 | 34 | def _put(self, key, value, current_node): 35 | if key < current_node.key: 36 | if current_node.left_child: 37 | self._put( 38 | key, value, current_node.left_child 39 | ) 40 | else: 41 | current_node.left_child = AVLTreeNode( 42 | key, value, 0, parent=current_node 43 | ) 44 | self.update_balance(current_node.left_child) 45 | else: 46 | if current_node.right_child: 47 | self._put( 48 | key, value, current_node.right_child, 49 | ) 50 | else: 51 | current_node.right_child = AVLTreeNode( 52 | key, value, 0, parent=current_node 53 | ) 54 | self.update_balance(current_node.right_child) 55 | 56 | def update_balance(self, node): 57 | if ( 58 | node.balance_factor > 1 59 | or node.balance_factor < -1 60 | ): 61 | self.rebalance(node) 62 | return 63 | if node.parent: 64 | if node.is_left_child(): 65 | node.parent.balance_factor += 1 66 | elif node.is_right_child(): 67 | node.parent.balance_factor -= 1 68 | 69 | if node.parent.balance_factor != 0: 70 | self.update_balance(node.parent) 71 | 72 | def rotate_left(self, rotation_root): 73 | new_root = rotation_root.right_child 74 | rotation_root.right_child = new_root.left_child 75 | if new_root.left_child: 76 | new_root.left_child.parent = rotation_root 77 | new_root.parent = rotation_root.parent 78 | if rotation_root.is_root(): 79 | self.root = new_root 80 | else: 81 | if rotation_root.is_left_child(): 82 | rotation_root.parent.left_child = new_root 83 | else: 84 | rotation_root.parent.right_child = new_root 85 | new_root.left_child = rotation_root 86 | rotation_root.parent = new_root 87 | rotation_root.balance_factor = ( 88 | rotation_root.balance_factor 89 | + 1 90 | - min(new_root.balance_factor, 0) 91 | ) 92 | new_root.balance_factor = ( 93 | new_root.balance_factor 94 | + 1 95 | + max(rotation_root.balance_factor, 0) 96 | ) 97 | 98 | def rotate_right(self, rotation_root): 99 | ... 100 | 101 | def rebalance(self, node): 102 | if node.balance_factor < 0: 103 | if node.right_child.balance_factor > 0: 104 | self.rotate_right(node.right_child) 105 | self.rotate_left(node) 106 | else: 107 | self.rotate_left(node) 108 | elif node.balance_factor > 0: 109 | if node.left_child.balance_factor < 0: 110 | self.rotate_left(node.left_child) 111 | self.rotate_right(node) 112 | else: 113 | self.rotate_right(node) 114 | -------------------------------------------------------------------------------- /Listings/3. Basic Data Structures/lists.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Linked Lists Example""" 3 | # from pythonds3.basic import LinkedList 4 | 5 | 6 | class Node: 7 | """A node of a linked list""" 8 | 9 | def __init__(self, node_data): 10 | self._data = node_data 11 | self._next = None 12 | 13 | def get_data(self): 14 | """Get node data""" 15 | return self._data 16 | 17 | def set_data(self, node_data): 18 | """Set node data""" 19 | self._data = node_data 20 | 21 | data = property(get_data, set_data) 22 | 23 | def get_next(self): 24 | """Get next node""" 25 | return self._next 26 | 27 | def set_next(self, node_next): 28 | """Set next node""" 29 | self._next = node_next 30 | 31 | next = property(get_next, set_next) 32 | 33 | def __str__(self): 34 | """String""" 35 | return str(self._data) 36 | 37 | 38 | class UnorderedList: 39 | def __init__(self): 40 | self.head = None 41 | 42 | def is_empty(self): 43 | return self.head == None 44 | 45 | def add(self, item): 46 | temp = Node(item) 47 | temp.set_next(self.head) 48 | self.head = temp 49 | 50 | def size(self): 51 | current = self.head 52 | count = 0 53 | while current is not None: 54 | count = count + 1 55 | current = current.next 56 | 57 | return count 58 | 59 | def search(self, item): 60 | current = self.head 61 | while current is not None: 62 | if current.data == item: 63 | return True 64 | current = current.next 65 | 66 | return False 67 | 68 | def remove(self, item): 69 | current = self.head 70 | previous = None 71 | 72 | while current is not None: 73 | if current.data == item: 74 | break 75 | previous = current 76 | current = current.next 77 | 78 | if current is None: 79 | raise ValueError("{} is not in the list".format(item)) 80 | if previous is None: 81 | self.head = current.next 82 | else: 83 | previous.next = current.next 84 | 85 | 86 | my_list = UnorderedList() 87 | my_list.add(31) 88 | my_list.add(77) 89 | my_list.add(17) 90 | my_list.add(93) 91 | my_list.add(26) 92 | my_list.add(54) 93 | 94 | print(my_list.size()) 95 | print(my_list.search(93)) 96 | print(my_list.search(100)) 97 | 98 | my_list.add(100) 99 | print(my_list.search(100)) 100 | print(my_list.size()) 101 | 102 | my_list.remove(54) 103 | print(my_list.size()) 104 | my_list.remove(93) 105 | print(my_list.size()) 106 | my_list.remove(31) 107 | print(my_list.size()) 108 | print(my_list.search(93)) 109 | 110 | try: 111 | my_list.remove(27) 112 | except ValueError as ve: 113 | print(ve) 114 | 115 | 116 | class OrderedList: 117 | """Ordered linked list implementation""" 118 | def __init__(self): 119 | self.head = None 120 | 121 | def search(self, item): 122 | """Search for a node with a specific value""" 123 | current = self.head 124 | while current is not None: 125 | if current.data == item: 126 | return True 127 | if current.data > item: 128 | return False 129 | current = current.next 130 | 131 | return False 132 | 133 | def add(self, item): 134 | """Add a new node""" 135 | current = self.head 136 | previous = None 137 | temp = Node(item) 138 | 139 | while current is not None and current.data < item: 140 | previous = current 141 | current = current.next 142 | 143 | if previous is None: 144 | temp.next = self.head 145 | self.head = temp 146 | else: 147 | temp.next = current 148 | previous.next = temp 149 | 150 | def is_empty(self): 151 | """Is the list empty""" 152 | return self.head == None 153 | 154 | def size(self): 155 | """Size of the list""" 156 | current = self.head 157 | count = 0 158 | while current is not None: 159 | count = count + 1 160 | current = current.next 161 | 162 | return count 163 | 164 | 165 | print("Ordered list") 166 | my_list = OrderedList() 167 | my_list.add(31) 168 | my_list.add(77) 169 | my_list.add(17) 170 | my_list.add(93) 171 | my_list.add(26) 172 | my_list.add(54) 173 | 174 | print(my_list.size()) 175 | print(my_list.search(93)) 176 | print(my_list.search(100)) 177 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/skiplist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Skip list implementation""" 3 | 4 | 5 | from random import randrange 6 | 7 | import importlib.util 8 | import pathlib 9 | import sys 10 | 11 | try: 12 | importlib.util.find_spec( 13 | ".".join(pathlib.Path(__file__).parts[-3]), 14 | "pythonds3", 15 | ) 16 | except ModuleNotFoundError: 17 | sys.path.append( 18 | f"{pathlib.Path(__file__).parents[1]}/" 19 | ) 20 | finally: 21 | from pythonds3.basic import Stack 22 | 23 | 24 | class HeaderNode: 25 | def __init__(self): 26 | self._next = None 27 | self._down = None 28 | 29 | @property 30 | def next(self): 31 | return self._next 32 | 33 | @next.setter 34 | def next(self, value): 35 | self._next = value 36 | 37 | @property 38 | def down(self): 39 | return self._down 40 | 41 | @down.setter 42 | def down(self, value): 43 | self._down = value 44 | 45 | 46 | class DataNode: 47 | def __init__(self, key, value): 48 | self._key = key 49 | self._data = value 50 | self._next = None 51 | self._down = None 52 | 53 | @property 54 | def key(self): 55 | return self._key 56 | 57 | @property 58 | def data(self): 59 | return self._data 60 | 61 | @data.setter 62 | def data(self, value): 63 | self._data = value 64 | 65 | @property 66 | def next(self): 67 | return self._next 68 | 69 | @next.setter 70 | def next(self, value): 71 | self._next = value 72 | 73 | @property 74 | def down(self): 75 | return self._down 76 | 77 | @down.setter 78 | def down(self, value): 79 | self._down = value 80 | 81 | 82 | class SkipList: 83 | def __init__(self): 84 | self._head = None 85 | 86 | def search(self, key): 87 | current = self._head 88 | while current: 89 | if current.next is None: 90 | current = current.down 91 | else: 92 | if current.next.key == key: 93 | return current.next.data # found 94 | if key < current.next.key: 95 | current = current.down 96 | else: 97 | current = current.next 98 | return None 99 | 100 | def insert(self, key, value): 101 | if self._head is None: 102 | self._head = HeaderNode() 103 | temp = DataNode(key, value) 104 | self._head.next = temp 105 | top = temp 106 | while randrange(2) == 1: 107 | newhead = HeaderNode() 108 | temp = DataNode(key, value) 109 | temp.down = top 110 | newhead.next = temp 111 | newhead.down = self._head 112 | self._head = newhead 113 | top = temp 114 | else: 115 | tower = Stack() 116 | current = self._head 117 | while current: 118 | if current.next is None: 119 | tower.push(current) 120 | current = current.down 121 | else: 122 | if current.next.key > key: 123 | tower.push(current) 124 | current = current.down 125 | else: 126 | current = current.next 127 | 128 | lowest_level = tower.pop() 129 | temp = DataNode(key, value) 130 | temp.next = lowest_level.next 131 | lowest_level.next = temp 132 | top = temp 133 | while randrange(2) == 1: 134 | if tower.is_empty(): 135 | newhead = HeaderNode() 136 | temp = DataNode(key, value) 137 | temp.down = top 138 | newhead.next = temp 139 | newhead.down = self._head 140 | self._head = newhead 141 | top = temp 142 | else: 143 | next_level = tower.pop() 144 | temp = DataNode(key, value) 145 | temp.down = top 146 | temp.next = next_level.next 147 | next_level.next = temp 148 | top = temp 149 | 150 | 151 | class Map: 152 | def __init__(self): 153 | self.collection = SkipList() 154 | 155 | def put(self, key, value): 156 | self.collection.insert(key, value) 157 | 158 | def get(self, key): 159 | return self.collection.search(key) 160 | 161 | 162 | hn = HeaderNode() 163 | print(hn) 164 | print(hn.next) 165 | print(hn.down) 166 | hn.next = 1 167 | hn.down = 2 168 | print(hn.next) 169 | print(hn.down) 170 | 171 | s = SkipList() 172 | s.insert(10, "a") 173 | s.insert(50, "e") 174 | s.insert(30, "c") 175 | s.insert(20, "b") 176 | print(s.search(10)) 177 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/knight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Solving Knight's Tour problem""" 3 | import importlib.util 4 | import pathlib 5 | import sys 6 | 7 | try: 8 | importlib.util.find_spec( 9 | ".".join(pathlib.Path(__file__).parts[-3]), 10 | "pythonds3", 11 | ) 12 | except ModuleNotFoundError: 13 | sys.path.append( 14 | f"{pathlib.Path(__file__).parents[1]}/" 15 | ) 16 | finally: 17 | from pythonds3.graphs import Graph 18 | 19 | 20 | def knight_graph(board_size): 21 | kt_graph = Graph() 22 | for row in range(board_size): 23 | for col in range(board_size): 24 | node_id = row * board_size + col 25 | new_positions = gen_legal_moves( 26 | row, col, board_size 27 | ) 28 | for row2, col2 in new_positions: 29 | other_node_id = row2 * board_size + col2 30 | kt_graph.add_edge(node_id, other_node_id) 31 | return kt_graph 32 | 33 | 34 | def pos_to_node_id(row, col, board_size): 35 | return row * board_size + col 36 | 37 | 38 | def gen_legal_moves(row, col, board_size): 39 | new_moves = [] 40 | move_offsets = [ 41 | (-1, -2), # left-down-down 42 | (-1, 2), # left-up-up 43 | (-2, -1), # left-left-down 44 | (-2, 1), # left-left-up 45 | (1, -2), # right-down-down 46 | (1, 2), # right-up-up 47 | (2, -1), # right-right-down 48 | (2, 1), # right-right-up 49 | ] 50 | for r_off, c_off in move_offsets: 51 | if ( 52 | 0 <= row + r_off < board_size 53 | and 0 <= col + c_off < board_size 54 | ): 55 | new_moves.append((row + r_off, col + c_off)) 56 | return new_moves 57 | 58 | 59 | def legal_coord(row, col, board_size): 60 | return 0 <= row < board_size and 0 <= col < board_size 61 | 62 | 63 | def knight_tour(n, path, u, limit): 64 | u.color = "gray" 65 | path.append(u) 66 | if n < limit: 67 | neighbors = sorted(list(u.get_neighbors())) 68 | i = 0 69 | done = False 70 | while i < len(neighbors) and not done: 71 | if neighbors[i].color == "white": 72 | done = knight_tour( 73 | n + 1, path, neighbors[i], limit 74 | ) 75 | i = i + 1 76 | if not done: # prepare to backtrack 77 | path.pop() 78 | u.color = "white" 79 | else: 80 | done = True 81 | return done 82 | 83 | 84 | def order_by_avail(n): 85 | res_list = [] 86 | for v in n.get_neighbors(): 87 | if v.color == "white": 88 | c = 0 89 | for w in v.get_neighbors(): 90 | if w.color == "white": 91 | c = c + 1 92 | res_list.append((c, v)) 93 | res_list.sort(key=lambda x: x[0]) 94 | return [y[1] for y in res_list] 95 | 96 | 97 | class DFSGraph(Graph): 98 | def __init__(self): 99 | super().__init__() 100 | self.time = 0 101 | 102 | def dfs(self): 103 | for vertex in self: 104 | vertex.color = "white" 105 | vertex.previous = -1 106 | for vertex in self: 107 | if vertex.color == "white": 108 | self.dfs_visit(vertex) 109 | 110 | def dfs_visit(self, start_vertex): 111 | start_vertex.color = "gray" 112 | self.time = self.time + 1 113 | start_vertex.discovery_time = self.time 114 | for next_vertex in start_vertex.get_neighbors(): 115 | if next_vertex.color == "white": 116 | next_vertex.previous = start_vertex 117 | self.dfs_visit(next_vertex) 118 | start_vertex.color = "black" 119 | self.time = self.time + 1 120 | start_vertex.closing_time = self.time 121 | 122 | 123 | # 124 | # drawKnight 125 | # 126 | # Created by Brad Miller on 2005-03-17. 127 | # Copyright (c) 2005 Luther College. All rights reserved. 128 | # 129 | 130 | import sys 131 | import os 132 | from graphics import * 133 | 134 | def main(): 135 | 136 | tDat = file('tour.dat') 137 | win = GraphWin('tour',500,500) 138 | win.setCoords(0,0,8,8) 139 | rList = [] 140 | for i in range(8): 141 | for j in range(8): 142 | rList.append(Rectangle(Point(i,j),Point(i+1,j+1))) 143 | 144 | for i in rList: 145 | i.draw(win) 146 | stepList = tDat.read().split() 147 | print(stepList) 148 | start = int(stepList[0]) 149 | startSquare = rList[start] 150 | i = 1 151 | while i < len(stepList): 152 | endSquare = rList[int(stepList[i])] 153 | l = Line(startSquare.getCenter(),endSquare.getCenter()) 154 | l.draw(win) 155 | t = Text(endSquare.getCenter(),str(i)) 156 | t.draw(win) 157 | startSquare = endSquare 158 | i = i + 1 159 | 160 | 161 | def NodeToPos(id): 162 | return ((id/8, id%8)) 163 | 164 | 165 | if __name__ == '__main__': 166 | main() 167 | 168 | -------------------------------------------------------------------------------- /Listings/3. Basic Data Structures/stacks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Anagram Detection Example""" 3 | from pythonds3.basic import Stack 4 | 5 | 6 | def rev_string(my_str): 7 | s = Stack() 8 | for c in my_str: 9 | s.push(c) 10 | result = [] 11 | while not s.is_empty(): 12 | result.append(s.pop()) 13 | 14 | return "".join(result) 15 | 16 | 17 | assert rev_string("apple") == "elppa" 18 | assert rev_string("x") == "x" 19 | assert rev_string("1234567890") == "0987654321" 20 | 21 | 22 | def par_checker(symbol_string): 23 | s = Stack() 24 | for symbol in symbol_string: 25 | if symbol == "(": 26 | s.push(symbol) 27 | else: 28 | if s.is_empty(): 29 | return False 30 | else: 31 | s.pop() 32 | 33 | return s.is_empty() 34 | 35 | 36 | assert par_checker("((()))") == True 37 | assert par_checker("((()()))") == True 38 | assert par_checker("(()") == False 39 | assert par_checker(")(") == False 40 | 41 | 42 | def balance_checker(symbol_string): 43 | s = Stack() 44 | for symbol in symbol_string: 45 | if symbol in "([{": 46 | s.push(symbol) 47 | else: 48 | if s.is_empty(): 49 | return False 50 | else: 51 | if not matches(s.pop(), symbol): 52 | return False 53 | 54 | return s.is_empty() 55 | 56 | 57 | def matches(sym_left, sym_right): 58 | all_lefts = "([{" 59 | all_rights = ")]}" 60 | return all_lefts.index(sym_left) == all_rights.index(sym_right) 61 | 62 | 63 | assert balance_checker("{({([][])}())}") == True 64 | assert balance_checker("[{()]") == False 65 | 66 | 67 | def divide_by_2(decimal_num): 68 | rem_stack = Stack() 69 | 70 | while decimal_num > 0: 71 | rem = decimal_num % 2 72 | rem_stack.push(rem) 73 | decimal_num = decimal_num // 2 74 | 75 | bin_string = "" 76 | while not rem_stack.is_empty(): 77 | bin_string = bin_string + str(rem_stack.pop()) 78 | 79 | return bin_string 80 | 81 | 82 | assert divide_by_2(42) == "101010" 83 | assert divide_by_2(31) == "11111" 84 | 85 | 86 | def base_converter(decimal_num, base): 87 | digits = "0123456789ABCDEF" 88 | rem_stack = Stack() 89 | 90 | while decimal_num > 0: 91 | rem = decimal_num % base 92 | rem_stack.push(rem) 93 | decimal_num = decimal_num // base 94 | 95 | new_string = "" 96 | while not rem_stack.is_empty(): 97 | new_string = new_string + digits[rem_stack.pop()] 98 | 99 | return new_string 100 | 101 | 102 | assert base_converter(25, 2) == "11001" 103 | assert base_converter(25, 16) == "19" 104 | 105 | 106 | def infix_to_postfix(infix_expr): 107 | prec = {} 108 | prec["*"] = 3 109 | prec["/"] = 3 110 | prec["+"] = 2 111 | prec["-"] = 2 112 | prec["("] = 1 113 | op_stack = Stack() 114 | postfix_list = [] 115 | token_list = infix_expr.split() 116 | 117 | for token in token_list: 118 | if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": 119 | postfix_list.append(token) 120 | elif token == "(": 121 | op_stack.push(token) 122 | elif token == ")": 123 | top_token = op_stack.pop() 124 | while top_token != "(": 125 | postfix_list.append(top_token) 126 | top_token = op_stack.pop() 127 | else: 128 | while (not op_stack.is_empty()) and ( 129 | prec[op_stack.peek()] >= prec[token] 130 | ): 131 | postfix_list.append(op_stack.pop()) 132 | op_stack.push(token) 133 | 134 | while not op_stack.is_empty(): 135 | postfix_list.append(op_stack.pop()) 136 | 137 | return " ".join(postfix_list) 138 | 139 | 140 | assert infix_to_postfix("A * B + C * D") == "A B * C D * +" 141 | assert ( 142 | infix_to_postfix("( A + B ) * C - ( D - E ) * ( F + G )") 143 | == "A B + C * D E - F G + * -" 144 | ) 145 | assert infix_to_postfix("( A + B ) * ( C + D )") == "A B + C D + *" 146 | assert infix_to_postfix("( A + B ) * C") == "A B + C *" 147 | assert infix_to_postfix("A + B * C") == "A B C * +" 148 | 149 | 150 | def postfix_eval(postfix_expr): 151 | operand_stack = Stack() 152 | token_list = postfix_expr.split() 153 | 154 | for token in token_list: 155 | if token in "0123456789": 156 | operand_stack.push(int(token)) 157 | else: 158 | operand2 = operand_stack.pop() 159 | operand1 = operand_stack.pop() 160 | result = do_math(token, operand1, operand2) 161 | operand_stack.push(result) 162 | return operand_stack.pop() 163 | 164 | 165 | def do_math(op, op1, op2): 166 | if op == "*": 167 | return op1 * op2 168 | elif op == "/": 169 | return op1 / op2 170 | elif op == "+": 171 | return op1 + op2 172 | else: 173 | return op1 - op2 174 | 175 | 176 | assert postfix_eval("7 8 + 3 2 + /") == 3 177 | 178 | -------------------------------------------------------------------------------- /Listings/5. Searching and Sorting/sorting.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Sorting algorithms""" 3 | 4 | 5 | def bubble_sort(a_list): 6 | for i in range(len(a_list) - 1, 0, -1): 7 | for j in range(i): 8 | if a_list[j] > a_list[j + 1]: 9 | temp = a_list[j] 10 | a_list[j] = a_list[j + 1] 11 | a_list[j + 1] = temp 12 | 13 | 14 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 15 | bubble_sort(a_list) 16 | assert a_list == sorted(a_list) 17 | 18 | 19 | def bubble_sort_short(a_list): 20 | for i in range(len(a_list) - 1, 0, -1): 21 | exchanges = False 22 | for j in range(i): 23 | if a_list[j] > a_list[j + 1]: 24 | exchanges = True 25 | a_list[j], a_list[j + 1] = a_list[j + 1], a_list[j] 26 | if not exchanges: 27 | break 28 | 29 | 30 | a_list = [20, 30, 40, 90, 50, 60, 70, 80, 100, 110] 31 | bubble_sort_short(a_list) 32 | assert a_list == sorted(a_list) 33 | 34 | 35 | def selection_sort(a_list): 36 | for i, item in enumerate(a_list): 37 | min_idx = len(a_list) - 1 38 | for j in range(i, len(a_list)): 39 | if a_list[j] < a_list[min_idx]: 40 | min_idx = j 41 | if min_idx != i: 42 | a_list[min_idx], a_list[i] = a_list[i], a_list[min_idx] 43 | 44 | 45 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 46 | selection_sort(a_list) 47 | assert a_list == sorted(a_list) 48 | 49 | 50 | def insertion_sort(a_list): 51 | for i in range(1, len(a_list)): 52 | cur_val = a_list[i] 53 | cur_pos = i 54 | 55 | while cur_pos > 0 and a_list[cur_pos - 1] > cur_val: 56 | a_list[cur_pos] = a_list[cur_pos - 1] 57 | cur_pos = cur_pos - 1 58 | a_list[cur_pos] = cur_val 59 | 60 | 61 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 62 | insertion_sort(a_list) 63 | assert a_list == sorted(a_list) 64 | 65 | 66 | def shell_sort(a_list): 67 | sublist_count = len(a_list) // 2 68 | while sublist_count > 0: 69 | for pos_start in range(sublist_count): 70 | gap_insertion_sort(a_list, pos_start, sublist_count) 71 | print("After increments of size", sublist_count, "the list is", a_list) 72 | sublist_count = sublist_count // 2 73 | 74 | 75 | def gap_insertion_sort(a_list, start, gap): 76 | for i in range(start + gap, len(a_list), gap): 77 | cur_val = a_list[i] 78 | cur_pos = i 79 | while cur_pos >= gap and a_list[cur_pos - gap] > cur_val: 80 | a_list[cur_pos] = a_list[cur_pos - gap] 81 | cur_pos = cur_pos - gap 82 | a_list[cur_pos] = cur_val 83 | 84 | 85 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 86 | shell_sort(a_list) 87 | assert a_list == sorted(a_list) 88 | 89 | 90 | def merge_sort(a_list): 91 | print("Splitting", a_list) 92 | if len(a_list) > 1: 93 | mid = len(a_list) // 2 94 | left_half = a_list[:mid] 95 | right_half = a_list[mid:] 96 | 97 | merge_sort(left_half) 98 | merge_sort(right_half) 99 | 100 | i, j, k = 0, 0, 0 101 | while i < len(left_half) and j < len(right_half): 102 | if left_half[i] <= right_half[j]: 103 | a_list[k] = left_half[i] 104 | i = i + 1 105 | else: 106 | a_list[k] = right_half[j] 107 | j = j + 1 108 | k = k + 1 109 | 110 | while i < len(left_half): 111 | a_list[k] = left_half[i] 112 | i = i + 1 113 | k = k + 1 114 | 115 | while j < len(right_half): 116 | a_list[k] = right_half[j] 117 | j = j + 1 118 | k = k + 1 119 | print("Merging", a_list) 120 | 121 | 122 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 123 | merge_sort(a_list) 124 | assert a_list == sorted(a_list) 125 | 126 | 127 | def quick_sort(a_list): 128 | quick_sort_helper(a_list, 0, len(a_list) - 1) 129 | 130 | 131 | def quick_sort_helper(a_list, first, last): 132 | if first < last: 133 | split = partition(a_list, first, last) 134 | quick_sort_helper(a_list, first, split - 1) 135 | quick_sort_helper(a_list, split + 1, last) 136 | 137 | 138 | def partition(a_list, first, last): 139 | pivot_val = a_list[first] 140 | left_mark = first + 1 141 | right_mark = last 142 | done = False 143 | 144 | while not done: 145 | while left_mark <= right_mark and a_list[left_mark] <= pivot_val: 146 | left_mark = left_mark + 1 147 | while left_mark <= right_mark and a_list[right_mark] >= pivot_val: 148 | right_mark = right_mark - 1 149 | if right_mark < left_mark: 150 | done = True 151 | else: 152 | a_list[left_mark], a_list[right_mark] = ( 153 | a_list[right_mark], 154 | a_list[left_mark], 155 | ) 156 | a_list[first], a_list[right_mark] = a_list[right_mark], a_list[first] 157 | 158 | return right_mark 159 | 160 | 161 | a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 162 | quick_sort(a_list) 163 | assert a_list == sorted(a_list) 164 | print("done") 165 | -------------------------------------------------------------------------------- /Listings/4. Recursion/maze.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Maze solver""" 3 | 4 | 5 | import turtle 6 | 7 | PART_OF_PATH = "O" 8 | TRIED = "." 9 | OBSTACLE = "+" 10 | DEAD_END = "-" 11 | 12 | 13 | class Maze: 14 | def __init__(self, maze_filename): 15 | rows_in_maze = 0 16 | columns_in_maze = 0 17 | self.maze_list = [] 18 | maze_file = open(maze_filename, "r") 19 | rows_in_maze = 0 20 | for line in maze_file: 21 | row_list = [] 22 | col = 0 23 | for ch in line[:-1]: 24 | row_list.append(ch) 25 | if ch == "S": 26 | self.start_row = rows_in_maze 27 | self.start_col = col 28 | col = col + 1 29 | rows_in_maze = rows_in_maze + 1 30 | self.maze_list.append(row_list) 31 | columns_in_maze = len(row_list) 32 | 33 | self.rows_in_maze = rows_in_maze 34 | self.columns_in_maze = columns_in_maze 35 | self.x_translate = -columns_in_maze / 2 36 | self.y_translate = rows_in_maze / 2 37 | self.t = turtle.Turtle() 38 | self.t.shape("turtle") 39 | self.wn = turtle.Screen() 40 | self.wn.setworldcoordinates( 41 | -(columns_in_maze - 1) / 2 - 0.5, 42 | -(rows_in_maze - 1) / 2 - 0.5, 43 | (columns_in_maze - 1) / 2 + 0.5, 44 | (rows_in_maze - 1) / 2 + 0.5, 45 | ) 46 | 47 | def draw_maze(self): 48 | self.t.speed(10) 49 | self.wn.tracer(0) 50 | for y in range(self.rows_in_maze): 51 | for x in range(self.columns_in_maze): 52 | if self.maze_list[y][x] == OBSTACLE: 53 | self.draw_centered_box( 54 | x + self.x_translate, -y + self.y_translate, "orange", 55 | ) 56 | self.t.color("black") 57 | self.t.fillcolor("blue") 58 | self.wn.update() 59 | self.wn.tracer(1) 60 | 61 | def draw_centered_box(self, x, y, color): 62 | self.t.up() 63 | self.t.goto(x - 0.5, y - 0.5) 64 | self.t.color(color) 65 | self.t.fillcolor(color) 66 | self.t.setheading(90) 67 | self.t.down() 68 | self.t.begin_fill() 69 | for i in range(4): 70 | self.t.forward(1) 71 | self.t.right(90) 72 | self.t.end_fill() 73 | 74 | def move_turtle(self, x, y): 75 | self.t.up() 76 | self.t.setheading( 77 | self.t.towards(x + self.x_translate, -y + self.y_translate,) 78 | ) 79 | self.t.goto(x + self.x_translate, -y + self.y_translate) 80 | 81 | def drop_bread_crumb(self, color): 82 | self.t.dot(10, color) 83 | 84 | def update_position(self, row, col, val=None): 85 | if val: 86 | self.maze_list[row][col] = val 87 | self.move_turtle(col, row) 88 | 89 | if val == PART_OF_PATH: 90 | color = "green" 91 | elif val == OBSTACLE: 92 | color = "red" 93 | elif val == TRIED: 94 | color = "black" 95 | elif val == DEAD_END: 96 | color = "red" 97 | else: 98 | color = None 99 | 100 | if color: 101 | self.drop_bread_crumb(color) 102 | 103 | def is_exit(self, row, col): 104 | return ( 105 | row == 0 106 | or row == self.rows_in_maze - 1 107 | or col == 0 108 | or col == self.columns_in_maze - 1 109 | ) 110 | 111 | def __getitem__(self, idx): 112 | return self.maze_list[idx] 113 | 114 | 115 | def search_from(maze, start_row, start_column): 116 | """Try each of four directions from this point 117 | until we find a way out.""" 118 | # Base Case return values: 119 | maze.update_position(start_row, start_column) 120 | # 1. We have run into an obstacle 121 | if maze[start_row][start_column] == OBSTACLE: 122 | return False 123 | # 2. We have found a square 124 | # that has already been explored 125 | if ( 126 | maze[start_row][start_column] == TRIED 127 | or maze[start_row][start_column] == DEAD_END 128 | ): 129 | return False 130 | # 3. We have found an outside edge 131 | # not occupied by an obstacle 132 | if maze.is_exit(start_row, start_column): 133 | maze.update_position(start_row, start_column, PART_OF_PATH) 134 | return True 135 | maze.update_position(start_row, start_column, TRIED) 136 | # Otherwise, use logical short circuiting 137 | # to try each direction in turn (if needed) 138 | found = ( 139 | search_from(maze, start_row - 1, start_column) 140 | or search_from(maze, start_row + 1, start_column) 141 | or search_from(maze, start_row, start_column - 1) 142 | or search_from(maze, start_row, start_column + 1) 143 | ) 144 | if found: 145 | maze.update_position(start_row, start_column, PART_OF_PATH) 146 | else: 147 | maze.update_position(start_row, start_column, DEAD_END) 148 | return found 149 | 150 | 151 | my_maze = Maze("src/Recursion/maze.txt") 152 | my_maze.draw_maze() 153 | my_maze.update_position(my_maze.start_row, my_maze.start_col) 154 | search_from(my_maze, my_maze.start_row, my_maze.start_col) 155 | # my_maze.wn.getcanvas().postscript(file=f"maze.ps") 156 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/python,macos,visualstudiocode 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,macos,visualstudiocode 3 | 4 | ### macOS ### 5 | # General 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # Icon must end with two \r 11 | Icon 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | .com.apple.timemachine.donotpresent 24 | 25 | # Directories potentially created on remote AFP share 26 | .AppleDB 27 | .AppleDesktop 28 | Network Trash Folder 29 | Temporary Items 30 | .apdisk 31 | 32 | ### macOS Patch ### 33 | # iCloud generated files 34 | *.icloud 35 | 36 | ### Python ### 37 | # Byte-compiled / optimized / DLL files 38 | __pycache__/ 39 | *.py[cod] 40 | *$py.class 41 | 42 | # C extensions 43 | *.so 44 | 45 | # Distribution / packaging 46 | .Python 47 | build/ 48 | develop-eggs/ 49 | dist/ 50 | downloads/ 51 | eggs/ 52 | .eggs/ 53 | lib/ 54 | lib64/ 55 | parts/ 56 | sdist/ 57 | var/ 58 | wheels/ 59 | share/python-wheels/ 60 | *.egg-info/ 61 | .installed.cfg 62 | *.egg 63 | MANIFEST 64 | 65 | # PyInstaller 66 | # Usually these files are written by a python script from a template 67 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 68 | *.manifest 69 | *.spec 70 | 71 | # Installer logs 72 | pip-log.txt 73 | pip-delete-this-directory.txt 74 | 75 | # Unit test / coverage reports 76 | htmlcov/ 77 | .tox/ 78 | .nox/ 79 | .coverage 80 | .coverage.* 81 | .cache 82 | nosetests.xml 83 | coverage.xml 84 | *.cover 85 | *.py,cover 86 | .hypothesis/ 87 | .pytest_cache/ 88 | cover/ 89 | 90 | # Translations 91 | *.mo 92 | *.pot 93 | 94 | # Django stuff: 95 | *.log 96 | local_settings.py 97 | db.sqlite3 98 | db.sqlite3-journal 99 | 100 | # Flask stuff: 101 | instance/ 102 | .webassets-cache 103 | 104 | # Scrapy stuff: 105 | .scrapy 106 | 107 | # Sphinx documentation 108 | docs/_build/ 109 | 110 | # PyBuilder 111 | .pybuilder/ 112 | target/ 113 | 114 | # Jupyter Notebook 115 | .ipynb_checkpoints 116 | 117 | # IPython 118 | profile_default/ 119 | ipython_config.py 120 | 121 | # pyenv 122 | # For a library or package, you might want to ignore these files since the code is 123 | # intended to run in multiple environments; otherwise, check them in: 124 | # .python-version 125 | 126 | # pipenv 127 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 128 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 129 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 130 | # install all needed dependencies. 131 | #Pipfile.lock 132 | 133 | # poetry 134 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 135 | # This is especially recommended for binary packages to ensure reproducibility, and is more 136 | # commonly ignored for libraries. 137 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 138 | #poetry.lock 139 | 140 | # pdm 141 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 142 | #pdm.lock 143 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 144 | # in version control. 145 | # https://pdm.fming.dev/#use-with-ide 146 | .pdm.toml 147 | 148 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 149 | __pypackages__/ 150 | 151 | # Celery stuff 152 | celerybeat-schedule 153 | celerybeat.pid 154 | 155 | # SageMath parsed files 156 | *.sage.py 157 | 158 | # Environments 159 | .env 160 | .venv 161 | env/ 162 | venv/ 163 | ENV/ 164 | env.bak/ 165 | venv.bak/ 166 | 167 | # Spyder project settings 168 | .spyderproject 169 | .spyproject 170 | 171 | # Rope project settings 172 | .ropeproject 173 | 174 | # mkdocs documentation 175 | /site 176 | 177 | # mypy 178 | .mypy_cache/ 179 | .dmypy.json 180 | dmypy.json 181 | 182 | # Pyre type checker 183 | .pyre/ 184 | 185 | # pytype static type analyzer 186 | .pytype/ 187 | 188 | # Cython debug symbols 189 | cython_debug/ 190 | 191 | # PyCharm 192 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 193 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 194 | # and can be added to the global gitignore or merged into this file. For a more nuclear 195 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 196 | #.idea/ 197 | 198 | ### Python Patch ### 199 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 200 | poetry.toml 201 | 202 | # ruff 203 | .ruff_cache/ 204 | 205 | # LSP config files 206 | pyrightconfig.json 207 | 208 | ### VisualStudioCode ### 209 | .vscode/* 210 | !.vscode/settings.json 211 | !.vscode/tasks.json 212 | !.vscode/launch.json 213 | !.vscode/extensions.json 214 | !.vscode/*.code-snippets 215 | 216 | # Local History for Visual Studio Code 217 | .history/ 218 | 219 | # Built Visual Studio Code Extensions 220 | *.vsix 221 | 222 | ### VisualStudioCode Patch ### 223 | # Ignore all local history of files 224 | .history 225 | .ionide 226 | 227 | # End of https://www.toptal.com/developers/gitignore/api/python,macos,visualstudiocode 228 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/octreeq.py: -------------------------------------------------------------------------------- 1 | # 2 | # octTreeQuant.py 3 | # 4 | # Created by Brad Miller on 2005-07-14. 5 | # Copyright (c) 2005 Luther College. All rights reserved. 6 | # 7 | 8 | import sys 9 | import os 10 | import Image 11 | 12 | class OctTree: 13 | def __init__(self): 14 | self.root = None 15 | self.maxLevel = 5 16 | self.numLeaves = 0 17 | self.leafList = [] 18 | 19 | def insert(self,r,g,b): 20 | if not self.root: 21 | self.root = self.otNode(outer=self) 22 | self.root.insert(r,g,b,0,self) 23 | 24 | def find(self,r,g,b): 25 | if self.root: 26 | return self.root.find(r,g,b,0) 27 | 28 | def findMinCube(self): 29 | minCount = sys.maxsize 30 | maxLev = 0 31 | minCube = None 32 | for i in self.leafList: 33 | if i.count <= minCount and i.level >= maxLev: 34 | minCube = i 35 | minCount = i.count 36 | maxLev = i.level 37 | return minCube 38 | 39 | def reduce(self,maxCubes): 40 | while len(self.leafList) > maxCubes: 41 | smallest = self.findMinCube() 42 | print("Smallest cube is: ", smallest.count, smallest.red, smallest.green, smallest.blue) 43 | smallest.parent.merge() 44 | self.leafList.append(smallest.parent) 45 | self.numLeaves = self.numLeaves + 1 46 | 47 | class otNode: 48 | def __init__(self,parent=None,level=0,outer=None): 49 | self.red = 0 50 | self.green = 0 51 | self.blue = 0 52 | self.count = 0 53 | self.parent = parent 54 | self.level = level 55 | self.oTree = outer 56 | self.children = [None]*8 57 | 58 | 59 | def insert(self,r,g,b,level,outer): 60 | if level < self.oTree.maxLevel: 61 | idx = self.computeIndex(r,g,b,level) 62 | if self.children[idx] == None: 63 | self.children[idx] = outer.otNode(parent=self,level=level+1,outer=outer) 64 | self.children[idx].insert(r,g,b,level+1,outer) 65 | else: 66 | if self.count == 0: 67 | self.oTree.numLeaves = self.oTree.numLeaves + 1 68 | self.oTree.leafList.append(self) 69 | self.red += r 70 | self.green += g 71 | self.blue += b 72 | self.count = self.count + 1 73 | 74 | def computeIndex(self,r,g,b,l): 75 | shift = 8 - l 76 | rc = r >> shift-2 & 0x4 77 | gc = g >> shift-1 & 0x2 78 | bc = b >> shift & 0x1 79 | return(rc | gc | bc) 80 | 81 | def find(self,r,g,b,level): 82 | if level < self.oTree.maxLevel: 83 | idx = self.computeIndex(r,g,b,level) 84 | if self.children[idx]: 85 | return self.children[idx].find(r,g,b,level+1) 86 | elif self.count > 0: 87 | return ((self.red/self.count, self.green/self.count, self.blue/self.count)) 88 | else: 89 | print("error: No leaf node to represent this color") 90 | else: 91 | return ((self.red/self.count, self.green/self.count, self.blue/self.count)) 92 | 93 | def merge(self): 94 | for i in self.children: 95 | if i: 96 | print("combining ", i.calcId(), i.count, i.red, i.green, i.blue) 97 | if i.count > 0: 98 | self.oTree.leafList.remove(i) 99 | self.oTree.numLeaves = self.oTree.numLeaves - 1 100 | else: 101 | print("Recursively Merging non-leaf...") 102 | i.merge() 103 | self.count += i.count 104 | self.red += i.red 105 | self.green += i.green 106 | self.blue += i.blue 107 | for i in range(8): 108 | self.children[i] = None 109 | 110 | def calcId(self): 111 | sId = "" 112 | if self.count > 0: 113 | for i in range(1,self.oTree.maxLevel+1): 114 | sId = sId + str(self.computeIndex(self.red/self.count, self.green/self.count,self.blue/self.count,i)) 115 | return sId 116 | 117 | 118 | 119 | 120 | def buildAndDisplay(): 121 | # im = Image.open('/Users/bmiller/Projects/PyExamples/Image/lcastle.jpg') 122 | im = Image.open('bubbles.jpg') 123 | w,h = im.size 124 | ot = OctTree() 125 | for row in range(0,h): 126 | for col in range(0,w): 127 | r,g,b = im.getpixel((col,row)) 128 | ot.insert(r,g,b) 129 | print("Num Leaves before reduce = ", ot.numLeaves, len(ot.leafList)) 130 | ot.reduce(256) 131 | diffCount = 0 132 | for row in range(0,h): 133 | for col in range(0,w): 134 | r,g,b = im.getpixel((col,row)) 135 | nr,ng,nb = ot.find(r,g,b) 136 | if nr != r or ng != g or nb != b: 137 | diffCount = diffCount + 1 138 | im.putpixel((col,row),(nr,ng,nb)) 139 | print("Num Leaves After = ", ot.numLeaves, len(ot.leafList)) 140 | print("There were ", diffCount, " pixel differences") 141 | for i in ot.leafList: 142 | print(i.red/i.count, i.green/i.count, i.blue/i.count) 143 | im.show() 144 | 145 | 146 | if __name__ == '__main__': 147 | buildAndDisplay() 148 | 149 | -------------------------------------------------------------------------------- /Listings/4. Recursion/snippets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Snippets of code""" 3 | 4 | 5 | def prime_factors(n: int): 6 | """Generate prime factors of a number""" 7 | if n < 1: 8 | raise ValueError(f"Number must be greater than 1") 9 | if n == 1: 10 | return 11 | i = 2 12 | while n % i: 13 | i = i + 1 14 | yield i 15 | yield from prime_factors(n / i) 16 | 17 | 18 | # n = 12345333478658347653 19 | # n = 111111111111111 20 | # for f in prime_factors(n): 21 | # print(f, end=" ") 22 | # print() 23 | 24 | 25 | def to_str(n, base): 26 | convert_string = "0123456789ABCDEF" 27 | if n < base: 28 | return convert_string[n] 29 | else: 30 | return to_str(n // base, base) + convert_string[n % base] 31 | 32 | 33 | # print(to_str(1453, 16)) 34 | 35 | 36 | from pythonds3.basic import Stack 37 | 38 | 39 | def to_str(n, base): 40 | r_stack = Stack() 41 | convert_string = "0123456789ABCDEF" 42 | while n > 0: 43 | if n < base: 44 | r_stack.push(convert_string[n]) 45 | else: 46 | r_stack.push(convert_string[n % base]) 47 | n = n // base 48 | res = "" 49 | while not r_stack.is_empty(): 50 | res = res + str(r_stack.pop()) 51 | return res 52 | 53 | 54 | # print(to_str(1453, 16)) 55 | 56 | import turtle 57 | 58 | 59 | # def draw_spiral(my_turtle, line_len): 60 | # if line_len > 0: 61 | # my_turtle.forward(line_len) 62 | # my_turtle.right(90) 63 | # draw_spiral(my_turtle, line_len - 5) 64 | 65 | 66 | # my_turtle = turtle.Turtle() 67 | # my_win = turtle.Screen() 68 | # draw_spiral(my_turtle, 100) 69 | # my_win.getcanvas().postscript(file=f"spiral.ps") 70 | # my_win.exitonclick() 71 | 72 | i = 0 73 | 74 | 75 | def tree(branch_len, t, w=None): 76 | global i 77 | i = i + 1 78 | if i == 7: # book 79 | # if i == 5: # site 80 | w.getcanvas().postscript(file=f"tree1.ps") 81 | # if i == 2 ** 7: # book 82 | if i == 2 ** 5: # site 83 | w.getcanvas().postscript(file=f"tree2.ps") 84 | if branch_len > 5: 85 | t.forward(branch_len) 86 | t.right(20) 87 | tree(branch_len - 15, t, w) 88 | t.left(40) 89 | tree(branch_len - 15, t, w) 90 | t.right(20) 91 | t.backward(branch_len) 92 | 93 | 94 | def draw_tree(): 95 | # turtle.setup(600, 600) # book 96 | turtle.setup(300, 300) # site 97 | t = turtle.Turtle() 98 | my_win = turtle.Screen() 99 | t.ht() 100 | t.left(90) 101 | t.up() 102 | # t.backward(200) # book 103 | t.backward(100) # site 104 | t.down() 105 | # t.color("black") # book 106 | t.color("green") # site 107 | # tree(110, t, my_win) # book 108 | tree(75, t, my_win) # site 109 | my_win.exitonclick() 110 | 111 | 112 | # draw_tree() 113 | 114 | 115 | from time import process_time 116 | from functools import lru_cache 117 | 118 | 119 | @lru_cache(None) 120 | def make_change_1(coin_value_list, change): 121 | min_coins = change 122 | if change in coin_value_list: 123 | return 1 124 | else: 125 | for i in [c for c in coin_value_list if c <= change]: 126 | num_coins = 1 + make_change_1(coin_value_list, change - i) 127 | if num_coins < min_coins: 128 | min_coins = num_coins 129 | return min_coins 130 | 131 | 132 | print("Counting change 1") 133 | start = process_time() 134 | result = make_change_1((1, 5, 10, 25), 63) 135 | end = process_time() 136 | print(f"result: {result}; calculated in {end - start:2.5g} sec") 137 | 138 | 139 | def make_change_2(coin_value_list, change, known_results): 140 | min_coins = change 141 | if change in coin_value_list: 142 | known_results[change] = 1 143 | return 1 144 | elif known_results[change] > 0: 145 | return known_results[change] 146 | else: 147 | for i in [c for c in coin_value_list if c <= change]: 148 | num_coins = 1 + make_change_2( 149 | coin_value_list, change - i, known_results, 150 | ) 151 | if num_coins < min_coins: 152 | min_coins = num_coins 153 | known_results[change] = min_coins 154 | return min_coins 155 | 156 | 157 | print("Counting change 2") 158 | start = process_time() 159 | result = make_change_2([1, 5, 10, 25], 63, [0] * 64) 160 | end = process_time() 161 | print(f"result: {result}; calculated in {end - start:2.5g} sec") 162 | 163 | 164 | def make_change_3(coin_value_list, change, min_coins): 165 | for cents in range(change + 1): 166 | coin_count = cents 167 | for j in [c for c in coin_value_list if c <= cents]: 168 | if min_coins[cents - j] + 1 < coin_count: 169 | coin_count = min_coins[cents - j] + 1 170 | min_coins[cents] = coin_count 171 | return min_coins[change] 172 | 173 | 174 | print("Counting change 3") 175 | start = process_time() 176 | result = make_change_3([1, 5, 10, 25], 63, [0] * 64) 177 | end = process_time() 178 | print(f"result: {result}; calculated in {end - start:2.5g} sec") 179 | 180 | 181 | def make_change_4(coin_value_list, change, min_coins, coins_used): 182 | for cents in range(change + 1): 183 | coin_count = cents 184 | new_coin = 1 185 | for j in [c for c in coin_value_list if c <= cents]: 186 | if min_coins[cents - j] + 1 < coin_count: 187 | coin_count = min_coins[cents - j] + 1 188 | new_coin = j 189 | min_coins[cents] = coin_count 190 | coins_used[cents] = new_coin 191 | return min_coins[change] 192 | 193 | 194 | def print_coins(coins_used, change): 195 | coin = change 196 | while coin > 0: 197 | this_coin = coins_used[coin] 198 | print(this_coin, end=" ") 199 | coin = coin - this_coin 200 | print() 201 | 202 | 203 | def main(): 204 | amnt = 63 205 | clist = [1, 5, 10, 21, 25] 206 | coins_used = [0] * (amnt + 1) 207 | coin_count = [0] * (amnt + 1) 208 | 209 | print("Making change for {}".format(amnt), end=" ") 210 | print( 211 | "requires the following {} coins: ".format( 212 | make_change_4(clist, amnt, coin_count, coins_used), 213 | ), 214 | end="", 215 | ) 216 | print_coins(coins_used, amnt) 217 | print("The used list is as follows:") 218 | print(coins_used) 219 | 220 | 221 | main() 222 | -------------------------------------------------------------------------------- /Listings/8. Advanced Topics/octree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Octree implementation""" 3 | 4 | import sys 5 | from PIL import Image 6 | 7 | 8 | class Octree: 9 | def __init__(self): 10 | self.root = None 11 | self.max_level = 5 12 | self.num_leaves = 0 13 | self.all_leaves = [] 14 | 15 | def insert(self, r, g, b): 16 | if not self.root: 17 | self.root = self.OTNode(outer=self) 18 | self.root.insert(r, g, b, 0, self) 19 | 20 | def find(self, r, g, b): 21 | if self.root: 22 | return self.root.find(r, g, b, 0) 23 | 24 | def reduce(self, max_cubes): 25 | while len(self.all_leaves) > max_cubes: 26 | smallest = self.find_min_cube() 27 | # print(f"Smallest cube is: {smallest.count}, {smallest.red}, {smallest.green}, {smallest.blue}") 28 | smallest.parent.merge() 29 | self.all_leaves.append(smallest.parent) 30 | self.num_leaves = self.num_leaves + 1 31 | 32 | def find_min_cube(self): 33 | min_count = sys.maxsize 34 | max_level = 0 35 | min_cube = None 36 | for i in self.all_leaves: 37 | if ( 38 | i.count <= min_count 39 | and i.level >= max_level 40 | ): 41 | min_cube = i 42 | min_count = i.count 43 | max_level = i.level 44 | return min_cube 45 | 46 | class OTNode: 47 | def __init__( 48 | self, parent=None, level=0, outer=None 49 | ): 50 | self.red = 0 51 | self.green = 0 52 | self.blue = 0 53 | self.count = 0 54 | self.parent = parent 55 | self.level = level 56 | self.o_tree = outer 57 | self.children = [None] * 8 58 | 59 | def insert(self, r, g, b, level, outer): 60 | if level < self.o_tree.max_level: 61 | idx = self.compute_index(r, g, b, level) 62 | if self.children[idx] is None: 63 | self.children[idx] = outer.OTNode( 64 | parent=self, 65 | level=level + 1, 66 | outer=outer, 67 | ) 68 | self.children[idx].insert( 69 | r, g, b, level + 1, outer 70 | ) 71 | else: 72 | if self.count == 0: 73 | self.o_tree.num_leaves = ( 74 | self.o_tree.num_leaves + 1 75 | ) 76 | self.o_tree.all_leaves.append(self) 77 | self.red += r 78 | self.green += g 79 | self.blue += b 80 | self.count = self.count + 1 81 | 82 | def compute_index(self, r, g, b, l): 83 | shift = 8 - l 84 | rc = r >> shift - 2 & 0x4 85 | gc = g >> shift - 1 & 0x2 86 | bc = b >> shift & 0x1 87 | return rc | gc | bc 88 | 89 | def find(self, r, g, b, level): 90 | if level < self.o_tree.max_level: 91 | idx = self.compute_index(r, g, b, level) 92 | if self.children[idx]: 93 | return self.children[idx].find( 94 | r, g, b, level + 1 95 | ) 96 | elif self.count > 0: 97 | return ( 98 | self.red // self.count, 99 | self.green // self.count, 100 | self.blue // self.count, 101 | ) 102 | else: 103 | print( 104 | "error: No leaf node to represent this color" 105 | ) 106 | else: 107 | return ( 108 | self.red // self.count, 109 | self.green // self.count, 110 | self.blue // self.count, 111 | ) 112 | 113 | def merge(self): 114 | for child in [c for c in self.children if c]: 115 | # print(f"combining {child.calc_id()} {child.count} {child.red} {child.green} {child.blue}") 116 | if child.count > 0: 117 | self.o_tree.all_leaves.remove(child) 118 | self.o_tree.num_leaves -= 1 119 | else: 120 | print("Recursively merging non-leaf...") 121 | child.merge() 122 | self.count += child.count 123 | self.red += child.red 124 | self.green += child.green 125 | self.blue += child.blue 126 | for i in range(8): 127 | self.children[i] = None 128 | 129 | def calc_id(self): 130 | s_id = "" 131 | if self.count > 0: 132 | for i in range( 133 | 1, self.o_tree.max_level + 1 134 | ): 135 | s_id = s_id + str( 136 | self.compute_index( 137 | self.red // self.count, 138 | self.green // self.count, 139 | self.blue // self.count, 140 | i, 141 | ) 142 | ) 143 | return s_id 144 | 145 | 146 | def build_and_display(filename): 147 | img = Image.open(filename) 148 | w, h = img.size 149 | ot = Octree() 150 | for row in range(h): 151 | for col in range(w): 152 | r, g, b = img.getpixel((col, row)) 153 | ot.insert(r, g, b) 154 | ot.reduce(256) 155 | 156 | for row in range(h): 157 | for col in range(w): 158 | r, g, b = img.getpixel((col, row)) 159 | nr, ng, nb = ot.find(r, g, b) 160 | img.putpixel((col, row), (nr, ng, nb)) 161 | img.show() 162 | 163 | 164 | def simple_quant(filename): 165 | img = Image.open(filename) 166 | w, h = img.size 167 | for row in range(h): 168 | for col in range(w): 169 | r, g, b, alpha = img.getpixel((col, row)) 170 | r = r // 36 * 36 171 | g = g // 42 * 42 172 | b = b // 42 * 42 173 | img.putpixel((col, row), (r, g, b)) 174 | img.show() 175 | 176 | 177 | if __name__ == "__main__": 178 | build_and_display("Advanced/bubbles.jpg") 179 | # simple_quant("Advanced/bubbles.jpg") 180 | # simple_quant("Advanced/dice.png") 181 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/adjacency_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Implementing Graph as an adjacency matrix""" 3 | 4 | 5 | import importlib.util 6 | import pathlib 7 | import sys 8 | 9 | try: 10 | importlib.util.find_spec( 11 | ".".join(pathlib.Path(__file__).parts[-3]), 12 | "pythonds3", 13 | ) 14 | except ModuleNotFoundError: 15 | sys.path.append( 16 | f"{pathlib.Path(__file__).parents[1]}/" 17 | ) 18 | finally: 19 | from pythonds3.trees import PriorityQueue 20 | 21 | 22 | class Vertex: 23 | def __init__(self, key): 24 | self.key = key 25 | self.neighbors = {} 26 | self.distance = sys.maxsize 27 | self.previous = None 28 | self.color = None 29 | 30 | def get_neighbor(self, other): 31 | return self.neighbors.get(other, None) 32 | 33 | def set_neighbor(self, other, weight=0): 34 | self.neighbors[other] = weight 35 | 36 | def __repr__(self): 37 | return f"Vertex({self.key})" 38 | 39 | def __str__(self): 40 | return ( 41 | f"{self.key} connected to: " 42 | + f"{[x.key for x in self.neighbors]}" 43 | ) 44 | 45 | def get_neighbors(self): 46 | return self.neighbors.keys() 47 | 48 | def get_key(self): 49 | return self.key 50 | 51 | def __eq__(self, other): 52 | if isinstance(other, Vertex): 53 | return self.key == other.key 54 | return False 55 | 56 | def __lt__(self, other): 57 | if isinstance(other, Vertex): 58 | return self.distance < other.distance 59 | return False 60 | 61 | def __hash__(self): 62 | return hash(self.key) 63 | 64 | 65 | class Graph: 66 | def __init__(self): 67 | self.vertices = {} 68 | 69 | def set_vertex(self, key): 70 | self.vertices[key] = Vertex(key) 71 | 72 | def get_vertex(self, key): 73 | return self.vertices.get(key, None) 74 | 75 | def __contains__(self, key): 76 | return key in self.vertices 77 | 78 | def add_edge(self, from_vert, to_vert, weight=0): 79 | if from_vert not in self.vertices: 80 | self.set_vertex(from_vert) 81 | if to_vert not in self.vertices: 82 | self.set_vertex(to_vert) 83 | self.vertices[from_vert].set_neighbor( 84 | self.vertices[to_vert], weight 85 | ) 86 | 87 | def get_vertices(self): 88 | return self.vertices.keys() 89 | 90 | def __iter__(self): 91 | return iter(self.vertices.values()) 92 | 93 | 94 | print("\n---Graph---\n") 95 | g = Graph() 96 | for i in range(6): 97 | g.set_vertex(i) 98 | print(g.vertices) 99 | g.add_edge(0, 1, 5) 100 | g.add_edge(0, 5, 2) 101 | g.add_edge(1, 2, 4) 102 | g.add_edge(2, 3, 9) 103 | g.add_edge(3, 4, 7) 104 | g.add_edge(3, 5, 3) 105 | g.add_edge(4, 0, 1) 106 | g.add_edge(5, 4, 8) 107 | g.add_edge(5, 2, 1) 108 | for v in g: 109 | for w in v.get_neighbors(): 110 | print(f"({v.get_key()}, {w.get_key()})") 111 | 112 | 113 | def dijkstra(graph, start): 114 | pq = PriorityQueue() 115 | start.distance = 0 116 | pq.heapify([(v.distance, v) for v in graph]) 117 | while pq: 118 | distance, current_v = pq.delete() 119 | for next_v in current_v.get_neighbors(): 120 | new_distance = ( 121 | current_v.distance 122 | + current_v.get_neighbor(next_v) 123 | ) 124 | if new_distance < next_v.distance: 125 | next_v.distance = new_distance 126 | next_v.previous = current_v 127 | pq.change_priority(next_v, new_distance) 128 | # print("".join(f"{v.distance % 1000:<5d}" for v in graph)) 129 | 130 | 131 | print("\n---Dijkstra's---\n") 132 | g = Graph() 133 | vertices = ["u", "v", "w", "x", "y", "z"] 134 | for v in vertices: 135 | g.set_vertex(v) 136 | g.add_edge("u", "v", 2) 137 | g.add_edge("u", "w", 5) 138 | g.add_edge("u", "x", 1) 139 | g.add_edge("v", "u", 2) 140 | g.add_edge("v", "w", 3) 141 | g.add_edge("v", "x", 1) 142 | g.add_edge("w", "u", 5) 143 | g.add_edge("w", "v", 3) 144 | g.add_edge("w", "x", 3) 145 | g.add_edge("w", "y", 1) 146 | g.add_edge("w", "z", 5) 147 | g.add_edge("x", "u", 1) 148 | g.add_edge("x", "v", 2) 149 | g.add_edge("x", "w", 3) 150 | g.add_edge("x", "y", 1) 151 | g.add_edge("y", "w", 1) 152 | g.add_edge("y", "x", 1) 153 | g.add_edge("y", "z", 1) 154 | g.add_edge("z", "w", 5) 155 | g.add_edge("z", "y", 1) 156 | print("".join(f"{v:5s}" for v in vertices)) 157 | dijkstra(g, g.get_vertex("u")) 158 | print( 159 | "".join( 160 | f"{g.get_vertex(v).distance:<5d}" 161 | for v in vertices 162 | ) 163 | ) 164 | 165 | 166 | def prim(graph, start): 167 | pq = PriorityQueue() 168 | for vertex in graph: 169 | vertex.distance = sys.maxsize 170 | vertex.previous = None 171 | start.distance = 0 172 | pq.heapify( 173 | [(vertex.distance, vertex) for vertex in graph] 174 | ) 175 | while not pq.is_empty(): 176 | # print(", ".join(f"{(v[1].key, v[1].distance % 1000)}" for v in pq._heap)) 177 | distance, current_v = pq.delete() 178 | for next_v in current_v.get_neighbors(): 179 | new_distance = current_v.get_neighbor(next_v) 180 | if ( 181 | next_v in pq 182 | and new_distance < next_v.distance 183 | ): 184 | next_v.previous = current_v 185 | next_v.distance = new_distance 186 | pq.change_priority(next_v, new_distance) 187 | # print("".join(f"{v.distance % 1000:<5d}" for v in graph)) 188 | 189 | 190 | print("\n---Prim's---\n") 191 | g = Graph() 192 | vertices = ["A", "B", "C", "D", "E", "F", "G"] 193 | for v in vertices: 194 | g.set_vertex(v) 195 | g.add_edge("A", "B", 2) 196 | g.add_edge("A", "C", 3) 197 | g.add_edge("B", "A", 2) 198 | g.add_edge("B", "C", 1) 199 | g.add_edge("B", "D", 1) 200 | g.add_edge("B", "E", 4) 201 | g.add_edge("C", "A", 3) 202 | g.add_edge("C", "B", 1) 203 | g.add_edge("C", "F", 5) 204 | g.add_edge("D", "B", 1) 205 | g.add_edge("D", "E", 1) 206 | g.add_edge("E", "B", 4) 207 | g.add_edge("E", "D", 1) 208 | g.add_edge("E", "F", 1) 209 | g.add_edge("F", "C", 5) 210 | g.add_edge("F", "E", 1) 211 | g.add_edge("F", "G", 1) 212 | g.add_edge("G", "F", 1) 213 | print("".join(f"{v:5s}" for v in vertices)) 214 | prim(g, g.get_vertex("A")) 215 | print( 216 | "".join( 217 | f"{g.get_vertex(v).distance:<5d}" 218 | for v in vertices 219 | ) 220 | ) 221 | -------------------------------------------------------------------------------- /Listings/6. Trees and Tree Algorithms/bst.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Binary Search Tree""" 3 | 4 | 5 | class TreeNode: 6 | """Binary Tree Node""" 7 | 8 | def __init__( 9 | self, 10 | key, 11 | value, 12 | left=None, 13 | right=None, 14 | parent=None, 15 | ): 16 | self.key = key 17 | self.value = value 18 | self.left_child = left 19 | self.right_child = right 20 | self.parent = parent 21 | 22 | def is_left_child(self): 23 | return ( 24 | self.parent and self.parent.left_child is self 25 | ) 26 | 27 | def is_right_child(self): 28 | return ( 29 | self.parent and self.parent.right_child is self 30 | ) 31 | 32 | def is_root(self): 33 | return not self.parent 34 | 35 | def is_leaf(self): 36 | return not (self.right_child or self.left_child) 37 | 38 | def has_any_child(self): 39 | return self.right_child or self.left_child 40 | 41 | def has_children(self): 42 | return self.right_child and self.left_child 43 | 44 | def replace_value(self, key, value, left, right): 45 | self.key = key 46 | self.value = value 47 | self.left_child = left 48 | self.right_child = right 49 | if self.left_child: 50 | self.left_child.parent = self 51 | if self.right_child: 52 | self.right_child.parent = self 53 | 54 | def find_successor(self): 55 | successor = None 56 | if self.right_child: 57 | successor = self.right_child.find_min() 58 | else: 59 | if self.parent: 60 | if self.is_left_child(): 61 | successor = self.parent 62 | else: 63 | self.parent.right_child = None 64 | successor = ( 65 | self.parent.find_successor() 66 | ) 67 | self.parent.right_child = self 68 | return successor 69 | 70 | def find_min(self): 71 | current = self 72 | while current.left_child: 73 | current = current.left_child 74 | return current 75 | 76 | def splice_out(self): 77 | if self.is_leaf(): 78 | if self.is_left_child(): 79 | self.parent.left_child = None 80 | else: 81 | self.parent.right_child = None 82 | elif self.has_any_child(): 83 | if self.left_child: 84 | if self.is_left_child(): 85 | self.parent.left_child = ( 86 | self.left_child 87 | ) 88 | else: 89 | self.parent.right_child = ( 90 | self.left_child 91 | ) 92 | self.left_child.parent = self.parent 93 | else: 94 | if self.is_left_child(): 95 | self.parent.left_child = ( 96 | self.right_child 97 | ) 98 | else: 99 | self.parent.right_child = ( 100 | self.right_child 101 | ) 102 | self.right_child.parent = self.parent 103 | 104 | def __iter__(self): 105 | if self: 106 | if self.left_child: 107 | for elem in self.left_child: 108 | yield elem 109 | yield self.key 110 | if self.right_child: 111 | for elem in self.right_child: 112 | yield elem 113 | 114 | 115 | class BinarySearchTree: 116 | """Binary Search Tree""" 117 | 118 | def __init__(self): 119 | self.root = None 120 | self.size = 0 121 | 122 | def __len__(self): 123 | return self.size 124 | 125 | def __iter__(self): 126 | return self.root.__iter__() 127 | 128 | def put(self, key, value): 129 | if self.root: 130 | self._put(key, value, self.root) 131 | else: 132 | self.root = TreeNode(key, value) 133 | self.size = self.size + 1 134 | 135 | def _put(self, key, value, current): 136 | if key < current.key: 137 | if current.left_child: 138 | self._put(key, value, current.left_child) 139 | else: 140 | current.left_child = TreeNode( 141 | key, value, parent=current 142 | ) 143 | else: 144 | if current.right_child: 145 | self._put(key, value, current.right_child) 146 | else: 147 | current.right_child = TreeNode( 148 | key, value, parent=current 149 | ) 150 | 151 | def __setitem__(self, key, value): 152 | self.put(key, value) 153 | 154 | def get(self, key): 155 | if self.root: 156 | result = self._get(key, self.root) 157 | if result: 158 | return result.value 159 | return None 160 | 161 | def _get(self, key, current): 162 | if not current: 163 | return None 164 | if current.key == key: 165 | return current 166 | if key < current.key: 167 | return self._get(key, current.left_child) 168 | return self._get(key, current.right_child) 169 | 170 | def __getitem__(self, key): 171 | return self.get(key) 172 | 173 | def delete(self, key): 174 | if self.size > 1: 175 | node_to_remove = self._get(key, self.root) 176 | if node_to_remove: 177 | self._delete(node_to_remove) 178 | self.size = self.size - 1 179 | else: 180 | raise KeyError("Error, key not in tree") 181 | elif self.size == 1 and self.root.key == key: 182 | self.root = None 183 | self.size = self.size - 1 184 | else: 185 | raise KeyError("Error, key not in tree") 186 | 187 | def __delitem__(self, key): 188 | self.delete(key) 189 | 190 | def _delete(self, current): 191 | if current.is_leaf(): 192 | if current.is_left_child(): 193 | current.parent.left_child = None 194 | else: 195 | current.parent.right_child = None 196 | elif current.has_children(): 197 | # removing a node with two children 198 | successor = current.find_successor() 199 | successor.splice_out() 200 | current.key = successor.key 201 | current.value = successor.value 202 | else: # removing a node with one child 203 | if current.left_child: 204 | if current.is_left_child(): 205 | current.left_child.parent = ( 206 | current.parent 207 | ) 208 | current.parent.left_child = ( 209 | current.left_child 210 | ) 211 | elif current.is_right_child(): 212 | current.left_child.parent = ( 213 | current.parent 214 | ) 215 | current.parent.right_child = ( 216 | current.left_child 217 | ) 218 | else: 219 | current.replace_value( 220 | current.left_child.key, 221 | current.left_child.value, 222 | current.left_child.left_child, 223 | current.left_child.right_child, 224 | ) 225 | else: 226 | if current.is_left_child(): 227 | current.right_child.parent = ( 228 | current.parent 229 | ) 230 | current.parent.left_child = ( 231 | current.right_child 232 | ) 233 | elif current.is_right_child(): 234 | current.right_child.parent = ( 235 | current.parent 236 | ) 237 | current.parent.right_child = ( 238 | current.right_child 239 | ) 240 | else: 241 | current.replace_value( 242 | current.right_child.key, 243 | current.right_child.value, 244 | current.right_child.left_child, 245 | current.right_child.right_child, 246 | ) 247 | -------------------------------------------------------------------------------- /Listings/6. Trees and Tree Algorithms/tree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Binary Tree""" 3 | 4 | import os 5 | import sys 6 | 7 | sys.path.insert( 8 | 0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) 9 | ) 10 | 11 | 12 | my_tree = [ 13 | "a", # root 14 | ["b", ["d", [], []], ["e", [], []]], # left subtree 15 | ["c", ["f", [], []], []], # right subtree 16 | ] 17 | 18 | my_tree = ["a", ["b", ["d", [], []], ["e", [], []]], ["c", ["f", [], []], []]] 19 | # print(my_tree) 20 | # print("left subtree = ", my_tree[1]) 21 | # print("root = ", my_tree[0]) 22 | # print("right subtree = ", my_tree[2]) 23 | 24 | 25 | def make_binary_tree(root): 26 | return [root, [], []] 27 | 28 | 29 | def insert_left(root, new_child): 30 | old_child = root.pop(1) 31 | if len(old_child) > 1: 32 | root.insert(1, [new_child, old_child, []]) 33 | else: 34 | root.insert(1, [new_child, [], []]) 35 | return root 36 | 37 | 38 | def insert_right(root, new_child): 39 | old_child = root.pop(2) 40 | if len(old_child) > 1: 41 | root.insert(2, [new_child, [], old_child]) 42 | else: 43 | root.insert(2, [new_child, [], []]) 44 | return root 45 | 46 | 47 | def get_root_val(root): 48 | return root[0] 49 | 50 | 51 | def set_root_val(root, new_value): 52 | root[0] = new_value 53 | 54 | 55 | def get_left_child(root): 56 | return root[1] 57 | 58 | 59 | def get_right_child(root): 60 | return root[2] 61 | 62 | 63 | # a_tree = make_binary_tree(3) 64 | # insert_left(a_tree, 4) 65 | # insert_left(a_tree, 5) 66 | # insert_right(a_tree, 6) 67 | # insert_right(a_tree, 7) 68 | # left_child = get_left_child(a_tree) 69 | # print(left_child) 70 | 71 | # set_root_val(left_child, 9) 72 | # print(a_tree) 73 | # insert_left(left_child, 11) 74 | # print(a_tree) 75 | # print(get_right_child(get_right_child(a_tree))) 76 | 77 | 78 | class BinaryTree: 79 | def __init__(self, root_obj): 80 | self.key = root_obj 81 | self.left_child = None 82 | self.right_child = None 83 | 84 | def insert_left(self, new_node): 85 | if self.left_child is None: 86 | self.left_child = BinaryTree(new_node) 87 | else: 88 | new_child = BinaryTree(new_node) 89 | new_child.left_child = self.left_child 90 | self.left_child = new_child 91 | 92 | def insert_right(self, new_node): 93 | if self.right_child == None: 94 | self.right_child = BinaryTree(new_node) 95 | else: 96 | new_child = BinaryTree(new_node) 97 | new_child.right_child = self.right_child 98 | self.right_child = new_child 99 | 100 | def get_root_val(self): 101 | return self.key 102 | 103 | def set_root_val(self, new_obj): 104 | self.key = new_obj 105 | 106 | def get_left_child(self): 107 | return self.left_child 108 | 109 | def get_right_child(self): 110 | return self.right_child 111 | 112 | def preorder(self): 113 | print(self.key, end=" ") 114 | if self.left_child: 115 | self.left_child.preorder() 116 | if self.right_child: 117 | self.right_child.preorder() 118 | 119 | 120 | # a_tree = BinaryTree("a") 121 | # print(a_tree.get_root_val()) 122 | # print(a_tree.get_left_child()) 123 | # a_tree.insert_left("b") 124 | # print(a_tree.get_left_child()) 125 | # print(a_tree.get_left_child().get_root_val()) 126 | # a_tree.insert_right("c") 127 | # print(a_tree.get_right_child()) 128 | # print(a_tree.get_right_child().get_root_val()) 129 | # a_tree.get_right_child().set_root_val("hello") 130 | # print(a_tree.get_right_child().get_root_val()) 131 | # a_tree.preorder() 132 | # print() 133 | 134 | 135 | def build_tree(): 136 | tree = BinaryTree(None) 137 | tree.set_root_val("a") 138 | tree.insert_left("b") 139 | tree.insert_right("c") 140 | tree.get_left_child().insert_right("d") 141 | tree.get_right_child().insert_left("e") 142 | tree.get_right_child().insert_right("f") 143 | return tree 144 | 145 | 146 | # ttree = build_tree() 147 | 148 | # assert ttree.get_right_child().get_root_val() == "c" 149 | # assert ttree.get_left_child().get_right_child().get_root_val() == "d" 150 | # assert ttree.get_right_child().get_left_child().get_root_val() == "e" 151 | 152 | 153 | from pythonds3.basic import Stack 154 | from pythonds3.trees import BinaryTree 155 | 156 | 157 | def build_parse_tree(fp_expr): 158 | fp_list = fp_expr.split() 159 | p_stack = Stack() 160 | expr_tree = BinaryTree("") 161 | p_stack.push(expr_tree) 162 | current_tree = expr_tree 163 | 164 | for i in fp_list: 165 | if i == "(": 166 | current_tree.insert_left("") 167 | p_stack.push(current_tree) 168 | current_tree = current_tree.left_child 169 | 170 | elif i in ["+", "-", "*", "/"]: 171 | current_tree.root = i 172 | current_tree.insert_right("") 173 | p_stack.push(current_tree) 174 | current_tree = current_tree.right_child 175 | 176 | elif i == ")": 177 | current_tree = p_stack.pop() 178 | 179 | elif i not in ["+", "-", "*", "/", ")"]: 180 | try: 181 | current_tree.root = int(i) 182 | parent = p_stack.pop() 183 | current_tree = parent 184 | 185 | except ValueError: 186 | raise ValueError("token '{}' is not a valid integer".format(i)) 187 | 188 | return expr_tree 189 | 190 | 191 | # pt = build_parse_tree("( ( 10 + 5 ) * 3 )") 192 | # pt.postorder() # defined and explained in the next section 193 | # print() 194 | 195 | # from contextlib import redirect_stdout 196 | # import io 197 | 198 | # f = io.StringIO() 199 | # with redirect_stdout(f): 200 | # pt.postorder() 201 | # assert f.getvalue() == "10 5 + 3 * " 202 | 203 | import operator 204 | 205 | 206 | def evaluate(parse_tree): 207 | operators = { 208 | "+": operator.add, 209 | "-": operator.sub, 210 | "*": operator.mul, 211 | "/": operator.truediv, 212 | } 213 | 214 | left_child = parse_tree.left_child 215 | right_child = parse_tree.right_child 216 | 217 | if left_child and right_child: 218 | fn = operators[parse_tree.root] 219 | return fn(evaluate(left_child), evaluate(right_child)) 220 | else: 221 | return parse_tree.root 222 | 223 | 224 | # print(evaluate(pt)) 225 | 226 | # pt = build_parse_tree("( 3 + ( 4 * 5 ) )") 227 | # assert evaluate(pt) == 23 228 | # assert pt.postorder_eval() == 23 229 | 230 | 231 | def preorder(tree): 232 | if tree: 233 | print(tree.get_root_val()) 234 | preorder(tree.get_left_child()) 235 | preorder(tree.get_right_child()) 236 | 237 | 238 | def inorder(tree): 239 | if tree: 240 | inorder(tree.get_left_child()) 241 | print(tree.get_root_val()) 242 | inorder(tree.get_right_child()) 243 | 244 | 245 | def postorder(tree): 246 | if tree: 247 | postorder(tree.get_left_child()) 248 | postorder(tree.get_right_child()) 249 | print(tree.get_root_val()) 250 | 251 | 252 | # preorder(pt) 253 | 254 | 255 | def postordereval(tree): 256 | operators = { 257 | "+": operator.add, 258 | "-": operator.sub, 259 | "*": operator.mul, 260 | "/": operator.truediv, 261 | } 262 | result_1 = None 263 | result_2 = None 264 | if tree: 265 | result_1 = postordereval(tree.get_left_child()) 266 | result_2 = postordereval(tree.get_right_child()) 267 | if result_1 and result_2: 268 | return operators[tree.get_root_val()](result_1, result_2) 269 | else: 270 | return tree.get_root_val() 271 | 272 | 273 | # assert postordereval(pt) == 23 274 | 275 | 276 | def print_exp(tree): 277 | result = "" 278 | if tree: 279 | result = "(" + print_exp(tree.get_left_child()) 280 | result = result + str(tree.get_root_val()) 281 | result = result + print_exp(tree.get_right_child()) + ")" 282 | return result 283 | 284 | 285 | # print(print_exp(pt)) 286 | 287 | 288 | class BinarySearchTree: 289 | def __init__(self): 290 | self.root = None 291 | self.size = 0 292 | 293 | def __len__(self): 294 | return self.size 295 | 296 | def __iter__(self): 297 | return self.root.__iter__() 298 | 299 | def put(self, key, value): 300 | if self.root: 301 | self._put(key, value, self.root) 302 | else: 303 | self.root = TreeNode(key, value) 304 | self.size = self.size + 1 305 | 306 | def _put(self, key, value, current_node): 307 | if key < current_node.key: 308 | if current_node.left_child: 309 | self._put(key, value, current_node.left_child) 310 | else: 311 | current_node.left_child = TreeNode( 312 | key, value, parent=current_node 313 | ) 314 | else: 315 | if current_node.right_child: 316 | self._put(key, value, current_node.right_child) 317 | else: 318 | current_node.right_child = TreeNode( 319 | key, value, parent=current_node 320 | ) 321 | 322 | def __setitem__(self, key, value): 323 | self.put(key, value) 324 | 325 | def get(self, key): 326 | if self.root: 327 | result = self._get(key, self.root) 328 | if result: 329 | return result.value 330 | return None 331 | 332 | def _get(self, key, current_node): 333 | if not current_node: 334 | return None 335 | if current_node.key == key: 336 | return current_node 337 | elif key < current_node.key: 338 | return self._get(key, current_node.left_child) 339 | else: 340 | return self._get(key, current_node.right_child) 341 | 342 | def __getitem__(self, key): 343 | return self.get(key) 344 | 345 | def __contains__(self, key): 346 | return bool(self._get(key, self.root)) 347 | 348 | def delete(self, key): 349 | if self.size > 1: 350 | node_to_remove = self._get(key, self.root) 351 | if node_to_remove: 352 | self._delete(node_to_remove) 353 | self.size = self.size - 1 354 | else: 355 | raise KeyError("Error, key not in tree") 356 | elif self.size == 1 and self.root.key == key: 357 | self.root = None 358 | self.size = self.size - 1 359 | else: 360 | raise KeyError("Error, key not in tree") 361 | 362 | def _delete(self, current_node): 363 | if current_node.is_leaf(): # removing a leaf 364 | if current_node == current_node.parent.left_child: 365 | current_node.parent.left_child = None 366 | else: 367 | current_node.parent.right_child = None 368 | elif current_node.has_children(): # removing a node with two children 369 | successor = current_node.find_successor() 370 | successor.splice_out() 371 | current_node.key = successor.key 372 | current_node.value = successor.value 373 | else: # removing a node with one child 374 | if current_node.left_child: 375 | if current_node.is_left_child(): 376 | current_node.left_child.parent = current_node.parent 377 | current_node.parent.left_child = current_node.left_child 378 | elif current_node.is_right_child(): 379 | current_node.left_child.parent = current_node.parent 380 | current_node.parent.right_child = current_node.left_child 381 | else: 382 | current_node.replace_value( 383 | current_node.left_child.key, 384 | current_node.left_child.value, 385 | current_node.left_child.left_child, 386 | current_node.left_child.right_child, 387 | ) 388 | else: 389 | if current_node.is_left_child(): 390 | current_node.right_child.parent = current_node.parent 391 | current_node.parent.left_child = current_node.right_child 392 | elif current_node.is_right_child(): 393 | current_node.right_child.parent = current_node.parent 394 | current_node.parent.right_child = current_node.right_child 395 | else: 396 | current_node.replace_value( 397 | current_node.right_child.key, 398 | current_node.right_child.value, 399 | current_node.right_child.left_child, 400 | current_node.right_child.right_child, 401 | ) 402 | 403 | def __delitem__(self, key): 404 | self.delete(key) 405 | 406 | 407 | class TreeNode: 408 | def __init__(self, key, value, left=None, right=None, parent=None): 409 | self.key = key 410 | self.value = value 411 | self.left_child = left 412 | self.right_child = right 413 | self.parent = parent 414 | 415 | def is_left_child(self): 416 | return self.parent and self.parent.left_child is self 417 | 418 | def is_right_child(self): 419 | return self.parent and self.parent.right_child is self 420 | 421 | def is_root(self): 422 | return not self.parent 423 | 424 | def is_leaf(self): 425 | return not (self.right_child or self.left_child) 426 | 427 | def has_a_child(self): 428 | return self.right_child or self.left_child 429 | 430 | def has_children(self): 431 | return self.right_child and self.left_child 432 | 433 | def replace_value(self, key, value, left, right): 434 | self.key = key 435 | self.value = value 436 | self.left_child = left 437 | self.right_child = right 438 | if self.left_child: 439 | self.left_child.parent = self 440 | if self.right_child: 441 | self.right_child.parent = self 442 | 443 | def find_successor(self): 444 | successor = None 445 | if self.right_child: 446 | successor = self.right_child.find_min() 447 | else: 448 | if self.parent: 449 | if self.is_left_child(): 450 | successor = self.parent 451 | else: 452 | self.parent.right_child = None 453 | successor = self.parent.find_successor() 454 | self.parent.right_child = self 455 | return successor 456 | 457 | def find_min(self): 458 | current = self 459 | while current.left_child: 460 | current = current.left_child 461 | return current 462 | 463 | def splice_out(self): 464 | if self.is_leaf(): 465 | if self.is_left_child(): 466 | self.parent.left_child = None 467 | else: 468 | self.parent.right_child = None 469 | elif self.has_a_child(): 470 | if self.left_child: 471 | if self.is_left_child(): 472 | self.parent.left_child = self.left_child 473 | else: 474 | self.parent.right_child = self.left_child 475 | self.left_child.parent = self.parent 476 | else: 477 | if self.is_left_child(): 478 | self.parent.left_child = self.right_child 479 | else: 480 | self.parent.right_child = self.right_child 481 | self.right_child.parent = self.parent 482 | 483 | def __iter__(self): 484 | if self: 485 | if self.left_child: 486 | for elem in self.left_child: 487 | yield elem 488 | yield self.key 489 | if self.right_child: 490 | for elem in self.right_child: 491 | yield elem 492 | 493 | 494 | # my_tree = BinarySearchTree() 495 | # my_tree["a"] = "a" 496 | # my_tree["q"] = "quick" 497 | # my_tree["b"] = "brown" 498 | # my_tree["f"] = "fox" 499 | # my_tree["j"] = "jumps" 500 | # my_tree["o"] = "over" 501 | # my_tree["t"] = "the" 502 | # my_tree["l"] = "lazy" 503 | # my_tree["d"] = "dog" 504 | 505 | # print(my_tree["q"]) 506 | # print(my_tree["l"]) 507 | # print("There are {} items in this tree".format(len(my_tree))) 508 | # my_tree.delete("a") 509 | # print("There are {} items in this tree".format(len(my_tree))) 510 | 511 | # for node in my_tree: 512 | # print(my_tree[node], end=" ") 513 | # print() 514 | 515 | # assert my_tree["a"] == None 516 | # assert my_tree["b"] == "brown" 517 | # assert len(my_tree) == 8 518 | 519 | -------------------------------------------------------------------------------- /Listings/7. Graphs and Graphing Algorithms/graphics.py: -------------------------------------------------------------------------------- 1 | # graphics.py 2 | """Simple object oriented graphics library 3 | 4 | The library is designed to make it very easy for novice programmers to 5 | experiment with computer graphics in an object oriented fashion. It is 6 | written by John Zelle for use with the book "Python Programming: An 7 | Introduction to Computer Science" (Franklin, Beedle & Associates). 8 | 9 | LICENSE: This is open-source software released under the terms of the 10 | GPL (http://www.gnu.org/licenses/gpl.html). 11 | 12 | PLATFORMS: The package is a wrapper around Tkinter and should run on 13 | any platform where Tkinter is available. 14 | 15 | INSTALLATION: Put this file somewhere where Python can see it. 16 | 17 | OVERVIEW: There are two kinds of objects in the library. The GraphWin 18 | class implements a window where drawing can be done, and various 19 | GraphicsObjects are provided that can be drawn into a GraphWin. As a 20 | simple example, here is a complete program to draw a circle of radius 21 | 10 centered in a 100x100 window: 22 | 23 | -------------------------------------------------------------------- 24 | from graphics import * 25 | 26 | def main(): 27 | win = GraphWin("My Circle", 100, 100) 28 | c = Circle(Point(50,50), 10) 29 | c.draw(win) 30 | 31 | main() 32 | -------------------------------------------------------------------- 33 | GraphWin objects support coordinate transformation through the 34 | setCoords method and pointer-based input through getMouse. 35 | 36 | The library provides the following graphical objects: 37 | Point 38 | Line 39 | Circle 40 | Oval 41 | Rectangle 42 | Polygon 43 | Text 44 | Entry (for text-based input) 45 | Image 46 | 47 | Various attributes of graphical objects can be set such as 48 | outline-color, fill-color and line-width. Graphical objects also 49 | support moving and hiding for animation effects. 50 | 51 | DOCUMENTATION: For complete documentation, see Chapter 5 of "Python 52 | Programming: An Introduction to Computer Science" by John Zelle, 53 | published by Franklin, Beedle & Associates. """ 54 | 55 | # Version 2.0 56 | # Updated Documentation 57 | # Made Polygon accept a list of Points in constructor 58 | # Made all drawing functions call TK update for easier animations 59 | # and to make the overall package work better with 60 | # Python 2.3 and IDLE 1.0 under Windows (still some issues). 61 | # Removed vestigial turtle graphics. 62 | # Added ability to configure font for Entry objects (analogous to Text) 63 | # Added setTextColor for Text as an alias of setFill 64 | # Changed to class-style exceptions 65 | # Fixed cloning of Text objects 66 | 67 | # Version 1.6 68 | # Fixed Entry so StringVar uses _root as master, solves weird 69 | # interaction with shell in Idle 70 | # Fixed bug in setCoords. X and Y coordinates can increase in 71 | # "non-intuitive" direction. 72 | # Tweaked wm_protocol so window is not resizable and kill box closes. 73 | 74 | # Version 1.5 75 | # Fixed bug in Entry. Can now define entry before creating a 76 | # GraphWin. All GraphWins are now toplevel windows and share 77 | # a fixed root (called _root). 78 | 79 | # Version 1.4 80 | # Fix Garbage collection of Tkinter images bug. 81 | # Add ability to set text atttributes. 82 | # Add Entry boxes. 83 | 84 | 85 | import Tkinter 86 | tk = Tkinter 87 | 88 | from copy import copy 89 | 90 | import exceptions 91 | 92 | class GraphicsError(exceptions.Exception): 93 | """Generic error class for graphics module exceptions.""" 94 | def __init__(self, args=None): 95 | self.args=args 96 | 97 | OBJ_ALREADY_DRAWN = "Object currently drawn" 98 | UNSUPPORTED_METHOD = "Object doesn't support operation" 99 | BAD_OPTION = "Illegal option value" 100 | 101 | 102 | # create an invisible global main root for all windows 103 | _root = tk.Tk() 104 | _root.withdraw() 105 | 106 | class GraphWin(tk.Canvas): 107 | 108 | """A GraphWin is a toplevel window for displaying graphics.""" 109 | 110 | def __init__(self, title="Graphics Window", width=200, height=200): 111 | master = tk.Toplevel(_root) 112 | master.protocol("WM_DELETE_WINDOW", self.close) 113 | tk.Canvas.__init__(self, master, width=width, height=height) 114 | self.master.title(title) 115 | self.pack() 116 | master.resizable(0,0) 117 | self.foreground = "black" 118 | self.items = [] 119 | self.mouseX = None 120 | self.mouseY = None 121 | self.bind("", self._onClick) 122 | self.height = height 123 | self.width = width 124 | self._mouseCallback = None 125 | self.trans = None 126 | _root.update() 127 | 128 | def setBackground(self, color): 129 | """Set background color of the window""" 130 | self.config(bg=color) 131 | 132 | def setCoords(self, x1, y1, x2, y2): 133 | """Set coordinates of window to run from (x1,y1) in the 134 | lower-left corner to (x2,y2) in the upper-right corner.""" 135 | 136 | self.trans = Transform(self.width, self.height, x1, y1, x2, y2) 137 | 138 | def close(self): 139 | """Close the window""" 140 | self.master.destroy() 141 | self.quit() 142 | _root.update() 143 | 144 | def plot(self, x, y, color="black"): 145 | """Set pixel (x,y) to the given color""" 146 | xs,ys = self.toScreen(x,y) 147 | self.create_line(xs,ys,xs+1,ys, fill=color) 148 | _root.update() 149 | 150 | def plotPixel(self, x, y, color="black"): 151 | """Set pixel raw (independent of window coordinates) pixel 152 | (x,y) to color""" 153 | self.create_line(x,y,x+1,y, fill=color) 154 | _root.update() 155 | 156 | def flush(self): 157 | """Update drawing to the window (deprecated)""" 158 | self.update_idletasks() 159 | 160 | def getMouse(self): 161 | """Wait for mouse click and return Point object representing 162 | the click""" 163 | self.mouseX = None 164 | self.mouseY = None 165 | while self.mouseX == None or self.mouseY == None: 166 | self.update() 167 | x,y = self.toWorld(self.mouseX, self.mouseY) 168 | return Point(x,y) 169 | 170 | def getHeight(self): 171 | """Return the height of the window""" 172 | return self.height 173 | 174 | def getWidth(self): 175 | """Return the width of the window""" 176 | return self.width 177 | 178 | def toScreen(self, x, y): 179 | trans = self.trans 180 | if trans: 181 | return self.trans.screen(x,y) 182 | else: 183 | return x,y 184 | 185 | def toWorld(self, x, y): 186 | trans = self.trans 187 | if trans: 188 | return self.trans.world(x,y) 189 | else: 190 | return x,y 191 | 192 | def setMouseHandler(self, func): 193 | self._mouseCallback = func 194 | 195 | def _onClick(self, e): 196 | self.mouseX = e.x 197 | self.mouseY = e.y 198 | if self._mouseCallback: 199 | self._mouseCallback(Point(e.x, e.y)) 200 | 201 | class Transform: 202 | 203 | """Internal class for 2-D coordinate transformations""" 204 | 205 | def __init__(self, w, h, xlow, ylow, xhigh, yhigh): 206 | # w, h are width and height of window 207 | # (xlow,ylow) coordinates of lower-left [raw (0,h-1)] 208 | # (xhigh,yhigh) coordinates of upper-right [raw (w-1,0)] 209 | xspan = (xhigh-xlow) 210 | yspan = (yhigh-ylow) 211 | self.xbase = xlow 212 | self.ybase = yhigh 213 | self.xscale = xspan/float(w-1) 214 | self.yscale = yspan/float(h-1) 215 | 216 | def screen(self,x,y): 217 | # Returns x,y in screen (actually window) coordinates 218 | xs = (x-self.xbase) / self.xscale 219 | ys = (self.ybase-y) / self.yscale 220 | return int(xs+0.5),int(ys+0.5) 221 | 222 | def world(self,xs,ys): 223 | # Returns xs,ys in world coordinates 224 | x = xs*self.xscale + self.xbase 225 | y = self.ybase - ys*self.yscale 226 | return x,y 227 | 228 | 229 | # Default values for various item configuration options. Only a subset of 230 | # keys may be present in the configuration dictionary for a given item 231 | DEFAULT_CONFIG = {"fill":"", 232 | "outline":"black", 233 | "width":"1", 234 | "arrow":"none", 235 | "text":"", 236 | "justify":"center", 237 | "font": ("helvetica", 12, "normal")} 238 | 239 | class GraphicsObject: 240 | 241 | """Generic base class for all of the drawable objects""" 242 | # A subclass of GraphicsObject should override _draw and 243 | # and _move methods. 244 | 245 | def __init__(self, options): 246 | # options is a list of strings indicating which options are 247 | # legal for this object. 248 | 249 | # When an object is drawn, canvas is set to the GraphWin(canvas) 250 | # object where it is drawn and id is the TK identifier of the 251 | # drawn shape. 252 | self.canvas = None 253 | self.id = None 254 | 255 | # config is the dictionary of configuration options for the widget. 256 | config = {} 257 | for option in options: 258 | config[option] = DEFAULT_CONFIG[option] 259 | self.config = config 260 | 261 | def setFill(self, color): 262 | """Set interior color to color""" 263 | self._reconfig("fill", color) 264 | 265 | def setOutline(self, color): 266 | """Set outline color to color""" 267 | self._reconfig("outline", color) 268 | 269 | def setWidth(self, width): 270 | """Set line weight to width""" 271 | self._reconfig("width", width) 272 | 273 | def draw(self, graphwin): 274 | 275 | """Draw the object in graphwin, which should be a GraphWin 276 | object. A GraphicsObject may only be drawn into one 277 | window. Raises an error if attempt made to draw an object that 278 | is already visible.""" 279 | 280 | if self.canvas: raise GraphicsError, OBJ_ALREADY_DRAWN 281 | self.canvas=graphwin 282 | self.id = self._draw(graphwin, self.config) 283 | _root.update() 284 | 285 | def undraw(self): 286 | 287 | """Undraw the object (i.e. hide it). Returns silently if the 288 | object is not currently drawn.""" 289 | 290 | if not self.canvas: return 291 | self.canvas.delete(self.id) 292 | self.canvas = None 293 | self.id = None 294 | _root.update() 295 | 296 | def move(self, dx, dy): 297 | 298 | """move object dx units in x direction and dy units in y 299 | direction""" 300 | 301 | self._move(dx,dy) 302 | canvas = self.canvas 303 | if canvas: 304 | trans = canvas.trans 305 | if trans: 306 | x = dx/ trans.xscale 307 | y = -dy / trans.yscale 308 | else: 309 | x = dx 310 | y = dy 311 | self.canvas.move(self.id, x, y) 312 | _root.update() 313 | 314 | def _reconfig(self, option, setting): 315 | # Internal method for changing configuration of the object 316 | # Raises an error if the option does not exist in the config 317 | # dictionary for this object 318 | if not self.config.has_key(option): 319 | raise GraphicsError, UNSUPPORTED_METHOD 320 | options = self.config 321 | options[option] = setting 322 | if self.canvas: self.canvas.itemconfig(self.id, options) 323 | _root.update() 324 | 325 | def _draw(self, canvas, options): 326 | """draws appropriate figure on canvas with options provided 327 | Returns Tk id of item drawn""" 328 | pass # must override in subclass 329 | 330 | def _move(self, dx, dy): 331 | """updates internal state of object to move it dx,dy units""" 332 | pass # must override in subclass 333 | 334 | class Point(GraphicsObject): 335 | def __init__(self, x, y): 336 | GraphicsObject.__init__(self, ["outline", "fill"]) 337 | self.setFill = self.setOutline 338 | self.x = x 339 | self.y = y 340 | 341 | def _draw(self, canvas, options): 342 | x,y = canvas.toScreen(self.x,self.y) 343 | return canvas.create_rectangle(x,y,x+1,y+1,options) 344 | 345 | def _move(self, dx, dy): 346 | self.x = self.x + dx 347 | self.y = self.y + dy 348 | 349 | def clone(self): 350 | other = Point(self.x,self.y) 351 | other.config = self.config 352 | return other 353 | 354 | def getX(self): return self.x 355 | def getY(self): return self.y 356 | 357 | class _BBox(GraphicsObject): 358 | # Internal base class for objects represented by bounding box 359 | # (opposite corners) Line segment is a degenerate case. 360 | 361 | def __init__(self, p1, p2, options=["outline","width","fill"]): 362 | GraphicsObject.__init__(self, options) 363 | self.p1 = p1.clone() 364 | self.p2 = p2.clone() 365 | 366 | def _move(self, dx, dy): 367 | self.p1.x = self.p1.x + dx 368 | self.p1.y = self.p1.y + dy 369 | self.p2.x = self.p2.x + dx 370 | self.p2.y = self.p2.y + dy 371 | 372 | def getP1(self): return self.p1 373 | 374 | def getP2(self): return self.p2 375 | 376 | def getCenter(self): 377 | p1 = self.p1 378 | p2 = self.p2 379 | return Point((p1.x+p2.x)/2.0, (p1.y+p2.y)/2.0) 380 | 381 | class Rectangle(_BBox): 382 | 383 | def __init__(self, p1, p2): 384 | _BBox.__init__(self, p1, p2) 385 | 386 | def _draw(self, canvas, options): 387 | p1 = self.p1 388 | p2 = self.p2 389 | x1,y1 = canvas.toScreen(p1.x,p1.y) 390 | x2,y2 = canvas.toScreen(p2.x,p2.y) 391 | return canvas.create_rectangle(x1,y1,x2,y2,options) 392 | 393 | def clone(self): 394 | other = Rectangle(self.p1, self.p2) 395 | other.config = self.config 396 | return other 397 | 398 | class Oval(_BBox): 399 | 400 | def __init__(self, p1, p2): 401 | _BBox.__init__(self, p1, p2) 402 | 403 | def clone(self): 404 | other = Oval(self.p1, self.p2) 405 | other.config = self.config 406 | return other 407 | 408 | def _draw(self, canvas, options): 409 | p1 = self.p1 410 | p2 = self.p2 411 | x1,y1 = canvas.toScreen(p1.x,p1.y) 412 | x2,y2 = canvas.toScreen(p2.x,p2.y) 413 | return canvas.create_oval(x1,y1,x2,y2,options) 414 | 415 | class Circle(Oval): 416 | 417 | def __init__(self, center, radius): 418 | p1 = Point(center.x-radius, center.y-radius) 419 | p2 = Point(center.x+radius, center.y+radius) 420 | Oval.__init__(self, p1, p2) 421 | self.radius = radius 422 | 423 | def clone(self): 424 | other = Circle(self.getCenter(), self.radius) 425 | other.config = self.config 426 | return other 427 | 428 | def getRadius(self): 429 | return self.radius 430 | 431 | class Line(_BBox): 432 | 433 | def __init__(self, p1, p2): 434 | _BBox.__init__(self, p1, p2, ["arrow","fill","width"]) 435 | self.setFill(DEFAULT_CONFIG['outline']) 436 | self.setOutline = self.setFill 437 | 438 | def clone(self): 439 | other = Line(self.p1, self.p2) 440 | other.config = self.config 441 | return other 442 | 443 | def _draw(self, canvas, options): 444 | p1 = self.p1 445 | p2 = self.p2 446 | x1,y1 = canvas.toScreen(p1.x,p1.y) 447 | x2,y2 = canvas.toScreen(p2.x,p2.y) 448 | return canvas.create_line(x1,y1,x2,y2,options) 449 | 450 | def setArrow(self, option): 451 | if not option in ["first","last","both","none"]: 452 | raise GraphicsError, BAD_OPTION 453 | self._reconfig("arrow", option) 454 | 455 | 456 | class Polygon(GraphicsObject): 457 | 458 | def __init__(self, *points): 459 | # if points passed as a list, extract it 460 | if len(points) == 1 and type(points[0] == type([])): 461 | points = points[0] 462 | self.points = map(Point.clone, points) 463 | GraphicsObject.__init__(self, ["outline", "width", "fill"]) 464 | 465 | def clone(self): 466 | other = apply(Polygon, self.points) 467 | other.config = self.config 468 | return other 469 | 470 | def getPoints(self): 471 | return map(Point.clone, self.points) 472 | 473 | def _move(self, dx, dy): 474 | for p in self.points: 475 | p.move(dx,dy) 476 | 477 | def _draw(self, canvas, options): 478 | args = [canvas] 479 | for p in self.points: 480 | x,y = canvas.toScreen(p.x,p.y) 481 | args.append(x) 482 | args.append(y) 483 | args.append(options) 484 | return apply(GraphWin.create_polygon, args) 485 | 486 | class Text(GraphicsObject): 487 | 488 | def __init__(self, p, text): 489 | GraphicsObject.__init__(self, ["justify","fill","text","font"]) 490 | self.setText(text) 491 | self.anchor = p.clone() 492 | self.setFill(DEFAULT_CONFIG['outline']) 493 | self.setOutline = self.setFill 494 | 495 | def _draw(self, canvas, options): 496 | p = self.anchor 497 | x,y = canvas.toScreen(p.x,p.y) 498 | return canvas.create_text(x,y,options) 499 | 500 | def _move(self, dx, dy): 501 | self.anchor.move(dx,dy) 502 | 503 | def clone(self): 504 | other = Text(self.anchor, self.config['text']) 505 | other.config = self.config 506 | return other 507 | 508 | def setText(self,text): 509 | self._reconfig("text", text) 510 | 511 | def getText(self): 512 | return self.config["text"] 513 | 514 | def getAnchor(self): 515 | return self.anchor.clone() 516 | 517 | def setFace(self, face): 518 | if face in ['helvetica','arial','courier','times roman']: 519 | f,s,b = self.config['font'] 520 | self._reconfig("font",(face,s,b)) 521 | else: 522 | raise GraphicsError, BAD_OPTION 523 | 524 | def setSize(self, size): 525 | if 5 <= size <= 36: 526 | f,s,b = self.config['font'] 527 | self._reconfig("font", (f,size,b)) 528 | else: 529 | raise GraphicsError, BAD_OPTION 530 | 531 | def setStyle(self, style): 532 | if style in ['bold','normal','italic', 'bold italic']: 533 | f,s,b = self.config['font'] 534 | self._reconfig("font", (f,s,style)) 535 | else: 536 | raise GraphicsError, BAD_OPTION 537 | 538 | def setTextColor(self, color): 539 | self.setFill(color) 540 | 541 | 542 | class Entry(GraphicsObject): 543 | 544 | def __init__(self, p, width): 545 | GraphicsObject.__init__(self, []) 546 | self.anchor = p.clone() 547 | #print self.anchor 548 | self.width = width 549 | self.text = tk.StringVar(_root) 550 | self.text.set("") 551 | self.fill = "gray" 552 | self.color = "black" 553 | self.font = DEFAULT_CONFIG['font'] 554 | self.entry = None 555 | 556 | def _draw(self, canvas, options): 557 | p = self.anchor 558 | x,y = canvas.toScreen(p.x,p.y) 559 | frm = tk.Frame(canvas.master) 560 | self.entry = tk.Entry(frm, 561 | width=self.width, 562 | textvariable=self.text, 563 | bg = self.fill, 564 | fg = self.color, 565 | font=self.font) 566 | self.entry.pack() 567 | self.setFill(self.fill) 568 | return canvas.create_window(x,y,window=frm) 569 | 570 | def getText(self): 571 | return self.text.get() 572 | 573 | def _move(self, dx, dy): 574 | self.anchor.move(dx,dy) 575 | 576 | def getAnchor(self): 577 | return self.anchor.clone() 578 | 579 | def clone(self): 580 | other = Entry(self.anchor, self.width) 581 | other.config = self.config 582 | other.text = tk.StringVar() 583 | other.text.set(self.text.get()) 584 | other.fill = self.fill 585 | return other 586 | 587 | def setText(self, t): 588 | self.text.set(t) 589 | 590 | def setFill(self, color): 591 | self.fill = color 592 | if self.entry: 593 | self.entry.config(bg=color) 594 | 595 | def _setFontComponent(self, which, value): 596 | font = list(self.font) 597 | font[which] = value 598 | self.font = tuple(font) 599 | if self.entry: 600 | self.entry.config(font=self.font) 601 | 602 | def setFace(self, face): 603 | if face in ['helvetica','arial','courier','times roman']: 604 | self._setFontComponent(0, face) 605 | else: 606 | raise GraphicsError, BAD_OPTION 607 | 608 | def setSize(self, size): 609 | if 5 <= size <= 36: 610 | self._setFontComponent(1,size) 611 | else: 612 | raise GraphicsError, BAD_OPTION 613 | 614 | def setStyle(self, style): 615 | if style in ['bold','normal','italic', 'bold italic']: 616 | self._setFontComponent(2,style) 617 | else: 618 | raise GraphicsError, BAD_OPTION 619 | 620 | def setTextColor(self, color): 621 | self.color=color 622 | if self.entry: 623 | self.entry.config(fg=color) 624 | 625 | 626 | class Image(GraphicsObject): 627 | 628 | idCount = 0 629 | imageCache = {} # keep images here to avoid gc 630 | 631 | def __init__(self, p, file=None): 632 | GraphicsObject.__init__(self, []) 633 | self.file = file 634 | self.anchor = p.clone() 635 | self.imageId = Image.idCount 636 | Image.idCount = Image.idCount + 1 637 | 638 | def _draw(self, canvas, options): 639 | p = self.anchor 640 | x,y = canvas.toScreen(p.x,p.y) 641 | img = tk.PhotoImage(file=self.file, master=canvas) 642 | self.imageCache[self.imageId] = img # save in cache to avoid gc 643 | return canvas.create_image(x,y,image=img) 644 | 645 | def _move(self, dx, dy): 646 | self.anchor.move(dx,dy) 647 | 648 | def undraw(self): 649 | del self.imageCache[self.imageId] # allow gc of tk photoimage 650 | GraphicsObject.undraw(self) 651 | 652 | def getAnchor(self): 653 | return self.anchor.clone() 654 | 655 | def clone(self): 656 | other = Image(self.anchor, self.file) 657 | other.config = self.config 658 | return other 659 | 660 | def color_rgb(r,g,b): 661 | """r,g,b are intensities of red, green, and blue in range (0-255) 662 | Returns color specifier string for the resulting color""" 663 | return "#%02x%02x%02x" % (r,g,b) 664 | 665 | def test(): 666 | win = GraphWin() 667 | win.setCoords(0,0,10,10) 668 | t = Text(Point(5,5), "Centered Text") 669 | t.draw(win) 670 | p = Polygon(Point(1,1), Point(5,3), Point(2,7)) 671 | p.draw(win) 672 | e = Entry(Point(5,6), 10) 673 | e.draw(win) 674 | win.getMouse() 675 | p.setFill("red") 676 | p.setOutline("blue") 677 | p.setWidth(2) 678 | s = "" 679 | for pt in p.getPoints(): 680 | s = s + "(%0.1f,%0.1f) " % (pt.getX(), pt.getY()) 681 | t.setText(e.getText()) 682 | e.setFill("green") 683 | e.setText("Spam!") 684 | e.move(2,0) 685 | win.getMouse() 686 | p.move(2,3) 687 | s = "" 688 | for pt in p.getPoints(): 689 | s = s + "(%0.1f,%0.1f) " % (pt.getX(), pt.getY()) 690 | t.setText(s) 691 | win.getMouse() 692 | p.undraw() 693 | e.undraw() 694 | t.setStyle("bold") 695 | win.getMouse() 696 | t.setStyle("normal") 697 | win.getMouse() 698 | t.setStyle("italic") 699 | win.getMouse() 700 | t.setStyle("bold italic") 701 | win.getMouse() 702 | t.setSize(14) 703 | win.getMouse() 704 | t.setFace("arial") 705 | t.setSize(20) 706 | win.getMouse() 707 | win.close() 708 | 709 | if __name__ == "__main__": 710 | test() 711 | --------------------------------------------------------------------------------