├── .gitignore ├── Automaton ├── DFA3.1.py ├── DPDA4.1.py ├── GrammarAnalyzer4.3.2.py ├── LexicalAnalyzer4.3.1.py ├── NFA3.2.py ├── NFASimulation3.4.py ├── NPDA4.2.py └── Pattern3.3.py ├── LICENSE ├── LambdaCalculus ├── FizzBuzz.py ├── LambdaCalculus7.1.py └── lambda6.1.py ├── README.md ├── Simple ├── Denotation2.4.py ├── Evaluate2.3.2.py ├── Machine2.3.1-1.py └── Machine2.3.1-2.py ├── Turing └── DTM.py ├── combinations ├── MultiInt.py ├── combinations_generater.py ├── enumerations_generater.py └── permutations_generater.py ├── graphs ├── depth_first_paths.py ├── depth_first_search.py └── undirected_graphs.py ├── search ├── binary_search_tree.py ├── print_tree │ ├── MANIFEST │ ├── Makefile │ ├── README │ ├── mdoc.l │ ├── sample │ ├── tex.c │ ├── texsample │ ├── tpar │ ├── tpar.l │ ├── tpsample │ ├── tree.1 │ ├── tree.l │ ├── unpar │ ├── unpar.l │ └── use.raw └── tree_ergodic.py └── sort ├── QuickSortDemo.java ├── counting_sort.py ├── heap_sort.py ├── insertion_sort.py ├── merge_sort.py ├── quick_sort.py ├── radix_sort.py ├── selection_sort.py └── shell_sort.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### C ### 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Libraries 15 | *.lib 16 | *.a 17 | *.la 18 | *.lo 19 | 20 | # Shared objects (inc. Windows DLLs) 21 | *.dll 22 | *.so 23 | *.so.* 24 | *.dylib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | *.i*86 31 | *.x86_64 32 | *.hex 33 | 34 | 35 | ### Python ### 36 | # Byte-compiled / optimized / DLL files 37 | __pycache__/ 38 | *.py[cod] 39 | 40 | # C extensions 41 | *.so 42 | 43 | # Distribution / packaging 44 | .Python 45 | env/ 46 | build/ 47 | develop-eggs/ 48 | dist/ 49 | downloads/ 50 | eggs/ 51 | lib/ 52 | lib64/ 53 | parts/ 54 | sdist/ 55 | var/ 56 | *.egg-info/ 57 | .installed.cfg 58 | *.egg 59 | 60 | # PyInstaller 61 | # Usually these files are written by a python script from a template 62 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 63 | *.manifest 64 | *.spec 65 | 66 | # Installer logs 67 | pip-log.txt 68 | pip-delete-this-directory.txt 69 | 70 | # Unit test / coverage reports 71 | htmlcov/ 72 | .tox/ 73 | .coverage 74 | .cache 75 | nosetests.xml 76 | coverage.xml 77 | 78 | # Translations 79 | *.mo 80 | *.pot 81 | 82 | # Django stuff: 83 | *.log 84 | 85 | # Sphinx documentation 86 | docs/_build/ 87 | 88 | # PyBuilder 89 | target/ 90 | 91 | # Created by https://www.gitignore.io 92 | 93 | ### Ruby ### 94 | *.gem 95 | *.rbc 96 | /.config 97 | /coverage/ 98 | /InstalledFiles 99 | /pkg/ 100 | /spec/reports/ 101 | /test/tmp/ 102 | /test/version_tmp/ 103 | /tmp/ 104 | 105 | ## Specific to RubyMotion: 106 | .dat* 107 | .repl_history 108 | build/ 109 | 110 | ## Documentation cache and generated files: 111 | /.yardoc/ 112 | /_yardoc/ 113 | /doc/ 114 | /rdoc/ 115 | 116 | ## Environment normalisation: 117 | /.bundle/ 118 | /lib/bundler/man/ 119 | 120 | # for a library or gem, you might want to ignore these files since the code is 121 | # intended to run in multiple environments; otherwise, check them in: 122 | # Gemfile.lock 123 | # .ruby-version 124 | # .ruby-gemset 125 | 126 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 127 | .rvmrc 128 | 129 | 130 | ### vim ### 131 | [._]*.s[a-w][a-z] 132 | [._]s[a-w][a-z] 133 | *.un~ 134 | Session.vim 135 | .netrwhist 136 | *~ 137 | -------------------------------------------------------------------------------- /Automaton/DFA3.1.py: -------------------------------------------------------------------------------- 1 | ##Deterministic Finite Automaton,DFA 2 | ##3.1 确定性有限自动机 3 | ##python 3.4.1 4 | 5 | class FARule(object): 6 | def __init__(self, state, character, next_state): 7 | self.state = state 8 | self.character = character 9 | self.next_state = next_state 10 | 11 | def applies_to(self, state, character): 12 | return self.state == state and self.character == character 13 | 14 | def follow(self): 15 | return self.next_state 16 | 17 | 18 | class DFARulebook(object): 19 | def __init__(self, rules): 20 | self.rules = rules 21 | 22 | def next_state(self, state, character): 23 | return self.rule_for(state, character).follow() 24 | 25 | def rule_for(self, state, character): 26 | for rule in self.rules: 27 | if rule.applies_to(state, character): 28 | return rule 29 | 30 | 31 | class DFA(object): 32 | def __init__(self, current_state, accept_states, rulebook): 33 | self.current_state = current_state 34 | self.accept_states = accept_states 35 | self.rulebook = rulebook 36 | 37 | def accepting(self): 38 | return self.current_state in self.accept_states 39 | 40 | def read_character(self, character): 41 | self.current_state = self.rulebook.next_state(self.current_state, character) 42 | 43 | def read_string(self, string): 44 | for character in string: 45 | self.read_character(character) 46 | 47 | 48 | class DFADesign(object): 49 | def __init__(self, start_state, accept_states, rulebook): 50 | self.start_state = start_state 51 | self.accept_states = accept_states 52 | self.rulebook = rulebook 53 | 54 | def to_dfa(self): 55 | return DFA(self.start_state, self.accept_states, self.rulebook) 56 | 57 | def accepts(self, string): 58 | dfa = self.to_dfa() 59 | dfa.read_string(string) 60 | return dfa.accepting() 61 | 62 | 63 | ##test 64 | rulebook = DFARulebook([ 65 | FARule(1, 'a', 2), FARule(1, 'b', 1), 66 | FARule(2, 'a', 2), FARule(2, 'b', 3), 67 | FARule(3, 'a', 3), FARule(3, 'b', 3) 68 | ]) 69 | 70 | print(rulebook.next_state(1, 'a')) 71 | print(rulebook.next_state(1, 'b')) 72 | print(rulebook.next_state(2, 'b')) 73 | 74 | dfa_design = DFADesign(1, [3], rulebook) 75 | 76 | print(dfa_design.accepts('a')) 77 | print(dfa_design.accepts('baa')) 78 | print(dfa_design.accepts('baba')) 79 | -------------------------------------------------------------------------------- /Automaton/DPDA4.1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Deterministic PushDown Automaton,DPDA""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 4.1 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | class Stack(object): 10 | """ The realization of the stack 11 | """ 12 | def __init__(self, contents): 13 | self.contents = contents 14 | 15 | def push(self, character): 16 | return Stack([character] + self.contents) 17 | 18 | @property 19 | def pop(self): 20 | return Stack(self.contents[1:]) 21 | 22 | @property 23 | def top(self): 24 | return self.contents[0] 25 | 26 | def __str__(self): 27 | top = self.contents[0] 28 | underside = ''.join(self.contents[1:]) 29 | return '#'.format(**locals()) 30 | 31 | __repr__ = __str__ 32 | 33 | 34 | class PDAConfiguration(object): 35 | """ Used to store the PDA configuration (a state and a stack) 36 | """ 37 | STUCK_STATE = object() 38 | 39 | def __init__(self, state, stack): 40 | self.state = state 41 | self.stack = stack 42 | 43 | @property 44 | def stuck(self): 45 | return PDAConfiguration(self.__class__.STUCK_STATE, self.stack) 46 | 47 | @property 48 | def if_stuck(self): 49 | return self.state == self.__class__.STUCK_STATE 50 | 51 | def __str__(self): 52 | state = self.state 53 | stack = repr(self.stack) 54 | return '#'.format(**locals()) 55 | 56 | __repr__ = __str__ 57 | 58 | 59 | class PDARule(object): 60 | """ Used to express a rule, in a rule book of PDA 61 | """ 62 | def __init__(self, state, character, next_state, pop_character, push_characters): 63 | self.state = state 64 | self.character = character 65 | self.next_state = next_state 66 | self.pop_character = pop_character 67 | self.push_characters = push_characters 68 | 69 | def applies_to(self, configuration, character): 70 | return self.state == configuration.state and \ 71 | self.pop_character == configuration.stack.top and \ 72 | self.character == character 73 | 74 | def follow(self, configuration): 75 | return PDAConfiguration(self.next_state, self.next_stack(configuration)) 76 | 77 | def next_stack(self, configuration): 78 | popped_stack = configuration.stack.pop 79 | for item in self.push_characters[::-1]: 80 | popped_stack = popped_stack.push(item) 81 | return popped_stack 82 | 83 | def __str__(self): 84 | s = repr(self.state) 85 | char = repr(self.character) 86 | nexts = repr(self.next_state) 87 | pop_char = repr(self.pop_character) 88 | push_chars = repr(self.push_characters) 89 | 90 | return '#') 196 | self.assertEqual(stack.pop.pop.top, 'c') 197 | self.assertEqual(stack.push('x').push('y').top, 'y') 198 | self.assertEqual(stack.push('x').push('y').pop.top, 'x') 199 | 200 | def test_PDARule(self): 201 | rule = PDARule(1, '(', 2, '$', ['b', '$']) 202 | configuration = PDAConfiguration(1, Stack(['$'])) 203 | print(rule, end = '\n\n') 204 | self.assertEqual(str(configuration), '#>') 205 | self.assertEqual(rule.applies_to(configuration, '('), True) 206 | 207 | self.assertEqual(str(rule.follow(configuration)), '#>') 208 | 209 | def test_DPDARulebook(self): 210 | rulebook = DPDARulebook([ 211 | PDARule(1, '(', 2, '$', ['b', '$']), 212 | PDARule(2, '(', 2, 'b', ['b', 'b']), 213 | PDARule(2, ')', 2, 'b', []), 214 | PDARule(2, None, 1, '$', ['$']) 215 | ]) 216 | configuration = PDAConfiguration(1, Stack(['$'])) 217 | configuration = rulebook.next_configuration(configuration, '(') 218 | self.assertEqual(str(configuration), '#>') 219 | configuration = rulebook.next_configuration(configuration, '(') 220 | self.assertEqual(str(configuration), '#>') 221 | configuration = rulebook.next_configuration(configuration, ')') 222 | self.assertEqual(str(configuration), '#>') 223 | 224 | def test_DPDA(self): 225 | rulebook = DPDARulebook([ 226 | PDARule(1, '(', 2, '$', ['b', '$']), 227 | PDARule(2, '(', 2, 'b', ['b', 'b']), 228 | PDARule(2, ')', 2, 'b', []), 229 | PDARule(2, None, 1, '$', ['$']) 230 | ]) 231 | dpda = DPDA(PDAConfiguration(1, Stack(['$'])), [1], rulebook) 232 | self.assertEqual(dpda.accepting, True) 233 | dpda.read_string('(()') 234 | self.assertEqual(dpda.accepting, False) 235 | self.assertEqual(str(dpda.current_configuration), '#>') 236 | 237 | def test_follow_free_moves(self): 238 | rulebook = DPDARulebook([ 239 | PDARule(1, '(', 2, '$', ['b', '$']), 240 | PDARule(2, '(', 2, 'b', ['b', 'b']), 241 | PDARule(2, ')', 2, 'b', []), 242 | PDARule(2, None, 1, '$', ['$']) 243 | ]) 244 | configuration = PDAConfiguration(2, Stack(['$'])) 245 | self.assertEqual(str(configuration), '#>') 246 | self.assertEqual(str(rulebook.follow_free_moves(configuration)), '#>') 247 | 248 | def test_DPDA_follow_free_moves(self): 249 | rulebook = DPDARulebook([ 250 | PDARule(1, '(', 2, '$', ['b', '$']), 251 | PDARule(2, '(', 2, 'b', ['b', 'b']), 252 | PDARule(2, ')', 2, 'b', []), 253 | PDARule(2, None, 1, '$', ['$']) 254 | ]) 255 | dpda = DPDA(PDAConfiguration(1, Stack(['$'])), [1], rulebook) 256 | dpda.read_string('(()(') 257 | self.assertEqual(dpda.accepting, False) 258 | self.assertEqual(str(dpda.current_configuration), '#>') 259 | dpda.read_string('))()') 260 | self.assertEqual(dpda.accepting, True) 261 | self.assertEqual(str(dpda.current_configuration), '#>') 262 | 263 | def test_DPDADesign(self): 264 | rulebook = DPDARulebook([ 265 | PDARule(1, '(', 2, '$', ['b', '$']), 266 | PDARule(2, '(', 2, 'b', ['b', 'b']), 267 | PDARule(2, ')', 2, 'b', []), 268 | PDARule(2, None, 1, '$', ['$']) 269 | ]) 270 | dpda_design = DPDADesign(1, '$', [1], rulebook) 271 | self.assertEqual(dpda_design.accepts('(((((((((())))))))))'), True) 272 | self.assertEqual(dpda_design.accepts('()(())((()))(()(()))'), True) 273 | self.assertEqual(dpda_design.accepts('(()(()(()()(()()))()'), False) 274 | 275 | def test_DPDA_stuck(self): 276 | rulebook = DPDARulebook([ 277 | PDARule(1, '(', 2, '$', ['b', '$']), 278 | PDARule(2, '(', 2, 'b', ['b', 'b']), 279 | PDARule(2, ')', 2, 'b', []), 280 | PDARule(2, None, 1, '$', ['$']) 281 | ]) 282 | dpda = DPDA(PDAConfiguration(1, Stack(['$'])), [1], rulebook) 283 | dpda_design = DPDADesign(1, '$', [1], rulebook) 284 | dpda.read_string('())') 285 | self.assertEqual(dpda.accepting, False) 286 | self.assertEqual(dpda.if_stuck, True) 287 | self.assertEqual(dpda_design.accepts('())'), False) 288 | 289 | 290 | if __name__ == '__main__': 291 | unittest.main() 292 | -------------------------------------------------------------------------------- /Automaton/GrammarAnalyzer4.3.2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Grammar Analyzer""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 4.3.2 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | import re 10 | 11 | class Stack(object): 12 | """ The realization of the stack 13 | """ 14 | def __init__(self, contents): 15 | self.contents = contents 16 | 17 | def push(self, character): 18 | return Stack([character] + self.contents) 19 | 20 | @property 21 | def pop(self): 22 | return Stack(self.contents[1:]) 23 | 24 | @property 25 | def top(self): 26 | return self.contents[0] 27 | 28 | def __str__(self): 29 | top = self.contents[0] 30 | underside = ''.join(self.contents[1:]) 31 | return '#'.format(**locals()) 32 | 33 | __repr__ = __str__ 34 | 35 | 36 | class PDAConfiguration(object): 37 | """ Used to store the PDA configuration (a state and a stack) 38 | """ 39 | STUCK_STATE = object() 40 | 41 | def __init__(self, state, stack): 42 | self.state = state 43 | self.stack = stack 44 | 45 | @property 46 | def stuck(self): 47 | return PDAConfiguration(self.__class__.STUCK_STATE, self.stack) 48 | 49 | @property 50 | def if_stuck(self): 51 | return self.state == self.__class__.STUCK_STATE 52 | 53 | def __str__(self): 54 | state = self.state 55 | stack = repr(self.stack) 56 | return '#'.format(**locals()) 57 | 58 | __repr__ = __str__ 59 | 60 | 61 | class PDARule(object): 62 | """ Used to express a rule, in a rule book of PDA 63 | """ 64 | def __init__(self, state, character, next_state, pop_character, push_characters): 65 | self.state = state 66 | self.character = character 67 | self.next_state = next_state 68 | self.pop_character = pop_character 69 | self.push_characters = push_characters 70 | 71 | def applies_to(self, configuration, character): 72 | return self.state == configuration.state and \ 73 | self.pop_character == configuration.stack.top and \ 74 | self.character == character 75 | 76 | def follow(self, configuration): 77 | return PDAConfiguration(self.next_state, self.next_stack(configuration)) 78 | 79 | def next_stack(self, configuration): 80 | popped_stack = configuration.stack.pop 81 | for item in self.push_characters[::-1]: 82 | popped_stack = popped_stack.push(item) 83 | return popped_stack 84 | 85 | def __str__(self): 86 | s = repr(self.state) 87 | char = repr(self.character) 88 | nexts = repr(self.next_state) 89 | pop_char = repr(self.pop_character) 90 | push_chars = repr(self.push_characters) 91 | 92 | return '# ::= | 260 | PDARule(2, None, 2, 'S', ['W']), 261 | PDARule(2, None, 2, 'S', ['A']), 262 | 263 | # ::= 'w' '(' ')' '{' '}' 264 | PDARule(2, None, 2, 'W', ['w', '(', 'E', ')', '{', 'S', '}']), 265 | 266 | # ::= 'v' '=' 267 | PDARule(2, None, 2, 'A', ['v', '=', 'E']), 268 | 269 | # ::= 270 | PDARule(2, None, 2, 'E', ['L']), 271 | 272 | # ::= '<' | 273 | PDARule(2, None, 2, 'L', ['M', '<', 'L']), 274 | PDARule(2, None, 2, 'L', ['M']), 275 | 276 | # ::= '*' | 277 | PDARule(2, None, 2, 'M', ['T', '*', 'M']), 278 | PDARule(2, None, 2, 'M', ['T']), 279 | 280 | # ::= 'n' | 'v' 281 | PDARule(2, None, 2, 'T', ['n']), 282 | PDARule(2, None, 2, 'T', ['v']) 283 | ] 284 | 285 | token_rules = [PDARule(2, rule['token'], 2, rule['token'], []) for rule in LexicalAnalyzer.GRAMMAR] 286 | 287 | stop_rule = PDARule(2, None, 3, '$', ['$']) 288 | 289 | rulebook = NPDARulebook([start_rule, stop_rule] + symbol_rules + token_rules) 290 | 291 | npda_design = NPDADesign(1, '$', [3], rulebook) 292 | 293 | token_string = ''.join(LexicalAnalyzer('while (x < 5) { x = x * 3 }').analyze) 294 | 295 | print('while (x < 5) { x = x * 3 }') 296 | print(token_string) 297 | 298 | print(npda_design.accepts(token_string)) 299 | 300 | print(npda_design.accepts(''.join(LexicalAnalyzer('while (x < 5 x = x * }').analyze))) 301 | -------------------------------------------------------------------------------- /Automaton/LexicalAnalyzer4.3.1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Lexical Analyzer""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 4.3.1 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | import re 10 | 11 | class LexicalAnalyzer(object): 12 | """ 词法分析 13 | 将代码字符串解析成符号列表 14 | """ 15 | GRAMMAR = [ 16 | { 'token': 'i', 'pattern': r'if' }, # if 关键字 17 | { 'token': 'e', 'pattern': r'else' }, # else 关键字 18 | { 'token': 'w', 'pattern': r'while' }, # while 关键字 19 | { 'token': 'd', 'pattern': r'do-nothing' }, # do-nothing 关键字 20 | { 'token': '(', 'pattern': r'\(' }, # 左小括号 21 | { 'token': ')', 'pattern': r'\)' }, # 右小括号 22 | { 'token': '{', 'pattern': r'\{' }, # 左大括号 23 | { 'token': '}', 'pattern': r'\}' }, # 右大括号 24 | { 'token': ';', 'pattern': r';' }, # 分号 25 | { 'token': '=', 'pattern': r'=' }, # 等号 26 | { 'token': '+', 'pattern': r'\+' }, # 加号 27 | { 'token': '*', 'pattern': r'\*' }, # 乘号 28 | { 'token': '<', 'pattern': r'\<' }, # 小于号 29 | { 'token': 'n', 'pattern': r'[0-9]+' }, # 数字 30 | { 'token': 'b', 'pattern': r'true|false' }, # 布尔值 31 | { 'token': 'v', 'pattern': r'[a-z]+' } # 变量名 32 | ] 33 | 34 | def __init__(self, string): 35 | self.string = string 36 | 37 | @property 38 | def analyze(self): 39 | tokens = [] 40 | while self.more_tokens: 41 | tokens.append(self.next_token) 42 | return tokens 43 | 44 | @property 45 | def more_tokens(self): 46 | if self.string != '': 47 | return True 48 | else: 49 | return False 50 | 51 | @property 52 | def next_token(self): 53 | rule, match = self.rule_matching(self.string) 54 | self.string = self.string_after(match) 55 | return rule['token'] 56 | 57 | def rule_matching(self, string): 58 | grammar = self.__class__.GRAMMAR 59 | matches = [self.match_at_beginning(rule['pattern'], string) for rule in grammar] 60 | rules_with_matches = [[rule, match] for rule, match in zip(grammar, matches) if match != None] 61 | return self.rule_with_longest_match(rules_with_matches) 62 | 63 | def match_at_beginning(self, pattern, string): 64 | result = re.match(pattern, string) 65 | if result == None: 66 | return None 67 | else: 68 | return result.group(0) 69 | 70 | def rule_with_longest_match(self, rules_with_matches): 71 | return max(rules_with_matches, key = lambda value: len(value[1])) 72 | 73 | def string_after(self, match): 74 | index = self.string.find(match) + len(match) 75 | return self.string[index:].strip() 76 | 77 | 78 | ##test 79 | print('y = x * 7') 80 | print(LexicalAnalyzer('y = x * 7').analyze) 81 | 82 | print('\n') 83 | print('while (x < 5) { x = x * 3 }') 84 | print(LexicalAnalyzer('while (x < 5) { x = x * 3 }').analyze) 85 | 86 | print('\n') 87 | print('if (x < 10) { y = true; x = 0 } else { do-nothing }') 88 | print(LexicalAnalyzer('if (x < 10) { y = true; x = 0 } else { do-nothing }').analyze) 89 | 90 | print('\n') 91 | print('x = false') 92 | print(LexicalAnalyzer('x = false').analyze) 93 | 94 | print('\n') 95 | print('x = falsehood') 96 | print(LexicalAnalyzer('x = falsehood').analyze) 97 | -------------------------------------------------------------------------------- /Automaton/NFA3.2.py: -------------------------------------------------------------------------------- 1 | ##Nondeterministic Finite Automata,NFA 2 | ##3.2 非确定性有限自动机 3 | ##python 3.4.1 4 | 5 | class FARule(object): 6 | def __init__(self, state, character, next_state): 7 | self.state = state 8 | self.character = character 9 | self.next_state = next_state 10 | 11 | def applies_to(self, state, character): 12 | return self.state == state and self.character == character 13 | 14 | def follow(self): 15 | return self.next_state 16 | 17 | 18 | class NFARulebook(object): 19 | def __init__(self, rules): 20 | self.rules = rules 21 | 22 | def next_states(self, states, character): 23 | nexts = [] 24 | for state in states: 25 | nexts += self.follow_rules_for(state, character) 26 | return set(nexts) 27 | 28 | def follow_rules_for(self, state, character): 29 | return [rule.follow() for rule in self.rules_for(state, character)] 30 | 31 | def rules_for(self, state, character): 32 | return [rule for rule in self.rules if rule.applies_to(state, character)] 33 | 34 | def follow_free_moves(self, states): 35 | more_states = self.next_states(states, None) 36 | if more_states.issubset(states): 37 | return states 38 | else: 39 | return self.follow_free_moves(states.union(more_states)) 40 | 41 | 42 | class NFA(object): 43 | def __init__(self, current_states, accept_states, rulebook): 44 | self._current_states = current_states 45 | self.accept_states = accept_states 46 | self.rulebook = rulebook 47 | 48 | @property 49 | def current_states(self): 50 | return self.rulebook.follow_free_moves(self._current_states) 51 | 52 | def accepting(self): 53 | if [state for state in self.current_states if state in self.accept_states]: 54 | return True 55 | else: 56 | return False 57 | 58 | def read_character(self, character): 59 | '''读取一个字符,获取通过自由移动能到达的所有状态集合,再计算出包含所有下一个状态的集合 60 | ''' 61 | self._current_states = self.rulebook.next_states(self.current_states, character) 62 | 63 | def read_string(self, string): 64 | for character in string: 65 | self.read_character(character) 66 | 67 | 68 | class NFADesign(object): 69 | def __init__(self, start_state, accept_states, rulebook): 70 | self.start_state = start_state 71 | self.accept_states = accept_states 72 | self.rulebook = rulebook 73 | 74 | def to_nfa(self): 75 | return NFA(set([self.start_state]), self.accept_states, self.rulebook) 76 | 77 | def accepts(self, string): 78 | nfa = self.to_nfa() 79 | nfa.read_string(string) 80 | return nfa.accepting() 81 | 82 | 83 | ##NFA 84 | rulebook = NFARulebook([ 85 | FARule(1, 'a', 1), FARule(1, 'b', 1), FARule(1, 'b', 2), 86 | FARule(2, 'a', 3), FARule(2, 'b', 3), 87 | FARule(3, 'a', 4), FARule(3, 'b', 4) 88 | ]) 89 | 90 | print(rulebook.next_states(set([1]), 'a')) 91 | print(rulebook.next_states(set([1, 2]), 'a')) 92 | print(rulebook.next_states(set([1, 3]), 'b')) 93 | 94 | nfa_design = NFADesign(1, [4], rulebook) 95 | 96 | print(nfa_design.accepts('bab')) 97 | print(nfa_design.accepts('bbbbbb')) 98 | print(nfa_design.accepts('bbabb')) 99 | 100 | ##自由移动 101 | rulebook2 = NFARulebook([ 102 | FARule(1, None, 2), FARule(1, None, 4), 103 | FARule(2, 'a', 3), 104 | FARule(3, 'a', 2), 105 | FARule(4, 'a', 5), 106 | FARule(5, 'a', 6), 107 | FARule(6, 'a', 4), 108 | ]) 109 | 110 | print(rulebook2.next_states(set([1]), None)) 111 | print(rulebook2.follow_free_moves(set([1]))) 112 | 113 | nfa_design2 = NFADesign(1,[2, 4], rulebook2) 114 | 115 | print(nfa_design2.accepts('aa')) 116 | print(nfa_design2.accepts('aaa')) 117 | print(nfa_design2.accepts('aaaaa')) 118 | print(nfa_design2.accepts('aaaaaa')) 119 | -------------------------------------------------------------------------------- /Automaton/NFASimulation3.4.py: -------------------------------------------------------------------------------- 1 | ##NFA Simulation 2 | ##3.4 等价性 3 | ##python 3.4.1 4 | 5 | from pprint import pprint 6 | ##NFA 7 | class FARule(object): 8 | def __init__(self, state, character, next_state): 9 | self.state = state 10 | self.character = character 11 | self.next_state = next_state 12 | 13 | def applies_to(self, state, character): 14 | return self.state == state and self.character == character 15 | 16 | def follow(self): 17 | return self.next_state 18 | 19 | def __str__(self): 20 | state = self.state 21 | character = self.character 22 | next_state = self.next_state 23 | return ' --{character}--> #>'.format(**locals()) 24 | 25 | __repr__ = __str__ 26 | 27 | 28 | class DFARulebook(object): 29 | def __init__(self, rules): 30 | self.rules = rules 31 | 32 | def next_state(self, state, character): 33 | return self.rule_for(state, character).follow() 34 | 35 | def rule_for(self, state, character): 36 | for rule in self.rules: 37 | if rule.applies_to(state, character): 38 | return rule 39 | 40 | 41 | class DFA(object): 42 | def __init__(self, current_state, accept_states, rulebook): 43 | self.current_state = current_state 44 | self.accept_states = accept_states 45 | self.rulebook = rulebook 46 | 47 | def accepting(self): 48 | return self.current_state in self.accept_states 49 | 50 | def read_character(self, character): 51 | self.current_state = self.rulebook.next_state(self.current_state, character) 52 | 53 | def read_string(self, string): 54 | for character in string: 55 | self.read_character(character) 56 | 57 | 58 | class DFADesign(object): 59 | def __init__(self, start_state, accept_states, rulebook): 60 | self.start_state = start_state 61 | self.accept_states = accept_states 62 | self.rulebook = rulebook 63 | 64 | def to_dfa(self): 65 | return DFA(self.start_state, self.accept_states, self.rulebook) 66 | 67 | def accepts(self, string): 68 | dfa = self.to_dfa() 69 | dfa.read_string(string) 70 | return dfa.accepting() 71 | 72 | 73 | class NFARulebook(object): 74 | def __init__(self, rules): 75 | self.rules = rules 76 | 77 | def next_states(self, states, character): 78 | nexts = [] 79 | for state in states: 80 | nexts += self.follow_rules_for(state, character) 81 | return set(nexts) 82 | 83 | def follow_rules_for(self, state, character): 84 | return [rule.follow() for rule in self.rules_for(state, character)] 85 | 86 | def rules_for(self, state, character): 87 | return [rule for rule in self.rules if rule.applies_to(state, character)] 88 | 89 | def follow_free_moves(self, states): 90 | more_states = self.next_states(states, None) 91 | if more_states.issubset(states): 92 | return states 93 | else: 94 | return self.follow_free_moves(states.union(more_states)) 95 | 96 | def alphabet(self): 97 | return(list(set([rule.character for rule in self.rules if not rule.character == None]))) 98 | 99 | 100 | class NFA(object): 101 | def __init__(self, current_states, accept_states, rulebook): 102 | self._current_states = current_states 103 | self.accept_states = accept_states 104 | self.rulebook = rulebook 105 | 106 | @property 107 | def current_states(self): 108 | return self.rulebook.follow_free_moves(self._current_states) 109 | 110 | def accepting(self): 111 | if [state for state in self.current_states if state in self.accept_states]: 112 | return True 113 | else: 114 | return False 115 | 116 | def read_character(self, character): 117 | '''读取一个字符,获取通过自由移动能到达的所有状态集合,再计算出包含所有下一个状态的集合 118 | ''' 119 | self._current_states = self.rulebook.next_states(self.current_states, character) 120 | 121 | def read_string(self, string): 122 | for character in string: 123 | self.read_character(character) 124 | 125 | 126 | class NFADesign(object): 127 | def __init__(self, start_state, accept_states, rulebook): 128 | self.start_state = start_state 129 | self.accept_states = accept_states 130 | self.rulebook = rulebook 131 | 132 | def to_nfa(self, current_states = None): 133 | if current_states == None: 134 | current_states = set([self.start_state]) 135 | return NFA(current_states, self.accept_states, self.rulebook) 136 | 137 | def accepts(self, string): 138 | nfa = self.to_nfa() 139 | nfa.read_string(string) 140 | return nfa.accepting() 141 | 142 | 143 | class NFASimulation(object): 144 | def __init__(self, nfa_design): 145 | self.nfa_design = nfa_design 146 | 147 | def next_state(self, state, character): 148 | nfa = self.nfa_design.to_nfa(state) 149 | nfa.read_character(character) 150 | return nfa.current_states 151 | 152 | def rules_for(self, state): 153 | return [FARule(state, character, self.next_state(state, character)) 154 | for character in self.nfa_design.rulebook.alphabet()] 155 | 156 | def discover_states_and_rules(self, states): 157 | rules = [] 158 | for state in states: 159 | rules += self.rules_for(state) 160 | more_states = [rule.follow() for rule in rules] 161 | 162 | temp = [] 163 | for s in more_states: 164 | if s not in states: 165 | temp += [s] 166 | 167 | if temp: 168 | return self.discover_states_and_rules(states + temp) 169 | else: 170 | return [states, rules] 171 | 172 | def to_dfa_design(self): 173 | start_state = self.nfa_design.to_nfa().current_states 174 | states, rules = self.discover_states_and_rules([set(start_state)]) 175 | accept_states = [state for state in states if self.nfa_design.to_nfa(state).accepting()] 176 | 177 | return DFADesign(start_state, accept_states, DFARulebook(rules)) 178 | 179 | 180 | ##test 181 | rulebook = NFARulebook([ 182 | FARule(1, 'a', 1), FARule(1, 'a', 2), FARule(1, None, 2), 183 | FARule(2, 'b', 3), 184 | FARule(3, 'b', 1), FARule(3, None, 2) 185 | ]) 186 | 187 | nfa_design = NFADesign(1, [3], rulebook) 188 | print(nfa_design.to_nfa().current_states) 189 | print(nfa_design.to_nfa(set([2])).current_states) 190 | print(nfa_design.to_nfa(set([3])).current_states) 191 | 192 | print('') 193 | nfa = nfa_design.to_nfa(set([2, 3])) 194 | nfa.read_character('b') 195 | print(nfa.current_states) 196 | 197 | print('') 198 | simulation = NFASimulation(nfa_design) 199 | print(simulation.next_state(set([1, 2]), 'a')) 200 | print(simulation.next_state(set([1, 2]), 'b')) 201 | print(simulation.next_state(set([3, 2]), 'b')) 202 | print(simulation.next_state(set([1, 3, 2]), 'b')) 203 | print(simulation.next_state(set([1, 3, 2]), 'a')) 204 | 205 | print('') 206 | print(rulebook.alphabet()) 207 | pprint(simulation.rules_for(set([1, 2]))) 208 | 209 | print('') 210 | pprint(simulation.rules_for(set([3, 2]))) 211 | 212 | print('') 213 | start_state = nfa_design.to_nfa().current_states 214 | print(start_state) 215 | pprint(simulation.discover_states_and_rules([start_state])) 216 | 217 | print('') 218 | dfa_design = simulation.to_dfa_design() 219 | print(dfa_design.accepts('aaa')) 220 | print(dfa_design.accepts('aab')) 221 | print(dfa_design.accepts('bbbabb')) 222 | -------------------------------------------------------------------------------- /Automaton/NPDA4.2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Nondeterministic PushDown Automaton,NPDA""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 4.2 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | from pprint import pprint 9 | 10 | class Stack(object): 11 | """ The realization of the stack 12 | """ 13 | def __init__(self, contents): 14 | self.contents = contents 15 | 16 | def push(self, character): 17 | return Stack([character] + self.contents) 18 | 19 | @property 20 | def pop(self): 21 | return Stack(self.contents[1:]) 22 | 23 | @property 24 | def top(self): 25 | return self.contents[0] 26 | 27 | def __str__(self): 28 | top = self.contents[0] 29 | underside = ''.join(self.contents[1:]) 30 | return '#'.format(**locals()) 31 | 32 | __repr__ = __str__ 33 | 34 | 35 | class PDAConfiguration(object): 36 | """ Used to store the PDA configuration (a state and a stack) 37 | """ 38 | STUCK_STATE = object() 39 | 40 | def __init__(self, state, stack): 41 | self.state = state 42 | self.stack = stack 43 | 44 | @property 45 | def stuck(self): 46 | return PDAConfiguration(self.__class__.STUCK_STATE, self.stack) 47 | 48 | @property 49 | def if_stuck(self): 50 | return self.state == self.__class__.STUCK_STATE 51 | 52 | def __str__(self): 53 | state = self.state 54 | stack = repr(self.stack) 55 | return '#'.format(**locals()) 56 | 57 | __repr__ = __str__ 58 | 59 | 60 | class PDARule(object): 61 | """ Used to express a rule, in a rule book of PDA 62 | """ 63 | def __init__(self, state, character, next_state, pop_character, push_characters): 64 | self.state = state 65 | self.character = character 66 | self.next_state = next_state 67 | self.pop_character = pop_character 68 | self.push_characters = push_characters 69 | 70 | def applies_to(self, configuration, character): 71 | return self.state == configuration.state and \ 72 | self.pop_character == configuration.stack.top and \ 73 | self.character == character 74 | 75 | def follow(self, configuration): 76 | return PDAConfiguration(self.next_state, self.next_stack(configuration)) 77 | 78 | def next_stack(self, configuration): 79 | popped_stack = configuration.stack.pop 80 | for item in self.push_characters[::-1]: 81 | popped_stack = popped_stack.push(item) 82 | return popped_stack 83 | 84 | def __str__(self): 85 | s = repr(self.state) 86 | char = repr(self.character) 87 | nexts = repr(self.next_state) 88 | pop_char = repr(self.pop_character) 89 | push_chars = repr(self.push_characters) 90 | 91 | return '#') 197 | self.assertEqual(stack.pop.pop.top, 'c') 198 | self.assertEqual(stack.push('x').push('y').top, 'y') 199 | self.assertEqual(stack.push('x').push('y').pop.top, 'x') 200 | 201 | def test_PDARule(self): 202 | rule = PDARule(1, '(', 2, '$', ['b', '$']) 203 | configuration = PDAConfiguration(1, Stack(['$'])) 204 | self.assertEqual(str(configuration), '#>') 205 | self.assertEqual(rule.applies_to(configuration, '('), True) 206 | 207 | self.assertEqual(str(rule.follow(configuration)), '#>') 208 | 209 | def test_NPDA(self): 210 | rulebook = NPDARulebook([ 211 | PDARule(1, 'a', 1, '$', ['a', '$']), 212 | PDARule(1, 'a', 1, 'a', ['a', 'a']), 213 | PDARule(1, 'a', 1, 'b', ['a', 'b']), 214 | PDARule(1, 'b', 1, '$', ['b', '$']), 215 | PDARule(1, 'b', 1, 'a', ['b', 'a']), 216 | PDARule(1, 'b', 1, 'b', ['b', 'b']), 217 | PDARule(1, None, 2, '$', ['$']), 218 | PDARule(1, None, 2, 'a', ['a']), 219 | PDARule(1, None, 2, 'b', ['b']), 220 | PDARule(2, 'a', 2, 'a', []), 221 | PDARule(2, 'b', 2, 'b', []), 222 | PDARule(2, None, 3, '$', ['$']) 223 | ]) 224 | configuration = PDAConfiguration(1, Stack(['$'])) 225 | self.assertEqual(str(configuration), '#>') 226 | npda = NPDA(set([configuration]), [3], rulebook) 227 | self.assertEqual(npda.accepting, True) 228 | pprint(npda.current_configurations) 229 | 230 | npda.read_string('abb') 231 | self.assertEqual(npda.accepting, False) 232 | pprint(npda.current_configurations) 233 | 234 | npda.read_character('a') 235 | self.assertEqual(npda.accepting, True) 236 | pprint(npda.current_configurations) 237 | 238 | def test_NPDADesign(self): 239 | rulebook = NPDARulebook([ 240 | PDARule(1, 'a', 1, '$', ['a', '$']), 241 | PDARule(1, 'a', 1, 'a', ['a', 'a']), 242 | PDARule(1, 'a', 1, 'b', ['a', 'b']), 243 | PDARule(1, 'b', 1, '$', ['b', '$']), 244 | PDARule(1, 'b', 1, 'a', ['b', 'a']), 245 | PDARule(1, 'b', 1, 'b', ['b', 'b']), 246 | PDARule(1, None, 2, '$', ['$']), 247 | PDARule(1, None, 2, 'a', ['a']), 248 | PDARule(1, None, 2, 'b', ['b']), 249 | PDARule(2, 'a', 2, 'a', []), 250 | PDARule(2, 'b', 2, 'b', []), 251 | PDARule(2, None, 3, '$', ['$']) 252 | ]) 253 | npda_design = NPDADesign(1, '$', [3], rulebook) 254 | self.assertEqual(npda_design.accepts('abba'), True) 255 | self.assertEqual(npda_design.accepts('babbaabbab'), True) 256 | self.assertEqual(npda_design.accepts('abb'), False) 257 | self.assertEqual(npda_design.accepts('baabaa'), False) 258 | 259 | 260 | if __name__ == '__main__': 261 | unittest.main() 262 | -------------------------------------------------------------------------------- /Automaton/Pattern3.3.py: -------------------------------------------------------------------------------- 1 | ##Regular Expression 2 | ##3.3 正则表达式 3 | ##python 3.4.1 4 | 5 | ##NFA 6 | class FARule(object): 7 | def __init__(self, state, character, next_state): 8 | self.state = state 9 | self.character = character 10 | self.next_state = next_state 11 | 12 | def applies_to(self, state, character): 13 | return self.state == state and self.character == character 14 | 15 | def follow(self): 16 | return self.next_state 17 | 18 | 19 | class NFARulebook(object): 20 | def __init__(self, rules): 21 | self.rules = rules 22 | 23 | def next_states(self, states, character): 24 | nexts = [] 25 | for state in states: 26 | nexts += self.follow_rules_for(state, character) 27 | return set(nexts) 28 | 29 | def follow_rules_for(self, state, character): 30 | return [rule.follow() for rule in self.rules_for(state, character)] 31 | 32 | def rules_for(self, state, character): 33 | return [rule for rule in self.rules if rule.applies_to(state, character)] 34 | 35 | def follow_free_moves(self, states): 36 | more_states = self.next_states(states, None) 37 | if more_states.issubset(states): 38 | return states 39 | else: 40 | return self.follow_free_moves(states.union(more_states)) 41 | 42 | 43 | class NFA(object): 44 | def __init__(self, current_states, accept_states, rulebook): 45 | self._current_states = current_states 46 | self.accept_states = accept_states 47 | self.rulebook = rulebook 48 | 49 | @property 50 | def current_states(self): 51 | return self.rulebook.follow_free_moves(self._current_states) 52 | 53 | def accepting(self): 54 | if [state for state in self.current_states if state in self.accept_states]: 55 | return True 56 | else: 57 | return False 58 | 59 | def read_character(self, character): 60 | '''读取一个字符,获取通过自由移动能到达的所有状态集合,再计算出包含所有下一个状态的集合 61 | ''' 62 | self._current_states = self.rulebook.next_states(self.current_states, character) 63 | 64 | def read_string(self, string): 65 | for character in string: 66 | self.read_character(character) 67 | 68 | 69 | class NFADesign(object): 70 | def __init__(self, start_state, accept_states, rulebook): 71 | self.start_state = start_state 72 | self.accept_states = accept_states 73 | self.rulebook = rulebook 74 | 75 | def to_nfa(self): 76 | return NFA(set([self.start_state]), self.accept_states, self.rulebook) 77 | 78 | def accepts(self, string): 79 | nfa = self.to_nfa() 80 | nfa.read_string(string) 81 | return nfa.accepting() 82 | 83 | 84 | ##正则表达式 85 | class Pattern(object): 86 | def bracket(self, outer_precedence): 87 | if self.precedence < outer_precedence: 88 | return '(' + self.to_s() + ')' 89 | else: 90 | return self.to_s() 91 | 92 | def __str__(self): 93 | return '/' + self.to_s() + '/' 94 | 95 | def matches(self, string): 96 | return self.to_nfa_design().accepts(string) 97 | 98 | 99 | class Empty(Pattern): 100 | def __init__(self): 101 | self.character = None 102 | self.precedence = 3 103 | 104 | def to_s(self): 105 | return '' 106 | 107 | def to_nfa_design(self): 108 | start_state = object() 109 | accept_states = [start_state] 110 | rulebook = NFARulebook([]) 111 | return NFADesign(start_state, accept_states, rulebook) 112 | 113 | 114 | class Literal(Pattern): 115 | def __init__(self, character): 116 | self.character = character 117 | self.precedence = 3 118 | 119 | def to_s(self): 120 | return self.character 121 | 122 | def to_nfa_design(self): 123 | start_state = object() 124 | accept_state = object() 125 | rule = FARule(start_state, self.character, accept_state) 126 | rulebook = NFARulebook([rule]) 127 | return NFADesign(start_state, [accept_state], rulebook) 128 | 129 | 130 | class Concatenate(Pattern): 131 | def __init__(self, first, second): 132 | self.first = first 133 | self.second = second 134 | self.precedence = 1 135 | 136 | def to_s(self): 137 | return ''.join([pattern.bracket(self.precedence) for pattern in [self.first, self.second]]) 138 | 139 | def to_nfa_design(self): 140 | first_nfa_design = self.first.to_nfa_design() 141 | second_nfa_design = self.second.to_nfa_design() 142 | 143 | start_state = first_nfa_design.start_state 144 | accept_states = second_nfa_design.accept_states 145 | rules = first_nfa_design.rulebook.rules + second_nfa_design.rulebook.rules 146 | extra_rules = [FARule(state, None, second_nfa_design.start_state) for state in first_nfa_design.accept_states] 147 | rulebook = NFARulebook(rules + extra_rules) 148 | 149 | return NFADesign(start_state, accept_states, rulebook) 150 | 151 | 152 | class Choose(Pattern): 153 | def __init__(self, first, second): 154 | self.first = first 155 | self.second = second 156 | self.precedence = 0 157 | 158 | def to_s(self): 159 | return '|'.join([pattern.bracket(self.precedence) for pattern in [self.first, self.second]]) 160 | 161 | def to_nfa_design(self): 162 | first_nfa_design = self.first.to_nfa_design() 163 | second_nfa_design = self.second.to_nfa_design() 164 | 165 | start_state = object() 166 | accept_states = first_nfa_design.accept_states + second_nfa_design.accept_states 167 | 168 | rules = first_nfa_design.rulebook.rules + second_nfa_design.rulebook.rules 169 | extra_rules = [FARule(start_state, None, nfa_design.start_state) for nfa_design in [first_nfa_design, second_nfa_design]] 170 | 171 | rulebook = NFARulebook(rules + extra_rules) 172 | 173 | return NFADesign(start_state, accept_states, rulebook) 174 | 175 | 176 | class Repeat(Pattern): 177 | def __init__(self, pattern): 178 | self.pattern = pattern 179 | self.precedence = 2 180 | 181 | def to_s(self): 182 | return self.pattern.bracket(self.precedence) + '*' 183 | 184 | def to_nfa_design(self): 185 | pattern_nfa_design = self.pattern.to_nfa_design() 186 | 187 | start_state = object() 188 | accept_states = pattern_nfa_design.accept_states + [start_state] 189 | rules = pattern_nfa_design.rulebook.rules 190 | extra_rules = [FARule(accept_state, None, pattern_nfa_design.start_state) for accept_state in pattern_nfa_design.accept_states] + [FARule(start_state, None, pattern_nfa_design.start_state)] 191 | rulebook = NFARulebook(rules + extra_rules) 192 | 193 | return NFADesign(start_state, accept_states, rulebook) 194 | 195 | 196 | ##test 197 | ##为每类正则表达式定义一个类,并使用这些类的实例表示任何正则表达式的抽象语法树 198 | pattern = Repeat( 199 | Choose( 200 | Concatenate(Literal('a'), Literal('b')), 201 | Literal('a') 202 | ) 203 | ) 204 | 205 | print(pattern) 206 | 207 | print('') 208 | nfa_design = Empty().to_nfa_design() 209 | print(nfa_design.accepts('')) 210 | print(nfa_design.accepts('a')) 211 | nfa_design = Literal('a').to_nfa_design() 212 | print(nfa_design.accepts('')) 213 | print(nfa_design.accepts('a')) 214 | print(nfa_design.accepts('b')) 215 | 216 | print('') 217 | print(Empty().matches('a')) 218 | print(Literal('a').matches('a')) 219 | 220 | print('') 221 | pattern = Concatenate(Literal('a'), Literal('b')) 222 | print(pattern) 223 | print(pattern.matches('a')) 224 | print(pattern.matches('ab')) 225 | print(pattern.matches('abc')) 226 | 227 | print('') 228 | pattern = Concatenate( 229 | Literal('a'), 230 | Concatenate(Literal('b'), Literal('c')) 231 | ) 232 | print(pattern) 233 | print(pattern.matches('a')) 234 | print(pattern.matches('ab')) 235 | print(pattern.matches('abc')) 236 | 237 | print('') 238 | pattern = Choose(Literal('a'),Literal('b')) 239 | print(pattern) 240 | print(pattern.matches('a')) 241 | print(pattern.matches('b')) 242 | print(pattern.matches('c')) 243 | 244 | print('') 245 | pattern = Repeat(Literal('a')) 246 | print(pattern) 247 | print(pattern.matches('')) 248 | print(pattern.matches('a')) 249 | print(pattern.matches('aaaa')) 250 | print(pattern.matches('b')) 251 | 252 | print('') 253 | pattern = Repeat( 254 | Concatenate( 255 | Literal('a'), 256 | Choose(Empty(),Literal('b')) 257 | ) 258 | ) 259 | print(pattern) 260 | print(pattern.matches('')) 261 | print(pattern.matches('a')) 262 | print(pattern.matches('ab')) 263 | print(pattern.matches('aba')) 264 | print(pattern.matches('abab')) 265 | print(pattern.matches('abaab')) 266 | print(pattern.matches('abba')) 267 | -------------------------------------------------------------------------------- /LambdaCalculus/FizzBuzz.py: -------------------------------------------------------------------------------- 1 | def to_integer(proc): 2 | return proc(lambda n: n + 1)(0) 3 | 4 | 5 | def to_boolean(proc): 6 | return (lambda b: b)(proc)(True)(False) 7 | 8 | 9 | def to_array(proc): 10 | array = [] 11 | while True: 12 | if to_boolean((lambda p: p(lambda x: lambda y: x))(proc)): 13 | break 14 | array.append((lambda l: (lambda p: p(lambda x: lambda y: x))((lambda p: p(lambda x: lambda y: y))(l)))(proc)) 15 | proc = (lambda l: (lambda p: p(lambda x: lambda y: y))((lambda p: p(lambda x: lambda y: y))(l)))(proc) 16 | 17 | return array 18 | 19 | 20 | def to_char(c): 21 | return '0123456789BFiuz'[to_integer(c)] 22 | 23 | 24 | def to_string(s): 25 | return ''.join([to_char(c) for c in to_array(s)]) 26 | 27 | 28 | # 用lambda演算实现FizzBuzz游戏 29 | solution = ((lambda k: lambda f: ((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda l: lambda x: lambda g: (lambda b: b)((lambda p: p(lambda x: lambda y: x))(l))(x)(lambda y: g(f((lambda l: (lambda p: p(lambda x: lambda y: y))((lambda p: p(lambda x: lambda y: y))(l)))(l))(x)(g))((lambda l: (lambda p: p(lambda x: lambda y: x))((lambda p: p(lambda x: lambda y: y))(l)))(l))(y))))(k)(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(lambda l: lambda x: (lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(l)(f(x))))(((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(m)(n))( lambda x: (lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(f((lambda n: lambda p: lambda x: p(n(p)(x)))(m))(n))(m)(x))( (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x)) )))((lambda p: lambda x: p(x)))((lambda p: lambda x: p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(x)))))))))))))))))))))))))))))))))))))))))))))))))))))(lambda n: (lambda b: b)((lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)(m))(lambda x: f((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n))(n)(x))(m))(n)((lambda p: lambda x: p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(x)))))))))))))))))))(((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x)))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x)))))))))))))((lambda b: b)((lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)(m))(lambda x: f((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n))(n)(x))(m))(n)((lambda p: lambda x: p(p(p(x)))))))(((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x)))))))))))))((lambda b: b)((lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)(m))(lambda x: f((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n))(n)(x))(m))(n)((lambda p: lambda x: p(p(p(p(p(x)))))))))(((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda n: lambda p: lambda x: p(n(p)(x)))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))))))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x)))))))))))(((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda n: (lambda l: lambda x: ((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda l: lambda x: lambda g: (lambda b: b)((lambda p: p(lambda x: lambda y: x))(l))(x)(lambda y: g(f((lambda l: (lambda p: p(lambda x: lambda y: y))((lambda p: p(lambda x: lambda y: y))(l)))(l))(x)(g))((lambda l: (lambda p: p(lambda x: lambda y: x))((lambda p: p(lambda x: lambda y: y))(l)))(l))(y))))(l)((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(x))((lambda l: lambda x: (lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: y))((lambda x: lambda y: lambda f: f(x)(y))(x)(l)))))((lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x)))))(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x)))))))))))(((lambda x: lambda y: lambda f: f(x)(y))((lambda x: lambda y: x))((lambda x: lambda y: x))))(lambda x: f(((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)(m))(lambda x: (lambda n: lambda p: lambda x: p(n(p)(x)))(f((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n))(n))(x))((lambda p: lambda x: x))))(n)(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))(x)))((lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))))(lambda f: lambda m: lambda n: (lambda b: b)((lambda m: lambda n: (lambda n: n(lambda x: (lambda x: lambda y: y))(lambda x: lambda y: x))((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n)))(n)(m))(lambda x: f((lambda m: lambda n: n((lambda n :(lambda p: p(lambda x: lambda y: x))(n(lambda p: (lambda x: lambda y: lambda f: f(x)(y))((lambda p: p(lambda x: lambda y: y))(p))((lambda n: lambda p: lambda x: p(n(p)(x)))((lambda p: p(lambda x: lambda y: y))(p))))((lambda x: lambda y: lambda f: f(x)(y))((lambda p: lambda x: x))((lambda p: lambda x: x))))))(m))(m)(n))(n)(x))(m))(n)(((lambda m: lambda n: n((lambda m: lambda n: n((lambda n: lambda p: lambda x: p(n(p)(x))))(m))(m))((lambda p: lambda x: x)))((lambda p: lambda x: p(p(x))))((lambda p: lambda x: p(p(p(p(p(x))))))))))))(n)))))) 30 | 31 | 32 | import unittest 33 | 34 | class TestLambda(unittest.TestCase): 35 | def test_FizzBuzz(self): 36 | for p in to_array(solution): 37 | print(to_string(p)) 38 | 39 | if __name__ == '__main__': 40 | unittest.main() -------------------------------------------------------------------------------- /LambdaCalculus/LambdaCalculus7.1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Lambda Calculus""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 7.1 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | # 6.1.3 实现数字 10 | ZERO = lambda p: lambda x: x 11 | ONE = lambda p: lambda x: p(x) 12 | TWO = lambda p: lambda x: p(p(x)) 13 | THREE = lambda p: lambda x: p(p(p(x))) 14 | FIVE = lambda p: lambda x: p(p(p(p(p(x))))) 15 | 16 | def to_integer(proc): 17 | return proc(lambda n: n + 1)(0) 18 | 19 | 20 | # 6.1.4 实现布尔值 21 | TRUE = lambda x: lambda y: x 22 | FALSE = lambda x: lambda y: y 23 | 24 | def to_boolean(proc): 25 | return proc(True)(False) 26 | 27 | 28 | # 实现if语句 29 | IF = lambda b: lambda x: lambda y: b(x)(y) 30 | 31 | def to_boolean(proc): 32 | return IF(proc)(True)(False) 33 | 34 | 35 | # if语句简化 36 | IF = lambda b: b 37 | 38 | 39 | # 6.1.5 实现谓词 40 | IS_ZERO = lambda n: n(lambda x: FALSE)(TRUE) 41 | 42 | 43 | # 6.1.6 有序对 44 | PAIR = lambda x: lambda y: lambda f: f(x)(y) 45 | LEFT = lambda p: p(lambda x: lambda y: x) 46 | RIGHT = lambda p: p(lambda x: lambda y: y) 47 | 48 | 49 | # 6.1.7 数值运算 50 | INCREMENT = lambda n: lambda p: lambda x: p(n(p)(x)) 51 | SLIDE = lambda p: PAIR(RIGHT(p))(INCREMENT(RIGHT(p))) 52 | DECREMENT = lambda n :LEFT(n(SLIDE)(PAIR(ZERO)(ZERO))) 53 | ADD = lambda m: lambda n: n(INCREMENT)(m) 54 | SUBTRACT = lambda m: lambda n: n(DECREMENT)(m) 55 | MULTIPLY = lambda m: lambda n: n(ADD(m))(ZERO) 56 | POWER = lambda m: lambda n: n(MULTIPLY(m))(ONE) 57 | 58 | IS_LESS_OR_EQUAL = lambda m: lambda n: IS_ZERO(SUBTRACT(m)(n)) 59 | 60 | Y = lambda f: lambda x: f(x(x))(lambda x: f(x(x))) 61 | Z = lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))) 62 | 63 | MOD = \ 64 | Z(lambda f: lambda m: lambda n: \ 65 | IF(IS_LESS_OR_EQUAL(n)(m))( \ 66 | lambda x: \ 67 | f(SUBTRACT(m)(n))(n)(x) \ 68 | )( \ 69 | m \ 70 | ) 71 | ) 72 | 73 | 74 | # 6.1.8 列表 75 | EMPTY = PAIR(TRUE)(TRUE) 76 | UNSHIFT = lambda l: lambda x: PAIR(FALSE)(PAIR(x)(l)) 77 | IS_EMPTY = LEFT 78 | FIRST = lambda l: LEFT(RIGHT(l)) 79 | REST = lambda l: RIGHT(RIGHT(l)) 80 | 81 | def to_array(proc): 82 | array = [] 83 | while True: 84 | if to_boolean(IS_EMPTY(proc)): 85 | break 86 | array.append(FIRST(proc)) 87 | proc = REST(proc) 88 | 89 | return array 90 | 91 | # range 92 | RANGE = \ 93 | Z(lambda f: \ 94 | lambda m: lambda n: \ 95 | IF(IS_LESS_OR_EQUAL(m)(n))( \ 96 | lambda x: \ 97 | UNSHIFT(f(INCREMENT(m))(n))(m)(x) \ 98 | )( \ 99 | EMPTY \ 100 | 101 | ) 102 | ) 103 | 104 | # 实现map 105 | FOLD = \ 106 | Z(lambda f: \ 107 | lambda l: lambda x: lambda g: \ 108 | IF(IS_EMPTY(l))( \ 109 | x \ 110 | )( \ 111 | lambda y: \ 112 | g(f(REST(l))(x)(g))(FIRST(l))(y) \ 113 | ) 114 | 115 | ) 116 | 117 | MAP = \ 118 | lambda k: lambda f: \ 119 | FOLD(k)(EMPTY)( \ 120 | lambda l: lambda x: UNSHIFT(l)(f(x)) 121 | ) 122 | 123 | 124 | # 6.1.9 字符串 125 | TEN = MULTIPLY(TWO)(FIVE) 126 | B = TEN 127 | F = INCREMENT(B) 128 | I = INCREMENT(F) 129 | U = INCREMENT(I) 130 | ZED = INCREMENT(U) 131 | 132 | FIZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(I))(F) 133 | BUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(U))(B) 134 | FIZZBUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(BUZZ)(ZED))(ZED))(I))(F) 135 | 136 | def to_char(c): 137 | return '0123456789BFiuz'[to_integer(c)] 138 | 139 | def to_string(s): 140 | return ''.join([to_char(c) for c in to_array(s)]) 141 | 142 | DIV = \ 143 | Z(lambda f: lambda m: lambda n: \ 144 | IF(IS_LESS_OR_EQUAL(n)(m))( \ 145 | lambda x: \ 146 | INCREMENT(f(SUBTRACT(m)(n))(n))(x) \ 147 | )( \ 148 | ZERO \ 149 | ) \ 150 | ) 151 | 152 | PUSH = \ 153 | lambda l: \ 154 | lambda x: \ 155 | FOLD(l)(UNSHIFT(EMPTY)(x))(UNSHIFT) 156 | 157 | TO_DIGITS = \ 158 | Z(lambda f: lambda n: PUSH( \ 159 | IF(IS_LESS_OR_EQUAL(n)(DECREMENT(TEN)))( \ 160 | EMPTY \ 161 | )( \ 162 | lambda x: \ 163 | f(DIV(n)(TEN))(x) \ 164 | ) \ 165 | )(MOD(n)(TEN))) 166 | 167 | 168 | # 7.1 lambda演算 169 | TAPE = lambda l: lambda m: lambda r: lambda b: PAIR(PAIR(l)(m))(PAIR(r)(b)) 170 | TAPE_LEFT = lambda t: LEFT(LEFT(t)) 171 | TAPE_MIDDLE = lambda t: RIGHT(LEFT(t)) 172 | TAPE_RIGHT = lambda t: LEFT(RIGHT(t)) 173 | TAPE_BLANK = lambda t: RIGHT(RIGHT(t)) 174 | 175 | TAPE_WRITE = lambda t: lambda c: TAPE(TAPE_LEFT(t))(c)(TAPE_RIGHT(t))(TAPE_BLANK(t)) 176 | 177 | TAPE_MOVE_HEAD_RIGHT = \ 178 | lambda t: \ 179 | TAPE( 180 | PUSH(TAPE_LEFT(t))(TAPE_MIDDLE(t)) 181 | )( 182 | IF(IS_EMPTY(TAPE_RIGHT(t)))( 183 | TAPE_BLANK(t) 184 | )( 185 | FIRST(TAPE_RIGHT(t)) 186 | ) 187 | )( 188 | IF(IS_EMPTY(TAPE_RIGHT(t)))( 189 | EMPTY 190 | )( 191 | REST(TAPE_RIGHT(t)) 192 | ) 193 | )( 194 | TAPE_BLANK(t) 195 | ) 196 | 197 | 198 | current_tape = TAPE(EMPTY)(ZERO)(EMPTY)(ZERO) 199 | 200 | current_tape = TAPE_WRITE(current_tape)(ONE) 201 | 202 | current_tape = TAPE_MOVE_HEAD_RIGHT(current_tape) 203 | 204 | current_tape = TAPE_WRITE(current_tape)(TWO) 205 | 206 | current_tape = TAPE_MOVE_HEAD_RIGHT(current_tape) 207 | 208 | current_tape = TAPE_WRITE(current_tape)(THREE) 209 | 210 | current_tape = TAPE_MOVE_HEAD_RIGHT(current_tape) 211 | 212 | print([to_integer(p) for p in to_array(TAPE_LEFT(current_tape))]) 213 | 214 | print(to_integer(TAPE_MIDDLE(current_tape))) 215 | 216 | print([to_integer(p) for p in to_array(TAPE_RIGHT(current_tape))]) 217 | -------------------------------------------------------------------------------- /LambdaCalculus/lambda6.1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Untyped Lambda Calculus""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 6.1 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | # Python中没有类似Ruby的proc功能的函数,只能直接用lambda来实现 10 | 11 | # 6.1.3 实现数字 12 | ZERO = lambda p: lambda x: x 13 | ONE = lambda p: lambda x: p(x) 14 | TWO = lambda p: lambda x: p(p(x)) 15 | THREE = lambda p: lambda x: p(p(p(x))) 16 | FIVE = lambda p: lambda x: p(p(p(p(p(x))))) 17 | FIFTEEN = lambda p: lambda x: p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(x))))))))))))))) 18 | # 一百层嵌套括号会导致Python解释器解析溢出错误,改用九十层。cpython能解析的括号嵌套的最大层数为92层。 19 | NINETY = lambda p: lambda x: p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(p(x)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 20 | 21 | def to_integer(proc): 22 | return proc(lambda n: n + 1)(0) 23 | 24 | 25 | # 6.1.4 实现布尔值 26 | TRUE = lambda x: lambda y: x 27 | FALSE = lambda x: lambda y: y 28 | 29 | def to_boolean(proc): 30 | return proc(True)(False) 31 | 32 | 33 | # 实现if语句 34 | IF = lambda b: lambda x: lambda y: b(x)(y) 35 | 36 | def to_boolean(proc): 37 | return IF(proc)(True)(False) 38 | 39 | 40 | # if语句简化 41 | IF = lambda b: b 42 | 43 | 44 | # 6.1.5 实现谓词 45 | IS_ZERO = lambda n: n(lambda x: FALSE)(TRUE) 46 | 47 | 48 | # 6.1.6 有序对 49 | PAIR = lambda x: lambda y: lambda f: f(x)(y) 50 | LEFT = lambda p: p(lambda x: lambda y: x) 51 | RIGHT = lambda p: p(lambda x: lambda y: y) 52 | 53 | 54 | # 6.1.7 数值运算 55 | INCREMENT = lambda n: lambda p: lambda x: p(n(p)(x)) 56 | SLIDE = lambda p: PAIR(RIGHT(p))(INCREMENT(RIGHT(p))) 57 | DECREMENT = lambda n :LEFT(n(SLIDE)(PAIR(ZERO)(ZERO))) 58 | ADD = lambda m: lambda n: n(INCREMENT)(m) 59 | SUBTRACT = lambda m: lambda n: n(DECREMENT)(m) 60 | MULTIPLY = lambda m: lambda n: n(ADD(m))(ZERO) 61 | POWER = lambda m: lambda n: n(MULTIPLY(m))(ONE) 62 | 63 | IS_LESS_OR_EQUAL = lambda m: lambda n: IS_ZERO(SUBTRACT(m)(n)) 64 | 65 | Y = lambda f: lambda x: f(x(x))(lambda x: f(x(x))) 66 | Z = lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y))) 67 | 68 | MOD = \ 69 | Z(lambda f: lambda m: lambda n: \ 70 | IF(IS_LESS_OR_EQUAL(n)(m))( \ 71 | lambda x: \ 72 | f(SUBTRACT(m)(n))(n)(x) \ 73 | )( \ 74 | m \ 75 | ) 76 | ) 77 | 78 | 79 | # 6.1.8 列表 80 | EMPTY = PAIR(TRUE)(TRUE) 81 | UNSHIFT = lambda l: lambda x: PAIR(FALSE)(PAIR(x)(l)) 82 | IS_EMPTY = LEFT 83 | FIRST = lambda l: LEFT(RIGHT(l)) 84 | REST = lambda l: RIGHT(RIGHT(l)) 85 | 86 | def to_array(proc): 87 | array = [] 88 | while True: 89 | if to_boolean(IS_EMPTY(proc)): 90 | break 91 | array.append(FIRST(proc)) 92 | proc = REST(proc) 93 | 94 | return array 95 | 96 | # range 97 | RANGE = \ 98 | Z(lambda f: \ 99 | lambda m: lambda n: \ 100 | IF(IS_LESS_OR_EQUAL(m)(n))( \ 101 | lambda x: \ 102 | UNSHIFT(f(INCREMENT(m))(n))(m)(x) \ 103 | )( \ 104 | EMPTY \ 105 | 106 | ) 107 | ) 108 | 109 | # 实现map 110 | FOLD = \ 111 | Z(lambda f: \ 112 | lambda l: lambda x: lambda g: \ 113 | IF(IS_EMPTY(l))( \ 114 | x \ 115 | )( \ 116 | lambda y: \ 117 | g(f(REST(l))(x)(g))(FIRST(l))(y) \ 118 | ) 119 | 120 | ) 121 | 122 | MAP = \ 123 | lambda k: lambda f: \ 124 | FOLD(k)(EMPTY)( \ 125 | lambda l: lambda x: UNSHIFT(l)(f(x)) 126 | ) 127 | 128 | 129 | # 6.1.9 字符串 130 | TEN = MULTIPLY(TWO)(FIVE) 131 | B = TEN 132 | F = INCREMENT(B) 133 | I = INCREMENT(F) 134 | U = INCREMENT(I) 135 | ZED = INCREMENT(U) 136 | 137 | FIZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(I))(F) 138 | BUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(U))(B) 139 | FIZZBUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(BUZZ)(ZED))(ZED))(I))(F) 140 | 141 | def to_char(c): 142 | return '0123456789BFiuz'[to_integer(c)] 143 | 144 | def to_string(s): 145 | return ''.join([to_char(c) for c in to_array(s)]) 146 | 147 | DIV = \ 148 | Z(lambda f: lambda m: lambda n: \ 149 | IF(IS_LESS_OR_EQUAL(n)(m))( \ 150 | lambda x: \ 151 | INCREMENT(f(SUBTRACT(m)(n))(n))(x) \ 152 | )( \ 153 | ZERO \ 154 | ) \ 155 | ) 156 | 157 | PUSH = \ 158 | lambda l: \ 159 | lambda x: \ 160 | FOLD(l)(UNSHIFT(EMPTY)(x))(UNSHIFT) 161 | 162 | TO_DIGITS = \ 163 | Z(lambda f: lambda n: PUSH( \ 164 | IF(IS_LESS_OR_EQUAL(n)(DECREMENT(TEN)))( \ 165 | EMPTY \ 166 | )( \ 167 | lambda x: \ 168 | f(DIV(n)(TEN))(x) \ 169 | ) \ 170 | )(MOD(n)(TEN))) 171 | 172 | 173 | ####################################################### 174 | # 用lambda演算实现FizzBuzz游戏 175 | solution = \ 176 | MAP(RANGE(ONE)(NINETY))(lambda n: \ 177 | IF(IS_ZERO(MOD(n)(FIFTEEN)))( \ 178 | FIZZBUZZ \ 179 | )(IF(IS_ZERO(MOD(n)(THREE)))( \ 180 | FIZZ \ 181 | )(IF(IS_ZERO(MOD(n)(FIVE)))( \ 182 | BUZZ \ 183 | )( \ 184 | TO_DIGITS(n) \ 185 | ))) \ 186 | ) 187 | 188 | 189 | ## UnitTest 190 | import unittest 191 | 192 | class TestLambda(unittest.TestCase): 193 | """ Tests of the books's code 194 | """ 195 | 196 | def test_proc(self): 197 | self.assertEqual((lambda x: x + 2)(1), 3) 198 | self.assertEqual((lambda x:(lambda y: x + y))(3)(4), 7) 199 | p = lambda n: n * 2 200 | q = lambda x: p(x) 201 | self.assertEqual(p(5), 10) 202 | self.assertEqual(q(5), 10) 203 | 204 | def test_number(self): 205 | self.assertEqual(to_integer(ZERO), 0) 206 | self.assertEqual(to_integer(THREE), 3) 207 | self.assertEqual(to_integer(NINETY), 90) 208 | 209 | def test_boolean(self): 210 | self.assertEqual(to_boolean(TRUE), True) 211 | self.assertEqual(to_boolean(FALSE), False) 212 | 213 | def test_if(self): 214 | self.assertEqual(IF(TRUE)('happy')('sad'), 'happy') 215 | self.assertEqual(IF(FALSE)('happy')('sad'), 'sad') 216 | 217 | def test_is_zero(self): 218 | self.assertEqual(to_boolean(IS_ZERO(ZERO)), True) 219 | self.assertEqual(to_boolean(IS_ZERO(THREE)), False) 220 | 221 | def test_pair(self): 222 | my_pair = PAIR(THREE)(FIVE) 223 | self.assertEqual(to_integer(LEFT(my_pair)), 3) 224 | self.assertEqual(to_integer(RIGHT(my_pair)), 5) 225 | 226 | def test_calculation(self): 227 | self.assertEqual(to_integer(INCREMENT(FIVE)), 6) 228 | self.assertEqual(to_integer(DECREMENT(FIVE)), 4) 229 | self.assertEqual(to_integer(ADD(FIVE)(THREE)), 8) 230 | self.assertEqual(to_integer(SUBTRACT(FIVE)(THREE)), 2) 231 | self.assertEqual(to_integer(MULTIPLY(FIVE)(THREE)), 15) 232 | self.assertEqual(to_integer(POWER(THREE)(THREE)), 27) 233 | self.assertEqual(to_boolean(IS_LESS_OR_EQUAL(ONE)(TWO)), True) 234 | self.assertEqual(to_boolean(IS_LESS_OR_EQUAL(TWO)(TWO)), True) 235 | self.assertEqual(to_boolean(IS_LESS_OR_EQUAL(THREE)(TWO)), False) 236 | self.assertEqual(to_integer(MOD(THREE)(TWO)), 1) 237 | 238 | def test_list(self): 239 | my_list = UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(THREE))(TWO))(ONE) 240 | self.assertEqual(to_integer(FIRST(my_list)), 1) 241 | self.assertEqual(to_integer(FIRST(REST(my_list))), 2) 242 | self.assertEqual(to_integer(FIRST(REST(REST(my_list)))), 3) 243 | self.assertEqual(to_boolean(IS_EMPTY(my_list)), False) 244 | self.assertEqual(to_boolean(IS_EMPTY(EMPTY)), True) 245 | 246 | def test_array(self): 247 | my_list = UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(THREE))(TWO))(ONE) 248 | self.assertEqual([to_integer(p) for p in to_array(my_list)], [1, 2, 3]) 249 | 250 | def test_range(self): 251 | my_range = RANGE(ONE)(FIVE) 252 | self.assertEqual([to_integer(p) for p in to_array(my_range)], [1, 2, 3, 4, 5]) 253 | 254 | def test_map(self): 255 | self.assertEqual(to_integer(FOLD(RANGE(ONE)(FIVE))(ZERO)(ADD)), 15) 256 | self.assertEqual(to_integer(FOLD(RANGE(ONE)(FIVE))(ONE)(MULTIPLY)), 120) 257 | my_list = MAP(RANGE(ONE)(FIVE))(INCREMENT) 258 | self.assertEqual([to_integer(p) for p in to_array(my_list)], [2, 3, 4, 5, 6]) 259 | 260 | def test_string(self): 261 | self.assertEqual(to_char(ZED), 'z') 262 | self.assertEqual(to_string(FIZZBUZZ), 'FizzBuzz') 263 | self.assertEqual([to_integer(p) for p in to_array(TO_DIGITS(FIVE))], [5]) 264 | self.assertEqual([to_integer(p) for p in to_array(TO_DIGITS(POWER(FIVE)(THREE)))], [1, 2, 5]) 265 | self.assertEqual(to_string(TO_DIGITS(FIVE)), '5') 266 | self.assertEqual(to_string(TO_DIGITS(POWER(FIVE)(THREE))), '125') 267 | 268 | def test_FizzBuzz(self): 269 | for p in to_array(solution): 270 | print(to_string(p)) 271 | 272 | 273 | if __name__ == '__main__': 274 | unittest.main() 275 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 算法与数据结构练习(Python3) 2 | ===== 3 | 4 | 作者:Chai Fei 5 | E-mail:cforth [at] cfxyz.com 6 | 主要是Python写的算法与数据结构练习代码,还有《计算的本质:深入剖析程序和计算机》这本书中的演示代码。书中是Ruby语言实现的,我改写成了Python语言实现。 7 | 8 | 9 | combinations 10 | ------------ 11 | 数学中的组合、排列、枚举算法的演示代码。以及我设计的一种多进制数算术系统的实现。 12 | 1. [集合中所有组合的生成算法](https://github.com/cforth/toys/blob/master/combinations/combinations_generater.py) 13 | 2. [集合中所有排列的生成算法](https://github.com/cforth/toys/blob/master/combinations/permutations_generater.py) 14 | 3. [集合中所有枚举的生成算法](https://github.com/cforth/toys/blob/master/combinations/enumerations_generater.py) 15 | 4. [多进制数算术系统的实现](https://github.com/cforth/toys/blob/master/combinations/MultiInt.py) 16 | 17 | 18 | sort 19 | ------------ 20 | 常用的排序算法的演示代码。 21 | 1. [选择排序算法](https://github.com/cforth/toys/blob/master/sort/selection_sort.py) 22 | 2. [插入排序算法](https://github.com/cforth/toys/blob/master/sort/insertion_sort.py) 23 | 3. [希尔排序算法](https://github.com/cforth/toys/blob/master/sort/shell_sort.py) 24 | 4. [合并排序算法](https://github.com/cforth/toys/blob/master/sort/merge_sort.py) 25 | 5. [堆排序算法](https://github.com/cforth/toys/blob/master/sort/heap_sort.py) 26 | 6. [快速排序算法](https://github.com/cforth/toys/blob/master/sort/quick_sort.py) 27 | 7. [计数排序算法](https://github.com/cforth/toys/blob/master/sort/counting_sort.py) 28 | 8. [基数排序算法](https://github.com/cforth/toys/blob/master/sort/radix_sort.py) 29 | 30 | graphs 31 | ------------- 32 | 图的数据结构与算法。 33 | 1. [无向图的邻接列表表示](https://github.com/cforth/toys/blob/master/graphs/undirected_graphs.py) 34 | 2. [深度优先算法](https://github.com/cforth/toys/blob/master/graphs/depth_first_search.py) 35 | 3. [深度优先路径查询](https://github.com/cforth/toys/blob/master/graphs/depth_first_paths.py) 36 | 37 | search 38 | ------------- 39 | 常用的搜索算法的演示代码。 40 | 1. [二叉搜索树的实现](https://github.com/cforth/toys/blob/master/search/binary_search_tree.py) 41 | 2. [深度与广度优先遍历](https://github.com/cforth/toys/blob/master/search/tree_ergodic.py) 42 | 43 | 44 | search/print_tree 45 | ------------- 46 | 一个外国牛人写的[小工具](https://github.com/cforth/toys/tree/master/search/print_tree),打印出树结构图(C语言)。 47 | 48 | 49 | Simple 50 | ------------- 51 | [《计算的本质:深入剖析程序和计算机》](http://www.ituring.com.cn/book/1098)中第二章的Simple语言实现。 52 | 1. [小步操作语义-表达式](https://github.com/cforth/toys/blob/master/Simple/Machine2.3.1-1.py) 53 | 2. [小步操作语义-语句](https://github.com/cforth/toys/blob/master/Simple/Machine2.3.1-2.py) 54 | 3. [大步操作语义](https://github.com/cforth/toys/blob/master/Simple/Evaluate2.3.2.py) 55 | 4. [指称语义](https://github.com/cforth/toys/blob/master/Simple/Denotation2.4.py) 56 | 57 | 58 | Automaton 59 | ------------- 60 | [《计算的本质:深入剖析程序和计算机》](http://www.ituring.com.cn/book/1098)中第三章以及第四章的自动机实现。 61 | 1. [确定性有限自动机(Deterministic Finite Automaton,DFA)](https://github.com/cforth/toys/blob/master/Automaton/DFA3.1.py) 62 | 2. [非确定性有限自动机(Nondeterministic Finite Automata,NFA)](https://github.com/cforth/toys/blob/master/Automaton/NFA3.2.py) 63 | 3. [正则表达式的实现](https://github.com/cforth/toys/blob/master/Automaton/Pattern3.3.py) 64 | 4. [NFA与DFA的等价性](https://github.com/cforth/toys/blob/master/Automaton/NFASimulation3.4.py) 65 | 5. [确定性下推自动机(Deterministic PushDown Automaton,DPDA)](https://github.com/cforth/toys/blob/master/Automaton/DPDA4.1.py) 66 | 6. [非确定性下推自动机(Nondeterministic Pushdown Automaton,NPDA)](https://github.com/cforth/toys/blob/master/Automaton/NPDA4.2.py) 67 | 7. [词法分析(Lexical Analyzer)](https://github.com/cforth/toys/blob/master/Automaton/LexicalAnalyzer4.3.1.py) 68 | 8. [语法分析(Grammar Analyzer)](https://github.com/cforth/toys/blob/master/Automaton/GrammarAnalyzer4.3.2.py) 69 | 70 | 71 | Turing 72 | ------------- 73 | [《计算的本质:深入剖析程序和计算机》](http://www.ituring.com.cn/book/1098)中第五章的图灵机实现。 74 | 1. [确定型图灵机(Deterministic Turing Machine,DTM)](https://github.com/cforth/toys/blob/master/Turing/DTM.py) 75 | 76 | 77 | LambdaCalculus 78 | --------------- 79 | [《计算的本质:深入剖析程序和计算机》](http://www.ituring.com.cn/book/1098)中第六章、第七章的Lambda演算实现。 80 | 1. [模拟lambda演算](https://github.com/cforth/toys/blob/master/LambdaCalculus/lambda6.1.py) 81 | 2. [FizzBuzz游戏(0-50)](https://github.com/cforth/toys/blob/master/LambdaCalculus/FizzBuzz.py) 82 | 3. [lambda演算](https://github.com/cforth/toys/blob/master/LambdaCalculus/LambdaCalculus7.1.py) 83 | -------------------------------------------------------------------------------- /Simple/Denotation2.4.py: -------------------------------------------------------------------------------- 1 | ##Denotation 2.4 2 | ##指称语义 3 | ##python 3.4.1 4 | 5 | class Number(object): 6 | def __init__(self, value): 7 | self.value = value 8 | 9 | def to_python(self): 10 | return repr(self.value) 11 | 12 | 13 | class Boolean(object): 14 | def __init__(self, value): 15 | self.value = value 16 | 17 | def to_python(self): 18 | return repr(self.value) 19 | 20 | 21 | class Variable(object): 22 | def __init__(self, name): 23 | self.name = name 24 | 25 | def to_python(self): 26 | return self.name 27 | 28 | 29 | class Add(object): 30 | def __init__(self, left, right): 31 | self.left = left 32 | self.right = right 33 | 34 | def to_python(self): 35 | left = repr(self.left.to_python()) 36 | right = repr(self.right.to_python()) 37 | return 'eval({left}, globals()) + eval({right}, globals())'.format(**locals()) 38 | 39 | 40 | class Multiply(object): 41 | def __init__(self, left, right): 42 | self.left = left 43 | self.right = right 44 | 45 | def to_python(self): 46 | left = repr(self.left.to_python()) 47 | right = repr(self.right.to_python()) 48 | return 'eval({left}, globals()) * eval({right}, globals())'.format(**locals()) 49 | 50 | 51 | class LessThan(object): 52 | def __init__(self, left, right): 53 | self.left = left 54 | self.right = right 55 | 56 | def to_python(self): 57 | left = repr(self.left.to_python()) 58 | right = repr(self.right.to_python()) 59 | return 'eval({left}, globals()) < eval({right}, globals())'.format(**locals()) 60 | 61 | 62 | class Assign(object): 63 | def __init__(self, name, expression): 64 | self.name = name 65 | self.expression = expression 66 | 67 | def to_python(self): 68 | name = self.name 69 | expression = repr(self.expression.to_python()) 70 | return '{name} = eval({expression}, globals())'.format(**locals()) 71 | 72 | 73 | class DoNothing(object): 74 | def to_python(self): 75 | return '' 76 | 77 | 78 | class If(object): 79 | def __init__(self, condition, consequence, alternative): 80 | self.condition = condition 81 | self.consequence = consequence 82 | self.alternative = alternative 83 | 84 | def to_python(self): 85 | condition = self.condition.to_python() 86 | consequence = self.consequence.to_python() 87 | alternative = self.alternative.to_python() 88 | return 'if {condition} :\n {consequence}\nelse:\n {alternative}'.format(**locals()) 89 | 90 | 91 | class Sequence(object): 92 | def __init__(self, first, second): 93 | self.first = first 94 | self.second = second 95 | 96 | def to_python(self): 97 | first = self.first.to_python() 98 | second = self.second.to_python() 99 | return '{first}\n{second}'.format(**locals()) 100 | 101 | 102 | class While(object): 103 | def __init__(self, condition, body): 104 | self.condition = condition 105 | self.body = body 106 | 107 | def to_python(self): 108 | condition = self.condition.to_python() 109 | body = self.body.to_python() 110 | return 'while {condition}:\n {body}'.format(**locals()) 111 | 112 | 113 | ##test 114 | 115 | ##数值表达式 116 | proc = Number(5).to_python() 117 | print(proc) 118 | ##python的解释器中执行表达式的函数是eval() 119 | num = eval(proc,{}) 120 | print(num, end = '\n\n') 121 | 122 | ##布尔值表达式 123 | proc = Boolean(True).to_python() 124 | print(proc) 125 | thing = eval(proc,{}) 126 | print(thing, end = '\n\n') 127 | 128 | ##变量表达式 129 | proc = Variable('x').to_python() 130 | print(proc) 131 | var = eval(proc,{'x':7}) 132 | print(var, end = '\n\n') 133 | 134 | ##环境 135 | environment = {'x':3} 136 | print(environment, end = '\n\n') 137 | 138 | ##加法表达式 139 | proc = Add(Variable('x'), Number(1)).to_python() 140 | print(proc) 141 | result = eval(proc, environment) 142 | print(result, end = '\n\n') 143 | 144 | ##乘法表达式 145 | proc = Multiply(Variable('x'), Number(8)).to_python() 146 | print(proc) 147 | result = eval(proc, environment) 148 | print(result, end = '\n\n') 149 | 150 | ##比较表达式 151 | proc = LessThan(Variable('x'), Add(Multiply(Variable('x'), Number(8)), Number(3))).to_python() 152 | print(proc) 153 | result = eval(proc, environment) 154 | print(result, end = '\n\n') 155 | 156 | ##赋值语句 157 | environment = {'x':3} 158 | statement = Assign('y', Number(5)).to_python() 159 | print(statement) 160 | ##python的解释器中执行语句的函数是exec() 161 | exec(statement, environment) 162 | ##print(environment, end = '\n\n') 163 | ##经过exec()后的environment字典,为了方便演示,下面的语句不显示内建的__builtins__对象名称与属性 164 | print(dict([(k, v) for k, v in environment.items() if not k == '__builtins__']), end = '\n\n') 165 | 166 | ##if语句 167 | environment = {'x':3, 'y':5} 168 | statement = If(LessThan(Variable('x'), Variable('y')), Assign('z', Number(1)), Assign('z', Number(0))).to_python() 169 | print(statement) 170 | exec(statement, environment) 171 | print(dict([(k, v) for k, v in environment.items() if not k == '__builtins__']), end = '\n\n') 172 | 173 | ##语句序列 174 | environment = {'x':3, 'y':5, 'z':6} 175 | statement = Sequence(Assign('x', Number(1)), Assign('y', Number(2))).to_python() 176 | print(statement) 177 | exec(statement , environment) 178 | print(dict([(k, v) for k, v in environment.items() if not k == '__builtins__']), end = '\n\n') 179 | 180 | #while语句 181 | environment = {'x':1} 182 | statement = While( 183 | LessThan(Variable('x'), Number(8)), 184 | Assign('x', Multiply(Variable('x'), Number(3))) 185 | ).to_python() 186 | print(statement) 187 | exec(statement , environment) 188 | print(dict([(k, v) for k, v in environment.items() if not k == '__builtins__']), end = '\n\n') 189 | 190 | -------------------------------------------------------------------------------- /Simple/Evaluate2.3.2.py: -------------------------------------------------------------------------------- 1 | ## Evaluate 2.3.2 2 | ## 大步语义 3 | ## python 3.4 4 | 5 | class Number(object): 6 | def __init__(self, value): 7 | self.value = value 8 | 9 | def __str__(self): 10 | return str(self.value) 11 | 12 | def evaluate(self, environment): 13 | return self 14 | 15 | 16 | class Boolean(object): 17 | def __init__(self, value): 18 | self.value = value 19 | 20 | def __str__(self): 21 | return str(self.value) 22 | 23 | def evaluate(self, environment): 24 | return self 25 | 26 | 27 | class Variable(object): 28 | def __init__(self,name): 29 | self.name = name 30 | 31 | def evaluate(self, environment): 32 | return environment[self.name] 33 | 34 | 35 | class Add(object): 36 | def __init__(self, left, right): 37 | self.left = left 38 | self.right = right 39 | 40 | def evaluate(self, environment): 41 | return Number(self.left.evaluate(environment).value + self.right.evaluate(environment).value) 42 | 43 | 44 | class Multiply(object): 45 | def __init__(self, left, right): 46 | self.left = left 47 | self.right = right 48 | 49 | def evaluate(self, environment): 50 | return Number(self.left.evaluate(environment).value * self.right.evaluate(environment).value) 51 | 52 | 53 | class LessThan(object): 54 | def __init__(self, left, right): 55 | self.left = left 56 | self.right = right 57 | 58 | def evaluate(self, environment): 59 | return Boolean(self.left.evaluate(environment).value < self.right.evaluate(environment).value) 60 | 61 | 62 | class Assign(object): 63 | def __init__(self, name, expression): 64 | self.name = name 65 | self.expression = expression 66 | 67 | def evaluate(self, environment): 68 | return dict(environment, **{self.name:self.expression.evaluate(environment)} ) 69 | 70 | 71 | class DoNothing(object): 72 | def evaluate(self, environment): 73 | return environment 74 | 75 | 76 | class If(object): 77 | def __init__(self, condition, consequence, alternative): 78 | self.condition = condition 79 | self.consequence = consequence 80 | self.alternative = alternative 81 | 82 | def evaluate(self, environment): 83 | if self.condition.evaluate(environment).value == Boolean(True).value: 84 | return self.consequence.evaluate(environment) 85 | elif self.condition.evaluate(environment).value == Boolean(False).value: 86 | return self.alternative.evaluate(environment) 87 | 88 | 89 | class Sequence(object): 90 | def __init__(self, first, second): 91 | self.first = first 92 | self.second = second 93 | 94 | def evaluate(self, environment): 95 | return self.second.evaluate(self.first.evaluate(environment)) 96 | 97 | 98 | class While(object): 99 | def __init__(self, condition, body): 100 | self.condition = condition 101 | self.body = body 102 | 103 | def evaluate(self, environment): 104 | if self.condition.evaluate(environment).value == Boolean(True).value: 105 | return self.evaluate(self.body.evaluate(environment)) 106 | elif self.condition.evaluate(environment).value == Boolean(False).value: 107 | return environment 108 | 109 | 110 | ##test 111 | print(Number(21).evaluate({})) 112 | 113 | print(Boolean(True).evaluate({})) 114 | 115 | print(Variable('x').evaluate({'x':1212})) 116 | 117 | print(LessThan( 118 | Add(Variable('x'), Number(2)), 119 | Variable('y') 120 | ).evaluate({'x':Number(2), 'y':Number(5)})) 121 | 122 | 123 | statement = Sequence( 124 | Assign('x', Add(Number(1), Number(1))), 125 | Assign('y', Add(Variable('x'), Number(3))) 126 | ) 127 | print(statement.evaluate({})) 128 | print(dict([(k, v.value) for k,v in statement.evaluate({}).items()])) 129 | 130 | 131 | statement = While( 132 | LessThan(Variable('x'), Number(5)), 133 | Assign('x', Multiply(Variable('x'), Number(3))) 134 | ) 135 | 136 | print(statement.evaluate({'x': Number(1)})) 137 | print(dict([(k, v.value) for k,v in statement.evaluate({'x': Number(1)}).items()])) 138 | -------------------------------------------------------------------------------- /Simple/Machine2.3.1-1.py: -------------------------------------------------------------------------------- 1 | ## Virtual Machine 2.3.1 2 | ## 小步语义 -- 表达式 3 | ## python 3.4 4 | 5 | class Number(object): 6 | """ 数值符号类 7 | """ 8 | def __init__(self, value): 9 | self.value = value 10 | 11 | def reducible(self): 12 | return False 13 | 14 | def to_s(self): 15 | return str(self.value) 16 | 17 | 18 | class Boolean(object): 19 | """ 布尔值符号类型 20 | """ 21 | def __init__(self, value): 22 | self.value = value 23 | 24 | def reducible(self): 25 | return False 26 | 27 | def to_s(self): 28 | return str(self.value) 29 | 30 | 31 | 32 | class Add(object): 33 | """ 加法符号类 34 | """ 35 | def __init__(self, left, right): 36 | self.left = left 37 | self.right = right 38 | 39 | def reducible(self): 40 | return True 41 | 42 | def reduce(self, environment): 43 | if self.left.reducible(): 44 | return Add(self.left.reduce(environment), self.right) 45 | elif self.right.reducible(): 46 | return Add(self.left, self.right.reduce(environment)) 47 | else: 48 | return Number(self.left.value + self.right.value) 49 | 50 | def to_s(self): 51 | return self.left.to_s() + ' + ' + self.right.to_s() 52 | 53 | 54 | class Multiply(object): 55 | """ 乘法符号类 56 | """ 57 | def __init__(self, left, right): 58 | self.left = left 59 | self.right = right 60 | 61 | def reducible(self): 62 | return True 63 | 64 | def reduce(self, environment): 65 | if self.left.reducible(): 66 | return Multiply(self.left.reduce(environment), self.right) 67 | elif self.right.reducible(): 68 | return Multiply(self.left, self.right.reduce(environment)) 69 | else: 70 | return Number(self.left.value * self.right.value) 71 | 72 | def to_s(self): 73 | return self.left.to_s() + ' * ' + self.right.to_s() 74 | 75 | 76 | class LessThan(object): 77 | """ 小于符号类 78 | """ 79 | def __init__(self, left, right): 80 | self.left = left 81 | self.right = right 82 | 83 | def reducible(self): 84 | return True 85 | 86 | def reduce(self, environment): 87 | if self.left.reducible(): 88 | return LessThan(self.left.reduce(environment), self.right) 89 | elif self.right.reducible(): 90 | return LessThan(self.left, self.right.reduce(environment)) 91 | else: 92 | return Boolean(self.left.value < self.right.value) 93 | 94 | def to_s(self): 95 | return self.left.to_s() + ' < ' + self.right.to_s() 96 | 97 | 98 | class Variable(object): 99 | """ 变量符号类 100 | """ 101 | def __init__(self, name): 102 | self.name = name 103 | 104 | def reducible(self): 105 | return True 106 | 107 | def reduce(self, environment): 108 | return environment[self.name] 109 | 110 | def to_s(self): 111 | return str(self.name) 112 | 113 | 114 | class Machine(object): 115 | """ 虚拟机 116 | """ 117 | def __init__(self, expression, environment): 118 | self.expression = expression 119 | self.environment = environment 120 | 121 | def step(self): 122 | self.expression = self.expression.reduce(self.environment) 123 | 124 | def run(self): 125 | while self.expression.reducible(): 126 | print(self.expression.to_s()) 127 | self.step() 128 | print(self.expression.value) 129 | 130 | 131 | ## test 132 | ## 在虚拟机中运行表达式 133 | 134 | ##1 * 2 + 3 * 4 = 14 135 | Machine(Add(Multiply(Number(1), Number(2)), 136 | Multiply(Number(3), Number(4))), 137 | {} 138 | ).run() 139 | 140 | print('') 141 | 142 | ##5 < 2 + 2 143 | Machine( 144 | LessThan(Number(5), Add(Number(2), Number(2))), 145 | {} 146 | ).run() 147 | 148 | print('') 149 | 150 | 151 | ##x = 3; y = 4; x + y = 7 152 | Machine( 153 | Add(Variable('x'), Variable('y')), 154 | {'x':Number(3), 'y':Number(4)} 155 | ).run() 156 | 157 | -------------------------------------------------------------------------------- /Simple/Machine2.3.1-2.py: -------------------------------------------------------------------------------- 1 | ## Virtual Machine 2.3.1 2 | ## 小步语义 -- 表达式、语句、控制结构、语句序列 3 | ## python 3.4 4 | class Number(object): 5 | """ 数值符号类 6 | """ 7 | def __init__(self, value): 8 | self.value = value 9 | 10 | def reducible(self): 11 | return False 12 | 13 | def to_s(self): 14 | return str(self.value) 15 | 16 | 17 | class Boolean(object): 18 | """ 布尔值符号类型 19 | """ 20 | def __init__(self, value): 21 | self.value = value 22 | 23 | def reducible(self): 24 | return False 25 | 26 | def to_s(self): 27 | return str(self.value) 28 | 29 | 30 | 31 | class Add(object): 32 | """ 加法符号类 33 | """ 34 | def __init__(self, left, right): 35 | self.left = left 36 | self.right = right 37 | 38 | def reducible(self): 39 | return True 40 | 41 | def reduce(self, environment): 42 | if self.left.reducible(): 43 | return Add(self.left.reduce(environment), self.right) 44 | elif self.right.reducible(): 45 | return Add(self.left, self.right.reduce(environment)) 46 | else: 47 | return Number(self.left.value + self.right.value) 48 | 49 | def to_s(self): 50 | return self.left.to_s() + ' + ' + self.right.to_s() 51 | 52 | 53 | class Multiply(object): 54 | """ 乘法符号类 55 | """ 56 | def __init__(self, left, right): 57 | self.left = left 58 | self.right = right 59 | 60 | def reducible(self): 61 | return True 62 | 63 | def reduce(self, environment): 64 | if self.left.reducible(): 65 | return Multiply(self.left.reduce(environment), self.right) 66 | elif self.right.reducible(): 67 | return Multiply(self.left, self.right.reduce(environment)) 68 | else: 69 | return Number(self.left.value * self.right.value) 70 | 71 | def to_s(self): 72 | return self.left.to_s() + ' * ' + self.right.to_s() 73 | 74 | 75 | class LessThan(object): 76 | """ 小于符号类 77 | """ 78 | def __init__(self, left, right): 79 | self.left = left 80 | self.right = right 81 | 82 | def reducible(self): 83 | return True 84 | 85 | def reduce(self, environment): 86 | if self.left.reducible(): 87 | return LessThan(self.left.reduce(environment), self.right) 88 | elif self.right.reducible(): 89 | return LessThan(self.left, self.right.reduce(environment)) 90 | else: 91 | return Boolean(self.left.value < self.right.value) 92 | 93 | def to_s(self): 94 | return self.left.to_s() + ' < ' + self.right.to_s() 95 | 96 | 97 | class Variable(object): 98 | """ 变量符号类 99 | """ 100 | def __init__(self, name): 101 | self.name = name 102 | 103 | def reducible(self): 104 | return True 105 | 106 | def reduce(self, environment): 107 | return environment[self.name] 108 | 109 | def to_s(self): 110 | return str(self.name) 111 | 112 | 113 | class DoNothing(object): 114 | """ 什么都不做 115 | """ 116 | def to_s(self): 117 | return 'do-nothing' 118 | 119 | def __eq__(self, other_statement): 120 | return isinstance(other_statement, DoNothing) 121 | 122 | def reducible(self): 123 | return False 124 | 125 | 126 | class Assign(object): 127 | """ 变量赋值语句的实现 128 | """ 129 | def __init__(self, name, expression): 130 | self.name = name 131 | self.expression = expression 132 | 133 | def to_s(self): 134 | return '{name} = {exp}'.format(name=self.name, exp=self.expression.to_s()) 135 | 136 | def reducible(self): 137 | return True 138 | 139 | def reduce(self, environment): 140 | if self.expression.reducible(): 141 | return Assign(self.name, self.expression.reduce(environment)), environment 142 | else: 143 | return DoNothing(), dict(environment, **{self.name:self.expression}) 144 | 145 | 146 | class If(object): 147 | """ IF控制语句的实现 148 | """ 149 | def __init__(self, condition, consequence, alternative): 150 | self.condition = condition 151 | self.consequence = consequence 152 | self.alternative = alternative 153 | 154 | def to_s(self): 155 | return 'if (%s) {%s} else {%s}' % (self.condition.to_s(), self.consequence.to_s(), self.alternative.to_s()) 156 | 157 | def reducible(self): 158 | return True 159 | 160 | def reduce(self, environment): 161 | if self.condition.reducible(): 162 | return If(self.condition.reduce(environment), self.consequence, self.alternative), environment 163 | else: 164 | if self.condition.value == Boolean(True).value: 165 | return self.consequence, environment 166 | elif self.condition.value == Boolean(False).value: 167 | return self.alternative, environment 168 | 169 | 170 | class Sequence(object): 171 | """语句序列 172 | """ 173 | def __init__(self, first, second): 174 | self.first = first 175 | self.second = second 176 | 177 | def to_s(self): 178 | return '{first}; {second}'.format(first=self.first.to_s(), second=self.second.to_s()) 179 | 180 | def reducible(self): 181 | return True 182 | 183 | def reduce(self, environment): 184 | if self.first == DoNothing(): 185 | return self.second, environment 186 | else: 187 | reduced_first, reduced_environment = self.first.reduce(environment) 188 | return Sequence(reduced_first, self.second), reduced_environment 189 | 190 | 191 | class While(object): 192 | """ while循环语句实现 193 | """ 194 | def __init__(self, condition, body): 195 | self.condition = condition 196 | self.body = body 197 | 198 | def to_s(self): 199 | return 'while (%s) {%s}' % (self.condition.to_s(), self.body.to_s()) 200 | 201 | def reducible(self): 202 | return True 203 | 204 | def reduce(self, environment): 205 | return If(self.condition, Sequence(self.body, self), DoNothing()), environment 206 | 207 | 208 | class Machine(object): 209 | """ 虚拟机 210 | """ 211 | def __init__(self, statement, environment): 212 | self.statement = statement 213 | self.environment = environment 214 | 215 | def step(self): 216 | self.statement, self.environment = self.statement.reduce(self.environment) 217 | 218 | def run(self): 219 | while self.statement.reducible(): 220 | print(self.statement.to_s(), end=', ') 221 | print(dict([(k, v.value) for k, v in self.environment.items()])) 222 | self.step() 223 | print(self.statement.to_s(), end=', ') 224 | print(dict([(k, v.value) for k, v in self.environment.items()])) 225 | 226 | 227 | ##test 228 | ##x = 2; x = x + 1; x = 3 229 | Machine( 230 | Assign('x', Add(Variable('x'), Number(1))), 231 | {'x': Number(2)} 232 | ).run() 233 | 234 | print('') 235 | 236 | ##x = True; if (x) {y = 1} else {y = 2} 237 | Machine( 238 | If( 239 | Variable('x'), 240 | Assign('y', Number(1)), 241 | Assign('y', Number(2)) 242 | ), 243 | {'x':Boolean(True)} 244 | ).run() 245 | 246 | print('') 247 | 248 | ##x = 1 + 1; y = x + 3 249 | Machine( 250 | Sequence( 251 | Assign('x', Add(Number(1), Number(1))), 252 | Assign('y', Add(Variable('x'), Number(3))) 253 | ), 254 | {} 255 | ).run() 256 | 257 | print('') 258 | 259 | ##while (x < 5) { x = x * 3 } 260 | Machine( 261 | While( 262 | LessThan(Variable('x'), Number(5)), 263 | Assign('x', Multiply(Variable('x'), Number(3))) 264 | ), 265 | {'x':Number(1)} 266 | ).run() 267 | -------------------------------------------------------------------------------- /Turing/DTM.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | """Deterministic Turing Machine,DTM""" 4 | 5 | # "Understanding Computation: Impossible Code and the Meaning of Programs" 6 | # Chapter 5 's Code. Use Python3. 7 | # Authors: Chai Fei 8 | 9 | class Tape(object): 10 | def __init__(self, left, middle, right, blank): 11 | self.left = left 12 | self.middle = middle 13 | self.right = right 14 | self.blank = blank 15 | 16 | def __str__(self): 17 | left = ''.join(self.left) 18 | middle = self.middle 19 | right = ''.join(self.right) 20 | return '#'.format(**locals()) 21 | 22 | __repr__ = __str__ 23 | 24 | def write(self, character): 25 | return Tape(self.left, character, self.right, self.blank) 26 | 27 | @property 28 | def move_head_left(self): 29 | left = [] if not self.left else self.left[:-1] 30 | middle = self.blank if not self.left else self.left[-1] 31 | right = [self.middle] + self.right 32 | return Tape(left, middle, right, self.blank) 33 | 34 | @property 35 | def move_head_right(self): 36 | left = self.left + [self.middle] 37 | middle = self.blank if not self.right else self.right[0] 38 | right = [] if not self.right else self.right[1:] 39 | return Tape(left, middle, right, self.blank) 40 | 41 | 42 | class TMConfiguration(object): 43 | def __init__(self, state, tape): 44 | self.state = state 45 | self.tape = tape 46 | 47 | def __str__(self): 48 | state = self.state 49 | tape = self.tape 50 | return '#'.format(**locals()) 51 | 52 | __repr__ = __str__ 53 | 54 | 55 | class TMRule(object): 56 | def __init__(self, state, character, next_state, write_character, direction): 57 | self.state = state 58 | self.character = character 59 | self.next_state = next_state 60 | self.write_character = write_character 61 | self.direction = direction 62 | 63 | def applies_to(self, configuration): 64 | return self.state == configuration.state and self.character == configuration.tape.middle 65 | 66 | def follow(self, configuration): 67 | return TMConfiguration(self.next_state, self.next_tape(configuration)) 68 | 69 | def next_tape(self, configuration): 70 | written_tape = configuration.tape.write(self.write_character) 71 | 72 | if self.direction == 'left': 73 | return written_tape.move_head_left 74 | elif self.direction == 'right': 75 | return written_tape.move_head_right 76 | 77 | 78 | class DTMRulebook(object): 79 | def __init__(self, rules): 80 | self.rules = rules 81 | 82 | def next_configuration(self, configuration): 83 | return self.rule_for(configuration).follow(configuration) 84 | 85 | def rule_for(self, configuration): 86 | for rule in self.rules: 87 | if rule.applies_to(configuration): 88 | return rule 89 | 90 | def applies_to(self, configuration): 91 | return self.rule_for(configuration) != None 92 | 93 | 94 | class DTM(object): 95 | def __init__(self, current_configuration, accept_states, rulebook): 96 | self.current_configuration = current_configuration 97 | self.accept_states = accept_states 98 | self.rulebook = rulebook 99 | 100 | @property 101 | def accepting(self): 102 | return self.current_configuration.state in self.accept_states 103 | 104 | @property 105 | def step(self): 106 | self.current_configuration = self.rulebook.next_configuration(self.current_configuration) 107 | 108 | @property 109 | def run(self): 110 | while True: 111 | self.step 112 | if self.accepting or self.if_stuck: 113 | break 114 | 115 | @property 116 | def if_stuck(self): 117 | return not self.accepting and not self.rulebook.applies_to(self.current_configuration) 118 | 119 | 120 | ## UnitTest 121 | import unittest 122 | 123 | class TestDTM(unittest.TestCase): 124 | """ Tests of the books's code 125 | """ 126 | 127 | def test_Tape(self): 128 | tape = Tape(['1', '0', '1'], '1', [], '_') 129 | self.assertEqual(str(tape), '#') 130 | self.assertEqual(tape.middle, '1') 131 | self.assertEqual(str(tape.move_head_left), '#') 132 | self.assertEqual(str(tape.write('0')), '#') 133 | self.assertEqual(str(tape.move_head_right), '#') 134 | self.assertEqual(str(tape.move_head_right.write('0')), '#') 135 | 136 | def test_TMRule(self): 137 | rule = TMRule(1, '0', 2, '1', 'right') 138 | self.assertEqual(rule.applies_to(TMConfiguration(1, Tape([], '0', [], '_'))), True) 139 | self.assertEqual(rule.applies_to(TMConfiguration(1, Tape([], '1', [], '_'))), False) 140 | self.assertEqual(rule.applies_to(TMConfiguration(2, Tape([], '0', [], '_'))), False) 141 | 142 | def test_follow(self): 143 | rule = TMRule(1, '0', 2, '1', 'right') 144 | self.assertEqual(str(rule.follow(TMConfiguration(1, Tape([], '0', [], '_')))), 145 | '#>') 146 | 147 | def test_Rulebook(self): 148 | tape = Tape(['1', '0', '1'], '1', [], '_') 149 | rulebook = DTMRulebook([ 150 | TMRule(1, '0', 2, '1', 'right'), 151 | TMRule(1, '1', 1, '0', 'left'), 152 | TMRule(1, '_', 2, '1', 'right'), 153 | TMRule(2, '0', 2, '0', 'right'), 154 | TMRule(2, '1', 2, '1', 'right'), 155 | TMRule(2, '_', 3, '_', 'left') 156 | ]) 157 | configuration = TMConfiguration(1, tape) 158 | self.assertEqual(str(configuration), '#>') 159 | configuration = rulebook.next_configuration(configuration) 160 | self.assertEqual(str(configuration), '#>') 161 | configuration = rulebook.next_configuration(configuration) 162 | self.assertEqual(str(configuration), '#>') 163 | configuration = rulebook.next_configuration(configuration) 164 | self.assertEqual(str(configuration), '#>') 165 | 166 | def testDTM(self): 167 | tape = Tape(['1', '0', '1'], '1', [], '_') 168 | rulebook = DTMRulebook([ 169 | TMRule(1, '0', 2, '1', 'right'), 170 | TMRule(1, '1', 1, '0', 'left'), 171 | TMRule(1, '_', 2, '1', 'right'), 172 | TMRule(2, '0', 2, '0', 'right'), 173 | TMRule(2, '1', 2, '1', 'right'), 174 | TMRule(2, '_', 3, '_', 'left') 175 | ]) 176 | dtm = DTM(TMConfiguration(1, tape), [3], rulebook) 177 | self.assertEqual(str(dtm.current_configuration), '#>') 178 | self.assertEqual(dtm.accepting, False) 179 | dtm.step 180 | self.assertEqual(str(dtm.current_configuration), '#>') 181 | self.assertEqual(dtm.accepting, False) 182 | dtm.run 183 | self.assertEqual(str(dtm.current_configuration), '#>') 184 | self.assertEqual(dtm.accepting, True) 185 | 186 | def testStuck(self): 187 | tape = Tape(['1', '2', '1'], '1', [], '_') 188 | rulebook = DTMRulebook([ 189 | TMRule(1, '0', 2, '1', 'right'), 190 | TMRule(1, '1', 1, '0', 'left'), 191 | TMRule(1, '_', 2, '1', 'right'), 192 | TMRule(2, '0', 2, '0', 'right'), 193 | TMRule(2, '1', 2, '1', 'right'), 194 | TMRule(2, '_', 3, '_', 'left') 195 | ]) 196 | dtm = DTM(TMConfiguration(1, tape), [3], rulebook) 197 | dtm.run 198 | self.assertEqual(str(dtm.current_configuration), '#>') 199 | self.assertEqual(dtm.accepting, False) 200 | self.assertEqual(dtm.if_stuck, True) 201 | 202 | def test_aaabbbccc(self): 203 | rulebook = DTMRulebook([ 204 | # 状态1:向右扫描,查找a 205 | TMRule(1, 'X', 1, 'X', 'right'), # 跳过 X 206 | TMRule(1, 'a', 2, 'X', 'right'), # 删除 a,进入状态 2 207 | TMRule(1, '_', 6, '_', 'left'), # 查找空格,进入状态 6 (接受) 208 | 209 | # 状态2:向右扫描,查找b 210 | TMRule(2, 'a', 2, 'a', 'right'), # 跳过 a 211 | TMRule(2, 'X', 2, 'X', 'right'), # 跳过 X 212 | TMRule(2, 'b', 3, 'X', 'right'), # 删除 b,进入状态 3 213 | 214 | # 状态3:向右扫描,查找c 215 | TMRule(3, 'b', 3, 'b', 'right'), # 跳过 b 216 | TMRule(3, 'X', 3, 'X', 'right'), # 跳过 X 217 | TMRule(3, 'c', 4, 'X', 'right'), # 删除 c,进入状态 4 218 | 219 | # 状态4:向右扫描,查找字符串结束标记 220 | TMRule(4, 'c', 4, 'c', 'right'), # 跳过 c 221 | TMRule(4, '_', 5, '_', 'left'), # 查找空格,进入状态 5 222 | 223 | # 状态5:向左扫描,查找字符串开始标记 224 | TMRule(5, 'a', 5, 'a', 'left'), # 跳过 a 225 | TMRule(5, 'b', 5, 'b', 'left'), # 跳过 b 226 | TMRule(5, 'c', 5, 'c', 'left'), # 跳过 c 227 | TMRule(5, 'X', 5, 'X', 'left'), # 跳过 X 228 | TMRule(5, '_', 1, '_', 'right') # 查找空格,进入状态 1 229 | ]) 230 | tape = Tape([], 'a', ['a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'], '_') 231 | dtm = DTM(TMConfiguration(1, tape), [6], rulebook) 232 | 233 | for i in range(10): 234 | dtm.step 235 | self.assertEqual(str(dtm.current_configuration), '#>') 236 | 237 | for i in range(25): 238 | dtm.step 239 | self.assertEqual(str(dtm.current_configuration), '#>') 240 | 241 | dtm.run 242 | self.assertEqual(str(dtm.current_configuration), '#>') 243 | 244 | 245 | if __name__ == '__main__': 246 | unittest.main() 247 | -------------------------------------------------------------------------------- /combinations/MultiInt.py: -------------------------------------------------------------------------------- 1 | ## Multi-hexadecimal Integer Number Class 2 | ## python 3.4 3 | 4 | class MultiInt(object): 5 | """Multi-hexadecimal Integer Number Class 6 | example: 7 | num_list = [2, 3, 8] 8 | base = 12 9 | self._num = 2 * base**2 + 3 * base**1 + 8 * base**0 10 | """ 11 | def __init__(self, num_list=None, base=None): 12 | self._num_list = num_list 13 | self._base = base 14 | self._num = self.__change_to_base_10() 15 | 16 | def __change_to_base_10(self): 17 | result = 0 18 | for i in range(len(self._num_list)): 19 | result = result * self._base + self._num_list[i] 20 | return result 21 | 22 | def __add1(self): 23 | self._num += 1 24 | return self._num 25 | 26 | def __sub1(self): 27 | self._num -= 1 28 | return self._num 29 | 30 | def __num_list(self): 31 | num = self._num 32 | result = [] 33 | while True: 34 | result.insert(0, num % self._base) 35 | num = num // self._base 36 | if num <= 0: 37 | return result 38 | 39 | def __add__(self, obj): 40 | if isinstance(obj, MultiInt): 41 | return self._num + obj.num 42 | elif isinstance(obj, int): 43 | return self._num + obj 44 | else: 45 | raise BaseException('__add__ Error: Obj Not MultiInt Class!') 46 | 47 | def __sub__(self, obj): 48 | if isinstance(obj, MultiInt): 49 | return self._num - obj.num 50 | elif isinstance(obj, int): 51 | return self._num - obj 52 | else: 53 | raise BaseException('__sub__ Error: Obj Not MultiInt Class!') 54 | 55 | def __mul__(self, obj): 56 | if isinstance(obj, MultiInt): 57 | return self._num * obj.num 58 | elif isinstance(obj, int): 59 | return self._num * obj 60 | else: 61 | raise BaseException('__mul__ Error: Obj Not MultiInt Class!') 62 | 63 | def __truediv__(self, obj): 64 | if isinstance(obj, MultiInt): 65 | return self._num / obj.num 66 | elif isinstance(obj, int): 67 | return self._num / obj 68 | else: 69 | raise BaseException('__truediv__ Error: Obj Not MultiInt Class!') 70 | 71 | def __floordiv__(self, obj): 72 | if isinstance(obj, MultiInt): 73 | return self._num // obj.num 74 | elif isinstance(obj, int): 75 | return self._num // obj 76 | else: 77 | raise BaseException('__floordiv__ Error: Obj Not MultiInt Class!') 78 | 79 | def __mod__(self, obj): 80 | if isinstance(obj, MultiInt): 81 | return self._num % obj.num 82 | elif isinstance(obj, int): 83 | return self._num % obj 84 | else: 85 | raise BaseException('__mod__ Error: Obj Not MultiInt Class!') 86 | 87 | def change_base(self, base): 88 | num = self._num 89 | result = [] 90 | while True: 91 | result.insert(0, num % base) 92 | num = num // base 93 | if num <= 0: 94 | return MultiInt(result, base) 95 | 96 | @property 97 | def add1(self): 98 | return self.__add1() 99 | 100 | @property 101 | def sub1(self): 102 | return self.__sub1() 103 | 104 | @property 105 | def num(self): 106 | return self._num 107 | 108 | @property 109 | def base(self): 110 | return self._base 111 | 112 | @property 113 | def num_list(self): 114 | return self.__num_list() 115 | 116 | 117 | ## UnitTest 118 | import unittest 119 | 120 | class TestMultiInt(unittest.TestCase): 121 | 122 | def test_init(self): 123 | a = MultiInt([2, 3, 8], base=12) 124 | self.assertEqual(a.num, 332) 125 | self.assertEqual(a.base, 12) 126 | self.assertTrue(isinstance(a, MultiInt)) 127 | 128 | def test_num_list(self): 129 | a = MultiInt([2, 3, 8], base=12) 130 | self.assertEqual(a.num_list, [2,3,8]) 131 | 132 | def test_add1(self): 133 | a = MultiInt([2, 3, 8], base=10) 134 | a.add1 135 | self.assertEqual(a.num, 239) 136 | 137 | def test_sub1(self): 138 | a = MultiInt([2, 3, 9], base=10) 139 | a.sub1 140 | self.assertEqual(a.num, 238) 141 | 142 | def test_add(self): 143 | a = MultiInt([2, 3, 8], base=12) 144 | b = MultiInt([2, 3, 8], base=10) 145 | self.assertEqual(a + b, 570) 146 | self.assertEqual(a + 238, 570) 147 | 148 | def test_sub(self): 149 | a = MultiInt([2, 3, 8], base=12) 150 | b = MultiInt([2, 3, 8], base=10) 151 | self.assertEqual(a - b, 94) 152 | self.assertEqual(a - 238, 94) 153 | 154 | def test_mul(self): 155 | a = MultiInt([2, 3, 8], base=12) 156 | b = MultiInt([2, 3, 8], base=10) 157 | self.assertEqual(a * b, 79016) 158 | self.assertEqual(a * 238, 79016) 159 | 160 | def test_truediv(self): 161 | a = MultiInt([2, 3, 8], base=12) 162 | b = MultiInt([2, 3, 8], base=10) 163 | self.assertEqual(a / b, 1.3949579831932772) 164 | self.assertEqual(a / 238, 1.3949579831932772) 165 | 166 | def test_floordiv(self): 167 | a = MultiInt([2, 3, 8], base=12) 168 | b = MultiInt([2, 3, 8], base=10) 169 | self.assertEqual(a // b, 1) 170 | self.assertEqual(a // 238, 1) 171 | 172 | def test_mod(self): 173 | a = MultiInt([2, 3, 8], base=12) 174 | b = MultiInt([2, 3, 8], base=10) 175 | self.assertEqual(a % b, 94) 176 | self.assertEqual(a % 238, 94) 177 | 178 | def test_change_base(self): 179 | a = MultiInt([2, 3, 8], base=12) 180 | b = MultiInt([3, 3, 2], base=10) 181 | self.assertTrue(isinstance(a.change_base(10), MultiInt)) 182 | self.assertEqual(a.change_base(10).num, b.num) 183 | 184 | 185 | if __name__ == '__main__': 186 | unittest.main() 187 | -------------------------------------------------------------------------------- /combinations/combinations_generater.py: -------------------------------------------------------------------------------- 1 | ##combinations_generater 2 | ##组合算法 3 | ##python 3.4 4 | import time 5 | import codecs 6 | 7 | def intx(the_list, base): 8 | num = 0 9 | for i in range(len(the_list)): 10 | num = num * base + the_list[i] 11 | return num 12 | 13 | 14 | def change_base(num, base): 15 | result = [] 16 | while True: 17 | result.insert(0, num % base) 18 | num = num // base 19 | if num <= 0: 20 | return result 21 | 22 | 23 | def combination_sieve(num_list_start, num_list_end, base): 24 | for num in range(intx(num_list_start, base), intx(num_list_end, base) + 1, 1): 25 | num_list = change_base(num, base) 26 | choose = True 27 | for index in range(len(num_list) - 1): 28 | if num_list[index] >= num_list[index + 1]: 29 | choose = False 30 | break 31 | if choose: 32 | yield(num_list) 33 | 34 | 35 | def combinations_generater(elements, length): 36 | list_length = len(elements) 37 | index_start = [] 38 | index_end = [] 39 | 40 | for i in range(length): 41 | index_start.append(i+1) 42 | for j in range(list_length - length, list_length, 1): 43 | index_end.append(j+1) 44 | base = list_length + 1 45 | 46 | for index in combination_sieve(index_start, index_end, base): 47 | result = [] 48 | for k in index: 49 | result.append(elements[k-1]) 50 | yield(result) 51 | 52 | 53 | ##test 54 | ##Super Lotto(35 choose 5 and 12 choose 2) 55 | 56 | ##35 choose 5 57 | t1 = time.time() 58 | the_list = [] 59 | for i in range(1, 36, 1): 60 | the_list.append(str(i)) 61 | length = 5 62 | 63 | result_35c5 = {} 64 | numbers = 0 65 | for n in combinations_generater(the_list, length): 66 | numbers += 1 67 | result_35c5[numbers] = n 68 | 69 | t1 = time.time() - t1 70 | print("35 choose 5 total run time: %f" % t1) 71 | print("All numbers: %d" % numbers) 72 | 73 | 74 | ##12 choose 2 75 | t2 = time.time() 76 | the_list = [] 77 | for i in range(1, 13, 1): 78 | the_list.append(str(i)) 79 | length = 2 80 | 81 | result_12c2 = {} 82 | numbers = 0 83 | for n in combinations_generater(the_list, length): 84 | numbers += 1 85 | result_12c2[numbers] = n 86 | 87 | t2 = time.time() - t2 88 | print("12 choose 2 total run time: %f" % t2) 89 | print("All numbers: %d" % numbers) 90 | 91 | 92 | ##35 choose 5 and 12 choose 2 93 | t3 = time.time() 94 | numbers = 0 95 | with codecs.open('f:/temp/all', 'w', 'utf-8') as f: 96 | for i in range(1, 324632+1, 1): 97 | for j in range(1, 66+1, 1): 98 | numbers += 1 99 | c5 = ','.join(result_35c5[i]) 100 | c2 = ','.join(result_12c2[j]) 101 | result = c5 + ',' + c2 + '\n' 102 | f.write(result) 103 | 104 | t3 = time.time() - t3 105 | print("35 choose 5 and 12 choose 2 total run time: %f" % t3) 106 | print("All numbers: %d" % numbers) 107 | -------------------------------------------------------------------------------- /combinations/enumerations_generater.py: -------------------------------------------------------------------------------- 1 | ##enumerations_generater 2 | ##枚举算法 3 | ##python 3.4 4 | import time 5 | 6 | def enumerations_generater(elements, length): 7 | """对有N个元素的列表,取X次(可取重复的元素)。生成全部的组合情况。 8 | 参数: elements :有N个元素的列表。 9 | length :取元素的次数,也就是生成的组合的长度。 10 | 结果: 一个组合生成器,使用for循环进行迭代,给出所有组合。 11 | """ 12 | result = [None for n in range(length)] 13 | base = len(elements) 14 | for num in range(base ** length): 15 | for index in range(length): 16 | result[length - index - 1] = elements[num % base] 17 | num = num // base 18 | yield result 19 | 20 | 21 | ##test 22 | t = time.time() 23 | numbers = 0 24 | for n in enumerations_generater([0,1,2,3,4,5,6,7,8,9], 3): 25 | numbers += 1 26 | print(n) 27 | 28 | t = time.time() - t 29 | print("total run time: %f" % t) 30 | print("All numbers: %d" % numbers) 31 | -------------------------------------------------------------------------------- /combinations/permutations_generater.py: -------------------------------------------------------------------------------- 1 | ##permutations_generater 2 | ##排列算法 3 | ##python 3.4 4 | import time 5 | 6 | 7 | def permutations_generater(elements, length): 8 | result = [None for n in range(length)] 9 | base = len(elements) 10 | for num in range(base ** length): 11 | choose = True 12 | temp_set = set() 13 | for index in range(length): 14 | result[length-index-1] = elements[num % base] 15 | num = num // base 16 | for n in result: 17 | if n not in temp_set: 18 | temp_set.add(n) 19 | else: 20 | choose = False 21 | if choose: 22 | yield result 23 | 24 | 25 | ##test 26 | t = time.time() 27 | numbers = 0 28 | for i in permutations_generater([0,1,2,3,4,5,6,7,8,9], 3): 29 | numbers += 1 30 | print(i) 31 | 32 | t = time.time() - t 33 | print("10 choose 3 run time: %f" % t) 34 | print("All numbers: %d" % numbers) 35 | 36 | -------------------------------------------------------------------------------- /graphs/depth_first_paths.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Depth First Paths Algorithm 3 | 4 | from undirected_graphs import * 5 | 6 | class DepthFirstPaths(object): 7 | def __init__(self, graph, start): 8 | self.__g = graph 9 | self.__s = start 10 | self.__marked = [False for m in range(graph.get_verticals())] 11 | self.__edges_to = [None for e in range(graph.get_verticals())] 12 | 13 | def dfs(self, v): 14 | self.__marked[v] = True 15 | for w in self.__g.get_adjacency(v): 16 | if not self.__marked[w]: 17 | self.__edges_to[w] = v 18 | self.dfs(w) 19 | 20 | def has_path_to(self, v): 21 | return self.__marked[v] 22 | 23 | def path_to(self, v): 24 | if not self.has_path_to(v): 25 | return None 26 | path = [] 27 | x = v 28 | while x != self.__s: 29 | path.insert(0, x) 30 | x = self.__edges_to[x] 31 | path.insert(0, self.__s) 32 | return path 33 | 34 | def edges_to(self): 35 | return self.__edges_to 36 | 37 | 38 | ##test 39 | def main(): 40 | mygraph = Graph(6) 41 | mygraph.add_edge(0, 1) 42 | mygraph.add_edge(0, 2) 43 | mygraph.add_edge(0, 5) 44 | mygraph.add_edge(1, 2) 45 | mygraph.add_edge(2, 3) 46 | mygraph.add_edge(2, 4) 47 | mygraph.add_edge(3, 5) 48 | mygraph.add_edge(3, 4) 49 | 50 | mygraph.print_adjacency() 51 | 52 | dfp = DepthFirstPaths(mygraph, 0) 53 | dfp.dfs(0) 54 | print(dfp.path_to(5)) 55 | print(dfp.path_to(2)) 56 | print(dfp.edges_to()) 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /graphs/depth_first_search.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Depth First Search Algorithm 3 | 4 | from undirected_graphs import * 5 | 6 | class DepthFirstSearch(object): 7 | def __init__(self, g): 8 | self.__graph = g 9 | self.__marked = [False for m in range(g.get_verticals())] 10 | self.__count = 0 11 | 12 | def search(self, v): 13 | self.__marked[v] = True 14 | self.__count += 1 15 | for vertical in self.__graph.get_adjacency(v): 16 | if not self.__marked[vertical]: 17 | self.search(vertical) 18 | 19 | def is_marked(self, vertical): 20 | return self.__marked[vertical] 21 | 22 | def count(self): 23 | return self.__count 24 | 25 | def marked(self): 26 | return self.__marked 27 | 28 | ##test 29 | def main(): 30 | mygraph = Graph(13) 31 | mygraph.add_edge(0, 1) 32 | mygraph.add_edge(0, 2) 33 | mygraph.add_edge(0, 5) 34 | mygraph.add_edge(0, 6) 35 | mygraph.add_edge(5, 3) 36 | mygraph.add_edge(5, 4) 37 | mygraph.add_edge(3, 4) 38 | mygraph.add_edge(4, 6) 39 | 40 | mygraph.add_edge(7, 8) 41 | 42 | mygraph.add_edge(9, 10) 43 | mygraph.add_edge(9, 11) 44 | mygraph.add_edge(11, 12) 45 | mygraph.add_edge(9, 12) 46 | 47 | mygraph.print_adjacency() 48 | 49 | dfs = DepthFirstSearch(mygraph) 50 | dfs.search(5) 51 | print(dfs.marked()) 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /graphs/undirected_graphs.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Undirected Graphs Representation 3 | 4 | class Graph(object): 5 | """利用邻接列表表示无向图 6 | """ 7 | def __init__(self, vertical): 8 | self.__verticals = vertical 9 | self.__edges = 0 10 | self.__adjacency = [[] for v in range(vertical)] 11 | 12 | def get_verticals(self): 13 | return self.__verticals 14 | 15 | def get_edges(self): 16 | return self.__edges 17 | 18 | def add_edge(self, vertical_start, vertical_end): 19 | self.__adjacency[vertical_start].append(vertical_end) 20 | self.__adjacency[vertical_end].append(vertical_start) 21 | self.__edges += 1 22 | 23 | def get_adjacency(self, vetical): 24 | return self.__adjacency[vetical] 25 | 26 | def print_adjacency(self): 27 | print(self.__adjacency) 28 | 29 | 30 | ##test 31 | def main(): 32 | mygraph = Graph(13) 33 | mygraph.add_edge(0, 1) 34 | mygraph.add_edge(0, 2) 35 | mygraph.add_edge(0, 5) 36 | mygraph.add_edge(0, 6) 37 | mygraph.add_edge(5, 3) 38 | mygraph.add_edge(5, 4) 39 | mygraph.add_edge(3, 4) 40 | mygraph.add_edge(4, 6) 41 | 42 | mygraph.add_edge(7, 8) 43 | 44 | mygraph.add_edge(9, 10) 45 | mygraph.add_edge(9, 11) 46 | mygraph.add_edge(11, 12) 47 | mygraph.add_edge(9, 12) 48 | 49 | print(mygraph.get_adjacency(3)) 50 | mygraph.print_adjacency() 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /search/binary_search_tree.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## 二叉查找树 3 | import random 4 | import os 5 | 6 | class Node(object): 7 | """使用Node类模二叉树的节点 8 | """ 9 | def __init__(self, key, value, number, left=None, right=None): 10 | self.key = key 11 | self.value = value 12 | self.number = number 13 | self.left = left 14 | self.right = right 15 | 16 | 17 | def get(key, node): 18 | """查找二叉树中的key 19 | """ 20 | result = None 21 | while node != None: 22 | if key > node.key: 23 | node = node.right 24 | elif key < node.key: 25 | node = node.left 26 | else: 27 | result = node.value 28 | break 29 | return result 30 | 31 | 32 | def put(key, value, node): 33 | """在二叉树中增加一个节点 34 | """ 35 | if node == None: 36 | return Node(key, value, 1) 37 | if key < node.key: 38 | node.left = put(key, value, node.left) 39 | elif key > node.key: 40 | node.right = put(key, value, node.right) 41 | else: 42 | node.value = value 43 | node.number = size(node.left) + size(node.right) + 1 44 | return node 45 | 46 | 47 | def size(node): 48 | """返回二叉树节点中的子节点(包含自己)数量 49 | """ 50 | if node == None: 51 | return 0 52 | else: 53 | return node.number 54 | 55 | 56 | def get_max(node): 57 | """返回二叉树中所有节点中最大的key 58 | """ 59 | while node.right != None: 60 | node = node.right 61 | max_item = node.key 62 | return max_item 63 | 64 | 65 | def get_min(node): 66 | """返回二叉树中所有节点中最小的key 67 | """ 68 | while node.left != None: 69 | node = node.left 70 | min_item = node.key 71 | return min_item 72 | 73 | 74 | def floor(key, node): 75 | """返回二叉树所有节点的key中,小于等于key参数的最大的节点 76 | """ 77 | if node == None: 78 | return None 79 | if key == node.key: 80 | return node 81 | if key < node.key: 82 | return floor(key, node.left) 83 | else: 84 | right = floor(key, node.right) 85 | if right == None: 86 | return node 87 | else: 88 | return right 89 | 90 | 91 | def floor_key(key, node): 92 | """返回二叉树所有节点的key中,小于等于key参数的最大的节点的key 93 | """ 94 | floor_node = floor(key, node) 95 | if floor_node != None: 96 | return floor_node.key 97 | else: 98 | return None 99 | 100 | 101 | def ceiling(key, node): 102 | """返回二叉树所有节点的key中,大于等于key参数的最小的节点 103 | """ 104 | if node == None: 105 | return None 106 | if key == node.key: 107 | return node 108 | if key > node.key: 109 | return ceiling(key, node.right) 110 | else: 111 | left = ceiling(key, node.left) 112 | if left == None: 113 | return node 114 | else: 115 | return left 116 | 117 | 118 | def ceiling_key(key, node): 119 | """返回二叉树所有节点的key中,大于等于key参数的最小的节点的key 120 | """ 121 | ceiling_node = ceiling(key, node) 122 | if ceiling_node != None: 123 | return ceiling_node.key 124 | else: 125 | return None 126 | 127 | 128 | def del_min(node): 129 | """删除二叉树中所有节点key最小的节点 130 | """ 131 | if node.left == None: 132 | return node.right 133 | node.left = del_min(node.left) 134 | node.number = size(node.left) + size(node.right) + 1 135 | return node 136 | 137 | 138 | def del_max(node): 139 | """删除二叉树中所有节点key最大的节点 140 | """ 141 | if node.rigth == None: 142 | return node.left 143 | node.rigth = del_max(node.rigth) 144 | node.number = size(node.left) + size(node.right) + 1 145 | return node 146 | 147 | 148 | def get_min_node(node): 149 | """返回二叉树中最小key的节点 150 | """ 151 | if node.left == None: 152 | return node 153 | else: 154 | return get_min_node(node.left) 155 | 156 | 157 | def delete(key, node): 158 | """删除二叉树中指定key的节点 159 | """ 160 | if key > node.key: 161 | node.right = delete(key, node.right) 162 | elif key < node.key: 163 | node.left = delete(key, node.left) 164 | else: 165 | if node.left == None: 166 | return node.right 167 | elif node.right == None: 168 | return node.left 169 | else: 170 | t_left = node.left 171 | t_right = node.right 172 | node = get_min_node(t_right) 173 | node.right = del_min(t_right) 174 | node.left = t_left 175 | node.number = size(node.left) + size(node.right) + 1 176 | return node 177 | 178 | 179 | def depth_first_search(root): 180 | """使用深度优先遍历二叉树 181 | """ 182 | stack = [] 183 | stack.append(root) 184 | while len(stack) != 0 : 185 | node = stack[-1] 186 | print(node.value, end=' ') 187 | stack.pop() 188 | if node.right != None: 189 | stack.append(node.right) 190 | if node.left != None: 191 | stack.append(node.left) 192 | print('\n') 193 | 194 | 195 | def breadth_first_search(root): 196 | """使用广度优先遍历二叉树 197 | """ 198 | quene = [] 199 | quene.append(root) 200 | while len(quene) != 0 : 201 | node = quene[0] 202 | print(node.value, end = ' ') 203 | quene.pop(0) 204 | if node.left != None: 205 | quene.append(node.left) 206 | if node.right != None: 207 | quene.append(node.right) 208 | print('\n') 209 | 210 | 211 | def print_tree(root): 212 | """未完成!打印出每个节点的value和左右子节点的value,为了下一步打印出树结构做准备 213 | """ 214 | quene = [] 215 | quene.append(root) 216 | while len(quene) != 0 : 217 | node = quene[0] 218 | if node.left == None: 219 | ll = '-' 220 | else: 221 | ll = node.left.value 222 | if node.right == None: 223 | rr = '-' 224 | else: 225 | rr = node.right.value 226 | print(' {n} \n _|_ \n| |\n{l} {r}\n==========='.format(n = node.value, l = ll, r = rr)) 227 | quene.pop(0) 228 | if node.left != None: 229 | quene.append(node.left) 230 | if node.right != None: 231 | quene.append(node.right) 232 | print('\n') 233 | 234 | 235 | def inorder_traverse(root): 236 | """中序遍历二叉树 237 | """ 238 | if root != None: 239 | inorder_traverse(root.left) 240 | print (root.value, end=' ') 241 | inorder_traverse(root.right) 242 | 243 | 244 | def print_tree_r(root): 245 | """生成符合打印tree结构图语法的字符串 246 | 打印tree结构图的工具在/print_tree/tree.exe 247 | """ 248 | if root != None: 249 | return '(' + root.value + print_tree_r(root.left) + print_tree_r(root.right) + ')' 250 | else: 251 | return '()' 252 | 253 | 254 | ######################################## 255 | ## test 256 | ## 随机插入26个字母到二叉查找树 257 | char_table = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] 258 | char_index = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] 259 | length = len(char_index) 260 | num = random.randint(0, length-1) 261 | index = char_index[num] 262 | root = Node(char_index[num], char_table[index], 1) 263 | char_index.pop(num) 264 | length -= 1 265 | 266 | for i in range(25): 267 | num = random.randint(0, length-1) 268 | index = char_index[num] 269 | put(char_index[num], char_table[index], root) 270 | char_index.pop(num) 271 | length -= 1 272 | 273 | def test(root): 274 | print('All nodes number: %d' % root.number) 275 | print('Depth first search:') 276 | depth_first_search(root) 277 | print('Breadth first search:') 278 | breadth_first_search(root) 279 | print('inorder traverse:') 280 | inorder_traverse(root) 281 | 282 | print('\n\nPrint Tree:') 283 | tree = '\\tree' + print_tree_r(root) 284 | print(tree + '\n') 285 | 286 | print('Max Key: %d' % get_max(root)) 287 | print('Min Key: %d' % get_min(root)) 288 | print('Floor key with 26: %d' % floor_key(26, root)) 289 | print('Ceiling key with -1: %d' % ceiling_key(-1, root)) 290 | 291 | print('Destroy Tree:') 292 | breadth_first_search(root) 293 | for i in range(26): 294 | root = delete(i, root) 295 | if root != None: 296 | breadth_first_search(root) 297 | else: 298 | print('Tree have been destroyed!') 299 | 300 | ## 打印树结构图 301 | ## cd ./print_tree 302 | ## make tree 生成tree或tree.exe 303 | ## cd .. 304 | ## python3 binary_search_tree.py | ./print_tree/tree.exe 305 | if __name__ == '__main__': 306 | tree = '\\tree' + print_tree_r(root) 307 | print(tree) 308 | -------------------------------------------------------------------------------- /search/print_tree/MANIFEST: -------------------------------------------------------------------------------- 1 | File Name Archive # Description 2 | ----------------------------------------------------------- 3 | MANIFEST 1 this list of files 4 | Makefile 1 5 | README 1 6 | mdoc.l 1 source code for mdoc (makes use.tre) 7 | sample 1 sample to run tree on 8 | tex.c 2 source code, #included in tree.l 9 | texsample 1 sample to run tree on 10 | tpar.l 1 source code for tpar 11 | tpsample 1 sample to run tpar and tree on 12 | tree.1 1 man page 13 | tree.l 3 source code for tree 14 | unpar.l 1 source code for unpar 15 | use.raw 2 document (run mdoc & tree, then TeX) 16 | -------------------------------------------------------------------------------- /search/print_tree/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for tree, June, 1990. Greg Lee 2 | 3 | LEX = flex 4 | # LEXLIB = 5 | # or if you don't have flex, use: 6 | # LEX = lex 7 | LEXLIB = -lfl 8 | 9 | CC=gcc 10 | 11 | # Use flag -u or -t to make .tex files: 12 | UT = -u 13 | 14 | # Keyword required by PS driver at the begining of TeX 15 | # \specials to incorporate line of text directly in PS output 16 | # (see explanation at the beginning of tex.c). Default is 17 | # no keyword. 18 | DEFS = -DSKEY=\"ps:\" 19 | #DEFS = -DSKEY=\"ps::\" 20 | #DEFS = -DSKEY=\"ps-string \" 21 | #DEFS = -DSKEY=\"ps-string=\" 22 | #DEFS = -DSKEY=\"pstext=\" 23 | #DEFS = 24 | 25 | all: tree tpar unpar 26 | 27 | tree: tree.l tex.c 28 | $(LEX) tree.l 29 | $(CC) $(DEFS) -O -s -o tree lex.yy.c $(LEXLIB) 30 | rm lex.yy.c 31 | 32 | tpar: tpar.l 33 | $(LEX) tpar.l 34 | $(CC) -O -s -o tpar lex.yy.c $(LEXLIB) 35 | rm lex.yy.c 36 | 37 | unpar: unpar.l 38 | $(LEX) unpar.l 39 | $(CC) -O -s -o unpar lex.yy.c $(LEXLIB) 40 | rm lex.yy.c 41 | 42 | mdoc: mdoc.l 43 | $(LEX) mdoc.l 44 | $(CC) -O -s -o mdoc lex.yy.c $(LEXLIB) 45 | @rm lex.yy.c 46 | 47 | use.tre: use.raw mdoc 48 | rm -f use.tre 49 | mdoc use.tre 50 | 51 | tex: sample.tex texsample.tex tpsample.tex use.tex 52 | 53 | sample.tex: sample tree 54 | rm -f sample.tex 55 | @echo '--- Expect a warning about an ill-formed \tree command ---' 56 | tree $(UT) sample >sample.tex 57 | tpsample.tex: tpsample tree tpar 58 | rm -f tpsample.tex 59 | tpar -t tpsample |tree $(UT) >tpsample.tex 60 | texsample.tex: texsample tree 61 | rm -f texsample.tex 62 | tree $(UT) texsample >texsample.tex 63 | use.tex: use.tre tree 64 | rm -f use.tex 65 | @echo '--- Expect two warnings about discarded text ---' 66 | tree $(UT) use.tre >use.tex 67 | 68 | shar: 69 | makekit -m 70 | mv Part01 tree.shar1 71 | mv Part02 tree.shar2 72 | mv Part03 tree.shar3 73 | 74 | DIST = MANIFEST Makefile README mdoc.l sample tex.c \ 75 | texsample tpar.l tpsample tree.1 tree.l unpar.l use.raw 76 | 77 | tar: $(DIST) 78 | tar cf tree.tar $(DIST) 79 | 80 | zoo: $(DIST) 81 | zoo a tree $(DIST) 82 | -------------------------------------------------------------------------------- /search/print_tree/README: -------------------------------------------------------------------------------- 1 | 2 | Tree, a program for displaying trees. 3 | 4 | Greg Lee, lee@uhccux.uhcc.hawaii.edu, 7/90 5 | 6 | 7 | * * 8 | Announcement 9 | * ///////\\\\\\ * 10 | / \ 11 | * Tree Drawing Program * 12 | \ / 13 | * \\\\\\\////// * 14 | Available 15 | * * 16 | 17 | The above is from the following tree-definition: 18 | 19 | \tree -b9 20 | ( 21 | (*(*\O(*\O(*\O(*\O))))) 22 | ((Announcement\O(Available\I\O (Tree Drawing()) (\ \ \ \ Program()) ) )) 23 | (*(*\O(*\O(*\O(*\O))))) 24 | ) 25 | 26 | 27 | The `tree' program formats trees for screen display or printing with 28 | TeX. The program, supporting utilities, and accompanying documents are 29 | free and in the public domain. If you distribute a modified version of 30 | `tree', please keep your version in the public domain. 31 | 32 | At the University of Hawaii, the tree program is available on the 33 | uhccux system in directory ~lingua/bin with source code and documents 34 | in directory ~lee/src/Tree. And in the Linguistics Department, the 35 | program is available on uhl2 in directory /usr/local/bin with source 36 | code and documents in ~greg/Tree. 37 | 38 | The predecessor program to this was written by Chris Barker, the 39 | Linguistics Board at University of California, Santa Cruz, email: 40 | barker@ling.ucsc.edu. 41 | 42 | This version has been tested only on Unix: SunOS 3.5, Ultrix 3.1, and 43 | SysV 3.50 (Unixpc). It requires the `lex' utility to compile, or else 44 | `flex', which is the free version of Unix `lex' by Vern Pacson. The 45 | Makefile is set up to use `flex'. To compile the source, type "make", 46 | which will process the source code with flex then will invoke the C 47 | compiler. This creates 3 programs: `tree', `tpar', and `unpar'. The 48 | last two are minor utilities that you may not have any need for; they 49 | are described below. Typing "make tex" compiles `mdoc' and uses that 50 | and `tree' and `tpar' to create some .tex files with examples and 51 | a document on the tree program. 52 | 53 | Basic usage for screen display is: "tree textfile", where the 54 | textfile has some trees. After you've made the program, try displaying 55 | the example files with: 56 | 57 | % tree sample 58 | % tree texsample 59 | 60 | The texsample file is intended to illustrate printed output using TeX, 61 | which you can get with the following (adapted for your local conventions 62 | for using TeX and printing): 63 | 64 | % tree -t texsample > texsample.tex 65 | % tex texsample 66 | % lpr -d texsample.dvi 67 | 68 | And you can follow the similar procedure for the file sample. This 69 | should get you printout of trees done with horizontal and vertical 70 | lines. If you have a PostScript printer, the following may work to get 71 | trees made with slanty lines: 72 | 73 | % tree -u texsample > texsample.tex 74 | % tex texsample 75 | % lpr -d texsample.dvi 76 | 77 | That is, everything the same, except use `-u' instead of `-t'. (`-t' is 78 | for TeX; the only logic to the `-u' is that `u' comes after `t'.) If 79 | this last doesn't work right, the most likely thing to have gone wrong 80 | is that your local PostScript driver program does not treat TeX \special 81 | commands, which I've used to embed PS code, in the same way that mine 82 | does. If that's a problem, there are two things you can do about it. 83 | (1) Find out what should be in a TeX \special to tell your driver to 84 | just spit out literally into its output whatever it finds in a \special, 85 | then modify the Makefile or the C code in the source tex.c accordingly 86 | (see `SKEY' in the code), or (2) email me and I'll send you my PS driver 87 | program (which is a modification of the free dvi2ps program from MIT). 88 | 89 | The Makefile also provides for "make tex" to create TeXable files 90 | use.tex, sample.tex, texsample.tex, and ptsample.tex for a sort of user 91 | manual and some sample output. If you can't get the `-u' option to 92 | work, you can change the definition of UT in the Makefile to -t. 93 | 94 | Tree has some options for modifying or decorating trees in various ways. 95 | Some of these can be used either for all the trees in a source text file 96 | by giving the option on the command line after `tree', or for some 97 | individual tree by giving the option after the `\tree' command within 98 | the text file. For instance, if the text has 99 | 100 | \tree -t (S (Q (did) (V' (you go)))) 101 | 102 | then TeX code will be generated for this particular tree in the text, 103 | but not necessarily for other trees in that text file. Here is another 104 | example: 105 | 106 | % tree -L < filename 107 | \tree -L (S(NP(N(features)))(V'(V(galore)))) 108 | 109 | The first Unix command will have `tree' omit all connecting lines under 110 | nodes for all trees in the file `filename'. The second, as a line in a 111 | text file processed by tree, will do that for just the one tree that 112 | follows. There are other options that apply just to single nodes within 113 | a tree, which are given as backslash plus some capital letter. As it 114 | happens, in this instance there is an option \L for individual nodes, 115 | also: 116 | 117 | \tree (S(NP(N\L(features)))(V'(\L V(galore)))) 118 | 119 | which omits lines under just the two nodes `N' and `V'. The second \L 120 | in this example has to be separated by a space from the following V so 121 | `tree' can tell that this is not a TeX command with the name `LV'. (If 122 | it happens that you need to use a TeX command with the name `L' in a 123 | node, you could use \\L for this, but it is necessary to use \\ for 124 | TeX commands only in such cases of conflict.) 125 | 126 | Here is a reference list of the options or commands for formatting 127 | individual nodes. (See the man page and the "use" document for more 128 | info.) In this list, `' is an optional single digit argument, and 129 | `' is an obligatory non-negative integer argument. 130 | 131 | Command: Option: Function: 132 | 133 | \D "daughter" label discontinuous daughter 134 | \E "even" -E select basis for flatten command 135 | \F "flatten" -F move nodes to lowest level 136 | \H "head" center mother over this daughter 137 | \I "invert" -I turn tree upside down 138 | \L "lexical" -L don't put lines under nodes 139 | \M "mother" label mother of discontinuous daughter 140 | \O "omit" -O omit line above nodes 141 | \P "phantom" as "omit" but retain spacing 142 | \T "triangle" -T put triangles under nodes 143 | \R "relational" -R put aligned verticals at right of nodes 144 | \B "boldness" -b do shaded triangles or bold lines (see below) 145 | -g use n as the minimal gap between nodes 146 | -v don't suppress TeX commands on screen 147 | -q suppress warnings 148 | -x use IBM extended line drawing characters 149 | -X same as -x, but format for WordStar 150 | 151 | All commands of the form backslash plus capital letter `tree' assumes 152 | are intended for it, and it eats them up without comment, even though 153 | in most cases they don't do anything. 154 | 155 | The option `-b' has different effects depending on output is 156 | tty-style or TeX code. The sample files have examples for the latter. 157 | For tty output, here is a series of trees showing how the connecting 158 | "lines" can be varied. These are from the tree definition: 159 | 160 | \tree (bold =(family\T(Martha Henry))(uncle)(aunt)(kin(Fred)(Milly\H))) 161 | 162 | with values from 0 through 9 for and with option `-b': 163 | 164 | bold =0 165 | ____________|____________ 166 | | | | | 167 | family uncle aunt kin 168 | _____|______ _______| 169 | |__________| | | 170 | Martha Henry Fred Milly 171 | bold =1 172 | +-----------+-----------+ 173 | | | | | 174 | family uncle aunt kin 175 | +----+-----+ -------| 176 | |----------| | | 177 | Martha Henry Fred Milly 178 | bold =2 179 | ...........:........... 180 | : : : : 181 | family uncle aunt kin 182 | ....:..... .......: 183 | :::::::::::: : : 184 | Martha Henry Fred Milly 185 | bold =3 186 | ||||||||||||||||||||||||| 187 | | | | | 188 | family uncle aunt kin 189 | |||||||||||| |||||||| 190 | |||||||||||| | | 191 | Martha Henry Fred Milly 192 | bold =4 193 | ::::::::::::::::::::::::: 194 | : : : : 195 | family uncle aunt kin 196 | :::::::::::: :::::::: 197 | :::::::::::: : : 198 | Martha Henry Fred Milly 199 | bold =5 200 | ........../ \.......... 201 | / : : \ 202 | family uncle aunt kin 203 | ..../\.... .......: 204 | :::::::::::: / * 205 | Martha Henry Fred Milly 206 | bold =6 207 | __________/ \__________ 208 | / | | \ 209 | family uncle aunt kin 210 | ____/\____ _______| 211 | |||||||||||| / * 212 | Martha Henry Fred Milly 213 | bold =7 214 | <<<<<<<<<<< >>>>>>>>>>> 215 | / | | \ 216 | family uncle aunt kin 217 | <<<<<>>>>> <<<<<<<| 218 | |----------| / * 219 | Martha Henry Fred Milly 220 | bold =8 221 | ////////////\\\\\\\\\\\ 222 | / | | \ 223 | family uncle aunt kin 224 | /////\\\\\ ///////| 225 | |||||||||||| / * 226 | Martha Henry Fred Milly 227 | bold =9 228 | ////////////\\\\\\\\\\\ 229 | / | | \ 230 | family uncle aunt kin 231 | /////\\\\\ ///////| 232 | |**********| / * 233 | Martha Henry Fred Milly 234 | 235 | The \B command selects the different styles on a node-by-node 236 | basis, affecting the lines just below the node with the command. 237 | \B without argument is the same as \B9. 238 | 239 | The utilities `tpar' and `unpar' are for trees using indentation 240 | for indicating structure rather than parenthesization. For instance, 241 | feed this to `tpar': 242 | 243 | \tree 244 | S 245 | NP 246 | Det\L - the 247 | N - rain 248 | VP - V - falls 249 | 250 | to get back a parenthesized version that you can give to `tree': 251 | 252 | \tree 253 | (S 254 | (NP 255 | (Det\L(the)) 256 | (N(rain))) 257 | (VP(V(falls)))) 258 | 259 | With the option `-v', `tpar' will put some ending parens on new lines, 260 | and with the option `-t' it will turn bracketed digits and i,j,k,x,y,z 261 | into the TeX code for subscripting the digit or letter, and also 262 | translate N',A',V',P' into TeX code for putting bars over the letters. 263 | The `unpar' utility translates the other way, substituting indentation 264 | for parenthesization and, with the `-t' option, going back to the 265 | bracket and prime notation from the TeX code. The file tpsample has 266 | example trees in indented form. 267 | 268 | Bug reports and suggestions for changes are welcome. 269 | 270 | Greg Lee 271 | U.S.mail: 562 Moore Hall, Dept. of Linguistics, Univ. of Hawaii, HONO, HI 96822 272 | INTERNET: lee@uhccux.uhcc.hawaii.edu 273 | BITNET: lee@uhccux 274 | -------------------------------------------------------------------------------- /search/print_tree/mdoc.l: -------------------------------------------------------------------------------- 1 | %{ 2 | /* mdoc: utility to add \tree examples to "use" document for tree 3 | * Greg Lee, July 1990 4 | */ 5 | char *buf, *bufp; 6 | char *line[100]; 7 | int count = 0, last = 0, i; 8 | #define ADDCH(c) *bufp++ = c 9 | #define ADDS(s) strcpy(bufp,s); bufp += yyleng 10 | %} 11 | 12 | %s X 13 | 14 | %% 15 | 16 | ^"\\xtwo"[ \t\n]+ { 17 | ECHO; 18 | last = 2; 19 | line[0] = bufp; 20 | BEGIN(X); 21 | } 22 | 23 | ^"\\xthree"[ \t\n]+ { 24 | ECHO; 25 | last = 3; 26 | line[0] = bufp; 27 | BEGIN(X); 28 | } 29 | 30 | ^"\\xfour"[ \t\n]+ { 31 | ECHO; 32 | last = 4; 33 | line[0] = bufp; 34 | BEGIN(X); 35 | } 36 | 37 | ^"\\x"[ \t\n]+ { 38 | ECHO; 39 | last = 1; 40 | line[0] = bufp; 41 | BEGIN(X); 42 | } 43 | "$" { 44 | printf("\\$"); 45 | ADDCH('$'); 46 | } 47 | "\\ " { 48 | printf("\\xbs{\\ }"); 49 | ADDS(yytext); 50 | } 51 | \\[a-z]+ { 52 | printf("\\xbs{%s}", yytext+1); 53 | ADDS(yytext); 54 | } 55 | \\. { 56 | printf("\\xbs{%c}", yytext[1]); 57 | ADDS(yytext); 58 | } 59 | : { 60 | ECHO; 61 | ADDCH(0); 62 | count++; 63 | line[count] = bufp; 64 | } 65 | "." { 66 | ECHO; 67 | if (count < last) ADDCH('.'); 68 | else { 69 | ADDCH(0); 70 | 71 | printf("\n\\smallbreak{\\parindent=.5in\\par"); 72 | printf("\\hskip-.2in\\it gives:\\tfont\n\\tree "); 73 | for (i = 0; i < count; i++) 74 | printf("%s\n", line[i]); 75 | printf("}\\smallbreak\n"); 76 | 77 | count = last = 0; 78 | bufp = buf; 79 | BEGIN(0); 80 | } 81 | } 82 | . { 83 | ECHO; 84 | ADDCH(yytext[0]); 85 | } 86 | 87 | %% 88 | main() 89 | { char *malloc(); 90 | 91 | buf = bufp = malloc(BUFSIZ); 92 | yylex(); 93 | } 94 | -------------------------------------------------------------------------------- /search/print_tree/sample: -------------------------------------------------------------------------------- 1 | 2 | Here are some example trees to display with the tree program. First, 3 | the examples from the man page: 4 | 5 | (ex1) \tree (S(NP(John))(VP(runs))) 6 | 7 | (ex2) \tree ((((John)(runs)))) 8 | 9 | %(ex3) \tree \- this line will remain unchanged 10 | 11 | (ex4) is not given, since it has an error 12 | 13 | (ex5) \tree -q (a phrase composed of others(a phrase 14 | (a)(phrase)) 15 | This is a comment.(composed) (of others 16 | (of)(others)) ) 17 | 18 | (ex6) \tree ((S(John)(V(runs)(fast))) (==$>$) 19 | (S(V(runs)(fast))(S(John)(does)))) 20 | 21 | (ex7) \tree (S % Comments like this 22 | (NP % are skipped over. 23 | (John) 24 | ) 25 | (VP 26 | (runs) 27 | ) 28 | ) 29 | 30 | (ex8) \tree (NP (Det(John's \(genitive\))) 31 | (N\([+count]\)(legs)) ) 32 | 33 | (ex9) \tree (\T S (every) (good boy) 34 | (VP (\L V(does)) (\L A(fine)) )) 35 | 36 | (ex10) \tree (S(PP\O\D(near)(him))(NP(John)) 37 | (VP\M(saw)(a snake))) 38 | 39 | Then here are a couple of trees from the sample file Jeff Goldberg 40 | distributed: 41 | 42 | (1) \tree 43 | (S (NP[+WH] (Who)) 44 | (S/NP (V[INV] (did)) 45 | (NP (you)) 46 | (VP[BSE]/NP (V[BSE] (see)) 47 | (NP[NULL]/NP (e)) 48 | ) 49 | ) 50 | ) 51 | 52 | (2) \tree 53 | (S (PP (P1 (P (on)) 54 | (NP (which) 55 | (N1 (N (table))) 56 | ) 57 | ) 58 | ) 59 | (S/PP (V (do)) 60 | (NP (you)) 61 | (VP/PP (V (think)) 62 | (S/PP (NP (Martha)) 63 | (VP/PP (V (believes)) 64 | (S/PP (NP (Irving)) 65 | (VP/PP (V (put)) (NP (Det (the) (N1 (N (book))))) 66 | (PP/PP (e)) 67 | ) 68 | ) 69 | ) 70 | ) 71 | ) 72 | ) 73 | ) 74 | 75 | Chris Barker gave these examples (in a slightly different 76 | form): 77 | 78 | \tree 79 | ((S (NP (N) (PP (P) (NP))) 80 | (VP (V) (PP (P) (NP)))) 81 | 82 | (\I S (\I NP (N) (\I PP (P) (NP))) 83 | (VP (V) (\I PP (P) (NP))))) 84 | 85 | \tree 86 | (\I\(mutakaatib\)\L 87 | (u 88 | (u ((C\O)(V)(C\O))) 89 | (a (V) (C\O) 90 | (V) 91 | (V)) 92 | (i ((C\O)(V)(C\O)))) 93 | ) 94 | 95 | \tree 96 | ( (C 97 | (u\I 98 | (m) 99 | (\O) % leave space below first `V' in upper tree 100 | (g) 101 | (n) 102 | (\O) % leave space below second `V' in upper tree 103 | (t) 104 | ) 105 | ) 106 | (V) 107 | (C ()) % empty node attaches to `g' 108 | (C ()) % empty node attaches to `n' 109 | (V) 110 | (C ()) % empty node attaches to `t' 111 | ((\O(s\O))) 112 | ) 113 | 114 | \bye 115 | -------------------------------------------------------------------------------- /search/print_tree/texsample: -------------------------------------------------------------------------------- 1 | 2 | % before running TeX, process this with: 3 | % tree -t texsample.tex 4 | % or tree -u texsample.tex 5 | 6 | \nopagenumbers 7 | % hi is a strut to leave more room above overlined things 8 | \def\hi{\vrule width0em height10pt depth3.5pt} 9 | 10 | NP: Article Replacement 11 | \bigskip 12 | \tree 13 | (S$_0$ 14 | (NP 15 | (Det 16 | (John$_i$'s) 17 | ) 18 | (\hi $\overline{\rm N}$ 19 | (N\L 20 | (denunciation) 21 | ) 22 | (\hi $\overline{\rm P}$ 23 | (P\L 24 | (of) 25 | ) 26 | (NP$_i$ 27 | (himself) 28 | ) 29 | ) 30 | ) 31 | ) 32 | (\hi $\overline{\rm V}$ 33 | (V\L 34 | (surprise) 35 | ) 36 | (NP 37 | (us) 38 | ) 39 | ) 40 | ) 41 | 42 | \bigskip 43 | 44 | \noindent{\rm 2c. John's denunciation of himself surprised us.}\medskip 45 | 46 | \tree 47 | ( 48 | (S$_0$ 49 | (NP 50 | (Det\L 51 | (the) 52 | ) 53 | (\hi$\overline{\rm N}$ 54 | (N\L 55 | (ACTION) 56 | ) 57 | (S$_1$ 58 | (NP$_i$ 59 | (John) 60 | ) 61 | (\hi$\overline{\rm V}$ 62 | (V\L 63 | (denounce) 64 | ) 65 | (NP$_i$ 66 | (him) 67 | ) 68 | ) 69 | ) 70 | ) 71 | ) 72 | (\hi$\overline{\rm V}$ 73 | (V\L 74 | (surprise) 75 | ) 76 | (NP 77 | (us) 78 | ) 79 | ) 80 | ) 81 | (\rm S$_1$: Reflexivization $\rightarrow$) 82 | (S$_0$ 83 | (NP 84 | (Det\L 85 | (the) 86 | ) 87 | (\hi$\overline{\rm N}$ 88 | (N\L 89 | (ACTION) 90 | ) 91 | (S$_1$ 92 | (NP$_i$ 93 | (John) 94 | ) 95 | (\hi$\overline{\rm V}$ 96 | (V\L 97 | (denounce) 98 | ) 99 | (NP$_i$ 100 | (himself) 101 | ) 102 | ) 103 | ) 104 | ) 105 | ) 106 | (\hi$\overline{\rm V}$ 107 | (V\L 108 | (surprise) 109 | ) 110 | (NP 111 | (us) 112 | ) 113 | ) 114 | ) 115 | ) 116 | 117 | 118 | \noindent{\rm $\overline{\rm N}$: Nominalization}\smallskip 119 | \tree 120 | (S$_0$ 121 | (NP 122 | (Det\L 123 | (the) 124 | ) 125 | (\hi$\overline{\rm N}$ 126 | (\hi$\overline{\rm N}$ 127 | (N 128 | (V\L 129 | (denounce) 130 | ) 131 | (N\L 132 | (ACTION) 133 | ) 134 | ) 135 | (NP$_i$ 136 | (himself) 137 | ) 138 | ) 139 | (NP$_i$ 140 | (John) 141 | ) 142 | ) 143 | ) 144 | (\hi$\overline{\rm V}$ 145 | (V\L 146 | (surprise) 147 | ) 148 | (NP 149 | (us) 150 | ) 151 | ) 152 | ) 153 | 154 | 155 | \noindent{\rm $\overline{\rm N}$: Preposition insertion}\smallskip 156 | \tree 157 | (S$_0$ 158 | (NP 159 | (Det\L 160 | (the) 161 | ) 162 | (\hi$\overline{\rm N}$ 163 | (\hi$\overline{\rm N}$ 164 | (N\L 165 | (denunciation) 166 | ) 167 | (\hi$\overline{\rm P}$ 168 | (P\L 169 | (of) 170 | ) 171 | (NP$_i$ 172 | (himself) 173 | ) 174 | ) 175 | ) 176 | (\hi$\overline{\rm P}$ 177 | (P\L 178 | (by) 179 | ) 180 | (NP$_i$ 181 | (John) 182 | ) 183 | ) 184 | ) 185 | ) 186 | (\hi$\overline{\rm V}$ 187 | (V\L 188 | (surprise) 189 | ) 190 | (NP 191 | (us) 192 | ) 193 | ) 194 | ) 195 | 196 | 197 | \noindent{\rm NP: Article Replacement}\smallskip 198 | \tree 199 | (S$_0$ 200 | (NP 201 | (Det 202 | (John's) 203 | ) 204 | (\hi$\overline{\rm N}$ 205 | (N\L 206 | (denunciation) 207 | ) 208 | (\hi$\overline{\rm P}$ 209 | (P\L 210 | (of) 211 | ) 212 | (NP$_i$ 213 | (himself) 214 | ) 215 | ) 216 | ) 217 | ) 218 | (\hi$\overline{\rm V}$ 219 | (V\L 220 | (surprise) 221 | ) 222 | (NP 223 | (us) 224 | ) 225 | ) 226 | ) 227 | 228 | \bye 229 | -------------------------------------------------------------------------------- /search/print_tree/tpar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cforth/toys/44ccd01bafbbc7c796a7e5f2011be4cf81aa384d/search/print_tree/tpar -------------------------------------------------------------------------------- /search/print_tree/tpar.l: -------------------------------------------------------------------------------- 1 | %{ 2 | /* 3 | * tpar: pre-processor for tree; adds parens according to indentation. 4 | * Version 0.1 5 | * 6 | * Blank line ends the tree. 7 | * ` - ' adds following item on same line as single child. 8 | * Does not do forests -- add outer parens in source as part of 9 | * beginning and ending node names or use null command \Z. 10 | * Option -t converts N',V',A',P' by adding TeX \overline commands, 11 | * and [] by adding TeX subscripting 12 | * commands. 13 | * Option -v puts right parentheses on new lines, with indentation 14 | * the same as the preceding matching paren. 15 | * 16 | * Greg, lee@uhccux.uhcc.hawaii.edu, 6/24/90 17 | */ 18 | 19 | #define TRUE 1 20 | #define FALSE 0 21 | int tex_opt = FALSE; 22 | int v_opt = FALSE; 23 | 24 | int outercol = 0; 25 | int linenumber = 0; 26 | int indent = 0; 27 | int minindent = 0; 28 | int level = 0; 29 | int buried[100]; 30 | int extra = 0; 31 | %} 32 | 33 | %s T O X 34 | 35 | %% 36 | 37 | \n { 38 | outercol = 0; 39 | indent = 0; 40 | linenumber++; 41 | ECHO; 42 | } 43 | 44 | [ \t]*\n { 45 | if (!outercol) { 46 | descend(minindent); 47 | ECHO; 48 | BEGIN(O); 49 | } 50 | indent = outercol = 0; 51 | linenumber++; 52 | } 53 | 54 | \t { 55 | outercol++; 56 | while (outercol % 8) outercol++; 57 | ECHO; 58 | } 59 | 60 | \t { 61 | outercol++; 62 | while (outercol % 8) outercol++; 63 | } 64 | 65 | " " { 66 | outercol++; 67 | if (indent) ECHO; 68 | } 69 | 70 | [ \t]+"-"[ \t]+ { 71 | extra++; 72 | printf("("); 73 | } 74 | 75 | \\tree[ \t]*(-([tuvLTOIFER]+|[bg][0-9]+)[ \t]*)* { 76 | outercol += yyleng; 77 | level = extra = 0; 78 | minindent = 200; 79 | buried[0] = -1; 80 | if (tex_opt) BEGIN(X); 81 | else BEGIN(T); 82 | ECHO; 83 | } 84 | 85 | . { 86 | outercol++; 87 | ECHO; 88 | } 89 | 90 | [NVAP]' { 91 | ascend(); 92 | outercol += 2; 93 | printf("$\\overline{\\rm %c}$", yytext[0]); 94 | } 95 | 96 | \[[0-9ijkxyz]\] { 97 | ascend(); 98 | outercol += 3; 99 | printf("$_%c$", yytext[1]); 100 | } 101 | 102 | \\Z[ \t]*$ { 103 | ascend(); 104 | outercol += 2; 105 | } 106 | 107 | . { 108 | ascend(); 109 | outercol++; 110 | ECHO; 111 | } 112 | 113 | %% 114 | 115 | descend(indent) 116 | int indent; 117 | { int i; 118 | 119 | if (extra) do printf(")"); while (--extra); 120 | if (indent > buried[level]) { 121 | buried[++level] = indent; 122 | } 123 | else { 124 | printf(")"); 125 | while (level >= 0 && indent < buried[level]) { 126 | level--; 127 | if (v_opt) { 128 | printf("\n"); 129 | for (i = 1; i < buried[level]; i++) 130 | printf(" "); 131 | } 132 | printf(")"); 133 | } 134 | } 135 | printf("\n"); 136 | } 137 | 138 | ascend() 139 | { int i; 140 | 141 | if (indent) return; 142 | descend(indent = outercol+1); 143 | if (indent < minindent) minindent = indent; 144 | for (i = 1; i < indent; i++) printf(" "); 145 | printf("("); 146 | } 147 | 148 | extern char *optarg; /* from getopt */ 149 | extern int optind; 150 | 151 | main(argc, argv) 152 | int argc; 153 | char *argv[]; 154 | { int c; 155 | char *progname = NULL, *basename(); 156 | 157 | progname = basename (argv[0]); 158 | while ((c = getopt (argc, argv, "htv")) != EOF) 159 | switch (c) { 160 | case 't': tex_opt = TRUE; break; 161 | case 'v': v_opt = TRUE; break; 162 | case 'h': 163 | default: 164 | fprintf(stderr, "Usage: %s [options] [files]\n", progname); 165 | fprintf(stderr, "options = -t\t(TeX code)\n"); 166 | fprintf(stderr, " -v\t(parens on new lines)\n"); 167 | fprintf(stderr, " -h\t(print this information)\n"); 168 | exit(1); 169 | } 170 | 171 | BEGIN(O); 172 | 173 | if (optind >= argc) { 174 | (void) yylex (); 175 | } 176 | else for (; (optind < argc); optind++) { 177 | if (yyin == NULL) yyin = stdin; 178 | if (freopen (argv[optind], "r", stdin) != NULL) { 179 | #ifdef FLEX_SCANNER 180 | /* to get flex to look at > 1 file */ 181 | yy_init = 1; 182 | #endif 183 | (void) yylex (); 184 | if (level > 1) descend(minindent); 185 | outercol = linenumber = indent = minindent = 0; 186 | level = extra = 0; 187 | } 188 | else { 189 | (void) fprintf (stderr, 190 | "Couldn't open file: %s\n", argv[optind]); 191 | exit (1); 192 | } 193 | } 194 | if (level > 1) descend(minindent); 195 | } 196 | 197 | 198 | char *basename (s) 199 | char *s; 200 | { 201 | char *p, *strrchr(); 202 | 203 | if (p = strrchr(s, '/')) 204 | return(++p); 205 | else return(s); 206 | } 207 | -------------------------------------------------------------------------------- /search/print_tree/tpsample: -------------------------------------------------------------------------------- 1 | \noindent 2 | 3 | Here are some examples to illustrate the tpar program and the 4 | `T' triangle, `L' lexical, `O' omit, `M' mother, `D' daughter, 5 | and `P' phantom tree commands. 6 | 7 | %% For tty output, use 8 | %% % tpar tpsample |tree |more 9 | %% or % tpar -t tpsample |tree |more 10 | %% For TeX output, use 11 | %% % tpar -t tpsample |tree -t >tpsample.tex 12 | %% or % tpar -t tpsample |tree -u >tpsample.tex 13 | 14 | This is from the man page: 15 | 16 | (ex8) \tree \T S 17 | every 18 | good boy 19 | VP 20 | \L V - does 21 | \L A - fine 22 | 23 | A couple of examples from McCawley's text: 24 | 25 | p. 35 26 | (6)\tree -b2 27 | S[0] 28 | S[1] 29 | S[2] 30 | NP\T - the terrorists 31 | VP 32 | V\L - shoot 33 | NP\T - the hostage 34 | n't 35 | Adv\L - probably 36 | 37 | The V' with `say' in this next example came out too wide, originally, 38 | because the two constituents following the V, the P' and NP, couldn't be 39 | put close enough together. I wanted to lower the S[2] under the NP so 40 | it would go closer to the preceding P', so I've put a node with no name 41 | but with command Z between the NP and the S[2] below it. The 42 | Z command does not do anything except hold a place in the tree; 43 | it's a little tricky. 44 | 45 | p. 689 46 | (8)\tree 47 | S[0] 48 | NP[x] 49 | the 50 | S[3] 51 | NP - you 52 | V'\T - send $x$ many Christmas\L - cards to your friends 53 | S[1] 54 | NP - it 55 | V' 56 | V\L - say 57 | P'\T - in the Times Al. 58 | NP 59 | \Z 60 | S[2] 61 | NP\T - President R 62 | V'\T 63 | send more than\L - $x$ Christmas cards to\L - Republican supporters 64 | 65 | 66 | In this example from McCawley, p. 310, the V is made an unnatural 67 | mother of the Adv with the M and D commands, and the line that 68 | would have connected the Adv to the S is omitted with the O command. 69 | The original position of the Adv is marked with a phantom, to get the 70 | tree to look like something belongs here. 71 | 72 | (6b) \tree 73 | V' 74 | \M V 75 | V\L - prove 76 | ghost\P 77 | NP 78 | S\T - that the earth is round 79 | \D\O Adv\L - conclusively 80 | 81 | From McCawley, p. 423. There are two side-by-side trees here, but 82 | the left one has omitted lines, so that all that is visible is 83 | `RNR' and the arrow. The N-bar is connected to the S `who teach ...' 84 | with M and D commands, but the line connecting the S to its natural 85 | mother remains. To get the line connecting the two N-bars to slant 86 | to the left, the P command is used to put a phantom constituent in 87 | the original position of the RNR'd S. That first Z command is there 88 | just to hold a place in the tree. 89 | 90 | (21) \tree 91 | \Z 92 | \O - \O - RNR\O\L - ---$>$ 93 | NP 94 | NP 95 | Det\L - most 96 | N'\M 97 | N' - N\L - linguists 98 | some room\P 99 | and 100 | NP 101 | Det\L - almost\L - all 102 | N' 103 | N' - N\L - anthro-\L - pologists 104 | S\D\T - who teach at\L - American\L - universities 105 | 106 | \bye 107 | -------------------------------------------------------------------------------- /search/print_tree/tree.1: -------------------------------------------------------------------------------- 1 | .TH TREE 1 LOCAL 2 | .SH NAME 3 | tree, tpar 4 | .SH SYNOPSIS 5 | .B tree 6 | [ options ] [ files ] 7 | .br 8 | .B tpar 9 | [ 10 | .B \-t 11 | ] [ 12 | .B \-v 13 | ] [ files ] 14 | .br 15 | .B unpar 16 | [ 17 | .B \-t 18 | ] 19 | .B < 20 | file 21 | .SH DESCRIPTION 22 | .I Tree 23 | reformats trees in a text whose structure is given by parenthesization 24 | into trees displayed with horizontal and vertical lines (or diagonal 25 | lines) connecting the 26 | node names. 27 | The companion program 28 | .I tpar 29 | is an optional utility for adding parentheses to trees with structure 30 | indicated by indentation. 31 | See the example file ptsample and the comments at the beginning of 32 | the source tpar.l for more information. 33 | The other utility 34 | .I unpar 35 | does the opposite of 36 | .IR tpar : 37 | it removes parentheses. 38 | .PP 39 | .I Tree 40 | has 13 options: 41 | .TP 42 | .B \-t 43 | causes 44 | .I tree 45 | to emit 46 | .I TeX 47 | code. 48 | .TP 49 | .B \-u 50 | also produces 51 | .I TeX 52 | code, but with PostScript commands for 53 | diagonal lines. 54 | .TP 55 | .BR \-b 56 | sets the blackness of triangles drawn under certain nodes (see below). 57 | For the 58 | .B \-t 59 | option, extra verticals fill in the base of ``triangles'', the 60 | spacing of them depending on . 61 | For tty output, various characters are used to approximate connecting 62 | lines, again depending on . 63 | .TP 64 | .B \-v 65 | displays 66 | .I TeX 67 | commands for tty output \- normally they are suppressed. 68 | .TP 69 | .BR \-g 70 | uses for gap separating subtrees in place of default value of 2. 71 | .TP 72 | .BR \-q 73 | suppresses warning messages that are otherwise issued when various 74 | circumstances suggest a possible problem with the definition of a 75 | tree. 76 | The warnings are given for blank lines, `\\tree' commands, or text 77 | after a node name when any of these are found within a tree definition. 78 | .TP 79 | .B \-O 80 | causes the lines connecting node names to be omitted. 81 | This option has the same effect as giving the `\\O' command 82 | for each node. 83 | .TP 84 | .B \-L 85 | omits the lines connecting nodes, leaving no vertical space 86 | where the lines would have been. 87 | This option has the same effect as giving the `\\L' command for each node. 88 | .TP 89 | .B \-T 90 | draws triangles under nodes instead of branches. 91 | This option has the same effect as giving the `\\T' command for each node. 92 | .TP 93 | .B \-I 94 | turns trees upside down. 95 | This option has the same effect as giving the `\\I' command for the top node 96 | (or the top nodes, in the case of side-by-side trees). 97 | .TP 98 | .B \-F 99 | lowers terminals to lowest level found in the subtree whose top node 100 | is marked with `\\E'', or else to the lowest level in the entire 101 | tree if `\\E' has not been used. If a terminal has a node immediately 102 | above it with the `\\L' lexical command, this is lowered too. 103 | This option has the same effect as giving the `\\F' command for each 104 | terminal node (or lexical node above it). 105 | .TP 106 | .B \-E 107 | restricts the context for lowering with `\\F' commands or the 108 | .B \-F 109 | option to each subtree under a branching node. 110 | This option has the same effect as giving the `\\E' command for 111 | every branching node. 112 | .TP 113 | .B \-R 114 | places node names to the left of verticals. 115 | This option has the same effect as giving the `\\R' command for 116 | every non-terminal node. 117 | .TP 118 | .B \-x 119 | .TP 120 | .B \-X 121 | cause line drawing characters from the IBM-pc extended 122 | character set to be used for screen output. The 123 | .B \-X 124 | option surrounds these with control characters suitable 125 | for WordStar files. 126 | .PP 127 | .I Tree 128 | processes the text in the files named on the command line, 129 | and the resulting text with the 130 | reformatted trees is produced on the standard output. 131 | If no file names are given on the command line, input 132 | text is assumed on the standard input. 133 | .sp 134 | .DS 135 | % tree inputtextfile >outputtextfile 136 | .br 137 | % tree outputtextfile 138 | .br 139 | % tree -t old.tex >new.tex 140 | .DE 141 | .sp 142 | A tree in a text is introduced by the command `\\tree'. 143 | .sp 144 | .DS 145 | (ex1) \\tree (S(NP(John))(VP(runs))) 146 | .DE 147 | .sp 148 | The formatted tree will be indented by the space that separated the 149 | `\\tree' command from the left margin (8 spaces for the above example). 150 | The `\\tree' command may be followed by the same options that can 151 | be given on the command line. 152 | In case of a conflict, an option given in the text overrides 153 | one given on the command line. 154 | Nodes need not have names, but if the root node has no name, you need 155 | an extra pair of enclosing parentheses if the daughters of the 156 | root are to be connected by lines: 157 | .sp 158 | .DS 159 | (ex2) \\tree ((((John))((runs)))) 160 | .DE 161 | .sp 162 | .PP 163 | After any options, the `\\tree' command must be followed by a tree. 164 | In the case of inappropriate options, or when the next 165 | non-whitespace character after the command and valid options is not 166 | a `(', the command is ignored (and it remains in the processed text). 167 | .sp 168 | .DS 169 | (ex3) \\tree \- this line will remain unchanged 170 | .DE 171 | .sp 172 | If what follows the command does begin like a tree, but does not 173 | have enough right parens to balance the left ones, an error is reported. 174 | .sp 175 | .DS 176 | (ex4) \\tree (S(NP(John)(VP(runs))) \- a bad tree missing 177 | .br 178 | a right paren 179 | .DE 180 | .sp 181 | Trees contain node names and (sub)trees. 182 | The name of the node comes before any sub-trees; text after a sub-tree 183 | not in parentheses is treated as a comment and is discarded. 184 | Since placing text in this position is not an ordinary way of putting 185 | comments into a tree definition, unless the 186 | .B \-q 187 | option is given, warning messages are issued when such text is found. 188 | .sp 189 | .DS 190 | (ex5) \\tree -q (a phrase composed of others(a phrase 191 | .br 192 | \ \ \ \ \ (a)(phrase)) 193 | .br 194 | \ \ \ \ \ This is a comment.(composed) (of others 195 | .br 196 | \ \ \ \ \ (of)(others)) ) 197 | .DE 198 | .sp 199 | Several trees can be placed side-by-side by giving no name to the 200 | topmost node: 201 | .sp 202 | .DS 203 | (ex6) \\tree ((S(John)(V(runs)(fast))) (==>) 204 | .br 205 | (S(V(runs)(fast))(S(John)(does)))) 206 | .DE 207 | .sp 208 | Spacing and new lines are generally not significant, except that spacing 209 | between parts of a node name causes a space to be part of the name (only 210 | a single space appears for multiple blanks or tabs). 211 | As in 212 | .IR TeX , 213 | the percent character introduces a comment which continues through 214 | the end of the line. 215 | (ex7) produces the 216 | same tree as (ex1) above: 217 | .sp 218 | .DS 219 | (ex7) \\tree (S % Comments like this 220 | (NP % are skipped over. 221 | (John) 222 | ) 223 | (VP 224 | (runs) 225 | ) 226 | ) 227 | .DE 228 | .sp 229 | To include left or right paren as part of a node name, precede it with a 230 | back slash. 231 | .sp 232 | .DS 233 | (ex8) \\tree (NP (Det(John's \\(genitive\\))) 234 | .br 235 | (N\\([+count]\\)(legs)) ) 236 | .DE 237 | .sp 238 | A blank may also be made part of a node name by preceding it with a 239 | backslash (but this is not usually necessary). 240 | It is not necessary to use `\\\\' to 241 | make backslash part of a node name, although it is possible, since 242 | this will produce a single backslash in the output. 243 | A percent sign is counted a comment character, as in 244 | .IR TeX , 245 | so to include a percent that will print, use `\\%'. 246 | When generating 247 | .I TeX 248 | code, 249 | .I tree 250 | will leave the backslash there, as well as the percent, so that 251 | .I TeX 252 | will print a percent. 253 | .PP 254 | The horizontal space separating subparts of a tree is by default 255 | two spaces. This can be varied by calling 256 | .I tree 257 | with the 258 | .B -g 259 | (for ``gap'') option, for instance: 260 | .sp 261 | .DS 262 | % tree -g4 infile 263 | .DE 264 | .sp 265 | gives twice the default gap. 266 | You might need to increase the gap when using 267 | .IR TeX , 268 | because it's possible for node names to run into one another. 269 | .PP 270 | A node can be given a display attribute with a command of the 271 | form backslash plus capital letter. 272 | `\\T' draws a triangle under a node name instead of a vertical or 273 | diagonal lines, 274 | and `\\L' for `lexical' omits the vertical under a node with a single child. 275 | The triangle is for the common convention to indicate structure 276 | not given explicitly. 277 | Without the 278 | .B \-u 279 | option, it is not actually a triangle, but rather a box with a 280 | vertical at the top. 281 | With that option, it is an outlined triangle or, if the 282 | .B \-b 283 | option was given with a non-zero value, it is a filled triangle, 284 | with blackness determined by the number after 285 | .BR \-b . 286 | (This number is interpreted as a decimal fraction with higher 287 | values giving darker shades of gray; 8 is darker than 2, 288 | and 85 is just a tiny bit darker than 8.) 289 | .sp 290 | .DS 291 | (ex9) \\tree (\\T S (every) (good boy) 292 | .br 293 | (VP (\\L V(does)) (\\L A(fine)) )) 294 | .DE 295 | .sp 296 | In this example, a triangle is drawn under the S-node, and the 297 | `does' and `fine' are placed immediately under the `V' and `A' 298 | with no connecting vertical line. 299 | (The `\\L' command is also useful for piling up several lines of 300 | text to avoid using too much horizontal space \- see the ptsample 301 | file for illustration.) 302 | .PP 303 | Other commands are `\\I' for inverting a tree, 304 | and `\\H' for designating a node as head of a branching 305 | constituent so that the mother node will be aligned over it. 306 | `\\R' puts a vertical at the right of a node and aligns upper 307 | and lower parts of the tree with this vertical, so that the node 308 | name appears to the left of connecting tree lines. 309 | `\\B' and `\\B0'-`\\B9' are ``bolding'' commands that vary the 310 | style of the connecting lines beneath a node. 311 | .PP 312 | There are two commands for getting related constituents on 313 | the same horizontal level. 314 | `\\F' moves a node with everything under it down, if necessary, 315 | to get a subtree down to level of the lowest node found elsewhere 316 | in the tree. 317 | `\\E' modifies the effect of `\\F' commands by restricting the 318 | downward displacement to the lowest node found in the subtree 319 | with the its top node marked `\\E'. 320 | .PP 321 | There is also the bare beginning of a facility for drawing 322 | discontinuous constituents. The line that would ordinarily 323 | connect a node with the mother above it can be omitted 324 | with the `\\O' command. 325 | Alternatively, the line can be omitted with the `\\P' command, 326 | but then the name is also not displayed (though the tree is 327 | formatted as though there were a name present). 328 | Drawing a new line to connect a node 329 | to a node other than its natural mother requires PostScript 330 | commands, so it can only be done when using the 331 | .B \-u 332 | option (described below). 333 | You label the mother with `\\M' 334 | and label the (presumably) discontinuous daughter with `\\D'. 335 | A curvy line will then be drawn between the mother and the daughter. 336 | If you need to connect other pairs of nodes, you can add a single 337 | digit after the `\\M' and `\\D' (giving 10 more pairs of labels). 338 | Unfortunately, several 339 | daughters can be connected to the same mother in this way only 340 | when all the daughters save possibly one come lower in the tree 341 | than the mother or, if at the same level, to the right of the 342 | mother. 343 | It is not possible to connect more than one unnatural mother to a given 344 | daughter. 345 | Leaves cannot be unnatural mothers. 346 | .sp 347 | .DS 348 | (ex10) \\tree (S(PP\\O\\D(near)(him))(NP(John)) 349 | .br 350 | (VP\\M(saw)(a snake))) 351 | .DE 352 | .sp 353 | Here a line over `PP' is omitted and a curvy line drawn from the 354 | top of `PP', since it has the daughter label `\\D', to a position 355 | under `VP', since it has the corresponding mother label `\\M'. 356 | .PP 357 | The 358 | .I TeX 359 | code output with the 360 | .B \-t 361 | or 362 | .B \-u 363 | option is rather primitive, since 364 | .I tree 365 | uses a rough approximation for the widths of node names. 366 | The width of a 367 | node name is taken to be the number of characters in the name times the 368 | `en' space of the current font, the `en' space being half an `em' or 369 | `quad'. Each line of print making up the tree is assumed to be 12 370 | points high when the current `ex' height is that of Computer Modern 371 | Roman at 10 points, and is adjusted proportionately for `ex' heights 372 | different from this. 373 | .PP 374 | The approximation for the width of names may be off by quite a bit when 375 | node names have a lot of capital letters, or when they contain 376 | .I TeX 377 | commands. 378 | To compensate for this, 379 | .I tree 380 | adds some extra space for names that have lots of caps, 381 | and it removes space taken up by 382 | .I TeX 383 | commands, on the assumption that 384 | .I TeX 385 | commands will not change the width of printed stuff (which 386 | assumption may easily be wrong, of course). 387 | .PP 388 | If you do put font changing commands into node names, it is not 389 | necessary to group them in braces to confine their effects to the 390 | node names, since 391 | .I tree 392 | adds braces around node names, anyway. 393 | Every line of a tree is a paragraph, so one way to control left 394 | indentation is to give `\\parindent' an appropriate value. 395 | Page breaks are prevented within a tree, so if you have not provided 396 | enough vertically stretchable space around trees, you may get 397 | .I TeX 398 | underfull vbox error messages, or, in the case of a tree too long 399 | for a page, a fatal error. 400 | .PP 401 | The 402 | .B \-u 403 | option works like the 404 | .B \-t 405 | option, except that for right-side up trees, instead of having 406 | .I TeX 407 | draw horizontal and vertical rules, PostScript commands for 408 | diagonal lines are issued. 409 | Naturally, this method of obtaining slanty lines is going 410 | to work only if you have a PostScript printer. 411 | The PostScript code is stuck inside 412 | .I TeX 413 | .B special 414 | commands, and the dvi-file translator program is expected 415 | just to include this code in its PostScript output. 416 | (Not all PS drivers for 417 | .I TeX 418 | do this, or do it in the same way. 419 | If it's a problem, email Greg for a version of 420 | .I dvi2ps 421 | that behaves right.) 422 | .SH BUGS 423 | Curvy lines from `\\M' and `\\D' are likely to run through node 424 | names. 425 | .PP 426 | The thickness of diagonal lines is not varied with different 427 | font sizes. 428 | But you could change it 429 | .I ad hoc 430 | by including in the text a command of the form: 431 | .br 432 | \ \ \ \ \ `\\special{ setlinewidth}'. 433 | .PP 434 | Triangles over two or more nodes are not wide enough. 435 | .PP 436 | Lowering a node by enclosing it in multiple parentheses just extends 437 | the vertical line above it, causing a corner with the \-u option. 438 | A curve would be nicer. 439 | .PP 440 | There are undocumented \-d debug and \-h help options. 441 | .PP 442 | Terminal nodes of inverted trees that are re-attached to empty nodes 443 | of a larger construction are not treated correctly by the `\\R' 444 | command or the \-R option. 445 | .PP 446 | A node name in the same row as a very high or deep name will have 447 | excessive white space above or below it. 448 | Fonts with small ex-heights have tree lines too close to the tops 449 | of capitals, and fonts with large ex-heights have them too far away. 450 | .SH "SEE ALSO" 451 | tex(1) 452 | .SH AUTHOR 453 | Greg Lee, U. Hawaii Dept. of Linguistics, lee@uhccux.uhcc.hawaii.edu 454 | .PP 455 | .I Tree 456 | was inspired by a predecessor program written by Chris Barker, 457 | Linguistics Board at University of California, Santa Cruz, 458 | barker@ling.ucsc.edu 459 | -------------------------------------------------------------------------------- /search/print_tree/unpar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cforth/toys/44ccd01bafbbc7c796a7e5f2011be4cf81aa384d/search/print_tree/unpar -------------------------------------------------------------------------------- /search/print_tree/unpar.l: -------------------------------------------------------------------------------- 1 | %{ 2 | /* 3 | * unpar.l: substitute indentation for parenthesization. 4 | * Version 0.1 5 | * (unpar recognizes some \tree definitions as correct which tree 6 | * rejects.) 7 | * -- Greg Lee, lee@uhccux.uhcc.hawaii.edu, 6/24/90 8 | */ 9 | #define TRUE 1 10 | #define FALSE 0 11 | int tex_opt = FALSE; 12 | int level = 0; 13 | int havename = 0; 14 | int wait = 0; 15 | int i; 16 | %} 17 | 18 | %s T X C 19 | 20 | %% 21 | 22 | ^".tr" { 23 | printf("\\tree"); 24 | havename = 1; 25 | BEGIN(T); 26 | } 27 | 28 | \\tree[ \t]*(-([tuvLTOIFER]+|[bg][0-9]+)[ \t]*)* { 29 | ECHO; 30 | havename = 1; 31 | if (tex_opt) BEGIN(X); 32 | else BEGIN(T); 33 | } 34 | 35 | ^[ \t]+ ; 36 | [ \t]+$ ; 37 | 38 | \n ; 39 | 40 | \\\( { 41 | havename = 1; 42 | ECHO; 43 | } 44 | [^ \t\n\(\)]/\( { 45 | havename = 1; 46 | ECHO; 47 | putchar(' '); 48 | } 49 | "("([^\)\(]|\\\)|\\\()+"("([^\)\(]|\\\)|\\\()+")"([^\)\(]|\\\)|\\\()*")" { 50 | wait = 2; 51 | REJECT; 52 | } 53 | "("[ \t\n]* { 54 | level++; 55 | if (wait == 1) printf(" - "); 56 | else { 57 | if (!havename) printf("\\Z\n"); 58 | else putchar('\n'); 59 | indent(); 60 | } 61 | havename = 0; 62 | if (wait) wait--; 63 | } 64 | ")"[^\)\(]+ { 65 | if (level == 1) {REJECT;} 66 | else level--; 67 | } 68 | ")" { 69 | level--; 70 | if (!level) { 71 | printf("\n"); 72 | BEGIN(0); 73 | } 74 | } 75 | \$_[0-9ijkxyz]\$ { 76 | havename = 1; 77 | printf("[%c]", yytext[2]); 78 | } 79 | \$\\overline\{\\rm\ [NAVP]\}\$ { 80 | havename = 1; 81 | printf(" %c'", yytext[15]); 82 | } 83 | \\[%\(\)] { 84 | havename = 1; 85 | ECHO; 86 | } 87 | % { 88 | BEGIN(C); 89 | } 90 | \n { 91 | if (tex_opt) BEGIN(X); 92 | else BEGIN(T); 93 | } 94 | . ; 95 | . { 96 | havename = 1; 97 | ECHO; 98 | } 99 | 100 | %% 101 | 102 | indent() 103 | { int i; 104 | 105 | for (i = 0; i < 2*(level-1); i++) putchar(' '); 106 | } 107 | 108 | extern char *optarg; /* from getopt */ 109 | extern int optind; 110 | 111 | main(argc, argv) 112 | int argc; 113 | char *argv[]; 114 | { int c; 115 | char *progname = NULL, *basename(); 116 | 117 | progname = basename (argv[0]); 118 | while ((c = getopt (argc, argv, "ht")) != EOF) 119 | switch (c) { 120 | case 't': tex_opt = TRUE; break; 121 | case 'h': 122 | default: 123 | fprintf(stderr, "Usage: %s [options] [files]\n", progname); 124 | fprintf(stderr, "options = -t\t(remove TeX code)\n"); 125 | fprintf(stderr, " -h\t(print this information)\n"); 126 | exit(1); 127 | } 128 | 129 | if (optind >= argc) { 130 | (void) yylex (); 131 | } 132 | else for (; (optind < argc); optind++) { 133 | if (yyin == NULL) yyin = stdin; 134 | if (freopen (argv[optind], "r", stdin) != NULL) { 135 | #ifdef FLEX_SCANNER 136 | /* to get flex to look at > 1 file */ 137 | yy_init = 1; 138 | #endif 139 | (void) yylex (); 140 | } 141 | else { 142 | (void) fprintf (stderr, 143 | "Couldn't open file: %s\n", argv[optind]); 144 | exit (1); 145 | } 146 | } 147 | } 148 | 149 | 150 | char *basename (s) 151 | char *s; 152 | { 153 | char *p, *strrchr(); 154 | 155 | if (p = strrchr(s, '/')) 156 | return(++p); 157 | else return(s); 158 | } 159 | -------------------------------------------------------------------------------- /search/tree_ergodic.py: -------------------------------------------------------------------------------- 1 | ## 二叉树遍历 2 | 3 | ## 0 4 | ## ___|___ 5 | ## | | 6 | ## 1 4 7 | ## _|_ _|_ 8 | ## | | | | 9 | ## 2 3 5 6 10 | 11 | 12 | class BinaryTree: 13 | def __init__(self, data, lchild=None, rchild=None): 14 | self.data = data 15 | self.rchild = rchild 16 | self.lchild = lchild 17 | 18 | 19 | node2 = BinaryTree(2) 20 | node3 = BinaryTree(3) 21 | node5 = BinaryTree(5) 22 | node6 = BinaryTree(6) 23 | 24 | 25 | node1 = BinaryTree(1, lchild=node2, rchild=node3) 26 | node4 = BinaryTree(4, lchild=node5, rchild=node6) 27 | 28 | node0 = BinaryTree(0, lchild=node1, rchild=node4) 29 | 30 | 31 | ## 深度优先遍历二叉树 32 | def depth_first_search(root): 33 | stack = [] 34 | stack.append(root) 35 | while len(stack) != 0 : 36 | node = stack[-1] 37 | print(node.data, end=' ') 38 | stack.pop() 39 | if node.rchild != None: 40 | stack.append(node.rchild) 41 | if node.lchild != None: 42 | stack.append(node.lchild) 43 | print('\n') 44 | 45 | 46 | depth_first_search(node0) 47 | ## 0 1 2 3 4 5 6 48 | 49 | 50 | ## 广度优先遍历二叉树 51 | def breadth_first_search(root): 52 | quene = [] 53 | quene.append(root) 54 | while len(quene) != 0 : 55 | node = quene[0] 56 | print(node.data, end=' ') 57 | quene.pop(0) 58 | if node.lchild != None: 59 | quene.append(node.lchild) 60 | if node.rchild != None: 61 | quene.append(node.rchild) 62 | print('\n') 63 | 64 | breadth_first_search(node0) 65 | ## 0 1 4 2 3 5 6 66 | 67 | 68 | 69 | ## 普通树遍历 70 | 71 | ## 0 72 | ## _____|_____ 73 | ## | | | 74 | ## 1 5 8 75 | ## _|_ _|_ | 76 | ## | | | | | | 77 | ## 2 3 4 6 7 9 78 | 79 | 80 | class Tree: 81 | def __init__(self, data, child=None): 82 | self.data = data 83 | self.child = child 84 | 85 | 86 | node2 = Tree(2) 87 | node3 = Tree(3) 88 | node4 = Tree(4) 89 | node6 = Tree(6) 90 | node7 = Tree(7) 91 | node9 = Tree(9) 92 | 93 | node1 = Tree(1, [node2, node3, node4]) 94 | node5 = Tree(5, [node6, node7]) 95 | node8 = Tree(8, [node9]) 96 | 97 | node0 = Tree(0, [node1, node5, node8]) 98 | 99 | ## 深度优先遍历树 100 | def depth_first_search_tree(root): 101 | stack = [] 102 | stack.append(root) 103 | while len(stack) != 0 : 104 | node = stack[-1] 105 | print(node.data, end=' ') 106 | stack.pop() 107 | if node.child != None: 108 | length = len(node.child) 109 | for i in range(1, length+1): 110 | stack.append(node.child[-i]) 111 | print('\n') 112 | 113 | depth_first_search_tree(node0) 114 | ## 0 1 2 3 4 5 6 7 8 9 115 | 116 | 117 | ## 广度优先遍历树 118 | def breadth_first_search_tree(root): 119 | quene = [] 120 | quene.append(root) 121 | while len(quene) != 0 : 122 | node = quene[0] 123 | print(node.data, end=' ') 124 | quene.pop(0) 125 | if node.child != None: 126 | for item in node.child: 127 | quene.append(item) 128 | print('\n') 129 | 130 | breadth_first_search_tree(node0) 131 | ## 0 1 5 8 2 3 4 6 7 9 132 | -------------------------------------------------------------------------------- /sort/QuickSortDemo.java: -------------------------------------------------------------------------------- 1 | public class QuickSortDemo { 2 | public static void main(String args[]) { 3 | int data[] = new int[]{9,5,6,4,1,2,3,7,0}; 4 | print(data); 5 | quicksort(data); 6 | print(data); 7 | } 8 | 9 | public static void print(int arr[]) { 10 | for(int i=0; i arr[lo]) { 29 | if(j == lo) { 30 | break; 31 | } 32 | j--; 33 | } 34 | if (i >= j) { 35 | break; 36 | } 37 | int t = arr[i]; 38 | arr[i] = arr[j]; 39 | arr[j] = t; 40 | } 41 | int t = arr[lo]; 42 | arr[lo] = arr[j]; 43 | arr[j] = t; 44 | return j; 45 | } 46 | 47 | public static void sort(int arr[], int lo, int hi) { 48 | if(lo >= hi) { 49 | return; 50 | } 51 | int index = partition(arr, lo, hi); 52 | sort(arr, lo, index-1); 53 | sort(arr, index+1, hi); 54 | } 55 | 56 | public static void quicksort(int arr[]) { 57 | sort(arr, 0, arr.length-1); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /sort/counting_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Counting Sort Algorithm 3 | 4 | def counting_sort(A, B, k): 5 | #let C[0..k] be a new array 6 | C = [0 for i in range(0, k+1)] 7 | 8 | for j in range(0, len(A)): 9 | C[A[j]] = C[A[j]] + 1 10 | #C[i] now contains the number of elements equals to i. 11 | for i in range(1, k+1): 12 | C[i] = C[i] + C[i-1] 13 | #C[i] now contains the number of elements less than or equal to i. 14 | for j in range(len(A)-1, -1, -1): 15 | B[C[A[j]]-1] = A[j] 16 | C[A[j]] = C[A[j]] - 1 17 | 18 | 19 | 20 | ## test 21 | def main(): 22 | arr = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 23 | arr_out = [0 for i in range(0, len(arr))] 24 | counting_sort(arr, arr_out, 7) 25 | print(arr) 26 | print(arr_out) 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /sort/heap_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Heap Sort Algorithm 3 | 4 | def sink(pq, k, end_num): 5 | while 2*k < end_num: 6 | j = 2 * k 7 | if pq[j] < pq[j+1]: 8 | j += 1 9 | if pq[k] > pq[j]: 10 | break 11 | pq[k], pq[j] = pq[j], pq[k] 12 | k = j 13 | 14 | 15 | def heap_sort(pq): 16 | end_num = len(arr) - 1 17 | for k in range(end_num//2, 0, -1): 18 | sink(pq, k, end_num) 19 | 20 | 21 | while end_num > 1: 22 | pq[1], pq[end_num] = pq[end_num], pq[1] 23 | end_num -= 1 24 | sink(pq, 1, end_num) 25 | 26 | 27 | 28 | ## test 29 | arr = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 30 | arr.insert(0, None) 31 | heap_sort(arr) 32 | arr.pop(0) 33 | print(arr) 34 | -------------------------------------------------------------------------------- /sort/insertion_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Insertion Sort Algorithm 3 | 4 | def insertion_sort(the_list): 5 | length = len(the_list) 6 | for i in range(length): 7 | for n in range(i, 0, -1): 8 | if the_list[n] < the_list[n-1]: 9 | the_list[n], the_list[n-1] = the_list[n-1], the_list[n] 10 | else: 11 | break 12 | return the_list 13 | 14 | 15 | ## test 16 | test_list = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 17 | insertion_sort(test_list) 18 | print(test_list) 19 | 20 | -------------------------------------------------------------------------------- /sort/merge_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Merge Sort Algorithm 3 | 4 | class MergeSort(object): 5 | def __init__(self, array): 6 | self._array = array 7 | self._aux = [None] * len(array) 8 | 9 | def __merge(self, lo, mid, hi): 10 | i = lo 11 | j = mid + 1 12 | for k in range(lo, hi+1): 13 | self._aux[k] = self._array[k] 14 | for k in range(lo, hi+1, 1): 15 | if i > mid: 16 | self._array[k] = self._aux[j] 17 | j += 1 18 | elif j > hi: 19 | self._array[k] = self._aux[i] 20 | i += 1 21 | elif self._aux[i] < self._aux[j]: 22 | self._array[k] = self._aux[i] 23 | i += 1 24 | else: 25 | self._array[k] = self._aux[j] 26 | j += 1 27 | 28 | def __sort(self, lo, hi): 29 | if lo >= hi: 30 | return 31 | mid = lo + ((hi - lo) // 2) 32 | self.__sort(lo, mid) 33 | self.__sort(mid+1, hi) 34 | self.__merge(lo, mid, hi) 35 | 36 | def sort(self): 37 | self.__sort(0, len(self._array)-1) 38 | 39 | @property 40 | def array(self): 41 | return self._array 42 | 43 | 44 | ## test 45 | arr = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 46 | test_sort = MergeSort(arr) 47 | test_sort.sort() 48 | print(test_sort.array) 49 | 50 | 51 | -------------------------------------------------------------------------------- /sort/quick_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Quick Sort Algorithm 3 | 4 | def partition(array, lo, hi): 5 | i = lo 6 | j = hi + 1 7 | while(True): 8 | i += 1 9 | while array[i] < array[lo]: 10 | if i == hi: 11 | break 12 | i += 1 13 | j -= 1 14 | while array[j] > array[lo]: 15 | if j == lo: 16 | break 17 | j -= 1 18 | if i >= j: 19 | break 20 | array[i], array[j] = array[j], array[i] 21 | 22 | array[lo], array[j] = array[j], array[lo] 23 | return j 24 | 25 | 26 | def sort(array, lo, hi): 27 | if lo >= hi: 28 | return 29 | index = partition(array, lo, hi) 30 | sort(array, lo, index - 1) 31 | sort(array, index + 1, hi) 32 | 33 | 34 | def quick_sort(array): 35 | sort(array, 0, len(array) - 1) 36 | 37 | 38 | ## test 39 | arr = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 40 | quick_sort(arr) 41 | print(arr) 42 | -------------------------------------------------------------------------------- /sort/radix_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Radix Sort Algorithm 3 | 4 | def counting_part(arr_in, arr_out, bit): 5 | #bit为要排序的位 6 | bucket = [0 for i in range(11)] 7 | 8 | for i in range(len(arr_in)): 9 | j = arr_in[i]//(10**bit)%10 10 | bucket[j] = bucket[j] + 1 11 | 12 | for i in range(1, 11): 13 | bucket[i] = bucket[i] + bucket[i-1] 14 | 15 | for i in range(len(arr_in)-1, -1, -1): 16 | j = arr_in[i]//(10**bit)%10 17 | arr_out[bucket[j]-1] = arr_in[i] 18 | bucket[j] = bucket[j] - 1 19 | 20 | 21 | def radix_count(arr, maxbit): 22 | for i in range(0, maxbit): 23 | bucket = [0 for j in range(len(arr))] 24 | counting_part(arr, bucket, i) 25 | arr = bucket[:] 26 | 27 | return arr 28 | 29 | 30 | 31 | #test 32 | def main(): 33 | arr = [329, 457, 657, 839, 436, 720, 355] 34 | print(arr) 35 | print(radix_count(arr, 3)) 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /sort/selection_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Selection Sort Algorithm 3 | 4 | def selection_sort(the_list): 5 | length = len(the_list) 6 | for i in range(length): 7 | min_index = i 8 | for n in range(i, length, 1): 9 | if the_list[n] < the_list[min_index]: 10 | min_index = n 11 | the_list[i], the_list[min_index] = the_list[min_index], the_list[i] 12 | return the_list 13 | 14 | 15 | ## test 16 | test_list = [1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 5, 7, 7] 17 | selection_sort(test_list) 18 | print(test_list) 19 | 20 | -------------------------------------------------------------------------------- /sort/shell_sort.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/env python3 2 | ## Shell Sort Algorithm 3 | 4 | def shell_sort(the_list): 5 | n = len(the_list) 6 | h = 1 7 | while h < n//3: 8 | h = h * 3 + 1 9 | while h >= 1: 10 | for i in range(1, n, 1): 11 | if i < h: 12 | break 13 | for j in range(i, h-1, -h): 14 | if the_list[j] < the_list[j-h]: 15 | the_list[j-h], the_list[j] = the_list[j], the_list[j-h] 16 | else: 17 | break 18 | h = h //3 19 | return the_list 20 | 21 | 22 | ## test 23 | test_list = [0, 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5, 0, 5, 7, 7] 24 | shell_sort(test_list) 25 | print(test_list) 26 | 27 | --------------------------------------------------------------------------------