├── .gitignore
├── .python-version
├── .travis.yml
├── .vscode
└── settings.json
├── 10장_검색
├── 10_intersection_two_arrays.py
├── 1_sequential_search.py
├── 2_ordered_sequential_search.py
├── 3_quick_select.py
├── 4_binary_search.py
├── 5_search_entry_matrix.py
├── 6_searching_in_a_matrix.py
├── 7_find_max_unimodal_array.py
├── 8_find_sqrt_bin_search.py
├── 9_find_time_occurence_list.py
└── binary_search.py
├── 11장_동적_계획법
├── 1_memoized_fib.py
├── 2_memoized_longest_inc_subseq.py
├── benchmark.py
└── functools_wraps.py
├── 12장_그래프_기초
├── 1_tree.py
└── 2_bunchclass.py
├── 13장_이진_트리
├── 1_BT_lists.py
├── 2_binary_tree.py
├── 3_binary_search_tree.py
├── 4_AVL_BST.py
└── binary_tree.py
├── 14장_트리_순회
├── 1_transversal_BST_iteratively.py
├── 2_transversal_BST_recursively.py
├── 3_transversal_BST_ancestor.py
├── binary_search_tree.py
├── binary_tree.py
└── transversal_BST_recursively.py
├── 1장_숫자
├── .DS_Store
├── 10_finding_prime.py
├── 11_generate_prime.py
├── 12_testing_numpy.py
├── 13_testing_numpy_speed.py
├── 1_testing_floats.py
├── 2_convert_to_decimal.py
├── 3_convert_from_decimal.py
├── 4_convert_from_decimal_larger_bases.py
├── 5_convert_dec_to_any_base_rec.py
├── 6_finding_gcd.py
├── 7_testing_random.py
├── 8_find_fibonacci_seq.py
└── 9_find_fibonacci_by_generator.py
├── 2장_내장_시퀀스_타입
├── 10_combination.py
├── 11_palindrome.py
├── 1_count_unique_words.py
├── 2_runtime_lists_with_timeit_module.py
├── 3_reversing_string.py
├── 4_reversing_words_.py
├── 5_reversing_words.py
├── 6_reversing_words.py
├── 7_reversing_words.py
├── 8_simple_str_compression.py
└── 9_permutation.py
├── 3장_컬렉션_데이터_구조
├── 10_is_anagram_using_ord.py
├── 11_find_dice_probabilities.py
├── 12_delete_duplicate_char_str.py
├── 1_set_operations_with_lists.py
├── 2_set_operations_with_dicts.py
├── 3_setdefault_example.py
├── 4_runtime_dicts_with_timeit_module.py
├── 5_defaultdict_example.py
├── 6_orderedDict_example.py
├── 7_counterDict_example.py
├── 8_find_top_N_recurring_words.py
└── 9_is_anagram.py
├── 4장_구조와_모듈
├── 1_sys_example.py
├── 2_fib_generator.py
├── 3_grep_word_from_files.py
├── 4_remove_blank_lines.py
├── 5_remove_blank_lines_with.py
├── 6_change_ext_file.py
├── hello.py
└── hello.txt
├── 5장_객체지향_설계
├── 10_adapter_pattern_BETTER.py
├── 11_adapter_pattern_BEST.py
├── 12_facade_pattern.py
├── 13_observer_pattern.py
├── 1_hash_and_eq_NO.py
├── 2_hash_and_eq_NO.py
├── 3_hash_and_eq_OK.py
├── 4_benchmark_decorator.py
├── 5_class_and_static_decorator.py
├── 6_observer_pattern_with_set.py
├── 7_observer_pattern_with_dict.py
├── 8_observer_pattern_with_event.py
├── 9_adapter_pattern_OK.py
├── ShapeClass.py
└── hash_and_eq.py
├── 6장_파이썬_고급
├── 1_threading_with_queue.py
├── 2_threading_mutex.py
├── 3_threading_semaphore.py
├── 4_threading_with_condition.py
├── 5_using_time_module.py
├── 6_doctest_factorial.py
├── coroutine.py
├── event_simple.py
├── test_pytest.py
└── threading_event.py
├── 7장_추상_데이터_타입
├── 10_linkedlist_LIFO.py
├── 11_linkedlist_FIFO.py
├── 12_hash_table.py
├── 13_reverse_string_with_stack.py
├── 14_balance_parenthesis_str_stack.py
├── 15_dec2bin_with_stack.py
├── 16_stack_with_min.py
├── 17_set_of_stacks.py
├── 18_palindrome_checker_with_deque.py
├── 19_animal_shelter.py
├── 1_stack.py
├── 20_find_N_largest_smallest_items_seq.py
├── 21_merge_sorted_seqs.py
├── 22_find_kth_from_the_end.py
├── 23_part_linked_list.py
├── 24_doubled_linked_list_fifo.py
├── 25_check_pal.py
├── 26_sum_linked_list.py
├── 27_circular_linked_list.py
├── 2_stack_with_node.py
├── 3_queue.py
├── 4_queue_from_two_stacks.py
├── 5_linked_queue.py
├── 6_deque.py
├── 7_max_heapify.py
├── 8_priority_queue.py
├── 9_node.py
├── deque.py
├── linkedListFIFO.py
├── node.py
├── queue.py
└── stack.py
├── 8장_점근적_분석
└── find_fibonacci_seq.py
├── 9장_정렬
├── 10_heap_sort_2.py
├── 11_heap_sort_3.py
├── 1_bubble_sort.py
├── 2_selection_sort.py
├── 3_insertion_sort.py
├── 4_gnome_sort.py
├── 5_count_sort.py
├── 6_merge_sort.py
├── 7_quick_sort.py
├── 8_find_k_largest_seq_quicksort.py
├── 9_heap_sort_1.py
├── a.dat
├── b.dat
├── c.dat
└── heap.py
├── HALEIWA.jpg
├── README.md
├── README_old.md
├── ebook
└── book_second_edition.pdf
├── interview_problems
├── balanced.py
├── binary_search.py
├── bst.py
├── check_anagram.py
├── combination.py
├── hash_table.py
├── linked_list.py
├── longest_common_prefix.py
├── longest_increasing_subsequence.py
├── merge_sort.py
├── palindome.py
├── permutation.py
├── queue.py
├── quick_sort.py
├── reverse_str.py
└── stack.py
├── requirements.txt
└── source_code
├── .DS_Store
├── USEFUL
├── advanced
│ └── lru_cache.py
├── basic_examples
│ ├── example_OrderedDict.py
│ ├── example_args.py
│ ├── example_benchmark_decorator.py
│ ├── example_comp_lists.py
│ ├── example_counter.py
│ ├── example_decorators.py
│ ├── example_defaultdict.py
│ ├── example_doctest.py
│ ├── example_fractions.py
│ ├── example_generator.py
│ ├── example_lambda.py
│ ├── example_logging.py
│ ├── example_numpy.py
│ ├── example_open_files.py
│ ├── example_pickle.py
│ ├── example_queue.py
│ ├── example_random.py
│ ├── example_setdefault.py
│ ├── example_sets.py
│ ├── example_socket.py
│ ├── example_string_format.py
│ ├── example_subprocess.py
│ ├── example_telnet.py
│ ├── example_testing.py
│ ├── example_threads.py
│ └── example_time.py
├── dynamic_programming
│ ├── __init__.py
│ ├── memo.py
│ └── memoized_longest_inc_subseq.py
├── oop
│ ├── ShapeClass.py
│ └── __init__.py
└── useful_with_files
│ ├── change_ext_file.py
│ ├── count_unique_words_files.py
│ ├── count_unique_words_frequency.py
│ ├── grep_word_from_files.py
│ └── remove_blank_lines.py
├── abstract_structures
├── HashTable.py
├── Queue.py
├── Stack.py
├── __init__.py
├── heap
│ ├── __init__.py
│ ├── find_N_largest_smallest_items_seq.py
│ ├── heapify.py
│ ├── merge_sorted_seqs.py
│ └── priority_queue.py
├── linked_list
│ ├── __init__.py
│ ├── circular_ll.py
│ ├── double_linked_list_fifo.py
│ ├── find_kth_from_the_end.py
│ ├── linked_list_fifo.py
│ ├── linked_list_lifo.py
│ ├── node.py
│ ├── part_linked_list.py
│ └── sum_linked_list.py
├── queues
│ ├── __init__.py
│ ├── animal_shelter.py
│ ├── deque.py
│ ├── linked_queue.py
│ ├── palindrome_checker_with_deque.py
│ └── queue.py
└── stacks
│ ├── __init__.py
│ ├── dec2bin_with_stack.py
│ ├── linked_stack.py
│ ├── reverse_string_with_stack.py
│ ├── set_of_stacks.py
│ ├── stack.py
│ ├── stack_with_min.py
│ └── towers_of_hanoi.py
├── bitwise
├── bit_array.py
├── bitwise.txt
├── clear_bits.py
├── find_bit_len.py
├── find_how_many_1_binary.py
├── get_bit.py
├── get_float_rep_bin.py
├── insert_small_bin_into_big_bin.py
├── next_with_same_num_1s.py
├── num_bits_to_convert_2_nums.py
├── set_bit.py
├── swap_in_place.py
├── swap_odd_even.py
└── update_bit.py
├── builtin_structures
├── __init__.py
├── anagram.py
├── balance.txt
├── balance_symbols.py
├── check_if_2_numbers_sum_to_k.py
├── check_if_3_numbers_sum_to_zero.py
├── check_non_overlapping_intervals.py
├── convert_numerical_bases.py
├── convert_str_2_int.py
├── count_unique_words_On2.py
├── delete_duplicate_char_str.py
├── fibonacci.py
├── find_0_MxN_replace_cols_rows.py
├── find_dice_probabilities.py
├── find_edit_distance.py
├── find_first_non_repetead_char.py
├── find_gcd.py
├── find_if_substr.py
├── find_if_unique_char.py
├── find_largest_sum.py
├── find_longest_inc_subseq.py
├── find_longest_str_unique_chars.py
├── find_non_repeating_number.py
├── find_product_without_division.py
├── find_top_N_recurring_words.py
├── find_two_missing_numbers_in_sequence.py
├── get_float_rep_bin.py
├── interserction_two_arrays.py
├── max_subarray_stocks.py
├── number_of_zeros_factorial.txt
├── palindrome.py
├── permutations.py
├── permutations_alphanumeric.py
├── primes.py
├── prod_other_ints.py
├── ransom_note.py
├── reverse_string.py
├── reverse_words.py
├── rotate_NxN.py
├── runtime_dicts_with_timeit_module.py
├── runtime_lists_with_timeit_module.py
├── search_entry_matrix.py
├── simple_str_comprension.py
└── sum_two_numbers_as_strings.py
├── learning
└── decorator.py
├── searching_and_sorting
├── searching
│ ├── __init__.py
│ ├── binary_search.py
│ ├── binary_search_matrix.py
│ ├── find_item_rotated_sorted_array.py
│ ├── find_max_unimodal_array.py
│ ├── find_sqrt_bin_search.py
│ ├── find_str_array_with_empty_str.py
│ ├── find_time_occurence_list.py
│ ├── ordered_sequential_search.py
│ ├── quick_select.py
│ ├── searching_in_a_matrix.py
│ └── sequential_search.py
└── sorting
│ ├── 1.dat
│ ├── 2.dat
│ ├── 3.dat
│ ├── __init__.py
│ ├── bubble_sort.py
│ ├── count_sort.py
│ ├── gnome_sort.py
│ ├── heap.py
│ ├── heap_sort.py
│ ├── insertion_sort.py
│ ├── merge_and_sort_two_arrays.py
│ ├── merge_sort.py
│ ├── quick_sort.py
│ ├── selection_sort.py
│ └── sort_anagrams_together.py
└── trees
├── __init__.py
├── binary_search_tree.py
├── binary_tree.py
├── binary_tree_generators.py
├── bunchclass.py
├── check_ancestor.py
├── check_if_balanced.py
├── check_if_bst.py
├── check_largest_item.py
├── simple_tree.py
├── transversal.py
└── trie.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 | *~
3 |
4 | # C extensions
5 | *.so
6 |
7 | # Packages
8 | *.egg
9 | *.egg-info
10 | dist
11 | build
12 | eggs
13 | parts
14 | bin
15 | var
16 | sdist
17 | develop-eggs
18 | .installed.cfg
19 | lib
20 | lib64
21 |
22 | # Installer logs
23 | pip-log.txt
24 |
25 | # Unit test / coverage reports
26 | .coverage
27 | .tox
28 | nosetests.xml
29 |
30 | # Translations
31 | *.mo
32 |
33 | # Mr Developer
34 | .mr.developer.cfg
35 | .project
36 | .pydevproject
37 |
38 | # PyCharm
39 | .idea
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
1 | 3.7.0
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | # command to install dependencies
5 | install: "pip install -r requirements.txt"
6 | # command to run tests
7 | script: nosetests
8 | notifications:
9 | email: false
10 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.linting.pylintEnabled": false,
3 | "python.linting.pep8Enabled": true,
4 | "python.linting.enabled": true
5 | }
--------------------------------------------------------------------------------
/10장_검색/10_intersection_two_arrays.py:
--------------------------------------------------------------------------------
1 | from binary_search import binary_search_iter
2 |
3 |
4 | # 파이썬 set 사용
5 | def intersection_two_arrays_sets(seq1, seq2):
6 | set1 = set(seq1)
7 | set2 = set(seq2)
8 | return set1.intersection(set2)
9 |
10 |
11 | # 병합 정렬 사용
12 | def intersection_two_arrays_ms(seq1, seq2):
13 | res = []
14 | while seq1 and seq2:
15 | if seq1[-1] == seq2[-1]:
16 | res.append(seq1.pop())
17 | seq2.pop()
18 | elif seq1[-1] > seq2[-1]:
19 | seq1.pop()
20 | else:
21 | seq2.pop()
22 | res.reverse()
23 | return res
24 |
25 |
26 | # 이진 검색 사용
27 | def intersection_two_arrays_bs(seq1, seq2):
28 | if len(seq1) > len(seq2):
29 | seq, key = seq1, seq2
30 | else:
31 | seq, key = seq2, seq1
32 | intersec = []
33 | for item in key:
34 | if binary_search_iter(seq, item):
35 | intersec.append(item)
36 | return intersec
37 |
38 |
39 | def test_intersection_two_arrays():
40 | seq1 = [1, 2, 3, 5, 7, 8]
41 | seq2 = [3, 5, 6]
42 | assert(set(intersection_two_arrays_sets(seq1, seq2)) == set([3, 5]))
43 | assert(intersection_two_arrays_bs(seq1, seq2) == [3, 5])
44 | assert(intersection_two_arrays_ms(seq1, seq2) == [3, 5])
45 | print("테스트 통과!")
46 |
47 |
48 | if __name__ == "__main__":
49 | test_intersection_two_arrays()
50 |
--------------------------------------------------------------------------------
/10장_검색/1_sequential_search.py:
--------------------------------------------------------------------------------
1 | def sequential_search(seq, n):
2 | for item in seq:
3 | if item == n:
4 | return True
5 | return False
6 |
7 |
8 | def test_sequential_search():
9 | seq = [1, 5, 6, 8, 3]
10 | n1 = 5
11 | n2 = 7
12 | assert(sequential_search(seq, n1) is True)
13 | assert(sequential_search(seq, n2) is False)
14 | print("테스트 통과!")
15 |
16 |
17 | if __name__ == "__main__":
18 | test_sequential_search()
19 |
--------------------------------------------------------------------------------
/10장_검색/2_ordered_sequential_search.py:
--------------------------------------------------------------------------------
1 | def ordered_sequential_search(seq, n):
2 | item = 0
3 | for item in seq:
4 | if item > n:
5 | return False
6 | if item == n:
7 | return True
8 | return False
9 |
10 |
11 | def test_ordered_sequential_search():
12 | seq = [1, 2, 4, 5, 6, 8, 10]
13 | n1 = 10
14 | n2 = 7
15 | assert(ordered_sequential_search(seq, n1) is True)
16 | assert(ordered_sequential_search(seq, n2) is False)
17 | print("테스트 통과!")
18 |
19 |
20 | if __name__ == "__main__":
21 | test_ordered_sequential_search()
22 |
--------------------------------------------------------------------------------
/10장_검색/4_binary_search.py:
--------------------------------------------------------------------------------
1 | # 재귀함수
2 | def binary_search_rec(seq, target, low, high):
3 | if low > high:
4 | return None
5 | mid = (low + high) // 2
6 | if target == seq[mid]:
7 | return mid
8 | elif target < seq[mid]:
9 | return binary_search_rec(seq, target, low, mid-1)
10 | else:
11 | return binary_search_rec(seq, target, mid+1, high)
12 |
13 |
14 | # 반복문
15 | def binary_search_iter(seq, target):
16 | high, low = len(seq), 0
17 | while low < high:
18 | mid = (high + low) // 2
19 | if target == seq[mid]:
20 | return mid
21 | elif target < seq[mid]:
22 | high = mid
23 | else:
24 | low = mid + 1
25 | return None
26 |
27 |
28 | def test_binary_search():
29 | seq = [1, 2, 5, 6, 7, 10, 12, 12, 14, 15]
30 | target = 6
31 | assert(binary_search_iter(seq, target) == 3)
32 | assert(binary_search_rec(seq, target, 0, len(seq)) == 3)
33 | print("테스트 통과!")
34 |
35 |
36 | if __name__ == "__main__":
37 | test_binary_search()
38 |
--------------------------------------------------------------------------------
/10장_검색/5_search_entry_matrix.py:
--------------------------------------------------------------------------------
1 | def find_elem_matrix_bool(m1, value):
2 | found = False
3 | row = 0
4 | col = len(m1[0]) - 1
5 | while row < len(m1) and col >= 0:
6 | if m1[row][col] == value:
7 | found = True
8 | break
9 | elif m1[row][col] > value:
10 | col -= 1
11 | else:
12 | row += 1
13 | return found
14 |
15 |
16 | def test_find_elem_matrix_bool():
17 | m1 = [[1, 2, 8, 9], [2, 4, 9, 12], [4, 7, 10, 13], [6, 8, 11, 15]]
18 | assert(find_elem_matrix_bool(m1, 8) is True)
19 | assert(find_elem_matrix_bool(m1, 3) is False)
20 | m2 = [[0]]
21 | assert(find_elem_matrix_bool(m2, 0) is True)
22 | print("테스트 통과!")
23 |
24 |
25 | if __name__ == "__main__":
26 | test_find_elem_matrix_bool()
27 |
--------------------------------------------------------------------------------
/10장_검색/6_searching_in_a_matrix.py:
--------------------------------------------------------------------------------
1 | def searching_in_a_matrix(m1, value):
2 | rows = len(m1)
3 | cols = len(m1[0])
4 | lo = 0
5 | hi = rows*cols
6 | while lo < hi:
7 | mid = (lo + hi) // 2
8 | row = mid // cols
9 | col = mid % cols
10 | v = m1[row][col]
11 | if v == value:
12 | return True
13 | elif v > value:
14 | hi = mid
15 | else:
16 | lo = mid+1
17 | return False
18 |
19 |
20 | def test_searching_in_a_matrix():
21 | a = [[1, 3, 5], [7, 9, 11], [13, 15, 17]]
22 | import numpy
23 | b = numpy.array([(1, 2), (3, 4)])
24 | assert(searching_in_a_matrix(a, 13) is True)
25 | assert(searching_in_a_matrix(a, 14) is False)
26 | assert(searching_in_a_matrix(b, 3) is True)
27 | assert(searching_in_a_matrix(b, 5) is False)
28 | print("테스트 통과!")
29 |
30 |
31 | if __name__ == "__main__":
32 | test_searching_in_a_matrix()
33 |
--------------------------------------------------------------------------------
/10장_검색/7_find_max_unimodal_array.py:
--------------------------------------------------------------------------------
1 | def find_max_unimodal_array(A):
2 | if len(A) <= 2:
3 | return None
4 | left = 0
5 | right = len(A)-1
6 | while right > left + 1:
7 | mid = (left + right) // 2
8 | if A[mid] > A[mid-1] and A[mid] > A[mid+1]:
9 | return A[mid]
10 | elif A[mid] > A[mid-1] and A[mid] < A[mid+1]:
11 | left = mid
12 | else:
13 | right = mid
14 | return None
15 |
16 |
17 | def test_find_max_unimodal_array():
18 | seq = [1, 2, 5, 6, 7, 10, 12, 9, 8, 7, 6]
19 | assert(find_max_unimodal_array(seq) == max(seq))
20 | print("테스트 통과!")
21 |
22 |
23 | if __name__ == "__main__":
24 | test_find_max_unimodal_array()
25 |
--------------------------------------------------------------------------------
/10장_검색/8_find_sqrt_bin_search.py:
--------------------------------------------------------------------------------
1 | def find_sqrt_bin_search(n, error=0.001):
2 | lower = n < 1 and n or 1
3 | upper = n < 1 and 1 or n
4 | mid = lower + (upper - lower) / 2.0
5 | square = mid * mid
6 | while abs(square - n) > error:
7 | if square < n:
8 | lower = mid
9 | else:
10 | upper = mid
11 | mid = lower + (upper - lower) / 2.0
12 | square = mid * mid
13 | return mid
14 |
15 |
16 | if __name__ == "__main__":
17 | a = 2
18 | b = 9
19 | import math
20 | print(math.sqrt(a))
21 | print(find_sqrt_bin_search(a))
22 | print(math.sqrt(b))
23 | print(find_sqrt_bin_search(b))
24 |
--------------------------------------------------------------------------------
/10장_검색/9_find_time_occurence_list.py:
--------------------------------------------------------------------------------
1 | from binary_search import binary_search_iter
2 |
3 |
4 | def find_time_occurrence_list(seq, k):
5 | index_some_k = binary_search_iter(seq, k)
6 | count = 1
7 | sizet = len(seq)
8 | for i in range(index_some_k+1, sizet):
9 | if seq[i] == k:
10 | count += 1
11 | else:
12 | break
13 | for i in range(index_some_k-1, -1, -1):
14 | if seq[i] == k:
15 | count += 1
16 | else:
17 | break
18 | return count
19 |
20 |
21 | def test_find_time_occurrence_list():
22 | seq = [1, 2, 2, 2, 2, 2, 2, 5, 6, 6, 7, 8, 9]
23 | k = 2
24 | assert(find_time_occurrence_list(seq, k) == 6)
25 | print("테스트 통과!")
26 |
27 |
28 | if __name__ == "__main__":
29 | test_find_time_occurrence_list()
30 |
--------------------------------------------------------------------------------
/10장_검색/binary_search.py:
--------------------------------------------------------------------------------
1 | # 재귀함수
2 | def binary_search_rec(seq, target, low, high):
3 | if low > high:
4 | return None
5 | mid = (low + high) // 2
6 | if target == seq[mid]:
7 | return mid
8 | elif target < seq[mid]:
9 | return binary_search_rec(seq, target, low, mid-1)
10 | else:
11 | return binary_search_rec(seq, target, mid+1, high)
12 |
13 |
14 | # 반복문
15 | def binary_search_iter(seq, target):
16 | high, low = len(seq), 0
17 | while low < high:
18 | mid = (high + low) // 2
19 | if target == seq[mid]:
20 | return mid
21 | elif target < seq[mid]:
22 | high = mid
23 | else:
24 | low = mid + 1
25 | return None
26 |
--------------------------------------------------------------------------------
/11장_동적_계획법/1_memoized_fib.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from benchmark import benchmark
4 |
5 |
6 | def memo(func):
7 | cache = {}
8 |
9 | @wraps(func)
10 | def wrap(*args):
11 | if args not in cache:
12 | cache[args] = func(*args)
13 | return cache[args]
14 | return wrap
15 |
16 |
17 | def fib(n):
18 | if n < 2:
19 | return 1
20 | else:
21 | return fib(n-1) + fib(n-2)
22 |
23 |
24 | @memo
25 | def fib2(n):
26 | if n < 2:
27 | return 1
28 | else:
29 | return fib2(n-1) + fib2(n-2)
30 |
31 |
32 | def fib3(m, n):
33 | if m[n] == 0:
34 | m[n] = fib3(m, n-1) + fib3(m, n-2)
35 | return m[n]
36 |
37 |
38 | @benchmark
39 | def test_fib(n):
40 | print(fib(n))
41 |
42 |
43 | @benchmark
44 | def test_fib2(n):
45 | print(fib2(n))
46 |
47 |
48 | @benchmark
49 | def test_fib3(n):
50 | m = [0] * (n+1)
51 | m[0], m[1] = 1, 1
52 | print(fib3(m, n))
53 |
54 |
55 | if __name__ == "__main__":
56 | n = 35
57 | test_fib(n)
58 | test_fib2(n)
59 | test_fib3(n)
60 |
--------------------------------------------------------------------------------
/11장_동적_계획법/benchmark.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 | import time
3 |
4 |
5 | def benchmark(method):
6 | @wraps(method)
7 | def timed(*args, **kw):
8 | ts = time.time()
9 | result = method(*args, **kw)
10 | te = time.time()
11 | # print("%r: %2.2f ms" % (method.__name__, (te - ts) * 1000))
12 | # print(f"{method.__name__}: {((te-ts)*1000):.2f} ms")
13 | print("{0}: {1:0.2f} ms".format(method.__name__, ((te-ts)*1000)))
14 | return result
15 |
16 | return timed
17 |
--------------------------------------------------------------------------------
/11장_동적_계획법/functools_wraps.py:
--------------------------------------------------------------------------------
1 | # https://stackoverflow.com/questions/308999/what-does-functools-wraps-do
2 | from functools import wraps
3 |
4 |
5 | def logged(func):
6 | def with_logging(*args, **kwargs):
7 | """with_logging() 함수"""
8 | print(func.__name__ + " 호출")
9 | return func(*args, **kwargs)
10 | return with_logging
11 |
12 |
13 | @logged
14 | def f(x):
15 | """첫 번째, 데커레이터 사용 """
16 | return x + x * x
17 |
18 |
19 | def f2(x):
20 | """두 번째, 데커레이터 사용 X """
21 | return x + x * x
22 |
23 |
24 | def logged2(func):
25 | @wraps(func)
26 | def with_logging(*args, **kwargs):
27 | print(func.__name__ + " 호출")
28 | return func(*args, **kwargs)
29 | return with_logging
30 |
31 |
32 | @logged2
33 | def f3(x):
34 | """세 번째, wraps와 데커레이터 사용 """
35 | return x + x * x
36 |
37 |
38 | if __name__ == "__main__":
39 | print("결과: {0}".format(f(5)))
40 | print("__name__: {0}".format(f.__name__))
41 | print("__doc__: {0}".format(f.__doc__))
42 | print("-----------------------------")
43 | f2 = logged(f2)
44 | print("결과: {0}".format(f2(5)))
45 | print("__name__: {0}".format(f2.__name__))
46 | print("__doc__: {0}".format(f2.__doc__))
47 | print("-----------------------------")
48 | print("결과: {0}".format(f3(5)))
49 | print("__name__: {0}".format(f3.__name__))
50 | print("__doc__: {0}".format(f3.__doc__))
51 |
--------------------------------------------------------------------------------
/12장_그래프_기초/1_tree.py:
--------------------------------------------------------------------------------
1 | class SimpleTree(object):
2 | def __init__(self, value=None, children=None):
3 | self.value = value
4 | self.children = children
5 | if self.children is None:
6 | self.children = []
7 |
8 | def __repr__(self, level=0):
9 | ret = "\t"*level + repr(self.value) + "\n"
10 | for child in self.children:
11 | ret += child.__repr__(level+1)
12 | return ret
13 |
14 |
15 | def main():
16 | st = SimpleTree('a', [
17 | SimpleTree('b',
18 | [
19 | SimpleTree('d'),
20 | SimpleTree('e')
21 | ]),
22 | SimpleTree('c', [
23 | SimpleTree('h'),
24 | SimpleTree('g')
25 | ])
26 | ])
27 | print(st)
28 |
29 |
30 | if __name__ == "__main__":
31 | main()
32 |
--------------------------------------------------------------------------------
/12장_그래프_기초/2_bunchclass.py:
--------------------------------------------------------------------------------
1 |
2 | class BunchClass(dict):
3 | def __init__(self, *args, **kwds):
4 | super(BunchClass, self).__init__(*args, **kwds)
5 | self.__dict__ = self
6 |
7 |
8 | def main():
9 | # 1) 딕셔너리 특수화
10 | bc = BunchClass # ()가 없다.
11 | tree = bc(left=bc(left="Buffy", right="Angel"),
12 | right=bc(left="Willow", right="Xander"))
13 | print(tree)
14 |
15 | # 2) 일반 딕셔너리
16 | tree2 = dict(left=dict(left="Buffy", right="Angel"),
17 | right=dict(left="Willow", right="Xander"))
18 | print(tree2)
19 |
20 | if __name__ == "__main__":
21 | main()
22 |
--------------------------------------------------------------------------------
/13장_이진_트리/1_BT_lists.py:
--------------------------------------------------------------------------------
1 | def binary_tree_list(r):
2 | return [r, [], []]
3 |
4 |
5 | def insert_left(root, newBranch):
6 | t = root.pop(1)
7 | if len(t) > 1:
8 | root.insert(1, [newBranch, t, []])
9 | else:
10 | root.insert(1, [newBranch, [], []])
11 | return root
12 |
13 |
14 | def insert_right(root, newBranch):
15 | t = root.pop(2)
16 | if len(t) > 1:
17 | root.insert(2, [newBranch, [], t])
18 | else:
19 | root.insert(2, [newBranch, [], []])
20 | return root
21 |
22 |
23 | def get_root_val(root):
24 | return root[0]
25 |
26 |
27 | def set_root_val(root, new_val):
28 | root[0] = new_val
29 |
30 |
31 | def get_left_child(root):
32 | return root[1]
33 |
34 |
35 | def get_right_child(root):
36 | return root[2]
37 |
38 |
39 | def main():
40 | r = binary_tree_list(3)
41 | insert_left(r, 4)
42 | insert_left(r, 5)
43 | insert_right(r, 6)
44 | insert_right(r, 7)
45 | print(get_root_val(r))
46 | print(get_left_child(r))
47 | print(get_right_child(r))
48 |
49 |
50 | if __name__ == "__main__":
51 | main()
52 |
--------------------------------------------------------------------------------
/1장_숫자/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/1장_숫자/.DS_Store
--------------------------------------------------------------------------------
/1장_숫자/10_finding_prime.py:
--------------------------------------------------------------------------------
1 | import math
2 | import random
3 |
4 |
5 | def finding_prime(number):
6 | num = abs(number)
7 | if num < 4:
8 | return True
9 | for x in range(2, num):
10 | if num % x == 0:
11 | return False
12 | return True
13 |
14 |
15 | def finding_prime_sqrt(number):
16 | num = abs(number)
17 | if num < 4:
18 | return True
19 | for x in range(2, int(math.sqrt(num)) + 1):
20 | if number % x == 0:
21 | return False
22 | return True
23 |
24 |
25 | def finding_prime_fermat(number):
26 | if number <= 102:
27 | for a in range(2, number):
28 | if pow(a, number - 1, number) != 1:
29 | return False
30 | return True
31 | else:
32 | for i in range(100):
33 | a = random.randint(2, number - 1)
34 | if pow(a, number - 1, number) != 1:
35 | return False
36 | return True
37 |
38 |
39 | def test_finding_prime():
40 | number1 = 17
41 | number2 = 20
42 | assert(finding_prime(number1) is True)
43 | assert(finding_prime(number2) is False)
44 | assert(finding_prime_sqrt(number1) is True)
45 | assert(finding_prime_sqrt(number2) is False)
46 | assert(finding_prime_fermat(number1) is True)
47 | assert(finding_prime_fermat(number2) is False)
48 | print("테스트 통과!")
49 |
50 |
51 | if __name__ == "__main__":
52 | test_finding_prime()
53 |
--------------------------------------------------------------------------------
/1장_숫자/11_generate_prime.py:
--------------------------------------------------------------------------------
1 | import math
2 | import random
3 | import sys
4 |
5 |
6 | def finding_prime_sqrt(number):
7 | num = abs(number)
8 | if num < 4:
9 | return True
10 | for x in range(2, int(math.sqrt(num)) + 1):
11 | if number % x == 0:
12 | return False
13 | return True
14 |
15 |
16 | def generate_prime(number=3):
17 | while 1:
18 | p = random.randint(pow(2, number-2), pow(2, number-1)-1)
19 | p = 2 * p + 1
20 | if finding_prime_sqrt(p):
21 | return p
22 |
23 |
24 | if __name__ == "__main__":
25 | if len(sys.argv) < 2:
26 | print("Usage: generate_prime.py number")
27 | sys.exit()
28 | else:
29 | number = int(sys.argv[1])
30 | print(generate_prime(number))
31 |
--------------------------------------------------------------------------------
/1장_숫자/12_testing_numpy.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def testing_numpy():
5 | ax = np.array([1, 2, 3])
6 | ay = np.array([3, 4, 5])
7 | print(ax)
8 | print(ax*2)
9 | print(ax+10)
10 | print(np.sqrt(ax))
11 | print(np.cos(ax))
12 | print(ax-ay)
13 | print(np.where(ax < 2, ax, 10))
14 |
15 | m = np.matrix([ax, ay, ax])
16 | print(m)
17 | print(m.T)
18 |
19 | grid1 = np.zeros(shape=(10, 10), dtype=float)
20 | grid2 = np.ones(shape=(10, 10), dtype=float)
21 | print(grid1)
22 | print(grid2)
23 | print(grid1[1]+10)
24 | print(grid2[:, 2]*2)
25 |
26 |
27 | if __name__ == "__main__":
28 | testing_numpy()
29 |
--------------------------------------------------------------------------------
/1장_숫자/13_testing_numpy_speed.py:
--------------------------------------------------------------------------------
1 | import numpy
2 | import time
3 |
4 |
5 | def trad_version():
6 | t1 = time.time()
7 | X = range(10000000)
8 | Y = range(10000000)
9 | Z = []
10 | for i in range(len(X)):
11 | Z.append(X[i] + Y[i])
12 | return time.time() - t1
13 |
14 |
15 | def numpy_version():
16 | t1 = time.time()
17 | X = numpy.arange(10000000)
18 | Y = numpy.arange(10000000)
19 | Z = X + Y
20 | return time.time() - t1
21 |
22 |
23 | if __name__ == "__main__":
24 | print(trad_version())
25 | print(numpy_version())
26 |
--------------------------------------------------------------------------------
/1장_숫자/1_testing_floats.py:
--------------------------------------------------------------------------------
1 | from fractions import Fraction
2 |
3 |
4 | def rounding_floats(number1, places):
5 | return round(number1, places)
6 |
7 |
8 | def float_to_fractions(number):
9 | return Fraction(*number.as_integer_ratio())
10 |
11 |
12 | def get_denominator(number1, number2):
13 | """ 분모를 반환한다."""
14 | a = Fraction(number1, number2)
15 | return a.denominator
16 |
17 |
18 | def get_numerator(number1, number2):
19 | """ 분자를 반환한다."""
20 | a = Fraction(number1, number2)
21 | return a.numerator
22 |
23 |
24 | def test_testing_floats():
25 | number1 = 1.25
26 | number2 = 1
27 | number3 = -1
28 | number4 = 5/4
29 | number6 = 6
30 | assert(rounding_floats(number1, number2) == 1.2)
31 | assert(rounding_floats(number1*10, number3) == 10)
32 | assert(float_to_fractions(number1) == number4)
33 | assert(get_denominator(number2, number6) == number6)
34 | assert(get_numerator(number2, number6) == number2)
35 | print("테스트 통과!")
36 |
37 |
38 | if __name__ == "__main__":
39 | test_testing_floats()
40 |
--------------------------------------------------------------------------------
/1장_숫자/2_convert_to_decimal.py:
--------------------------------------------------------------------------------
1 | def convert_to_decimal(number, base):
2 | multiplier, result = 1, 0
3 | while number > 0:
4 | result += number % 10 * multiplier
5 | multiplier *= base
6 | number = number // 10
7 | return result
8 |
9 |
10 | def test_convert_to_decimal():
11 | number, base = 1001, 2
12 | assert(convert_to_decimal(number, base) == 9)
13 | print("테스트 통과!")
14 |
15 |
16 | if __name__ == "__main__":
17 | test_convert_to_decimal()
18 |
--------------------------------------------------------------------------------
/1장_숫자/3_convert_from_decimal.py:
--------------------------------------------------------------------------------
1 | def convert_from_decimal(number, base):
2 | multiplier, result = 1, 0
3 | while number > 0:
4 | result += number % base * multiplier
5 | multiplier *= 10
6 | number = number // base
7 | return result
8 |
9 |
10 | def test_convert_from_decimal():
11 | number, base = 9, 2
12 | assert(convert_from_decimal(number, base) == 1001)
13 | print("테스트 통과!")
14 |
15 |
16 | if __name__ == "__main__":
17 | test_convert_from_decimal()
18 |
--------------------------------------------------------------------------------
/1장_숫자/4_convert_from_decimal_larger_bases.py:
--------------------------------------------------------------------------------
1 | def convert_from_decimal_larger_bases(number, base):
2 | strings = "0123456789ABCDEFGHIJ"
3 | result = ""
4 | while number > 0:
5 | digit = number % base
6 | result = strings[digit] + result
7 | number = number // base
8 | return result
9 |
10 |
11 | def test_convert_from_decimal_larger_bases():
12 | number, base = 31, 16
13 | assert(convert_from_decimal_larger_bases(number, base) == "1F")
14 | print("테스트 통과!")
15 |
16 |
17 | if __name__ == "__main__":
18 | test_convert_from_decimal_larger_bases()
19 |
--------------------------------------------------------------------------------
/1장_숫자/5_convert_dec_to_any_base_rec.py:
--------------------------------------------------------------------------------
1 | def convert_dec_to_any_base_rec(number, base):
2 | convertString = "012345679ABCDEF"
3 | if number < base:
4 | return convertString[number]
5 | else:
6 | return convert_dec_to_any_base_rec(number // base, base) \
7 | + convertString[number % base]
8 |
9 |
10 | def test_convert_dec_to_any_base_rec():
11 | number = 9
12 | base = 2
13 | assert(convert_dec_to_any_base_rec(number, base) == "1001")
14 | print("테스트 통과!")
15 |
16 |
17 | if __name__ == "__main__":
18 | test_convert_dec_to_any_base_rec()
19 |
--------------------------------------------------------------------------------
/1장_숫자/6_finding_gcd.py:
--------------------------------------------------------------------------------
1 | def finding_gcd(a, b):
2 | while(b != 0):
3 | result = b
4 | a, b = b, a % b
5 | return result
6 |
7 |
8 | def test_finding_gcd():
9 | number1 = 21
10 | number2 = 12
11 | assert(finding_gcd(number1, number2) == 3)
12 | print("테스트 통과!")
13 |
14 |
15 | if __name__ == "__main__":
16 | test_finding_gcd()
17 |
--------------------------------------------------------------------------------
/1장_숫자/7_testing_random.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 |
4 | def testing_random():
5 | """ random 모듈 테스트 """
6 | values = [1, 2, 3, 4]
7 | print(random.choice(values))
8 | print(random.choice(values))
9 | print(random.choice(values))
10 | print(random.sample(values, 2))
11 | print(random.sample(values, 3))
12 |
13 | """ values 리스트를 섞는다. """
14 | random.shuffle(values)
15 | print(values)
16 |
17 | """ 0~10의 임의의 정수를 생성한다. """
18 | print(random.randint(0, 10))
19 | print(random.randint(0, 10))
20 |
21 |
22 | if __name__ == "__main__":
23 | testing_random()
24 |
--------------------------------------------------------------------------------
/1장_숫자/8_find_fibonacci_seq.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 |
4 | def find_fibonacci_seq_iter(n):
5 | if n < 2:
6 | return n
7 | a, b = 0, 1
8 | for i in range(n):
9 | a, b = b, a + b
10 | return a
11 |
12 |
13 | def find_fibonacci_seq_rec(n):
14 | if n < 2:
15 | return n
16 | return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2)
17 |
18 |
19 | def find_fibonacci_seq_form(n):
20 | sq5 = math.sqrt(5)
21 | phi = (1 + sq5) / 2
22 | return int(math.floor(phi ** n / sq5))
23 |
24 |
25 | def test_find_fib():
26 | n = 10
27 | assert(find_fibonacci_seq_rec(n) == 55)
28 | assert(find_fibonacci_seq_iter(n) == 55)
29 | assert(find_fibonacci_seq_form(n) == 55)
30 | print("테스트 통과!")
31 |
32 |
33 | if __name__ == "__main__":
34 | test_find_fib()
35 |
--------------------------------------------------------------------------------
/1장_숫자/9_find_fibonacci_by_generator.py:
--------------------------------------------------------------------------------
1 | def fib_generator():
2 | a, b = 0, 1
3 | while True:
4 | yield b
5 | a, b = b, a+b
6 |
7 |
8 | if __name__ == "__main__":
9 | fg = fib_generator()
10 | for _ in range(10):
11 | print(next(fg), end=" ")
12 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/10_combination.py:
--------------------------------------------------------------------------------
1 | def combinations(s):
2 | if len(s) < 2:
3 | return s
4 | res = []
5 | for i, c in enumerate(s):
6 | res.append(c) # 추가된 부분
7 | for j in combinations(s[:i] + s[i+1:]):
8 | res.append(c + j)
9 | return res
10 |
11 |
12 | if __name__ == "__main__":
13 | result = combinations("abc")
14 | print(result)
15 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/11_palindrome.py:
--------------------------------------------------------------------------------
1 | def is_palindrome(s):
2 | l = s.split(" ")
3 | s2 = ''.join(l)
4 | return s2 == s2[::-1]
5 |
6 |
7 | def is_palindrome2(s):
8 | l = len(s)
9 | f, b = 0, l-1
10 | while f < l // 2:
11 | while s[f] == " ":
12 | f += 1
13 | while s[b] == " ":
14 | b -= 1
15 | if s[f] != s[b]:
16 | return False
17 | f += 1
18 | b -= 1
19 | return True
20 |
21 |
22 | def is_palindrome3(s):
23 | s = s.strip()
24 | if len(s) < 2:
25 | return True
26 | if s[0] == s[-1]:
27 | return is_palindrome(s[1:-1])
28 | else:
29 | return False
30 |
31 |
32 | if __name__ == "__main__":
33 | str1 = "다시 합창합시다"
34 | str2 = ""
35 | str3 = "hello"
36 | print(is_palindrome(str1))
37 | print(is_palindrome(str2))
38 | print(is_palindrome(str3))
39 | print(is_palindrome2(str1))
40 | print(is_palindrome2(str2))
41 | print(is_palindrome2(str3))
42 | print(is_palindrome3(str1))
43 | print(is_palindrome3(str2))
44 | print(is_palindrome3(str3))
45 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/1_count_unique_words.py:
--------------------------------------------------------------------------------
1 | import string
2 | import sys
3 |
4 |
5 | def count_unique_word():
6 | words = {}
7 | strip = string.whitespace + string.punctuation + string.digits + "\"'"
8 | for filename in sys.argv[1:]:
9 | with open(filename) as file:
10 | for line in file:
11 | for word in line.lower().split():
12 | word = word.strip(strip)
13 | if len(word) > 2:
14 | words[word] = words.get(word, 0) + 1
15 |
16 | for word in sorted(words):
17 | print("'{0}': {1}번".format(word, words[word]))
18 |
19 |
20 | if __name__ == "__main__":
21 | count_unique_word()
22 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/2_runtime_lists_with_timeit_module.py:
--------------------------------------------------------------------------------
1 | def test1():
2 | l = []
3 | for i in range(1000):
4 | l = l + [i]
5 |
6 |
7 | def test2():
8 | l = []
9 | for i in range(1000):
10 | l.append(i)
11 |
12 |
13 | def test3():
14 | l = [i for i in range(1000)]
15 |
16 |
17 | def test4():
18 | l = list(range(1000))
19 |
20 |
21 | if __name__ == "__main__":
22 | import timeit
23 | t1 = timeit.Timer("test1()", "from __main__ import test1")
24 | print("concat ", t1.timeit(number=1000), "milliseconds")
25 | t2 = timeit.Timer("test2()", "from __main__ import test2")
26 | print("append ", t2.timeit(number=1000), "milliseconds")
27 | t3 = timeit.Timer("test3()", "from __main__ import test3")
28 | print("comprehension ", t3.timeit(number=1000), "milliseconds")
29 | t4 = timeit.Timer("test4()", "from __main__ import test4")
30 | print("list range ", t4.timeit(number=1000), "milliseconds")
31 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/3_reversing_string.py:
--------------------------------------------------------------------------------
1 | def revert(s):
2 | if s:
3 | s = s[-1] + revert(s[:-1])
4 | return s
5 |
6 |
7 | def revert2(string):
8 | return string[::-1]
9 |
10 |
11 | if __name__ == "__main__":
12 | str1 = "안녕 세상!"
13 | str2 = revert(str1)
14 | str3 = revert2(str1)
15 | print(str2)
16 | print(str3)
17 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/4_reversing_words_.py:
--------------------------------------------------------------------------------
1 | def reverser(string1, p1=0, p2=None):
2 | if len(string1) < 2:
3 | return string1
4 | p2 = p2 or len(string1)-1
5 | while p1 < p2:
6 | string1[p1], string1[p2] = string1[p2], string1[p1]
7 | p1 += 1
8 | p2 -= 1
9 |
10 |
11 | def reversing_words_setence_logic(string1):
12 | # 먼저, 문장 전체를 반전한다.
13 | reverser(string1)
14 | # print(string1)
15 | p = 0
16 | start = 0
17 | while p < len(string1):
18 | if string1[p] == u"\u0020":
19 | # 단어를 다시 반전한다(단어를 원위치로 돌려놓는다).
20 | reverser(string1, start, p-1)
21 | # print(string1)
22 | start = p+1
23 | p += 1
24 | # 마지막 단어를 반전한다(단어를 원위치로 돌려놓는다).
25 | reverser(string1, start, p-1)
26 | # print(string1)
27 | return ''.join(string1)
28 |
29 |
30 | if __name__ == "__main__":
31 | str1 = "파이썬 알고리즘 정말 재미있다"
32 | str2 = reversing_words_setence_logic(list(str1))
33 | print(str2)
34 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/5_reversing_words.py:
--------------------------------------------------------------------------------
1 | def reverse_words_brute(string):
2 | word, sentence = [], []
3 | for character in string:
4 | if character != " ":
5 | word.append(character)
6 | else:
7 | # 조건문에서 빈 리스트는 False다. 여러 공백이 있는 경우, 조건문을 건너뛴다.
8 | if word:
9 | sentence.append(''.join(word))
10 | word = []
11 |
12 | # 마지막 단어가 있다면, 문장에 추가한다.
13 | if word != '':
14 | sentence.append(''.join(word))
15 | sentence.reverse()
16 | return " ".join(sentence)
17 |
18 |
19 | if __name__ == "__main__":
20 | str1 = "파이썬 알고리즘 정말 재미있다"
21 | str2 = reverse_words_brute(str1)
22 | print(str2)
23 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/6_reversing_words.py:
--------------------------------------------------------------------------------
1 | def reversing_words_slice(word):
2 | new_word = []
3 | words = word.split(" ")
4 | for word in words[::-1]:
5 | new_word.append(word)
6 | return " ".join(new_word)
7 |
8 |
9 | if __name__ == "__main__":
10 | str1 = "파이썬 알고리즘 정말 재미있다"
11 | str2 = reversing_words_slice(str1)
12 | print(str2)
13 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/7_reversing_words.py:
--------------------------------------------------------------------------------
1 | def reversing_words(str1):
2 | words = str1.split(" ")
3 | rev_set = " ".join(reversed(words))
4 | return rev_set
5 |
6 |
7 | def reversing_words2(str1):
8 | words = str1.split(" ")
9 | words.reverse()
10 | return " ".join(words)
11 |
12 |
13 | if __name__ == "__main__":
14 | str1 = "파이썬 알고리즘 정말 재미있다"
15 | str2 = reversing_words(str1)
16 | str3 = reversing_words2(str1)
17 | print(str2)
18 | print(str3)
19 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/8_simple_str_compression.py:
--------------------------------------------------------------------------------
1 | def str_compression(s):
2 | count, last = 1, ""
3 | list_aux = []
4 | for i, c in enumerate(s):
5 | if last == c:
6 | count += 1
7 | else:
8 | if i != 0:
9 | list_aux.append(str(count))
10 | list_aux.append(c)
11 | count = 1
12 | last = c
13 | list_aux.append(str(count))
14 | return "".join(list_aux)
15 |
16 |
17 | if __name__ == "__main__":
18 | result = str_compression("aabcccccaaa")
19 | print(result)
20 |
--------------------------------------------------------------------------------
/2장_내장_시퀀스_타입/9_permutation.py:
--------------------------------------------------------------------------------
1 | import itertools
2 |
3 |
4 | def perm(s):
5 | if len(s) < 2:
6 | return s
7 | res = []
8 | for i, c in enumerate(s):
9 | for cc in perm(s[:i] + s[i+1:]):
10 | res.append(c + cc)
11 | return res
12 |
13 |
14 | def perm2(s):
15 | res = itertools.permutations(s)
16 | return ["".join(i) for i in res]
17 |
18 |
19 | if __name__ == "__main__":
20 | val = "012"
21 | print(perm(val))
22 | print(perm2(val))
23 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/10_is_anagram_using_ord.py:
--------------------------------------------------------------------------------
1 | import string
2 |
3 |
4 | def hash_func(astring):
5 | s = 0
6 | for one in astring:
7 | if one in string.whitespace:
8 | continue
9 | s = s + ord(one)
10 | return s
11 |
12 |
13 | def find_anagram_hash_function(word1, word2):
14 | return hash_func(word1) == hash_func(word2)
15 |
16 |
17 | def test_find_anagram_hash_function():
18 | word1 = "buffy"
19 | word2 = "bffyu"
20 | word3 = "bffya"
21 | assert(find_anagram_hash_function(word1, word2) is True)
22 | assert(find_anagram_hash_function(word1, word3) is False)
23 | print("테스트 통과!")
24 |
25 |
26 | if __name__ == "__main__":
27 | test_find_anagram_hash_function()
28 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/11_find_dice_probabilities.py:
--------------------------------------------------------------------------------
1 | from collections import Counter, defaultdict
2 |
3 |
4 | def find_dice_probabilities(S, n_faces=6):
5 | if S > 2 * n_faces or S < 2:
6 | return None
7 |
8 | cdict = Counter()
9 | ddict = defaultdict(list)
10 |
11 | # 두 주사위의 합을 모두 더해서 딕셔너리에 넣는다.
12 | for dice1 in range(1, n_faces+1):
13 | for dice2 in range(1, n_faces+1):
14 | t = [dice1, dice2]
15 | cdict[dice1+dice2] += 1
16 | ddict[dice1+dice2].append(t)
17 |
18 | return [cdict[S], ddict[S]]
19 |
20 |
21 | def test_find_dice_probabilities():
22 | n_faces = 6
23 | S = 5
24 | results = find_dice_probabilities(S, n_faces)
25 | print(results)
26 | assert(results[0] == len(results[1]))
27 | print("테스트 통과!")
28 |
29 |
30 | if __name__ == "__main__":
31 | test_find_dice_probabilities()
32 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/12_delete_duplicate_char_str.py:
--------------------------------------------------------------------------------
1 | import string
2 |
3 |
4 | def delete_unique_word(str1):
5 | table_c = {key: 0 for key in string.ascii_lowercase}
6 | for i in str1:
7 | table_c[i] += 1
8 | for key, value in table_c.items():
9 | if value > 1:
10 | str1 = str1.replace(key, "")
11 | return str1
12 |
13 |
14 | def test_delete_unique_word():
15 | str1 = "google"
16 | assert(delete_unique_word(str1) == "le")
17 | print("테스트 통과!")
18 |
19 |
20 | if __name__ == "__main__":
21 | test_delete_unique_word()
22 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/1_set_operations_with_lists.py:
--------------------------------------------------------------------------------
1 | def remove_dup(l1):
2 | """ 리스트의 중복된 항목을 제거한 후 반환한다. """
3 | return list(set(l1))
4 |
5 |
6 | def intersection(l1, l2):
7 | """ 교집합 결과를 반환한다. """
8 | return list(set(l1) & set(l2))
9 |
10 |
11 | def union(l1, l2):
12 | """ 합집합 결과를 반환한다. """
13 | return list(set(l1) | set(l2))
14 |
15 |
16 | def test_sets_operations_with_lists():
17 | l1 = [1, 2, 3, 4, 5, 5, 9, 11, 11, 15]
18 | l2 = [4, 5, 6, 7, 8]
19 | l3 = []
20 | assert(remove_dup(l1) == [1, 2, 3, 4, 5, 9, 11, 15])
21 | assert(intersection(l1, l2) == [4, 5])
22 | assert(union(l1, l2) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15])
23 | assert(remove_dup(l3) == [])
24 | assert(intersection(l3, l2) == l3)
25 | assert(sorted(union(l3, l2)) == sorted(l2))
26 | print("테스트 통과!")
27 |
28 |
29 | if __name__ == "__main__":
30 | test_sets_operations_with_lists()
31 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/2_set_operations_with_dicts.py:
--------------------------------------------------------------------------------
1 | def set_operations_with_dict():
2 | pairs = [("a", 1), ("b", 2), ("c", 3)]
3 | d1 = dict(pairs)
4 | print("딕셔너리1\t: {0}".format(d1))
5 |
6 | d2 = {"a": 1, "c": 2, "d": 3, "e": 4}
7 | print("딕셔너리2\t: {0}".format(d2))
8 |
9 | intersection = d1.keys() & d2.keys()
10 | print("d1 ∩ d2 (키)\t: {0}".format(intersection))
11 |
12 | intersection_items = d1.items() & d2.items()
13 | print("d1 ∩ d2 (키,값)\t: {0}".format(intersection_items))
14 |
15 | subtraction1 = d1.keys() - d2.keys()
16 | print("d1 - d2 (키)\t: {0}".format(subtraction1))
17 |
18 | subtraction2 = d2.keys() - d1.keys()
19 | print("d2 - d1 (키)\t: {0}".format(subtraction2))
20 |
21 | subtraction_items = d1.items() - d2.items()
22 | print("d1 - d2 (키,값)\t: {0}".format(subtraction_items))
23 |
24 | """ 딕셔너리의 특정 키를 제외한다. """
25 | d3 = {key: d2[key] for key in d2.keys() - {"c", "d"}}
26 | print("d2 - {{c, d}}\t: {0}".format(d3))
27 |
28 |
29 | if __name__ == "__main__":
30 | set_operations_with_dict()
31 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/3_setdefault_example.py:
--------------------------------------------------------------------------------
1 | def usual_dict(dict_data):
2 | """ dict[key] 사용 """
3 | newdata = {}
4 | for k, v in dict_data:
5 | if k in newdata:
6 | newdata[k].append(v)
7 | else:
8 | newdata[k] = [v]
9 | return newdata
10 |
11 |
12 | def setdefault_dict(dict_data):
13 | """ setdefault() 메서드 사용 """
14 | newdata = {}
15 | for k, v in dict_data:
16 | newdata.setdefault(k, []).append(v)
17 | return newdata
18 |
19 |
20 | def test_setdef():
21 | dict_data = (("key1", "value1"),
22 | ("key1", "value2"),
23 | ("key2", "value3"),
24 | ("key2", "value4"),
25 | ("key2", "value5"),)
26 | print(usual_dict(dict_data))
27 | print(setdefault_dict(dict_data))
28 |
29 |
30 | if __name__ == "__main__":
31 | test_setdef()
32 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/4_runtime_dicts_with_timeit_module.py:
--------------------------------------------------------------------------------
1 | import timeit
2 | import random
3 |
4 | for i in range(10000, 1000001, 20000):
5 | t = timeit.Timer("random.randrange(%d) in x" % i,
6 | "from __main__ import random, x")
7 | x = list(range(i)) # 리스트
8 | lst_time = t.timeit(number=1000)
9 | x = {j: None for j in range(i)} # 딕셔너리
10 | d_time = t.timeit(number=1000)
11 | print("%d,%10.3f,%10.3f" % (i, lst_time, d_time))
12 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/5_defaultdict_example.py:
--------------------------------------------------------------------------------
1 | from collections import defaultdict
2 |
3 |
4 | def defaultdict_example():
5 | pairs = {("a", 1), ("b", 2), ("c", 3)}
6 |
7 | # 일반 딕셔너리
8 | d1 = {}
9 | for key, value in pairs:
10 | if key not in d1:
11 | d1[key] = []
12 | d1[key].append(value)
13 | print(d1)
14 |
15 | # defaultdict
16 | d2 = defaultdict(list)
17 | for key, value in pairs:
18 | d2[key].append(value)
19 | print(d2)
20 |
21 |
22 | if __name__ == "__main__":
23 | defaultdict_example()
24 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/6_orderedDict_example.py:
--------------------------------------------------------------------------------
1 | from collections import OrderedDict
2 |
3 |
4 | def orderedDict_example():
5 | pairs = [("c", 1), ("b", 2), ("a", 3)]
6 |
7 | # 일반 딕셔너리
8 | d1 = {}
9 | for key, value in pairs:
10 | if key not in d1:
11 | d1[key] = []
12 | d1[key].append(value)
13 | for key in d1:
14 | print(key, d1[key])
15 |
16 | # OrderedDict
17 | d2 = OrderedDict(pairs)
18 | for key in d2:
19 | print(key, d2[key])
20 |
21 |
22 | if __name__ == "__main__":
23 | orderedDict_example()
24 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/7_counterDict_example.py:
--------------------------------------------------------------------------------
1 | from collections import Counter
2 |
3 |
4 | def counter_example():
5 | """ 항목의 발생 횟수를 매핑하는 딕셔너리를 생성한다. """
6 | seq1 = [1, 2, 3, 5, 1, 2, 5, 5, 2, 5, 1, 4]
7 | seq_counts = Counter(seq1)
8 | print(seq_counts)
9 |
10 | """ 항목의 발생 횟수를 수동으로 갱신하거나, update() 메서드를 사용할 수 있다. """
11 | seq2 = [1, 2, 3]
12 | seq_counts.update(seq2)
13 | print(seq_counts)
14 |
15 | seq3 = [1, 4, 3]
16 | for key in seq3:
17 | seq_counts[key] += 1
18 | print(seq_counts)
19 |
20 | """ a+b, a-b와 같은 셋 연산을 사용할 수 있다. """
21 | seq_counts_2 = Counter(seq3)
22 | print(seq_counts_2)
23 | print(seq_counts + seq_counts_2)
24 | print(seq_counts - seq_counts_2)
25 |
26 |
27 | if __name__ == "__main__":
28 | counter_example()
29 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/8_find_top_N_recurring_words.py:
--------------------------------------------------------------------------------
1 | from collections import Counter
2 |
3 |
4 | def find_top_N_recurring_words(seq, N):
5 | dcounter = Counter()
6 | for word in seq.split():
7 | dcounter[word] += 1
8 | return dcounter.most_common(N)
9 |
10 |
11 | def test_find_top_N_recurring_words():
12 | seq = "버피 에인절 몬스터 잰더 윌로우 버피 몬스터 슈퍼 버피 에인절"
13 | N = 3
14 | assert(find_top_N_recurring_words(seq, N) ==
15 | [("버피", 3), ("에인절", 2), ("몬스터", 2)])
16 | print("테스트 통과!")
17 |
18 |
19 | if __name__ == "__main__":
20 | test_find_top_N_recurring_words()
21 |
--------------------------------------------------------------------------------
/3장_컬렉션_데이터_구조/9_is_anagram.py:
--------------------------------------------------------------------------------
1 | from collections import Counter
2 |
3 |
4 | def is_anagram(s1, s2):
5 | counter = Counter()
6 | for c in s1:
7 | counter[c] += 1
8 | for c in s2:
9 | counter[c] -= 1
10 | for i in counter.values():
11 | if i:
12 | return False
13 | return True
14 |
15 |
16 | def test_is_anagram():
17 | s1 = "marina"
18 | s2 = "aniram"
19 | assert(is_anagram(s1, s2) is True)
20 | s1 = "google"
21 | s2 = "gouglo"
22 | assert(is_anagram(s1, s2) is False)
23 | print("테스트 통과!")
24 |
25 |
26 | if __name__ == "__main__":
27 | test_is_anagram()
28 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/1_sys_example.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def main():
5 | for arg in sys.argv[1:]:
6 | print(arg)
7 |
8 |
9 | if __name__ == "__main__":
10 | main()
11 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/2_fib_generator.py:
--------------------------------------------------------------------------------
1 | def fib_generator():
2 | a, b = 0, 1
3 | while True:
4 | yield b
5 | a, b = b, a+b
6 |
7 |
8 | if __name__ == "__main__":
9 | fib = fib_generator()
10 | print(next(fib))
11 | print(next(fib))
12 | print(next(fib))
13 | print(next(fib))
14 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/3_grep_word_from_files.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def grep_word_from_files():
5 | word = sys.argv[1]
6 | for filename in sys.argv[2:]:
7 | with open(filename) as file:
8 | for lino, line in enumerate(file, start=1):
9 | if word in line:
10 | print("{0}:{1}:{2:.40}".format(
11 | filename, lino, line.rstrip()))
12 |
13 |
14 | if __name__ == "__main__":
15 | if len(sys.argv) < 2:
16 | print("Usage: python {0} [word] [file ...]".format(
17 | sys.argv[0]))
18 | sys.exit()
19 | else:
20 | grep_word_from_files()
21 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/4_remove_blank_lines.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def read_data(filename):
5 | lines = []
6 | fh = None
7 | try:
8 | fh = open(filename)
9 | for line in fh:
10 | if line.strip():
11 | lines.append(line)
12 | except (IOError, OSError) as err:
13 | print(err)
14 | finally:
15 | if fh is not None:
16 | fh.close()
17 | return lines
18 |
19 |
20 | def write_data(lines, filename):
21 | fh = None
22 | try:
23 | fh = open(filename, "w")
24 | for line in lines:
25 | fh.write(line)
26 | except (EnvironmentError) as err:
27 | print(err)
28 | finally:
29 | if fh is not None:
30 | fh.close()
31 |
32 |
33 | def remove_blank_lines():
34 | if len(sys.argv) < 2:
35 | print("Usage: python {0} [file ...]".format(sys.argv[0]))
36 |
37 | for filename in sys.argv[1:]:
38 | lines = read_data(filename)
39 | if lines:
40 | write_data(lines, filename)
41 |
42 |
43 | if __name__ == "__main__":
44 | remove_blank_lines()
45 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/5_remove_blank_lines_with.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def read_data(filename):
5 | lines = []
6 | with open(filename) as fh:
7 | for line in fh:
8 | if line.strip():
9 | lines.append(line)
10 | return lines
11 |
12 |
13 | def write_data(lines, filename):
14 | fh = None
15 | with open(filename, "w") as fh:
16 | for line in lines:
17 | fh.write(line)
18 |
19 |
20 | def remove_blank_lines():
21 | if len(sys.argv) < 2:
22 | print("Usage: python {0} [file ...]".format(sys.argv[0]))
23 |
24 | for filename in sys.argv[1:]:
25 | lines = read_data(filename)
26 | if lines:
27 | write_data(lines, filename)
28 |
29 |
30 | if __name__ == "__main__":
31 | remove_blank_lines()
32 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/6_change_ext_file.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import shutil
4 |
5 |
6 | def change_file_ext():
7 | if len(sys.argv) < 2:
8 | print("Usage: python {0} filename.old_ext 'new_ext'".format(
9 | sys.argv[0]))
10 | sys.exit()
11 |
12 | name = os.path.splitext(sys.argv[1])[0] + "." + sys.argv[2]
13 | print(name)
14 |
15 | try:
16 | shutil.copyfile(sys.argv[1], name)
17 | except OSError as err:
18 | print(err)
19 |
20 |
21 | if __name__ == "__main__":
22 | change_file_ext()
23 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/hello.py:
--------------------------------------------------------------------------------
1 | hello = "hello"
2 |
3 |
4 | def world():
5 | return "world"
6 |
7 |
8 | if __name__ == "__main__":
9 | print("{0} 직접 실행됨".format(__name__))
10 | else:
11 | print("{0} 임포트됨".format(__name__))
12 |
--------------------------------------------------------------------------------
/4장_구조와_모듈/hello.txt:
--------------------------------------------------------------------------------
1 | hello = "hello"
2 |
3 |
4 | def world():
5 | return "world"
6 |
7 |
8 | if __name__ == "__main__":
9 | print("{0} 직접 실행됨".format(__name__))
10 | else:
11 | print("{0} 임포트 됨".format(__name__))
12 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/10_adapter_pattern_BETTER.py:
--------------------------------------------------------------------------------
1 | """
2 | https://github.com/PJUllrich/Design-Patterns
3 | """
4 |
5 |
6 | class Elf(object):
7 | def nall_nin(self):
8 | print("Elf says: Calling the Overload ...")
9 |
10 |
11 | class Dwarf(object):
12 | def estver_narho(self):
13 | print("Dwarf says: Calling the Overload ...")
14 |
15 |
16 | class Human(object):
17 | def ring_mig(self):
18 | print("Human says: Calling the Overload ...")
19 |
20 |
21 | class ElfAdapter(object):
22 | def __init__(self, elf):
23 | self.elf = elf
24 |
25 | def call_me(self):
26 | self.elf.nall_nin()
27 |
28 |
29 | class DwarfAdapter(object):
30 | def __init__(self, dwarf):
31 | self.dwarf = dwarf
32 |
33 | def call_me(self):
34 | self.dwarf.estver_narho()
35 |
36 |
37 | class HumanAdapter(object):
38 | def __init__(self, human):
39 | self.human = human
40 |
41 | def call_me(self):
42 | self.human.ring_mig()
43 |
44 |
45 | if __name__ == "__main__":
46 | minions = [ElfAdapter(Elf()), DwarfAdapter(
47 | Dwarf()), HumanAdapter(Human())]
48 |
49 | for minion in minions:
50 | minion.call_me()
51 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/1_hash_and_eq_NO.py:
--------------------------------------------------------------------------------
1 | class Symbol(object):
2 | def __init__(self, value):
3 | self.value = value
4 |
5 |
6 | if __name__ == "__main__":
7 | x = Symbol("Py")
8 | y = Symbol("Py")
9 |
10 | symbols = set()
11 | symbols.add(x)
12 | symbols.add(y)
13 |
14 | print(x is y)
15 | print(x == y)
16 | print(len(symbols))
17 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/2_hash_and_eq_NO.py:
--------------------------------------------------------------------------------
1 | class Symbol(object):
2 | def __init__(self, value):
3 | self.value = value
4 |
5 | def __eq__(self, other):
6 | if isinstance(self, other.__class__):
7 | return self.value == other.value
8 | else:
9 | return NotImplemented
10 |
11 |
12 | if __name__ == "__main__":
13 | x = Symbol("Py")
14 | y = Symbol("Py")
15 |
16 | symbols = set()
17 | symbols.add(x)
18 | symbols.add(y)
19 |
20 | print(x is y)
21 | print(x == y)
22 | print(len(symbols))
23 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/3_hash_and_eq_OK.py:
--------------------------------------------------------------------------------
1 | class Symbol(object):
2 | def __init__(self, value):
3 | self.value = value
4 |
5 | def __eq__(self, other):
6 | if isinstance(self, other.__class__):
7 | return self.value == other.value
8 | else:
9 | return NotImplemented
10 |
11 | def __hash__(self):
12 | return hash(self.value)
13 |
14 |
15 | if __name__ == "__main__":
16 | x = Symbol("Py")
17 | y = Symbol("Py")
18 |
19 | symbols = set()
20 | symbols.add(x)
21 | symbols.add(y)
22 |
23 | print(x is y)
24 | print(x == y)
25 | print(len(symbols))
26 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/4_benchmark_decorator.py:
--------------------------------------------------------------------------------
1 | import random
2 | import time
3 |
4 |
5 | def benchmark(func):
6 | def wrapper(*args, **kwargs):
7 | t = time.perf_counter()
8 | res = func(*args, **kwargs)
9 | print("{0} {1}".format(func.__name__, time.perf_counter()-t))
10 | return res
11 | return wrapper
12 |
13 |
14 | @benchmark
15 | def random_tree(n):
16 | temp = [n for n in range(n)]
17 | for i in range(n+1):
18 | temp[random.choice(temp)] = random.choice(temp)
19 | return temp
20 |
21 |
22 | if __name__ == "__main__":
23 | random_tree(10000)
24 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/5_class_and_static_decorator.py:
--------------------------------------------------------------------------------
1 | class A(object):
2 | _hello = True
3 |
4 | def foo(self, x):
5 | print("foo({0}, {1}) 실행".format(self, x))
6 |
7 | @classmethod
8 | def class_foo(cls, x):
9 | print("class_foo({0}, {1}) 실행: {2}".format(cls, x, cls._hello))
10 |
11 | @staticmethod
12 | def static_foo(x):
13 | print("static_foo({0}) 실행".format(x))
14 |
15 |
16 | if __name__ == "__main__":
17 | a = A()
18 | a.foo(1)
19 | a.class_foo(2)
20 | A.class_foo(2)
21 | a.static_foo(3)
22 | A.static_foo(3)
23 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/6_observer_pattern_with_set.py:
--------------------------------------------------------------------------------
1 | class Subscriber(object):
2 | def __init__(self, name):
3 | self.name = name
4 |
5 | def update(self, message):
6 | print("{0}, {1}".format(self.name, message))
7 |
8 |
9 | class Publisher(object):
10 | def __init__(self):
11 | self.subscribers = set()
12 |
13 | def register(self, who):
14 | self.subscribers.add(who)
15 |
16 | def unregister(self, who):
17 | self.subscribers.discard(who)
18 |
19 | def dispatch(self, message):
20 | for subscriber in self.subscribers:
21 | subscriber.update(message)
22 |
23 |
24 | if __name__ == "__main__":
25 | pub = Publisher()
26 |
27 | astin = Subscriber("아스틴")
28 | james = Subscriber("제임스")
29 | jeff = Subscriber("제프")
30 |
31 | pub.register(astin)
32 | pub.register(james)
33 | pub.register(jeff)
34 |
35 | pub.dispatch("점심시간입니다.")
36 | pub.unregister(jeff)
37 | pub.dispatch("퇴근시간입니다.")
38 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/7_observer_pattern_with_dict.py:
--------------------------------------------------------------------------------
1 | class SubscriberOne(object):
2 | def __init__(self, name):
3 | self.name = name
4 |
5 | def update(self, message):
6 | print("{0}, {1}".format(self.name, message))
7 |
8 |
9 | class SubscriberTwo(object):
10 | def __init__(self, name):
11 | self.name = name
12 |
13 | def receive(self, message):
14 | print("{0}, {1}".format(self.name, message))
15 |
16 |
17 | class Publisher(object):
18 | def __init__(self):
19 | self.subscribers = dict()
20 |
21 | def register(self, who, callback=None):
22 | if callback is None:
23 | callback = getattr(who, 'update')
24 | self.subscribers[who] = callback
25 |
26 | def unregister(self, who):
27 | del self.subscribers[who]
28 |
29 | def dispatch(self, message):
30 | for subscriber, callback in self.subscribers.items():
31 | callback(message)
32 |
33 |
34 | if __name__ == "__main__":
35 | pub = Publisher()
36 |
37 | astin = SubscriberOne("아스틴")
38 | james = SubscriberTwo("제임스")
39 | jeff = SubscriberOne("제프")
40 |
41 | pub.register(astin, astin.update)
42 | pub.register(james, james.receive)
43 | pub.register(jeff)
44 |
45 | pub.dispatch("점심시간입니다.")
46 | pub.unregister(jeff)
47 | pub.dispatch("퇴근시간입니다.")
48 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/8_observer_pattern_with_event.py:
--------------------------------------------------------------------------------
1 | class Subscriber(object):
2 | def __init__(self, name):
3 | self.name = name
4 |
5 | def update(self, message):
6 | print("{0}, {1}".format(self.name, message))
7 |
8 |
9 | class Publisher(object):
10 | def __init__(self, events):
11 | self.subscribers = {event: dict() for event in events}
12 |
13 | def get_subscribers(self, event):
14 | return self.subscribers[event]
15 |
16 | def register(self, event, who, callback=None):
17 | if callback is None:
18 | callback = getattr(who, "update")
19 | self.get_subscribers(event)[who] = callback
20 |
21 | def unregister(self, event, who):
22 | del self.get_subscribers(event)[who]
23 |
24 | def dispatch(self, event, message):
25 | for subscriber, callback in self.get_subscribers(event).items():
26 | callback(message)
27 |
28 |
29 | if __name__ == "__main__":
30 | pub = Publisher(["점심", "퇴근"])
31 |
32 | astin = Subscriber("아스틴")
33 | james = Subscriber("제임스")
34 | jeff = Subscriber("제프")
35 |
36 | pub.register("점심", astin)
37 | pub.register("퇴근", astin)
38 | pub.register("퇴근", james)
39 | pub.register("점심", jeff)
40 |
41 | pub.dispatch("점심", "점심시간입니다.")
42 | pub.dispatch("퇴근", "저녁시간 입니다.")
43 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/9_adapter_pattern_OK.py:
--------------------------------------------------------------------------------
1 | """
2 | https://github.com/PJUllrich/Design-Patterns
3 | """
4 |
5 |
6 | class Elf(object):
7 | def nall_nin(self):
8 | print("Elf says: Calling the Overload ...")
9 |
10 |
11 | class Dwarf(object):
12 | def estver_narho(self):
13 | print("Dwarf says: Calling the Overload ...")
14 |
15 |
16 | class Human(object):
17 | def ring_mig(self):
18 | print("Human says: Calling the Overload ...")
19 |
20 |
21 | if __name__ == "__main__":
22 | minions = [Elf(), Dwarf(), Human()]
23 |
24 | for minion in minions:
25 | if isinstance(minion, Elf):
26 | minion.nall_nin()
27 | elif isinstance(minion, Dwarf):
28 | minion.estver_narho()
29 | else:
30 | minion.ring_mig()
31 |
--------------------------------------------------------------------------------
/5장_객체지향_설계/hash_and_eq.py:
--------------------------------------------------------------------------------
1 | class Symbol(object):
2 | def __init__(self, value):
3 | self.value = value
4 |
5 | # def __eq__(self, other):
6 | # if isinstance(self, other.__class__):
7 | # return self.value == other.value
8 | # else:
9 | # return NotImplemented
10 |
11 | # def __hash__(self):
12 | # return hash(self.value)
13 |
14 | symbols = {}
15 |
16 | @staticmethod
17 | def get(key):
18 | if key in Symbol.symbols:
19 | return Symbol.symbols[key]
20 | else:
21 | value = Symbol(key)
22 | Symbol.symbols[key] = value
23 | return value
24 |
25 |
26 | if __name__ == "__main__":
27 | x = Symbol.get("Py")
28 | y = Symbol.get("Py")
29 |
30 | symbols = set()
31 | symbols.add(x)
32 | symbols.add(y)
33 |
34 | print(x is y)
35 | print(x == y)
36 | print(len(symbols))
37 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/1_threading_with_queue.py:
--------------------------------------------------------------------------------
1 | import queue
2 | import threading
3 |
4 | q = queue.Queue()
5 |
6 |
7 | def worker(num):
8 | while True:
9 | item = q.get()
10 | if item is None:
11 | break
12 | # 작업을 처리한다.
13 | print("스레드 {0} : 처리 완료 {1}".format(num+1, item))
14 | q.task_done()
15 |
16 |
17 | if __name__ == "__main__":
18 | num_worker_threads = 5
19 | threads = []
20 | for i in range(num_worker_threads):
21 | t = threading.Thread(target=worker, args=(i,))
22 | t.start()
23 | threads.append(t)
24 |
25 | for item in range(20):
26 | q.put(item)
27 |
28 | # 모든 작업이 끝날 때까지 대기한다(block).
29 | q.join()
30 |
31 | # 워커 스레드를 종료한다(stop).
32 | for i in range(num_worker_threads):
33 | q.put(None)
34 | for t in threads:
35 | t.join()
36 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/2_threading_mutex.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, Lock
2 | import threading
3 |
4 |
5 | def worker(mutex, data, thread_safe):
6 | if thread_safe:
7 | mutex.acquire()
8 | try:
9 | print("스레드 {0}: {1}\n".format(threading.get_ident(), data))
10 | finally:
11 | if thread_safe:
12 | mutex.release()
13 |
14 |
15 | if __name__ == "__main__":
16 | threads = []
17 | thread_safe = True
18 | mutex = Lock()
19 | for i in range(20):
20 | t = Thread(target=worker, args=(mutex, i, thread_safe))
21 | t.start()
22 | threads.append(t)
23 | for t in threads:
24 | t.join()
25 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/3_threading_semaphore.py:
--------------------------------------------------------------------------------
1 | import threading
2 | import time
3 |
4 |
5 | class ThreadPool(object):
6 | def __init__(self):
7 | self.active = []
8 | self.lock = threading.Lock()
9 |
10 | def acquire(self, name):
11 | with self.lock:
12 | self.active.append(name)
13 | print("획득: {0} | 스레드 풀: {1}".format(name, self.active))
14 |
15 | def release(self, name):
16 | with self.lock:
17 | self.active.remove(name)
18 | print("반환: {0} | 스레드 풀: {1}".format(name, self.active))
19 |
20 |
21 | def worker(semaphore, pool):
22 | with semaphore:
23 | name = threading.currentThread().getName()
24 | pool.acquire(name)
25 | time.sleep(1)
26 | pool.release(name)
27 |
28 |
29 | if __name__ == '__main__':
30 | threads = []
31 | pool = ThreadPool()
32 | semaphore = threading.Semaphore(3)
33 | for i in range(10):
34 | t = threading.Thread(
35 | target=worker, name="스레드 " + str(i), args=(semaphore, pool))
36 | t.start()
37 | threads.append(t)
38 | for t in threads:
39 | t.join()
40 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/4_threading_with_condition.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 |
4 | def consumer(cond):
5 | name = threading.currentThread().getName()
6 | print("{0} 시작".format(name))
7 | with cond:
8 | print("{0} 대기".format(name))
9 | cond.wait()
10 | print("{0} 자원 소비".format(name))
11 |
12 |
13 | def producer(cond):
14 | name = threading.currentThread().getName()
15 | print("{0} 시작".format(name))
16 | with cond:
17 | print("{0} 자원 생산 후 모든 소비자에게 알림".format(name))
18 | cond.notifyAll()
19 |
20 |
21 | if __name__ == "__main__":
22 | condition = threading.Condition()
23 | consumer1 = threading.Thread(
24 | name="소비자1", target=consumer, args=(condition,))
25 | consumer2 = threading.Thread(
26 | name="소비자2", target=consumer, args=(condition,))
27 | producer = threading.Thread(name="생산자", target=producer, args=(condition,))
28 |
29 | consumer1.start()
30 | consumer2.start()
31 | producer.start()
32 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/5_using_time_module.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 |
4 | def sumOfN2(n):
5 | start = time.time()
6 | theSum = 0
7 | for i in range(1, n+1):
8 | theSum = theSum + i
9 | end = time.time()
10 | return theSum, end-start
11 |
12 |
13 | if __name__ == "__main__":
14 | n = 5
15 | print("총 합계: %d\t 시간: %10.7f초" % sumOfN2(n))
16 | n = 200
17 | print("총 합계: %d\t 시간: %10.7f초" % sumOfN2(n))
18 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/coroutine.py:
--------------------------------------------------------------------------------
1 | """
2 | [코딩도장] 코루틴
3 | https://dojang.io/mod/page/view.php?id=1122
4 | """
5 |
6 |
7 | def number_coroutine():
8 | try:
9 | while True:
10 | x = (yield)
11 | print(x)
12 | except GeneratorExit:
13 | print("종료")
14 |
15 |
16 | def sum_coroutine():
17 | try:
18 | total = 0
19 | while True:
20 | x = (yield total)
21 | if x is None:
22 | return total # raise StopIteration(total)
23 | total += x
24 | except RuntimeError as e:
25 | print(e)
26 | yield total
27 |
28 |
29 | def accumulate():
30 | while True:
31 | total = yield from sum_coroutine()
32 | print(total)
33 |
34 |
35 | if __name__ == "__main__":
36 | # 1
37 | co = number_coroutine()
38 | next(co)
39 | co.send(1)
40 | co.send(2)
41 | co.send(3)
42 | co.close()
43 |
44 | # 2
45 | sco = sum_coroutine()
46 | print(next(sco))
47 | print(sco.send(1))
48 | print(sco.send(2))
49 | print(sco.send(3))
50 | print(sco.throw(RuntimeError, "예외"))
51 |
52 | # 3
53 | aco = accumulate()
54 | next(aco)
55 |
56 | for i in range(11):
57 | aco.send(i)
58 | aco.send(None)
59 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/event_simple.py:
--------------------------------------------------------------------------------
1 | """
2 | [한빛미디어] 고성능 파이썬
3 | """
4 |
5 | from queue import Queue
6 | import time
7 |
8 | eventloop = None
9 |
10 |
11 | class EventLoop(Queue):
12 | def start(self):
13 | while True:
14 | function = self.get()
15 | function()
16 | time.sleep(1)
17 |
18 |
19 | def do_hello():
20 | global eventloop
21 | print("hello")
22 | eventloop.put(do_world)
23 |
24 |
25 | def do_world():
26 | global eventloop
27 | print("world")
28 | eventloop.put(do_hello)
29 |
30 |
31 | if __name__ == "__main__":
32 | eventloop = EventLoop()
33 | eventloop.put(do_hello)
34 | eventloop.start()
35 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/test_pytest.py:
--------------------------------------------------------------------------------
1 | def func(x):
2 | return x + 1
3 |
4 |
5 | def test_answer():
6 | assert func(3) == 51
7 |
--------------------------------------------------------------------------------
/6장_파이썬_고급/threading_event.py:
--------------------------------------------------------------------------------
1 | """
2 | https://www.bogotobogo.com/python/Multithread/python_multithreading_Event_Objects_between_Threads.php
3 | """
4 |
5 | import threading
6 | import time
7 | import logging
8 |
9 | logging.basicConfig(level=logging.DEBUG,
10 | format='(%(threadName)s) %(message)s',)
11 |
12 |
13 | def wait_for_event(event):
14 | logging.debug("wait_for_event 시작")
15 | event_is_set = event.wait()
16 | logging.debug("이벤트 셋: {0}".format(event_is_set))
17 |
18 |
19 | def wait_for_event_timeout(event, t):
20 | while not event.isSet():
21 | logging.debug("wait_for_event_timeout 시작")
22 | event_is_set = event.wait(t)
23 | logging.debug("이벤트 셋: {0}".format(event_is_set))
24 | if event_is_set:
25 | logging.debug("이벤트 수행")
26 | else:
27 | logging.debug("다른 일 수행")
28 |
29 |
30 | if __name__ == "__main__":
31 | event = threading.Event()
32 | t1 = threading.Thread(name="Blocking",
33 | target=wait_for_event,
34 | args=(event,))
35 | t1.start()
36 |
37 | t2 = threading.Thread(name="Non-Blocking",
38 | target=wait_for_event_timeout,
39 | args=(event, 2))
40 | t2.start()
41 |
42 | logging.debug("Event.set()이 호출될 때까지 대기")
43 | time.sleep(3)
44 | event.set()
45 | logging.debug("이벤트 설정됨")
46 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/12_hash_table.py:
--------------------------------------------------------------------------------
1 | from linkedListFIFO import LinkedListFIFO
2 |
3 |
4 | class HashTableLL(object):
5 | def __init__(self, size):
6 | self.size = size
7 | self.slots = []
8 | self._createHashTable()
9 |
10 | def _createHashTable(self):
11 | for i in range(self.size):
12 | self.slots.append(LinkedListFIFO())
13 |
14 | def _find(self, item):
15 | return item % self.size
16 |
17 | def _add(self, item):
18 | index = self._find(item)
19 | self.slots[index].addNode(item)
20 |
21 | def _delete(self, item):
22 | index = self._find(item)
23 | self.slots[index].deleteNodeByValue(item)
24 |
25 | def _print(self):
26 | for i in range(self.size):
27 | print("슬롯(slot) {0}:".format(i))
28 | self.slots[i]._printList()
29 |
30 |
31 | def test_hash_tables():
32 | H1 = HashTableLL(3)
33 | for i in range(0, 20):
34 | H1._add(i)
35 | H1._print()
36 | print("\n항목 0, 1, 2를 삭제합니다.")
37 | H1._delete(0)
38 | H1._delete(1)
39 | H1._delete(2)
40 | H1._print()
41 |
42 |
43 | if __name__ == "__main__":
44 | test_hash_tables()
45 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/13_reverse_string_with_stack.py:
--------------------------------------------------------------------------------
1 | from stack import Stack
2 |
3 |
4 | def reverse_string_with_stack(str1):
5 | s = Stack()
6 | revStr = ""
7 |
8 | for c in str1:
9 | s.push(c)
10 |
11 | while not s.isEmpty():
12 | revStr += s.pop()
13 |
14 | return revStr
15 |
16 |
17 | if __name__ == "__main__":
18 | str1 = "버피는 천사다."
19 | print(str1)
20 | print(reverse_string_with_stack(str1))
21 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/14_balance_parenthesis_str_stack.py:
--------------------------------------------------------------------------------
1 | from stack import Stack
2 |
3 |
4 | def balance_par_str_with_stack(str1):
5 | s = Stack()
6 | balanced = True
7 | index = 0
8 |
9 | while index < len(str1) and balanced:
10 | symbol = str1[index]
11 |
12 | if symbol == "(":
13 | s.push(symbol)
14 | else:
15 | if s.isEmpty():
16 | balanced = False
17 | else:
18 | s.pop()
19 |
20 | index = index + 1
21 |
22 | if balanced and s.isEmpty():
23 | return True
24 | else:
25 | return False
26 |
27 |
28 | if __name__ == "__main__":
29 | print(balance_par_str_with_stack('((()))'))
30 | print(balance_par_str_with_stack('(()'))
31 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/15_dec2bin_with_stack.py:
--------------------------------------------------------------------------------
1 | from stack import Stack
2 |
3 |
4 | def dec2bin_with_stack(decnum):
5 | s = Stack()
6 | str_aux = ""
7 |
8 | while decnum > 0:
9 | dig = decnum % 2
10 | decnum = decnum // 2
11 | s.push(dig)
12 |
13 | while not s.isEmpty():
14 | str_aux += str(s.pop())
15 |
16 | return str_aux
17 |
18 |
19 | if __name__ == "__main__":
20 | decnum = 9
21 | print(dec2bin_with_stack(decnum))
22 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/17_set_of_stacks.py:
--------------------------------------------------------------------------------
1 | from stack import Stack
2 |
3 |
4 | class SetOfStacks(Stack):
5 | def __init__(self, capacity=4):
6 | self.setofstacks = []
7 | self.items = []
8 | self.capacity = capacity
9 |
10 | def push(self, value):
11 | if self.size() >= self.capacity:
12 | self.setofstacks.append(self.items)
13 | self.items = []
14 | self.items.append(value)
15 |
16 | def pop(self):
17 | value = self.items.pop()
18 | if self.isEmpty() and self.setofstacks:
19 | self.items = self.setofstacks.pop()
20 | return value
21 |
22 | def sizeStack(self):
23 | return len(self.setofstacks) * self.capacity + self.size()
24 |
25 | def __repr__(self):
26 | aux = []
27 | for s in self.setofstacks:
28 | aux.extend(s)
29 | aux.extend(self.items)
30 | return repr(aux)
31 |
32 |
33 | if __name__ == "__main__":
34 | capacity = 5
35 | stack = SetOfStacks(capacity)
36 | print("스택이 비었나요? {0}".format(stack.isEmpty()))
37 | print("스택에 숫자 0~9를 추가합니다.")
38 | for i in range(10):
39 | stack.push(i)
40 | print(stack)
41 | print("스택 크기: {0}".format(stack.sizeStack()))
42 | print("peek: {0}".format(stack.peek()))
43 | print("pop: {0}".format(stack.pop()))
44 | print("peek: {0}".format(stack.peek()))
45 | print("스택이 비었나요? {0}".format(stack.isEmpty()))
46 | print(stack)
47 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/18_palindrome_checker_with_deque.py:
--------------------------------------------------------------------------------
1 | import string
2 | import collections
3 |
4 | from deque import Deque
5 |
6 |
7 | STRIP = string.whitespace + string.punctuation + "\"'"
8 |
9 |
10 | def palindrome_checker_with_deque(str1):
11 | d1 = Deque()
12 | d2 = collections.deque()
13 |
14 | for s in str1.lower():
15 | if s not in STRIP:
16 | d2.append(s)
17 | d1.enqueue(s)
18 |
19 | eq1 = True
20 | while d1.size() > 1 and eq1:
21 | if d1.dequeue_front() != d1.dequeue():
22 | eq1 = False
23 |
24 | eq2 = True
25 | while len(d2) > 1 and eq2:
26 | if d2.pop() != d2.popleft():
27 | eq2 = False
28 |
29 | return eq1, eq2
30 |
31 |
32 | if __name__ == "__main__":
33 | str1 = "Madam Im Adam"
34 | str2 = "Buffy is a Slayer"
35 | print(palindrome_checker_with_deque(str1))
36 | print(palindrome_checker_with_deque(str2))
37 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/1_stack.py:
--------------------------------------------------------------------------------
1 | class Stack(object):
2 | def __init__(self):
3 | self.items = []
4 |
5 | def isEmpty(self):
6 | return not bool(self.items)
7 |
8 | def push(self, value):
9 | self.items.append(value)
10 |
11 | def pop(self):
12 | value = self.items.pop()
13 | if value is not None:
14 | return value
15 | else:
16 | print("Stack is empty.")
17 |
18 | def size(self):
19 | return len(self.items)
20 |
21 | def peek(self):
22 | if self.items:
23 | return self.items[-1]
24 | else:
25 | print("Stack is empty.")
26 |
27 | def __repr__(self):
28 | return repr(self.items)
29 |
30 |
31 | if __name__ == "__main__":
32 | stack = Stack()
33 | print("스택이 비었나요? {0}".format(stack.isEmpty()))
34 | print("스택에 숫자 0~9를 추가합니다.")
35 | for i in range(10):
36 | stack.push(i)
37 | print("스택 크기: {0}".format(stack.size()))
38 | print("peek: {0}".format(stack.peek()))
39 | print("pop: {0}".format(stack.pop()))
40 | print("peek: {0}".format(stack.peek()))
41 | print("스택이 비었나요? {0}".format(stack.isEmpty()))
42 | print(stack)
43 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/20_find_N_largest_smallest_items_seq.py:
--------------------------------------------------------------------------------
1 | import heapq
2 |
3 |
4 | def find_N_largest_items_seq(seq, N):
5 | return heapq.nlargest(N, seq)
6 |
7 |
8 | def find_N_smallest_items_seq(seq, N):
9 | return heapq.nsmallest(N, seq)
10 |
11 |
12 | def find_smallest_items_seq_heap(seq):
13 | heapq.heapify(seq)
14 | return heapq.heappop(seq)
15 |
16 |
17 | def find_smallest_items_seq(seq):
18 | return min(seq)
19 |
20 |
21 | def find_N_smallest_items_seq_sorted(seq, N):
22 | return sorted(seq)[:N]
23 |
24 |
25 | def find_N_largest_items_seq_sorted(seq, N):
26 | return sorted(seq)[len(seq)-N:]
27 |
28 |
29 | def test_find_N_largest_smallest_items_seq():
30 | seq = [1, 3, 2, 8, 6, 10, 9]
31 | N = 3
32 | assert(find_N_largest_items_seq(seq, N) == [10, 9, 8])
33 | assert(find_N_largest_items_seq_sorted(seq, N) == [8, 9, 10])
34 | assert(find_N_smallest_items_seq(seq, N) == [1, 2, 3])
35 | assert(find_N_smallest_items_seq_sorted(seq, N) == [1, 2, 3])
36 | assert(find_smallest_items_seq(seq) == 1)
37 | assert(find_smallest_items_seq_heap(seq) == 1)
38 |
39 | print("테스트 통과!")
40 |
41 |
42 | if __name__ == "__main__":
43 | test_find_N_largest_smallest_items_seq()
44 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/21_merge_sorted_seqs.py:
--------------------------------------------------------------------------------
1 | import heapq
2 |
3 |
4 | def merge_sorted_seqs(seq1, seq2):
5 | result = []
6 | for c in heapq.merge(seq1, seq2):
7 | result.append(c)
8 | return result
9 |
10 |
11 | def test_merge_sorted_seqs():
12 | seq1 = [1, 2, 3, 8, 9, 10]
13 | seq2 = [2, 3, 4, 5, 6, 7, 9]
14 | seq3 = seq1 + seq2
15 | assert(merge_sorted_seqs(seq1, seq2) == sorted(seq3))
16 |
17 | print("테스트 통과!")
18 |
19 |
20 | if __name__ == "__main__":
21 | test_merge_sorted_seqs()
22 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/22_find_kth_from_the_end.py:
--------------------------------------------------------------------------------
1 | from linkedListFIFO import LinkedListFIFO
2 | from node import Node
3 |
4 |
5 | class KthFromLast(LinkedListFIFO):
6 | def find_kth_to_last(self, k):
7 | p1, p2 = self.head, self.head
8 | i = 0
9 | while p1:
10 | if i > k-1:
11 | try:
12 | p2 = p2.pointer
13 | except AttributeError:
14 | break
15 | p1 = p1.pointer
16 | i += 1
17 | return p2.value
18 |
19 |
20 | if __name__ == "__main__":
21 | ll = KthFromLast()
22 | for i in range(1, 11):
23 | ll.addNode(i)
24 | print("연결 리스트: ", end="")
25 | ll._printList()
26 | k = 3
27 | k_from_last = ll.find_kth_to_last(k)
28 | print("연결 리스트의 끝에서 {0}번째 항목은 {1}입니다.".format(k, k_from_last))
29 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/23_part_linked_list.py:
--------------------------------------------------------------------------------
1 | from linkedListFIFO import LinkedListFIFO
2 | from node import Node
3 |
4 |
5 | def partList(ll, n):
6 | more = LinkedListFIFO()
7 | less = LinkedListFIFO()
8 |
9 | node = ll.head
10 |
11 | while node:
12 | item = node.value
13 |
14 | if item < n:
15 | less.addNode(item)
16 |
17 | elif item > n:
18 | more.addNode(item)
19 |
20 | node = node.pointer
21 |
22 | less.addNode(n)
23 | nodemore = more.head
24 |
25 | while nodemore:
26 | less.addNode(nodemore.value)
27 | nodemore = nodemore.pointer
28 |
29 | return less
30 |
31 |
32 | if __name__ == "__main__":
33 | ll = LinkedListFIFO()
34 | l = [6, 7, 3, 4, 9, 5, 1, 2, 8]
35 | for i in l:
36 | ll.addNode(i)
37 |
38 | print("분할 전:")
39 | ll._printList()
40 |
41 | print("분할 후:")
42 | newll = partList(ll, 6)
43 | newll._printList()
44 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/25_check_pal.py:
--------------------------------------------------------------------------------
1 | from linkedListFIFO import LinkedListFIFO
2 | from node import Node
3 |
4 |
5 | def isPal(l1):
6 | if len(l1) < 2:
7 | return True
8 | if l1[0] != l1[-1]:
9 | return False
10 | return isPal(l1[1:-1])
11 |
12 |
13 | def checkllPal(ll):
14 | node = ll.head
15 | l = []
16 |
17 | while node is not None:
18 | l.append(node.value)
19 | node = node.pointer
20 |
21 | return isPal(l)
22 |
23 |
24 | def test_checkllPal():
25 | ll = LinkedListFIFO()
26 | l1 = [1, 2, 3, 2, 1]
27 | for i in l1:
28 | ll.addNode(i)
29 | assert(checkllPal(ll) is True)
30 |
31 | ll.addNode(2)
32 | ll.addNode(3)
33 | assert(checkllPal(ll) is False)
34 |
35 | print("테스트 통과!")
36 |
37 |
38 | if __name__ == "__main__":
39 | test_checkllPal()
40 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/27_circular_linked_list.py:
--------------------------------------------------------------------------------
1 | from linkedListFIFO import LinkedListFIFO
2 | from node import Node
3 |
4 |
5 | class CicularLinkedListFIFO(LinkedListFIFO):
6 | def _add(self, value):
7 | self.length += 1
8 | node = Node(value, self.head)
9 | if self.tail:
10 | self.tail.pointer = node
11 | self.tail = node
12 |
13 |
14 | def isCircularll(ll):
15 | p1 = ll.head
16 | p2 = ll.head
17 |
18 | while p2:
19 | try:
20 | p1 = p1.pointer
21 | p2 = p2.pointer.pointer
22 | except:
23 | break
24 |
25 | if p1 == p2:
26 | return True
27 | return False
28 |
29 |
30 | def test_isCircularll():
31 | ll = LinkedListFIFO()
32 | for i in range(10):
33 | ll.addNode(i)
34 | assert(isCircularll(ll) is False)
35 |
36 | lcirc = CicularLinkedListFIFO()
37 | for i in range(10):
38 | lcirc.addNode(i)
39 | assert(isCircularll(lcirc) is True)
40 |
41 | print("테스트 통과!")
42 |
43 |
44 | if __name__ == "__main__":
45 | test_isCircularll()
46 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/3_queue.py:
--------------------------------------------------------------------------------
1 | class Queue(object):
2 | def __init__(self):
3 | self.items = []
4 |
5 | def isEmpty(self):
6 | return not bool(self.items)
7 |
8 | def enqueue(self, item):
9 | self.items.insert(0, item)
10 |
11 | def dequeue(self):
12 | value = self.items.pop()
13 | if value is not None:
14 | return value
15 | else:
16 | print("Queue is empty.")
17 |
18 | def size(self):
19 | return len(self.items)
20 |
21 | def peek(self):
22 | if self.items:
23 | return self.items[-1]
24 | else:
25 | print("Queue is empty.")
26 |
27 | def __repr__(self):
28 | return repr(self.items)
29 |
30 |
31 | if __name__ == "__main__":
32 | queue = Queue()
33 | print("큐가 비었나요? {0}".format(queue.isEmpty()))
34 | print("큐에 숫자 0~9를 추가합니다.")
35 | for i in range(10):
36 | queue.enqueue(i)
37 | print("큐 크기: {0}".format(queue.size()))
38 | print("peek: {0}".format(queue.peek()))
39 | print("dequeue: {0}".format(queue.dequeue()))
40 | print("peek: {0}".format(queue.peek()))
41 | print("큐가 비었나요? {0}".format(queue.isEmpty()))
42 | print(queue)
43 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/6_deque.py:
--------------------------------------------------------------------------------
1 | from queue import Queue
2 |
3 |
4 | class Deque(Queue):
5 | def enqueue_back(self, item):
6 | self.items.append(item)
7 |
8 | def dequeue_front(self):
9 | value = self.items.pop(0)
10 | if value is not None:
11 | return value
12 | else:
13 | print("Deque is empty.")
14 |
15 |
16 | if __name__ == "__main__":
17 | deque = Deque()
18 | print("데크(Deque)가 비었나요? {0}".format(deque.isEmpty()))
19 | print("데크에 숫자 0~9를 추가합니다.")
20 | for i in range(10):
21 | deque.enqueue(i)
22 | print("데크 크기: {0}".format(deque.size()))
23 | print("peek: {0}".format(deque.peek()))
24 | print("dequeue: {0}".format(deque.dequeue()))
25 | print("peek: {0}".format(deque.peek()))
26 | print("데크가 비었나요? {0}".format(deque.isEmpty()))
27 | print()
28 | print("데크: {0}".format(deque))
29 | print("dequeue: {0}".format(deque.dequeue_front()))
30 | print("peek: {0}".format(deque.peek()))
31 | print("데크: {0}".format(deque))
32 | print("enqueue_back(50)을 수행합니다.")
33 | deque.enqueue_back(50)
34 | print("peek: {0}".format(deque.peek()))
35 | print("데크: {0}".format(deque))
36 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/8_priority_queue.py:
--------------------------------------------------------------------------------
1 | import heapq
2 |
3 |
4 | class PriorityQueue(object):
5 | def __init__(self):
6 | self._queue = []
7 | self._index = 0
8 |
9 | def push(self, item, priority):
10 | heapq.heappush(self._queue, (-priority, self._index, item))
11 | self._index += 1
12 |
13 | def pop(self):
14 | return heapq.heappop(self._queue)[-1]
15 |
16 |
17 | class Item(object):
18 | def __init__(self, name):
19 | self.name = name
20 |
21 | def __repr__(self):
22 | return "Item({0!r})".format(self.name)
23 |
24 |
25 | def test_priority_queue():
26 | """ push와 pop은 모두 O(logn)이다. """
27 | q = PriorityQueue()
28 | q.push(Item('test1'), 1)
29 | q.push(Item('test2'), 4)
30 | q.push(Item('test3'), 3)
31 | assert(str(q.pop()) == "Item('test2')")
32 | print("테스트 통과!")
33 |
34 |
35 | if __name__ == "__main__":
36 | test_priority_queue()
37 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/9_node.py:
--------------------------------------------------------------------------------
1 | class Node(object):
2 | def __init__(self, value=None, pointer=None):
3 | self.value = value
4 | self.pointer = pointer
5 |
6 | def getData(self):
7 | return self.value
8 |
9 | def getNext(self):
10 | return self.pointer
11 |
12 | def setData(self, newdata):
13 | self.value = newdata
14 |
15 | def setNext(self, newpointer):
16 | self.pointer = newpointer
17 |
18 |
19 | if __name__ == "__main__":
20 | L = Node("a", Node("b", Node("c", Node("d"))))
21 | assert(L.pointer.pointer.value == "c")
22 |
23 | print(L.getData())
24 | print(L.getNext().getData())
25 | L.setData("aa")
26 | L.setNext(Node("e"))
27 | print(L.getData())
28 | print(L.getNext().getData())
29 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/deque.py:
--------------------------------------------------------------------------------
1 | from queue import Queue
2 |
3 |
4 | class Deque(Queue):
5 | def enqueue_back(self, item):
6 | self.items.append(item)
7 |
8 | def dequeue_front(self):
9 | return self.items.pop(0)
10 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/node.py:
--------------------------------------------------------------------------------
1 | class Node(object):
2 | def __init__(self, value=None, pointer=None):
3 | self.value = value
4 | self.pointer = pointer
5 |
6 | def getData(self):
7 | return self.value
8 |
9 | def getNext(self):
10 | return self.pointer
11 |
12 | def setData(self, newdata):
13 | self.value = newdata
14 |
15 | def setNext(self, newpointer):
16 | self.pointer = newpointer
17 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/queue.py:
--------------------------------------------------------------------------------
1 | class Queue(object):
2 | def __init__(self):
3 | self.items = []
4 |
5 | def isEmpty(self):
6 | return not bool(self.items)
7 |
8 | def enqueue(self, item):
9 | self.items.insert(0, item)
10 |
11 | def dequeue(self):
12 | return self.items.pop()
13 |
14 | def size(self):
15 | return len(self.items)
16 |
17 | def peek(self):
18 | return self.items[-1]
19 |
20 | def __repr__(self):
21 | return repr(self.items)
22 |
--------------------------------------------------------------------------------
/7장_추상_데이터_타입/stack.py:
--------------------------------------------------------------------------------
1 | class Stack(object):
2 | def __init__(self):
3 | self.items = []
4 |
5 | def isEmpty(self):
6 | return not bool(self.items)
7 |
8 | def push(self, value):
9 | self.items.append(value)
10 |
11 | def pop(self):
12 | value = self.items.pop()
13 | if value is not None:
14 | return value
15 | else:
16 | print("Stack is empty.")
17 |
18 | def size(self):
19 | return len(self.items)
20 |
21 | def peek(self):
22 | if self.items:
23 | return self.items[-1]
24 | else:
25 | print("Stack is empty.")
26 |
27 | def __repr__(self):
28 | return repr(self.items)
29 |
--------------------------------------------------------------------------------
/8장_점근적_분석/find_fibonacci_seq.py:
--------------------------------------------------------------------------------
1 | def find_fibonacci_seq_rec(n):
2 | if n < 2:
3 | return n
4 | return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2)
5 |
6 |
7 | if __name__ == "__main__":
8 | print(find_fibonacci_seq_rec(5))
9 |
--------------------------------------------------------------------------------
/9장_정렬/10_heap_sort_2.py:
--------------------------------------------------------------------------------
1 | from heap import Heap
2 |
3 |
4 | def heap_sort2(seq):
5 | s = list(seq)
6 | heap = Heap(s)
7 | res = []
8 | for _ in range(len(s)):
9 | res.insert(0, heap.extract_max())
10 | return res
11 |
12 |
13 | def test_heap_sort2():
14 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
15 | assert(heap_sort2(seq) == sorted(seq))
16 | print("테스트 통과!")
17 |
18 |
19 | if __name__ == "__main__":
20 | test_heap_sort2()
21 |
--------------------------------------------------------------------------------
/9장_정렬/11_heap_sort_3.py:
--------------------------------------------------------------------------------
1 | def heap_sort3(seq):
2 | for start in range((len(seq)-2)//2, -1, -1):
3 | siftdown(seq, start, len(seq)-1)
4 | for end in range(len(seq)-1, 0, -1):
5 | seq[end], seq[0] = seq[0], seq[end]
6 | siftdown(seq, 0, end - 1)
7 | return seq
8 |
9 |
10 | def siftdown(seq, start, end):
11 | root = start
12 | while True:
13 | child = root * 2 + 1
14 | if child > end:
15 | break
16 | if child + 1 <= end and seq[child] < seq[child + 1]:
17 | child += 1
18 | if seq[root] < seq[child]:
19 | seq[root], seq[child] = seq[child], seq[root]
20 | root = child
21 | else:
22 | break
23 |
24 |
25 | def test_heap_sort():
26 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
27 | assert(heap_sort3(seq) == sorted(seq))
28 | print("테스트 통과!")
29 |
30 |
31 | if __name__ == "__main__":
32 | test_heap_sort()
33 |
--------------------------------------------------------------------------------
/9장_정렬/1_bubble_sort.py:
--------------------------------------------------------------------------------
1 | def bubble_sort(seq):
2 | length = len(seq) - 1
3 | for num in range(length, 0, -1):
4 | for i in range(num):
5 | if seq[i] > seq[i+1]:
6 | seq[i], seq[i+1] = seq[i+1], seq[i]
7 | print(seq)
8 | return seq
9 |
10 |
11 | def test_bubble_sort():
12 | seq = [11, 3, 28, 43, 9, 4]
13 | assert(bubble_sort(seq) == sorted(seq))
14 | print("테스트 통과!")
15 |
16 |
17 | if __name__ == "__main__":
18 | test_bubble_sort()
19 |
--------------------------------------------------------------------------------
/9장_정렬/2_selection_sort.py:
--------------------------------------------------------------------------------
1 | # def selection_sort(seq):
2 | # for i in range(len(seq) - 1, 0, -1):
3 | # max_j = i
4 | # for j in range(max_j):
5 | # if seq[j] > seq[max_j]:
6 | # max_j = j
7 | # seq[i], seq[max_j] = seq[max_j], seq[i]
8 | # return seq
9 |
10 |
11 | def selection_sort(seq):
12 | length = len(seq)
13 | for i in range(length-1):
14 | min_j = i
15 | for j in range(i+1, length):
16 | if seq[min_j] > seq[j]:
17 | min_j = j
18 | seq[i], seq[min_j] = seq[min_j], seq[i]
19 | print(seq)
20 | return seq
21 |
22 |
23 | def test_selection_sort():
24 | seq = [11, 3, 28, 43, 9, 4]
25 | assert(selection_sort(seq) == sorted(seq))
26 | print("테스트 통과!")
27 |
28 |
29 | if __name__ == "__main__":
30 | test_selection_sort()
31 |
--------------------------------------------------------------------------------
/9장_정렬/3_insertion_sort.py:
--------------------------------------------------------------------------------
1 | def insertion_sort(seq):
2 | for i in range(1, len(seq)):
3 | j = i
4 | while j > 0 and seq[j-1] > seq[j]:
5 | seq[j-1], seq[j] = seq[j], seq[j-1]
6 | j -= 1
7 | # print(seq)
8 | return seq
9 |
10 |
11 | def insertion_sort_rec(seq, i=None):
12 | if i is None:
13 | i = len(seq) - 1
14 | if i == 0:
15 | return i
16 | insertion_sort_rec(seq, i-1)
17 | j = i
18 | while j > 0 and seq[j-i] > seq[j]:
19 | seq[j-1], seq[j] = seq[j], seq[j-1]
20 | j -= 1
21 | return seq
22 |
23 |
24 | def test_insertion_sort():
25 | seq = [11, 3, 28, 43, 9, 4]
26 | assert(insertion_sort(seq) == sorted(seq))
27 | assert(insertion_sort_rec(seq) == sorted(seq))
28 | print("테스트 통과!")
29 |
30 |
31 | if __name__ == "__main__":
32 | test_insertion_sort()
33 |
--------------------------------------------------------------------------------
/9장_정렬/4_gnome_sort.py:
--------------------------------------------------------------------------------
1 | def gnome_sort(seq):
2 | i = 0
3 | while i < len(seq):
4 | if i == 0 or seq[i-1] <= seq[i]:
5 | i += 1
6 | else:
7 | seq[i], seq[i-1] = seq[i-1], seq[i]
8 | i -= 1
9 | print(seq)
10 | return seq
11 |
12 |
13 | def test_gnome_sort():
14 | seq = [11, 3, 28, 43, 9, 4]
15 | assert(gnome_sort(seq) == sorted(seq))
16 | print("테스트 통과!")
17 |
18 |
19 | if __name__ == "__main__":
20 | test_gnome_sort()
21 |
--------------------------------------------------------------------------------
/9장_정렬/5_count_sort.py:
--------------------------------------------------------------------------------
1 | from collections import defaultdict
2 |
3 |
4 | def count_sort_dict(a):
5 | b, c = [], defaultdict(list)
6 | for x in a:
7 | c[x].append(x)
8 | for k in range(min(c), max(c) + 1):
9 | b.extend(c[k])
10 | return b
11 |
12 |
13 | def test_count_sort():
14 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
15 | assert(count_sort_dict(seq) == sorted(seq))
16 | print("테스트 통과!")
17 |
18 |
19 | if __name__ == "__main__":
20 | test_count_sort()
21 |
--------------------------------------------------------------------------------
/9장_정렬/8_find_k_largest_seq_quicksort.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 |
4 | def swap(seq, x, y):
5 | seq[x], seq[y] = seq[y], seq[x]
6 |
7 |
8 | def quick_select(seq, k, left=None, right=None):
9 | left = left or 0
10 | right = right or len(seq) - 1
11 | ipivot = random.randint(left, right)
12 | pivot = seq[ipivot]
13 |
14 | # 피벗을 정렬 범위 밖으로 이동한다.
15 | swap(seq, ipivot, right)
16 | swapIndex, i = left, left
17 | while i < right:
18 | if seq[i] < pivot:
19 | swap(seq, i, swapIndex)
20 | swapIndex += 1
21 | i += 1
22 |
23 | # 피벗 위치를 확정한다.
24 | swap(seq, right, swapIndex)
25 | # 피벗 위치를 확인한다.
26 | rank = len(seq) - swapIndex
27 | if k == rank:
28 | return seq[swapIndex]
29 | elif k < rank:
30 | return quick_select(seq, k, left=swapIndex+1, right=right)
31 | else:
32 | return quick_select(seq, k, left=left, right=swapIndex-1)
33 |
34 |
35 | def find_k_largest_seq_quickselect(seq, k):
36 | # k번째로 큰 값을 찾는다.
37 | kth_largest = quick_select(seq, k)
38 |
39 | # k번째보다 큰 값을 저장한다.
40 | result = []
41 | for item in seq:
42 | if item >= kth_largest:
43 | result.append(item)
44 | return result
45 |
46 |
47 | if __name__ == "__main__":
48 | seq = [3, 10, 4, 5, 1, 8, 9, 11, 5]
49 | k = 3
50 | print(find_k_largest_seq_quickselect(seq, k))
51 |
--------------------------------------------------------------------------------
/9장_정렬/9_heap_sort_1.py:
--------------------------------------------------------------------------------
1 | import heapq
2 |
3 |
4 | def heap_sort1(seq):
5 | h = []
6 | for value in seq:
7 | heapq.heappush(h, value)
8 | return [heapq.heappop(h) for i in range(len(h))]
9 |
10 |
11 | def test_heap_sort1():
12 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
13 | assert(heap_sort1(seq) == sorted(seq))
14 | print("테스트 통과!")
15 |
16 |
17 | if __name__ == "__main__":
18 | test_heap_sort1()
19 |
--------------------------------------------------------------------------------
/9장_정렬/a.dat:
--------------------------------------------------------------------------------
1 | 1
2 | 3
3 | 5
4 | 6
5 | 8
6 |
--------------------------------------------------------------------------------
/9장_정렬/b.dat:
--------------------------------------------------------------------------------
1 | 1
2 | 3
3 | 5
4 | 7
5 |
--------------------------------------------------------------------------------
/9장_정렬/c.dat:
--------------------------------------------------------------------------------
1 | 2
2 | 3
3 | 4
4 | 5
--------------------------------------------------------------------------------
/9장_정렬/heap.py:
--------------------------------------------------------------------------------
1 | class Heap(object):
2 | def __init__(self, data=None):
3 | self.data = data or []
4 | for i in range(len(data)//2, -1, -1):
5 | self.__max_heapify__(i)
6 |
7 | def __repr__(self):
8 | return (f'{self.data}')
9 |
10 | def parent(self, i):
11 | return i >> 1
12 |
13 | def left_child(self, i):
14 | return (i << 1) + 1
15 |
16 | def right_child(self, i):
17 | return (i << 1) + 2
18 |
19 | def __max_heapify__(self, i):
20 | largest = i
21 | left = self.left_child(i)
22 | right = self.right_child(i)
23 | n = len(self.data)
24 | largest = (left < n and self.data[left] > self.data[i]) and left or i
25 | largest = (right < n and self.data[right]
26 | > self.data[largest]) and right or largest
27 | if i is not largest:
28 | self.data[i], self.data[largest] = self.data[largest], self.data[i]
29 | self.__max_heapify__(largest)
30 |
31 | def extract_max(self):
32 | n = len(self.data)
33 | max_element = self.data[0]
34 | self.data[0] = self.data[n - 1]
35 | self.data = self.data[:n - 1]
36 | self.__max_heapify__(0)
37 | return max_element
38 |
--------------------------------------------------------------------------------
/HALEIWA.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/HALEIWA.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## ✨ 파이썬 자료구조와 알고리즘 ✨
2 |
3 |
4 |
5 |
6 |
7 | * 🛒 [예스24](http://www.yes24.com/Product/Goods/74971408)
8 |
9 | * 📚 [원서 다운로드](https://github.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/blob/master/ebook/book_second_edition.pdf)
10 |
11 | * 폴더 이름 1장_xxx ~ 14장_xxx 부분이 책 내용입니다. 그 외 나머지 폴더 및 파일은 원서 저장소를 포크한 부분입니다.
12 |
13 | ## License
14 | 
15 |
16 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
17 |
--------------------------------------------------------------------------------
/README_old.md:
--------------------------------------------------------------------------------
1 | ## ✨ Algorithms & Data Structures in Python (Book, Hanbit Media, Inc.) ✨
2 |
3 | * Including Python solutions for every exercises from "Cracking the Code Interview".
4 | * #### 📚[Download the digital book here.](https://github.com/bt3gl/Python-and-Algorithms-and-Data-Structures/blob/master/ebook/book_second_edition.pdf)
5 |
6 | 
7 |
8 |
9 | ## ✨ Installation:
10 |
11 | The snippets are designed to be used individually. However, If you want to install all fo the libraries in your [virtualenv](https://coderwall.com/p/8-aeka), do this:
12 |
13 | ```
14 | $ pip install -r requirements.txt
15 | ```
16 |
17 |
18 |
19 | ----
20 |
21 |
22 | ## License
23 |
24 | When making a reference to my work, please use my [website](http://bt3gl.github.io/index.html).
25 |
26 | 
27 |
28 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
29 |
--------------------------------------------------------------------------------
/ebook/book_second_edition.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/ebook/book_second_edition.pdf
--------------------------------------------------------------------------------
/interview_problems/balanced.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def balance_par_str_with_stack(str1):
7 | i, stack = 0, []
8 |
9 | while i < len(str1):
10 | symbol = str1[i]
11 | if symbol == "(":
12 | stack.append(symbol)
13 | elif symbol == ")":
14 | stack.pop()
15 | i += 1
16 | return not stack
17 |
18 |
19 |
20 | if __name__ == "__main__":
21 | print(balance_par_str_with_stack('((()))'))
22 | print(balance_par_str_with_stack('(()'))
--------------------------------------------------------------------------------
/interview_problems/check_anagram.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import Counter
6 |
7 | def check_if_anagram(word1, word2):
8 | counter = Counter()
9 |
10 | for c in word1:
11 | counter[c] += 1
12 |
13 | for c in word2:
14 | counter[c] -= 1
15 |
16 | for values in counter.values():
17 | if values != 0:
18 | return False
19 |
20 | return True
21 |
22 |
23 |
24 | if __name__ == "__main__":
25 | word1 = 'abc'
26 | word2 = 'bca'
27 | assert(check_if_anagram(word1, word2) == True)
28 |
29 | word2 = 'bcd'
30 | assert(check_if_anagram(word1, word2) == False)
31 |
32 | word1 = ''
33 | word2 = ''
34 | assert(check_if_anagram(word1, word2) == True)
35 |
36 | word1 = 'a'
37 | word2 = 'a'
38 | assert(check_if_anagram(word1, word2) == True)
--------------------------------------------------------------------------------
/interview_problems/combination.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def combination(array):
6 | if len(array) < 2:
7 | return set(array)
8 |
9 | result = set()
10 | for index, item in enumerate(array):
11 | new_array = array[:index] + array[index+1:]
12 | result.add(item)
13 | for perm in combination(new_array):
14 | new_item = ''.join(sorted(item + perm))
15 | result.add(new_item)
16 |
17 | return result
18 |
19 |
20 |
21 | if __name__ == "__main__":
22 | array = ['a', 'b', 'c']
23 | result = set(['a', 'ac', 'ab', 'abc', 'bc', 'c', 'b'])
24 | assert(combination(array) == result)
25 |
26 | array = ['']
27 | result = set([''])
28 | assert(combination(array) == result)
29 |
30 | array = ['a']
31 | result = set(['a'])
32 | assert(combination(array) == result)
--------------------------------------------------------------------------------
/interview_problems/hash_table.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | class HashTable(object):
7 | def __init__(self, slots=10):
8 | self.slots = slots
9 | self.table = []
10 | self.create_table()
11 |
12 | # Get the slot
13 | def hash_key(self, value):
14 | return hash(value)%self.slots
15 |
16 | # When creating the table, add list struct
17 | # to each slot
18 | def create_table(self):
19 | for i in range(self.slots):
20 | self.table.append([])
21 |
22 | # Method to add a item in the right slot
23 | def add_item(self, value):
24 | key = self.hash_key(value)
25 | self.table[key].append(value)
26 |
27 | # Aux: print table
28 | def print_table(self):
29 | for key in range(self.slots):
30 | print "Key is {0}, value is {1}.".format(key, self.table[key])
31 |
32 | # Aux: find item
33 | def find_item(self, item):
34 | item_hash = self.hash_key(item)
35 | return item in self.table[item_hash]
36 |
37 |
38 | if __name__ == "__main__":
39 | dic = HashTable(5)
40 | for i in range(1, 40, 2):
41 | dic.add_item(i)
42 |
43 | dic.print_table()
44 | assert(dic.find_item(20) == False)
45 | assert(dic.find_item(21) == True)
--------------------------------------------------------------------------------
/interview_problems/longest_common_prefix.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def longest_common_substring(s1, s2):
7 | p1 = 0
8 | aux, lcp = '', ''
9 | string1 = max(s1, s2)
10 | string2 = min(s1, s2)
11 |
12 | while p1 < len(string1):
13 | p2 = 0
14 | while p2 < len(string2) and p1+p2 < len(string1):
15 | if string1[p1+p2] == string2[p2]:
16 | aux += string1[p1+p2]
17 | else:
18 | if len(lcp) < len(aux):
19 | lcp = aux
20 | aux = ''
21 | p2 += 1
22 | p1 += 1
23 |
24 | return lcp
25 |
26 |
27 |
28 | if __name__ == "__main__":
29 | str1 = 'hasfgeaae'
30 | str2 = 'bafgekk'
31 | result = 'fge'
32 | assert(longest_common_substring(str1, str2) == result)
--------------------------------------------------------------------------------
/interview_problems/longest_increasing_subsequence.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def longest_increasing_subsequence(seq):
7 | result, aux = [], []
8 | seq.append(-float('infinity'))
9 |
10 | for i, value in enumerate(seq[:-1]):
11 | aux.append(value)
12 | if value > seq[i+1]:
13 | if len(result) < len(aux):
14 | result = aux[:]
15 | aux = []
16 | return result
17 |
18 |
19 |
20 | if __name__ == "__main__":
21 | seq = [10, -12, 2, 3, -3, 5, -1, 2, -10]
22 | result = [-12, 2, 3]
23 | assert(longest_increasing_subsequence(seq) == result)
24 |
25 | seq = [2]
26 | result = [2]
27 | assert(longest_increasing_subsequence(seq) == result)
28 |
29 | seq = []
30 | result = []
31 | assert(longest_increasing_subsequence(seq) == result)
--------------------------------------------------------------------------------
/interview_problems/merge_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # AKA: do you believe in magic?
3 |
4 | __author__ = "bt3"
5 |
6 | def merge_sort(array):
7 | if len(array) < 2:
8 | return array
9 |
10 | # divide
11 | mid = len(array)//2
12 | left = merge_sort(array[:mid])
13 | right = merge_sort(array[mid:])
14 |
15 | # merge
16 | result = []
17 | i, j = 0, 0
18 |
19 | while i < len(left) and j < len(right):
20 | if left[i] < right[j]:
21 | result.append(left[i])
22 | i += 1
23 | else:
24 | result.append(right[j])
25 | j+= 1
26 |
27 | # make sure nothing is left behind
28 | if left[i:]:
29 | result.extend(left[i:])
30 | if right[j:]:
31 | result.extend(right[j:])
32 |
33 | return result
34 |
35 |
36 |
37 |
38 | if __name__ == "__main__":
39 | array = [3, 1, 6, 0, 7, 19, 7, 2, 22]
40 | sorted = [0, 1, 2, 3, 6, 7, 7, 19, 22]
41 | assert(merge_sort(array) == sorted)
42 |
43 | array = []
44 | assert(merge_sort(array) == array)
45 |
46 | array = [1]
47 | assert(merge_sort(array) == array)
--------------------------------------------------------------------------------
/interview_problems/permutation.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def permutation(array):
7 | if len(array) < 2:
8 | return [array]
9 |
10 | result = []
11 | for index, letter in enumerate(array):
12 | new_array = array[:index] + array[index+1:]
13 | for perm in permutation(new_array):
14 | result.append(letter + perm)
15 |
16 | return result
17 |
18 |
19 |
20 | if __name__ == "__main__":
21 | word = 'abc'
22 | result = ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
23 | assert(permutation(word) == result)
24 |
25 | word = ''
26 | result = ['']
27 | assert(permutation(word) == result)
28 |
29 | word = 'a'
30 | result = ['a']
31 | assert(permutation(word) == result)
--------------------------------------------------------------------------------
/interview_problems/queue.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | class Queue(object):
7 | def __init__(self):
8 | self.enq = []
9 | self.deq = []
10 |
11 | def enqueue(self, item):
12 | return self.enq.append(item)
13 |
14 | def deque(self):
15 | if not self.deq:
16 | while self.enq:
17 | self.deq.append(self.enq.pop())
18 | return self.deq.pop()
19 |
20 | def peak(self):
21 | if not self.deq:
22 | while self.enq:
23 | self.deq.append(self.enq.pop())
24 | if self.deq:
25 | return self.deq[-1]
26 |
27 | def size(self):
28 | return len(self.enq) + len(self.deq)
29 |
30 | def isempty(self):
31 | return not (self.enq + self.deq)
32 |
33 |
34 | if __name__ == "__main__":
35 | q = Queue()
36 | for i in range(1,11):
37 | q.enqueue(i)
38 | print 'Size:', q.size()
39 | print 'Is empty?', q.isempty()
40 | print 'Peak: ', q.peak()
41 | print
42 | print 'Dequeuing...'
43 | for i in range(10):
44 | print q.deque()
45 | print 'Size:', q.size()
46 | print 'Is empty?', q.isempty()
47 | print 'Peak: ', q.peak()
--------------------------------------------------------------------------------
/interview_problems/quick_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def quick_sort(array):
6 | if len(array) < 2:
7 | return array
8 |
9 | # partition
10 | ipivot = len(array)//2
11 | pivot = array[ipivot]
12 | new_array = array[:ipivot] + array[ipivot+1:]
13 |
14 | left = [x for x in new_array if x <= pivot]
15 | right = [x for x in new_array if x > pivot]
16 |
17 | return quick_sort(left) + [pivot] + quick_sort(right)
18 |
19 |
20 |
21 |
22 | if __name__ == "__main__":
23 | array = [3, 1, 6, 0, 7, 19, 7, 2, 22]
24 | sorted = [0, 1, 2, 3, 6, 7, 7, 19, 22]
25 | assert(quick_sort(array) == sorted)
26 |
27 | array = []
28 | assert(quick_sort(array) == array)
29 |
30 | array = [1]
31 | assert(quick_sort(array) == array)
--------------------------------------------------------------------------------
/interview_problems/reverse_str.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def reverse_str_inplace(_str):
6 | if len(_str) < 2:
7 | return _str
8 | return _str[-1] + reverse_str(_str[1:-1]) + _str[0]
9 |
10 |
11 | def reverse_str(_str):
12 | result = ''
13 | j = len(_str) - 1
14 |
15 | while j >= 0:
16 | result += _str[j]
17 |
18 | return result
19 |
20 |
21 | if __name__ == "__main__":
22 | _str = ''
23 | result = ''
24 | assert(reverse_str(_str) == result)
25 | assert(reverse_str_inplace(_str) == result)
26 |
27 | _str = 'a'
28 | result = 'a'
29 | assert(reverse_str(_str) == result)
30 | assert(reverse_str_inplace(_str) == result)
31 |
32 | _str = 'abcde'
33 | result = 'edcba'
34 | assert(reverse_str(_str) == result)
35 | assert(reverse_str_inplace(_str) == result)
36 |
37 | _str = 'abcdef'
38 | result = 'fedcba'
39 | assert(reverse_str(_str) == result)
40 | assert(reverse_str_inplace(_str) == result)
--------------------------------------------------------------------------------
/interview_problems/stack.py:
--------------------------------------------------------------------------------
1 |
2 | #!/usr/bin/env python
3 |
4 | __author__ = "bt3"
5 |
6 |
7 | class Stack(object):
8 | def __init__(self):
9 | self.content = []
10 |
11 | def push(self, value):
12 | self.content.append(value)
13 |
14 | def pop(self):
15 | if self.content:
16 | return self.content.pop()
17 | else:
18 | return 'Empty List. '
19 |
20 | def size(self):
21 | return len(self.content)
22 |
23 | def isEmpty(self):
24 | return not bool(self.content)
25 |
26 | def peek(self):
27 | if self.content:
28 | return self.content[-1]
29 | else:
30 | print("Stack is empty.")
31 |
32 |
33 | if __name__ == "__main__":
34 | q = Stack()
35 |
36 | for i in range(10):
37 | q.push(i)
38 | for i in range(11):
39 | print q.pop()
40 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==0.10.1
2 | SQLAlchemy==0.9.7
3 | bpython==0.13.1
4 | coverage==3.7.1
5 | curtsies==0.0.34
6 | graphviz==0.4.2
7 | ipython==0.13.2
8 | matplotlib==1.3.1
9 | nose==1.3.0
10 | numpy==1.8.2
11 | scapy==2.2.0
12 | scikit-learn==0.14.1
13 | scipy==0.12.1
--------------------------------------------------------------------------------
/source_code/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/.DS_Store
--------------------------------------------------------------------------------
/source_code/USEFUL/advanced/lru_cache.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from functools import lru_cache
7 |
8 |
9 | @lru_cache(maxsize=20)
10 | def fib(n):
11 | if n < 2:
12 | return n
13 | return fib(n-1) + fib(n-2)
14 |
15 |
16 | if __name__ == "__main__":
17 | print([fib(n) for n in range(10)])
18 | print(fib.cache_info())
19 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_OrderedDict.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import OrderedDict
6 |
7 | def OrderedDict_example():
8 | """ show some examples for OrderedDict """
9 | """ keep the order of insertion.
10 | maintains a doubly linked list, so size is more than twice than normal dict"""
11 |
12 |
13 | pairs = [('a', 1), ('b',2), ('c',3)]
14 |
15 | d1 = {}
16 | for key, value in pairs:
17 | if key not in d1:
18 | d1[key] = []
19 | d1[key].append(value)
20 | for key in d1:
21 | print(key, d1[key])
22 |
23 | d2 = OrderedDict(pairs)
24 | for key in d2:
25 | print(key, d2[key])
26 |
27 |
28 | if __name__ == "__main__":
29 | OrderedDict_example()
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_args.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def simple2(a, *args):
6 | print args
7 |
8 | def simple(*args):
9 | print args
10 |
11 | def simple3(**kwargs):
12 | print kwargs
13 |
14 |
15 | simple(1, 2, 3)
16 | simple2(1, 2, 3)
17 | simple3(x=1, y=2)
18 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_benchmark_decorator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | import random
7 |
8 | def benchmark(func):
9 | import time
10 | def wrapper(*args, **kwargs):
11 | t = time.clock()
12 | res = func(*args, **kwargs)
13 | print("\t%s" % func.__name__, time.clock()-t)
14 | return res
15 | return wrapper
16 |
17 |
18 | @benchmark
19 | def random_tree(n):
20 | temp = [n for n in range(n)]
21 | for i in range(n+1):
22 | temp[random.choice(temp)] = random.choice(temp)
23 | return temp
24 |
25 |
26 | if __name__ == "__main__":
27 | random_tree(10000)
28 |
29 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_comp_lists.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | a = [3, 4, 5, 6, 7]
6 |
7 |
8 | # Filter elements greater than 4
9 |
10 | # Bad:
11 |
12 | b = []
13 | for i in a:
14 | if i > 4:
15 | b.append(i)
16 | print b
17 |
18 | # Good:
19 | print [i for i in a if i > 4]
20 |
21 | # Or:
22 | print filter(lambda x: x > 4, a)
23 |
24 |
25 | # Add three to all list members:
26 |
27 | # Bad
28 | b = []
29 | for i in range(len(a)):
30 | b.append(a[i] + 3)
31 | print b
32 |
33 | # Good:
34 | print [i + 3 for i in a]
35 |
36 | # Or:
37 | print map(lambda i: i + 3, a)
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_counter.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import Counter
6 |
7 | def Counter_example():
8 | """ it is a dictionary that maps the items to the number of occurrences """
9 | seq1 = [1, 2, 3, 5, 1, 2, 5, 5, 2, 5, 1, 4]
10 | seq_counts = Counter(seq1)
11 | print(seq_counts)
12 |
13 | """ we can increment manually or use the update() method """
14 | seq2 = [1, 2, 3]
15 | seq_counts.update(seq2)
16 | print(seq_counts)
17 |
18 | seq3 = [1, 4, 3]
19 | for key in seq3:
20 | seq_counts[key] += 1
21 | print(seq_counts)
22 |
23 | """ also, we can use set operations such as a-b or a+b """
24 | seq_counts_2 = Counter(seq3)
25 | print(seq_counts_2)
26 | print(seq_counts + seq_counts_2)
27 | print(seq_counts - seq_counts_2)
28 |
29 | if __name__ == "__main__":
30 | Counter_example()
31 |
32 |
33 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_decorators.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | def logger(func):
8 | def inner(*args): #1
9 | print "Arguments were: {0}".format(args)
10 | return func(*args)
11 | return inner
12 |
13 | @logger
14 | def foo(x, y):
15 | return x+y
16 |
17 | print foo(1, 2)
18 |
19 |
20 | def sum(func):
21 | s = 0
22 | for i in func():
23 | s += i
24 | return s
25 |
26 | @sum
27 | def interate():
28 | a = []
29 | for i in range(10):
30 | a.append(i)
31 | return a
32 |
33 | print interate
34 |
35 | # which is the same as
36 | def interate():
37 | a = []
38 | for i in range(10):
39 | a.append(i)
40 | return a
41 |
42 | print sum(interate)
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_defaultdict.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import defaultdict
6 |
7 | def defaultdict_example():
8 | """ show some examples for defaultdicts """
9 | pairs = {('a', 1), ('b',2), ('c',3)}
10 |
11 | d1 = {}
12 | for key, value in pairs:
13 | if key not in d1:
14 | d1[key] = []
15 | d1[key].append(value)
16 | print(d1)
17 |
18 | d2 = defaultdict(list)
19 | for key, value in pairs:
20 | d2[key].append(value)
21 | print(d2)
22 |
23 |
24 | if __name__ == "__main__":
25 | defaultdict_example()
26 |
27 |
28 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_doctest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | __author__ = "bt3"
4 |
5 | """
6 | The doctest module automatically runs any statement beginning with >>>
7 | and compares the following line with the output from the interpreter.
8 |
9 | >>> 1 == 1
10 | False
11 | """
12 |
13 | if __name__ == "__main__":
14 | import doctest
15 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_fractions.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from fractions import Fraction
7 |
8 | def rounding_floats(number1, places):
9 | return round(number1, places)
10 |
11 |
12 | def float_to_fractions(number):
13 | return Fraction(*number.as_integer_ratio())
14 |
15 |
16 | def get_denominator(number1, number2):
17 | a = Fraction(number1, number2)
18 | return a.denominator
19 |
20 |
21 | def get_numerator(number1, number2):
22 | a = Fraction(number1, number2)
23 | return a.numerator
24 |
25 |
26 | def test_testing_floats(module_name='this module'):
27 | number1 = 1.25
28 | number2 = 1
29 | number3 = -1
30 | number4 = 5/4
31 | number6 = 6
32 | assert(rounding_floats(number1, number2) == 1.2)
33 | assert(rounding_floats(number1*10, number3) == 10)
34 | assert(float_to_fractions(number1) == number4)
35 | assert(get_denominator(number2, number6) == number6)
36 | assert(get_numerator(number2, number6) == number2)
37 |
38 | s = 'Tests in {name} have {con}!'
39 | print(s.format(name=module_name, con='passed'))
40 |
41 |
42 | if __name__ == "__main__":
43 | test_testing_floats()
44 |
45 |
46 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_generator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def interate(x):
7 | for i in range(x):
8 | yield i
9 |
10 | def gen1():
11 | a = interate(10)
12 | print a.next()
13 | print a.next()
14 | print a.next()
15 |
16 |
17 | def reverse(data):
18 | for i in range(len(data)-1, -1, -1):
19 | yield data[i]
20 |
21 | def gen2():
22 | for c in reverse('awesome'):
23 | print c
24 |
25 | if __name__ == "__main__":
26 | gen1()
27 | gen2()
28 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_lambda.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | test = lambda x: x**2
7 | print test(3)
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_logging.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import logging
6 |
7 | LOG_FILENAME = 'logging_example.out'
8 | logging.basicConfig(filename=LOG_FILENAME,
9 | level=logging.DEBUG,
10 | )
11 |
12 | logging.debug('This message should go to the log file')
13 |
14 | f = open(LOG_FILENAME, 'rt')
15 | try:
16 | body = f.read()
17 | finally:
18 | f.close()
19 |
20 | print 'FILE:'
21 | print body
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_numpy.py:
--------------------------------------------------------------------------------
1 |
2 | #!/usr/bin/env python
3 |
4 | __author__ = "bt3"
5 |
6 | import time
7 | import numpy as np
8 |
9 | def testing_numpy():
10 | """ tests many features of numpy """
11 | ax = np.array([1,2,3])
12 | ay = np.array([3,4,5])
13 | print(ax)
14 | print(ax*2)
15 | print(ax+10)
16 | print(np.sqrt(ax))
17 | print(np.cos(ax))
18 | print(ax-ay)
19 | print(np.where(ax<2, ax, 10))
20 |
21 | m = np.matrix([ax, ay, ax])
22 | print(m)
23 | print(m.T)
24 |
25 | grid1 = np.zeros(shape=(10,10), dtype=float)
26 | grid2 = np.ones(shape=(10,10), dtype=float)
27 | print(grid1)
28 | print(grid2)
29 | print(grid1[1]+10)
30 | print(grid2[:,2]*2)
31 |
32 |
33 | def trad_version():
34 | t1 = time.time()
35 | X = range(10000000)
36 | Y = range(10000000)
37 | Z = []
38 | for i in range(len(X)):
39 | Z.append(X[i] + Y[i])
40 | return time.time() - t1
41 |
42 | def numpy_version():
43 | t1 = time.time()
44 | X = np.arange(10000000)
45 | Y = np.arange(10000000)
46 | Z = X + Y
47 | return time.time() - t1
48 |
49 |
50 |
51 | if __name__ == "__main__":
52 | testing_numpy()
53 | print(trad_version())
54 | print(numpy_version())
55 |
56 |
57 | """
58 | 3.23564291
59 | 0.0714290142059
60 | """
61 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_open_files.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | filename = raw_input('Enter a file name: ')
6 | try:
7 | f = open(filename, "r")
8 | except:
9 | print 'There is no file named', filename
10 |
11 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_queue.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import Queue
6 |
7 | q = Queue.Queue()
8 |
9 | for i in range(10):
10 | q.put(i)
11 |
12 | for i in range(10):
13 | print q.get(i)
14 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_random.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import random
6 |
7 | def testing_random():
8 | """ testing the module random"""
9 | values = [1, 2, 3, 4]
10 | print(random.choice(values))
11 | print(random.choice(values))
12 | print(random.choice(values))
13 | print(random.sample(values, 2))
14 | print(random.sample(values, 3))
15 |
16 | """ shuffle in place """
17 | random.shuffle(values)
18 | print(values)
19 |
20 | """ create random integers """
21 | print(random.randint(0,10))
22 | print(random.randint(0,10))
23 |
24 |
25 | if __name__ == "__main__":
26 | testing_random()
27 |
28 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_setdefault.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def usual_dict(dict_data):
7 | newdata = {}
8 | for k, v in dict_data:
9 | if k in newdata:
10 | newdata[k].append(v)
11 | else:
12 | newdata[k] = [v]
13 | return newdata
14 |
15 |
16 | def setdefault_dict(dict_data):
17 | newdata = {}
18 | for k, v in dict_data:
19 | newdata.setdefault(k, []).append(v)
20 | return newdata
21 |
22 |
23 | def test_setdef(module_name='this module'):
24 | dict_data = (('key1', 'value1'),
25 | ('key1', 'value2'),
26 | ('key2', 'value3'),
27 | ('key2', 'value4'),
28 | ('key2', 'value5'),)
29 | print(usual_dict(dict_data))
30 | print(setdefault_dict(dict_data))
31 |
32 | s = 'Tests in {name} have {con}!'
33 | print(s.format(name=module_name, con='passed'))
34 |
35 |
36 | if __name__ == "__main__":
37 | test_setdef()
38 |
39 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_sets.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def difference(l1):
6 | """ return the list with duplicate elements removed """
7 | return list(set(l1))
8 |
9 | def intersection(l1, l2):
10 | """ return the intersection of two lists """
11 | return list(set(l1) & set(l2))
12 |
13 | def union(l1, l2):
14 | """ return the union of two lists """
15 | return list(set(l1) | set(l2))
16 |
17 |
18 | def test_sets_operations_with_lists():
19 | l1 = [1,2,3,4,5,9,11,15]
20 | l2 = [4,5,6,7,8]
21 | l3 = []
22 | assert(difference(l1) == [1, 2, 3, 4, 5, 9, 11, 15])
23 | assert(difference(l2) == [8, 4, 5, 6, 7])
24 | assert(intersection(l1, l2) == [4,5])
25 | assert(union(l1, l2) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15])
26 | assert(difference(l3) == [])
27 | assert(intersection(l3, l2) == l3)
28 | assert(sorted(union(l3, l2)) == sorted(l2))
29 | print('Tests passed!')
30 |
31 |
32 | if __name__ == "__main__":
33 | test_sets_operations_with_lists()
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_socket.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | __author__ = "bt3"
5 |
6 |
7 | import socket
8 |
9 |
10 | def netcat(hostname, port, content):
11 |
12 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13 |
14 | s.connect((hostname, port))
15 | s.sendall(content)
16 |
17 | adata = []
18 | while 1:
19 | data = s.recv(1024)
20 | if data == '':
21 | break
22 | adata.append(data)
23 |
24 | s.close()
25 | return adata
26 |
27 |
28 |
29 | if __name__ == "__main__":
30 |
31 | PORT = 12345
32 | HOSTNAME = '54.209.5.48'
33 |
34 | message = netcat(HOSTNAME, PORT, 'Hello!')[1]
35 | print message
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_string_format.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | foo = 'foo'
7 | bar = 'bar'
8 |
9 | print '%s%s' % (foo, bar) # It is OK
10 | print '{0}{1}'.format(foo, bar) # It is better
11 | print '{foo}{bar}'.format(foo=foo, bar=bar) # It is best
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_subprocess.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import subprocess,os
6 |
7 | os.system('ls')
8 | subprocess.call(['ls', '-1'], shell=True)
9 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_telnet.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | __author__ = "bt3"
5 |
6 |
7 | from telnetlib import Telnet
8 |
9 |
10 | # examples of telnet connections
11 | PORT = 12345
12 | HOST = '54.209.5.48'
13 |
14 | # creating connection
15 | tn = Telnet(HOST ,PORT)
16 |
17 | # reading input
18 | msg_in2 = tn.read_all().dec_msg()
19 | tn.read_until(b'psifer text: ')
20 |
21 | # writing outputs
22 | tn.write(msg.encode() + b'\n')
23 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_testing.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | def test_doctest():
8 | """
9 | >>> 1 == 1
10 | False
11 | """
12 | pass
13 |
14 | if __name__ == "__main__":
15 | import doctest
16 | doctest.testmod()
17 |
18 | #####
19 |
20 | import unittest
21 |
22 | class BasicsTestCase(unittest.TestCase):
23 |
24 | def test_find_name(self):
25 | self.assertTrue(1 == 1)
26 | self.assertFalse(1 == 2)
27 |
28 | if __name__ == "__main__":
29 | unittest.main()
30 |
31 |
32 |
33 | #####
34 |
35 | # content of test_example.py, run with $ py.test
36 | #
37 | # run tests over the directory
38 | # $ nosetest
39 |
40 |
41 | def func(x):
42 | return x + 1
43 |
44 | def test_answer():
45 | assert func(3) == 4
46 |
47 |
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_threads.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import threading
6 |
7 | def worker(num):
8 | """thread worker function"""
9 | print 'Worker: %s' % num
10 | return
11 |
12 | threads = []
13 | for i in range(5):
14 | t = threading.Thread(target=worker, args=(i,))
15 | threads.append(t)
16 | t.start()
--------------------------------------------------------------------------------
/source_code/USEFUL/basic_examples/example_time.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | __author__ = "bt3"
4 |
5 | """ a simple example of how to time a function """
6 |
7 | import time
8 |
9 | def sumOfN2(n):
10 | start = time.time()
11 | theSum = 0
12 | for i in range(1,n+1):
13 | theSum = theSum + i
14 | end = time.time()
15 | return theSum,end-start
16 |
17 |
18 |
19 | if __name__ == "__main__":
20 | n = 5
21 | print("Sum is %d and required %10.7f seconds"%sumOfN2(n))
22 | n = 200
23 | print("Sum is %d and required %10.7f seconds"%sumOfN2(n))
24 |
25 |
--------------------------------------------------------------------------------
/source_code/USEFUL/dynamic_programming/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/USEFUL/dynamic_programming/__init__.py
--------------------------------------------------------------------------------
/source_code/USEFUL/dynamic_programming/memo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from functools import wraps
7 | from do_benchmark import benchmark
8 |
9 | def memo(func):
10 | """ an example of dynamic programming using a memoizing decorator """
11 | cache = {}
12 | @wraps(func)
13 | def wrap(*args):
14 | if args not in cache:
15 | cache[args] = func(*args)
16 | return cache[args]
17 | return wrap
18 |
19 | @memo
20 | def find_fibonacci_seq_rec(n):
21 | """ implements the nth fibonacci value in a recursive exponential runtime """
22 | if n < 2: return n
23 | return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2)
24 |
25 | def test_memo():
26 | n = 50
27 | # find_fibonacci_seq_rec = memo(find_fibonacci_seq_rec)
28 | # @benchmark
29 | print(find_fibonacci_seq_rec(n))
30 |
31 |
32 | if __name__ == "__main__":
33 | test_memo()
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/source_code/USEFUL/oop/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/USEFUL/oop/__init__.py
--------------------------------------------------------------------------------
/source_code/USEFUL/useful_with_files/change_ext_file.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | __author__ = "bt3"
5 |
6 |
7 | import os
8 | import sys
9 | import shutil
10 |
11 | def change_file_ext():
12 | """ read a file and an extension from the command line and produces a copy with its extension changed"""
13 | if len(sys.argv) < 2:
14 | print("Usage: change_ext.py filename.old_ext 'new_ext'")
15 | sys.exit()
16 |
17 | name = os.path.splitext(sys.argv[1])[0] + "." + sys.argv[2]
18 | print (name)
19 |
20 | try:
21 | shutil.copyfile(sys.argv[1], name)
22 | except OSError as err:
23 | print (err)
24 |
25 |
26 |
27 | if __name__ == "__main__":
28 | change_file_ext()
29 |
30 |
31 |
--------------------------------------------------------------------------------
/source_code/USEFUL/useful_with_files/count_unique_words_files.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | import collections
7 | import string
8 | import sys
9 |
10 | def count_unique_word_file():
11 | if len(sys.argv) < 2:
12 | print "Usage: python count_unique_word.py NAMEFILE"
13 |
14 | words = collections.defaultdict(int)
15 | strip = string.whitespace + string.punctuation + string.digits + "\"'"
16 | for filename in sys.argv[1:]:
17 | with open(filename) as file:
18 | for line in file:
19 | for word in line.lower().split():
20 | word = word.strip(strip)
21 | if len(word) > 2:
22 | words[word] = +1
23 | for word in sorted(words):
24 | print("'{0}' occurs {1} times.".format(word, words[word]))
25 |
26 |
27 | if __name__ == "__main__":
28 | count_unique_word_file()
--------------------------------------------------------------------------------
/source_code/USEFUL/useful_with_files/count_unique_words_frequency.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | import collections
7 | import sys
8 |
9 | def count_unique_word_freq():
10 | return collections.Counter(\
11 | sys.stdin.read().lower().split()).most_common(n)
12 |
13 |
14 | if __name__ == "__main__":
15 | count_unique_word_freq()
--------------------------------------------------------------------------------
/source_code/USEFUL/useful_with_files/grep_word_from_files.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | __author__ = "bt3"
5 |
6 | import sys
7 |
8 | def grep_word_from_files():
9 | """ using iterator enumerate to create a grep command """
10 | word = sys.argv[1]
11 | for filename in sys.argv[2:]:
12 | with open(filename) as file:
13 | for lino, line in enumerate(file, start=1):
14 | if word in line:
15 | print("{0}:{1}:{2:.40}".format(filename, lino, line.rstrip()))
16 |
17 |
18 | if __name__ == "__main__":
19 | if len(sys.argv) < 2:
20 | print("Usage: grep_word_from_files.py word infile1 [infile2...]")
21 | sys.exit()
22 | else:
23 | grep_word_from_files()
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/source_code/USEFUL/useful_with_files/remove_blank_lines.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | __author__ = "bt3"
5 |
6 |
7 |
8 | import os
9 | import sys
10 |
11 | def read_data(filename):
12 | lines = []
13 | fh = None
14 | try:
15 | fh = open(filename)
16 | for line in fh:
17 | if line.strip():
18 | lines.append(line)
19 | except (IOError, OSError) as err:
20 | print(err)
21 | finally:
22 | if fh is not None:
23 | fh.close()
24 | return lines
25 |
26 |
27 | def write_data(lines, filename):
28 | fh = None
29 | try:
30 | fh = open(filename, "w")
31 | for line in lines:
32 | fh.write(line)
33 | except (EnvironmentError) as err:
34 | print(err)
35 | finally:
36 | if fh is not None:
37 | fh.close()
38 |
39 |
40 | def remove_blank_lines():
41 | """ read a list of filenames on the command line and for each one produces another file with the same content but with no blank lines """
42 |
43 | if len(sys.argv) < 2:
44 | print ("Usage: noblank.py infile1 [infile2...]")
45 |
46 | for filename in sys.argv[1:]:
47 | lines = read_data(filename)
48 | if lines:
49 | write_data(lines, filename)
50 |
51 |
52 | if __name__ == "__main__":
53 | remove_blank_lines()
54 |
55 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/HashTable.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | class HashTable(object):
7 | def __init__(self, slots=10):
8 | self.slots = slots
9 | self.table = []
10 | self.create_table()
11 |
12 | def hash_key(self, value):
13 | return hash(value)%self.slots
14 |
15 | def create_table(self):
16 | for i in range(self.slots):
17 | self.table.append([])
18 |
19 | def add_item(self, value):
20 | key = self.hash_key(value)
21 | self.table[key].append(value)
22 |
23 | def print_table(self):
24 | for key in range(len(self.table)):
25 | print "Key is %s, value is %s." %(key, self.table[key])
26 |
27 | def find_item(self, item):
28 | pos = self.hash_key(item)
29 | if item in self.table[pos]:
30 | return True
31 | else:
32 | return False
33 |
34 | if __name__ == "__main__":
35 | dic = HashTable(5)
36 | for i in range(1, 40, 2):
37 | dic.add_item(i)
38 |
39 | dic.print_table()
40 | assert(dic.find_item(20) == False)
41 | assert(dic.find_item(21) == True)
42 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/Queue.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Time: 5 min
3 |
4 | __author__ = "bt3"
5 |
6 |
7 | class Queue(object):
8 | def __init__(self):
9 | self.enq = []
10 | self.deq = []
11 |
12 | def enqueue(self, item):
13 | return self.enq.append(item)
14 |
15 | def deque(self):
16 | if not self.deq:
17 | while self.enq:
18 | self.deq.append(self.enq.pop())
19 | return self.deq.pop()
20 |
21 | def peak(self):
22 | if not self.deq:
23 | while self.enq:
24 | self.deq.append(self.enq.pop())
25 | if self.deq:
26 | return self.deq[-1]
27 |
28 | def size(self):
29 | return len(self.enq) + len(self.deq)
30 |
31 | def isempty(self):
32 | return not (self.enq + self.deq)
33 |
34 | if __name__ == "__main__":
35 | q = Queue()
36 | for i in range(1,11):
37 | q.enqueue(i)
38 | print 'Size:', q.size()
39 | print 'Is empty?', q.isempty()
40 | print 'Peak: ', q.peak()
41 | print
42 | print 'Dequeuing...'
43 | for i in range(10):
44 | print q.deque()
45 | print 'Size:', q.size()
46 | print 'Is empty?', q.isempty()
47 | print 'Peak: ', q.peak()
--------------------------------------------------------------------------------
/source_code/abstract_structures/__init__.py:
--------------------------------------------------------------------------------
1 | __all__=["hash_tables", "heap", "linked_list", "queues", "stacks"]
--------------------------------------------------------------------------------
/source_code/abstract_structures/heap/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/abstract_structures/heap/__init__.py
--------------------------------------------------------------------------------
/source_code/abstract_structures/heap/merge_sorted_seqs.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import heapq
6 |
7 |
8 | def merge_sorted_seq(seq1, seq2):
9 | """ merge two sorted sequences with little ovehead. the result
10 | will be sorted, which is different of doing just +"""
11 | result = []
12 | for c in heapq.merge(seq1, seq2):
13 | result.append(c)
14 | return result
15 |
16 |
17 | def test_merge_sorted_seq(module_name='this module'):
18 | seq1 = [1, 2, 3, 8, 9, 10]
19 | seq2 = [2, 3, 4, 5, 6, 7, 9]
20 | seq3 = seq1 + seq2
21 | assert(merge_sorted_seqseq1, seq2) == sorted(seq3))
22 |
23 |
24 |
25 | if __name__ == "__main__":
26 | test_merge_sorted_seq()
27 |
28 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/heap/priority_queue.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import heapq
6 |
7 | class PriorityQueue(object):
8 | """ implements a priority queue class """
9 | def __init__(self):
10 | self._queue = []
11 | self._index = 0 # comparying same priority level
12 |
13 | def push(self, item, priority):
14 | heapq.heappush(self._queue, (-priority, self._index, item))
15 | self._index += 1
16 |
17 | def pop(self):
18 | return heapq.heappop(self._queue)[-1]
19 |
20 |
21 | class Item:
22 | def __init__(self, name):
23 | self.name = name
24 | def __repr__(self):
25 | return "Item({!r})".format(self.name)
26 |
27 |
28 | def test_PriorityQueue():
29 | """ push and pop are all O(logN) """
30 | q = PriorityQueue()
31 | q.push(Item('test1'), 1)
32 | q.push(Item('test2'), 4)
33 | q.push(Item('test3'), 3)
34 | assert(str(q.pop()) == "Item('test2')")
35 |
36 |
37 | if __name__ == "__main__":
38 | test_PriorityQueue()
39 |
40 |
41 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/linked_list/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/abstract_structures/linked_list/__init__.py
--------------------------------------------------------------------------------
/source_code/abstract_structures/linked_list/circular_ll.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ implement a function to see whether a linked list is circular.
7 | To implement this, we just need two pointers with different
8 | paces (for example, one goes twice faster)"""
9 |
10 | from linked_list_fifo import LinkedListFIFO
11 | from node import Node
12 |
13 |
14 | class cicularLinkedListFIFO(LinkedListFIFO):
15 | def _add(self, value):
16 | self.length += 1
17 | node = Node(value, self.head)
18 | if self.tail:
19 | self.tail.pointer = node
20 | self.tail = node
21 |
22 |
23 |
24 |
25 | def isCircularll(ll):
26 | p1 = ll.head
27 | p2 = ll.head
28 |
29 | while p2:
30 | try:
31 | p1 = p1.pointer
32 | p2 = p2.pointer.pointer
33 | except:
34 | break
35 |
36 | if p1 == p2:
37 | return True
38 | return False
39 |
40 |
41 |
42 | if __name__ == "__main__":
43 |
44 | ll = LinkedListFIFO()
45 | for i in range(10):
46 | ll.addNode(i)
47 | ll._printList()
48 |
49 | print(isCircularll(ll))
50 |
51 | lcirc = cicularLinkedListFIFO()
52 | for i in range(10):
53 | lcirc.addNode(i)
54 | print(isCircularll(lcirc))
55 |
56 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/linked_list/find_kth_from_the_end.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Find the mth-to-last element of a linked list.
7 | One option is having two pointers, separated by m. P1 start at the roots
8 | (p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m.
9 | When p1 reach the end, p2 is the node. """
10 |
11 | from linked_list_fifo import LinkedListFIFO
12 | from node import Node
13 |
14 |
15 | class LinkedListFIFO_find_kth(LinkedListFIFO):
16 |
17 |
18 | def find_kth_to_last(self, k):
19 | p1, p2 = self.head, self.head
20 | i = 0
21 | while p1:
22 | if i > k:
23 | try:
24 | p2 = p2.pointer
25 | except:
26 | break
27 | p1 = p1.pointer
28 | i += 1
29 | return p2.value
30 |
31 |
32 |
33 | if __name__ == "__main__":
34 | ll = LinkedListFIFO_find_kth()
35 | for i in range(1, 11):
36 | ll.addNode(i)
37 | print('The Linked List:')
38 | print(ll._printList())
39 | k = 3
40 | k_from_last = ll.find_kth_to_last(k)
41 | print("The %dth element to the last of the LL of size %d is %d" %(k, ll.length, k_from_last))
42 |
43 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/linked_list/node.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | class Node(object):
6 | def __init__(self, value=None, pointer=None):
7 | self.value = value
8 | self.pointer = pointer
9 |
10 | def getData(self):
11 | return self.value
12 |
13 | def getNext(self):
14 | return self.pointer
15 |
16 | def setData(self, newdata):
17 | self.value = newdata
18 |
19 | def setNext(self, newpointer):
20 | self.pointer = newpointer
21 |
22 |
23 |
24 | if __name__ == "__main__":
25 | L = Node("a", Node("b", Node("c", Node("d"))))
26 | assert(L.pointer.pointer.value=='c')
27 |
28 | print(L.getData())
29 | print(L.getNext().getData())
30 | L.setData('aa')
31 | L.setNext(Node('e'))
32 | print(L.getData())
33 | print(L.getNext().getData())
34 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/linked_list/part_linked_list.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ This function divides a linked list in a value, where everything smaller than this value
6 | goes to the front, and everything large goes to the back:"""
7 |
8 |
9 | from linked_list_fifo import LinkedListFIFO
10 | from node import Node
11 |
12 |
13 | def partList(ll, n):
14 |
15 | more = LinkedListFIFO()
16 | less = LinkedListFIFO()
17 |
18 | node = ll.head
19 |
20 | while node:
21 | item = node.value
22 |
23 | if item < n:
24 | less.addNode(item)
25 |
26 | elif item > n:
27 | more.addNode(item)
28 |
29 | node = node.pointer
30 |
31 | less.addNode(n)
32 | nodemore = more.head
33 |
34 | while nodemore:
35 | less.addNode(nodemore.value)
36 | nodemore = nodemore.pointer
37 |
38 | return less
39 |
40 |
41 |
42 |
43 | if __name__ == "__main__":
44 |
45 | ll = LinkedListFIFO()
46 | l = [6, 7, 3, 4, 9, 5, 1, 2, 8]
47 | for i in l:
48 | ll.addNode(i)
49 |
50 | print('Before Part')
51 | ll._printList()
52 |
53 | print('After Part')
54 | newll = partList(ll, 6)
55 | newll._printList()
56 |
57 |
58 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/queues/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/abstract_structures/queues/__init__.py
--------------------------------------------------------------------------------
/source_code/abstract_structures/queues/deque.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ a class for a double ended queue (also inefficient) """
6 |
7 | from queue import Queue
8 |
9 | class Deque(Queue):
10 |
11 | def enqueue_back(self, item):
12 | self.items.append(item)
13 |
14 | def dequeue_front(self):
15 | return self.items.pop(0)
16 |
17 |
18 |
19 | if __name__ == "__main__":
20 | queue = Deque()
21 | print("Is the queue empty? ", queue.isEmpty())
22 | print("Adding 0 to 10 in the queue...")
23 | for i in range(10):
24 | queue.enqueue(i)
25 | print("Queue size: ", queue.size())
26 | print("Queue peek : ", queue.peek())
27 | print("Dequeue...", queue.dequeue())
28 | print("Queue peek: ", queue.peek())
29 | print("Is the queue empty? ", queue.isEmpty())
30 | print(queue)
31 |
32 | print("\nNow using the dequeue methods...")
33 | print("Dequeue from front...", queue.dequeue_front())
34 | print("Queue peek: ", queue.peek())
35 | print(queue)
36 | print("Queue from back...")
37 | queue.enqueue_back(50)
38 | print("Queue peek: ", queue.peek())
39 | print(queue)
40 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/queues/palindrome_checker_with_deque.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Using our deque class and Python's deque class """
7 |
8 |
9 | import string
10 | import collections
11 |
12 | from deque import Deque
13 |
14 |
15 | STRIP = string.whitespace + string.punctuation + "\"'"
16 |
17 | def palindrome_checker_with_deque(str1):
18 |
19 | d1 = Deque()
20 | d2 = collections.deque()
21 |
22 | for s in str1.lower():
23 | if s not in STRIP:
24 | d2.append(s)
25 | d1.enqueue(s)
26 |
27 |
28 | eq1 = True
29 | while d1.size() > 1 and eq1:
30 | if d1.dequeue_front() != d1.dequeue():
31 | eq1 = False
32 |
33 | eq2 = True
34 | while len(d2) > 1 and eq2:
35 | if d2.pop() != d2.popleft():
36 | eq2 = False
37 |
38 | return eq1, eq2
39 |
40 |
41 |
42 |
43 | if __name__ == "__main__":
44 | str1 = 'Madam Im Adam'
45 | str2 = 'Buffy is a Slayer'
46 | print(palindrome_checker_with_deque(str1))
47 | print(palindrome_checker_with_deque(str2))
--------------------------------------------------------------------------------
/source_code/abstract_structures/stacks/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/abstract_structures/stacks/__init__.py
--------------------------------------------------------------------------------
/source_code/abstract_structures/stacks/dec2bin_with_stack.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """transform a decimal number to a binary number with a stack """
7 |
8 |
9 | from stack import Stack
10 |
11 | def dec2bin_with_stack(decnum):
12 |
13 | s = Stack()
14 | str_aux = ''
15 |
16 | while decnum > 0:
17 | dig = decnum % 2
18 | decnum = decnum//2
19 | s.push(dig)
20 |
21 | while not s.isEmpty():
22 | str_aux += str(s.pop())
23 |
24 | return str_aux
25 |
26 |
27 |
28 | if __name__ == "__main__":
29 | decnum = 9
30 | assert(dec2bin_with_stack(decnum) == '1001')
31 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/stacks/reverse_string_with_stack.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Uses a stack to reverse a string """
7 |
8 | from stack import Stack
9 |
10 | def reverse_string_with_stack(str1):
11 |
12 | s = Stack()
13 | revStr = ''
14 |
15 | for c in str1:
16 | s.push(c)
17 |
18 | while not s.isEmpty():
19 | revStr += s.pop()
20 |
21 | return revStr
22 |
23 |
24 |
25 | if __name__ == "__main__":
26 | str1 = 'Buffy is a Slayer!'
27 | print(str1)
28 | print(reverse_string_with_stack(str1))
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source_code/abstract_structures/stacks/towers_of_hanoi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | """ Implement the 'towers of hanoi'"""
8 |
9 | from linked_stack import Stack, Node
10 |
11 |
12 | def moveTop(s1, s3):
13 |
14 | s3.append(s1.pop())
15 |
16 |
17 | def moveDisks(n, s1, s3, s2):
18 |
19 | if n < 1: return
20 | moveDisks(n - 1, s1, s2, s3)
21 | moveTop(s1, s3)
22 | moveDisks(n -1, s2, s3, s1)
23 |
24 |
25 |
26 | def towersOfHanoi(n):
27 | s1 = [x+1 for x in range(n)]
28 | s2 = []
29 | s3 = []
30 | print('The first stick is {0} and the third stick has {1}'.format(s1, s3))
31 |
32 | moveDisks(n, s1, s3, s2)
33 |
34 | print('The first stick is {0} and the third stick has {1}'.format(s1, s3))
35 |
36 | return s3
37 |
38 |
39 |
40 | if __name__ == "__main__":
41 | towersOfHanoi(6)
42 |
--------------------------------------------------------------------------------
/source_code/bitwise/bit_array.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Example of how to use a bit array in python as a "counter" dict"""
6 |
7 | def print_dupl_ba(l1):
8 | """
9 | >>> l1 = [0, 1, 2, 3, 4, 2, 6, 7, 8, 9]
10 | >>> print_dupl_ba(l1)
11 | 2
12 | """
13 |
14 | bs = bytearray(10)
15 | for i in range(len(l1)):
16 | if i == l1[i]:
17 | bs[i] = 1
18 | for index, bit in enumerate(bs):
19 | if bit == 0:
20 | return l1[index]
21 | return None
22 |
23 |
24 |
25 | if __name__ == "__main__":
26 | import doctest
27 | doctest.testmod()
28 |
29 |
--------------------------------------------------------------------------------
/source_code/bitwise/bitwise.txt:
--------------------------------------------------------------------------------
1 | BIT-WISE
2 | ----------------------
3 |
4 | 1. To find a number:
5 | 11000101 is 2^0+2^2+2^6+2^7 = 197
6 |
7 |
8 | 2. Left shifting:
9 | 0010 1011 << 4 ---> 1011 000
10 |
11 |
12 | 3. Right shifting:
13 | 0010 1011 >> 4 ---> 0000 0010
14 | or it can be filled with the copy of the first bit, instead of 0:
15 | 1011 0010 >> 4 ---> 1111 1011
16 |
17 |
18 | 4. XOR can cancels out:
19 | 15 ^ 12 ^ 15 = 12
20 |
21 |
22 | 5. 2^x:
23 | left-shift 1 by x:
24 | 0000 0001 << x
25 |
26 | so if x = 2, 2^2 = 4 -> 100
27 |
28 | 0000 0001 << 2 ---> 0000 0100
29 |
30 |
31 | 6. Is power of 2?
32 | just do x&(x-1).
33 | if 0 --> yes!
34 |
--------------------------------------------------------------------------------
/source_code/bitwise/clear_bits.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Clear a bit in a binary number.
6 | Like the reverse of set bit:
7 | 1) first create a number filled of 1s,
8 | with 0 at i (can create 0001000 and ~)
9 | 2) AND the number so it clears the ith bit
10 | """
11 |
12 |
13 |
14 | def clear_bit(num, i):
15 | mask = ~ (1 << i) # -0b10001
16 | return bin(num & mask)
17 |
18 |
19 | def clear_all_bits_from_i_to_0(num, i):
20 | mask = ~ ( (1 << (i+1)) - 1)
21 | return bin(num & mask)
22 |
23 |
24 | def clear_all_bits_from_most_sig_to_1(num, i):
25 | mask = ( 1 << i) -1
26 | return bin(num & mask)
27 |
28 |
29 | if __name__ == "__main__":
30 | num = int('10010000', 2)
31 | print clear_bit(num, 4) # '0b10000000'
32 |
33 | num = int('10010011', 2)
34 | print clear_all_bits_from_i_to_0(num, 2) # '0b10010000'
35 |
36 | num = int('1110011', 2)
37 | print clear_all_bits_from_most_sig_to_1(num, 2) #'0b11'
38 |
--------------------------------------------------------------------------------
/source_code/bitwise/find_bit_len.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Find how many bits a int has:
6 | 1) Start with a mask of 1
7 | 2) Mask with AND
8 | 3) if result (if true): count += 1
9 | (obs: to find the int of a bin do int('1001', 2)) and to show in bin
10 | do bin(int))
11 | """
12 |
13 |
14 | def find_bit_len(int_num):
15 | lenght = 0
16 | while int_num:
17 | int_num >>= 1
18 | lenght += 1
19 | return lenght
20 |
21 |
22 | if __name__ == "__main__":
23 | for i in range(17):
24 | print(find_bit_len(i))
25 | print i.bit_length()
26 |
--------------------------------------------------------------------------------
/source_code/bitwise/find_how_many_1_binary.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Find how many 1s in the binary:
6 | 1) Start with a mask of 1
7 | 2) Mask with AND
8 | 3) if result (if true): count += 1
9 | (obs: to find the int of a bin do int('1001',
10 | 2)) and to show in bin do bin(int))
11 | """
12 |
13 |
14 | def find_how_many_1_in_a_binary(n):
15 | """
16 | >>> find_how_many_1_in_a_binary(9)
17 | 2
18 | """
19 |
20 | counter = 0
21 | while n:
22 | if n & 1:
23 | counter += 1
24 | n >>= 1
25 | return counter
26 |
27 |
28 |
29 | if __name__ == "__main__":
30 | import doctest
31 | doctest.testmod()
32 |
33 |
--------------------------------------------------------------------------------
/source_code/bitwise/get_bit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Get a bit in a binary number:
6 | 1) Shifts 1 over by i bits
7 | 2) make an AND with the number
8 | 3) all the other than the bit at i are clean, now compare to 0
9 | 4) if the new value is not 0, bit i is 1
10 | """
11 |
12 |
13 | def get_bit(num, i):
14 | mask = 1 << i
15 | return num & mask != 0
16 |
17 |
18 | if __name__ == "__main__":
19 | num = int('0100100', 2)
20 | get_bit(num, 0) # 0
21 | get_bit(num, 1) # 0
22 | get_bit(num, 2) # 1
23 | get_bit(num, 3) # 0
24 | get_bit(num, 4) # 0
25 | get_bit(num, 5) # 1
26 | get_bit(num, 6) # 0
27 |
28 |
--------------------------------------------------------------------------------
/source_code/bitwise/get_float_rep_bin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ Given a real number between 0 and 1 (eg: 0.72), this method print the binary
6 | representation. If the Number cannot be represented accurately in binary, with at
7 | most 32 chars, print error:
8 | """
9 |
10 | def get_float_rep(num):
11 | """
12 | >>> get_float_rep(0.72)
13 | ('Error 2', '.1011100001010001111010111000010')
14 | >>> get_float_rep(0.1)
15 | ('Error 2', '.0001100110011001100110011001100')
16 | >>> get_float_rep(0.5)
17 | '.1'
18 | """
19 |
20 | if num >= 1 or num <= 0: return 'Error 1'
21 | result = '.'
22 | while num:
23 | if len(result) >= 32: return 'Error 2', result
24 | r = num*2
25 | if r >= 1:
26 | result += '1'
27 | num = r - 1
28 | else:
29 | result += '0'
30 | num = r
31 | return result
32 |
33 |
34 | if __name__ == "__main__":
35 | import doctest
36 | doctest.testmod()
37 |
38 |
--------------------------------------------------------------------------------
/source_code/bitwise/insert_small_bin_into_big_bin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Given two 32-bit numbers, N and M, and two bit positions, i and j, this
7 | method insert M into N such that M starts at bit j and ends at bit i:
8 | 1) clear the bits j thru i in N'
9 | 2) shift M so that it lines up with bits j thru i
10 | 3) merge M and N
11 | """
12 |
13 | def insert_small_bin_into_big_bin(M, N, i, j):
14 | """
15 | >>> N = 0b10000000000
16 | >>> M = 0b10011
17 | >>> j = 6
18 | >>> i = 2
19 | >>> insert_small_bin_into_big_bin(M, N, i, j)
20 | '0b10001001100'
21 | """
22 |
23 | allOnes = ~0
24 | left = allOnes << (j+1) # 1110000
25 | right = ( (1 << i) - 1) # 0000111
26 | mask = left | right # 1110111
27 | N_cleared = N & mask
28 | M_shifted = M << i
29 |
30 | return bin( N_cleared | M_shifted)
31 |
32 |
33 | if __name__ == "__main__":
34 | import doctest
35 | doctest.testmod()
36 |
37 |
--------------------------------------------------------------------------------
/source_code/bitwise/next_with_same_num_1s.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Give a positive int, print the next smallest and next largest ints with
7 | same number of 1 bits.
8 | The brute force is:
9 | 1) find number of 1 bits
10 | 2) loop above and down until find same, checking for each
11 | """
12 |
13 |
14 |
15 | def print_prev_same_1s(num):
16 | n1s = find_num_1s(num)
17 | # find prev
18 | i = num-1
19 | while True:
20 | n1s_here = find_num_1s(i)
21 | if n1s_here == n1s:
22 | return bin(i)
23 | i -= 1
24 | if i < 0:
25 | return None
26 |
27 | def print_next_same_1s(num):
28 | n1s = find_num_1s(num)
29 | # find next
30 | i = num+1
31 | while True:
32 | n1s_here = find_num_1s(i)
33 | if n1s_here == n1s:
34 | return bin(i)
35 | i += 1
36 | if i < 0:
37 | return None
38 |
39 |
40 |
41 | def find_num_1s(num):
42 | counter = 0
43 | while num:
44 | if num & 1:
45 | counter += 1
46 | num >>= 1
47 | return counter
48 |
49 |
50 |
51 |
52 |
53 | if __name__ == "__main__":
54 | num = 0b1001
55 | n = '0b1010'
56 | p = '0b110'
57 | print_prev_same_1s(num) == p
58 | print_next_same_1s(num) == n
59 |
60 |
--------------------------------------------------------------------------------
/source_code/bitwise/num_bits_to_convert_2_nums.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ This method returns the number of bits that are necessary to change to convert two
7 | numbers A and B:
8 | 1) XOR
9 | 2) count 1s
10 | """
11 |
12 | def count_bits_swap2(a, b):
13 | count = 0
14 | m = a^b
15 | while m:
16 | count +=1
17 | m = m & (m-1)
18 | return count
19 |
20 |
21 |
22 | def count_bits_swap(a, b):
23 | m = a^b
24 | return count_1s(m)
25 |
26 |
27 | def count_1s(m):
28 | count = 0
29 | while m:
30 | if m& 1 :
31 | count +=1
32 | m >>= 1
33 | return count
34 |
35 |
36 | if __name__ == "__main__":
37 | a = int('10010000', 2)
38 | b = int('01011010', 2)
39 | print count_bits_swap(a, b) #4
40 | print count_bits_swap2(a, b) #4
41 |
--------------------------------------------------------------------------------
/source_code/bitwise/set_bit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | """ Set a bit in a binary number:
8 | 1) Shifts 1 over by i bits
9 | 2) make an OR with the number, only the value at bit i will change and all the others bit
10 | of the mask are zero so will not affect the num
11 | """
12 |
13 |
14 | def set_bit(num, i):
15 | mask = 1 << i
16 | return bin( num | mask )
17 |
18 |
19 | if __name__ == "__main__":
20 | num = int('0100100', 2)
21 | print set_bit(num, 0) #'0b100101'
22 | print set_bit(num, 1) #'0b100110'
23 | print set_bit(num, 2) # nothing change '0b100100'
24 | print set_bit(num, 3) #'0b101100'
25 | print set_bit(num, 4) #'0b110100'
26 | print set_bit(num, 5) # nothing change '0b100100'
27 |
--------------------------------------------------------------------------------
/source_code/bitwise/swap_in_place.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """
6 | swapping values in place without extra memory
7 | """
8 |
9 |
10 | def swap_bit(a, b):
11 | """
12 | >>> swap_bit(14, 73)
13 | (73, 14)
14 | """
15 | a = a^b
16 | b = a^b
17 | a = a^b
18 | return a, b
19 |
20 |
21 | if __name__ == "__main__":
22 | import doctest
23 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/bitwise/swap_odd_even.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Swap odd and even bits in a smart way in a binary:
7 | 1) first for odds, take n and move the odd:
8 | (a) Mask all odd bits with 10101010 (0xAA)
9 | (b) shift by right by 1
10 | 2) do the same to ints with 01010101
11 | 3) merge
12 | """
13 |
14 |
15 |
16 | def swap_odd_even(num):
17 | """
18 | >>> num = 0b11011101
19 | >>> result = '0b1101110'
20 | >>> swap_odd_even(num) == result
21 | True
22 | """
23 |
24 | mask_odd = 0xAA # 0b10101010
25 | mask_even = 0x55 # 0b1010101
26 | odd = num & mask_odd
27 | odd >>= 1
28 | even = num & mask_even
29 | even >>= 1
30 | return bin(odd | even)
31 |
32 |
33 |
34 | if __name__ == "__main__":
35 | import doctest
36 | doctest.testmod()
37 |
38 |
--------------------------------------------------------------------------------
/source_code/bitwise/update_bit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ This method merges set bit and clean bit:
6 | 1) first clear the bit at i using a mask such as 1110111
7 | 2) then shift the intended value v by i bits
8 | 3) this will create a number with bit i to v and all other to 0
9 | 4) finally update the ith bit with or
10 | """
11 |
12 |
13 |
14 | def update_bit(num, i, v):
15 | mask = ~ (1 << i)
16 | return bin( (num & mask) | (v << i) )
17 |
18 |
19 | if __name__ == "__main__":
20 | num = int('10010000', 2)
21 | print update_bit(num, 2, 1) # '0b10010100'
22 |
23 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/builtin_structures/__init__.py
--------------------------------------------------------------------------------
/source_code/builtin_structures/anagram.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from collections import Counter
7 |
8 | def is_anagram(s1, s2):
9 | """
10 | >>> is_anagram('cat', 'tac')
11 | True
12 | >>> is_anagram('cat', 'hat')
13 | False
14 | """
15 | counter = Counter()
16 | for c in s1:
17 | counter[c] += 1
18 |
19 | for c in s2:
20 | counter[c] -= 1
21 |
22 | for i in counter.values():
23 | if i:
24 | return False
25 |
26 | return True
27 |
28 | """ verify if words are anagrams by comparing a sum of Unicode code
29 | point of the character"""
30 |
31 | def get_unicode_sum(word):
32 | s = 0
33 | for p in word:
34 | s += ord(p)
35 | return s
36 |
37 |
38 | def is_anagram2(word1, word2):
39 | """
40 | >>> is_anagram2('cat', 'tac')
41 | True
42 | >>> is_anagram2('cat', 'hat')
43 | False
44 | """
45 | return get_unicode_sum(word1) == get_unicode_sum(word2)
46 |
47 |
48 | if __name__ == "__main__":
49 | import doctest
50 | doctest.testmod()
51 |
52 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/balance.txt:
--------------------------------------------------------------------------------
1 | __author__ = "bt3"
2 |
3 |
4 | This is the classic "you have 8 balls/coins, which are the same weight, except for one which is slightly heavier than the others. You also have an old-style balance. What is the fewest number of weighings to find the heavy coin/ball?
5 |
6 | Answer: 2! You need to use every information available:
7 | Weight 3 x 3 balls/coins.
8 | If they weight the same: weight the 2 balls/coins left outside.
9 | Else, measure 2 of the 3 heavier balls/coins.
--------------------------------------------------------------------------------
/source_code/builtin_structures/balance_symbols.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """
6 | Given a N different open and close braces in a string "( { [ } ] )".
7 | How do you check whether the string has matching braces.
8 | """
9 |
10 | from collections import Counter
11 | def check_if_balance(string):
12 | """
13 | >>> check_if_balance('{[[(])}]')
14 | True
15 | >>> check_if_balance('{[[()}]')
16 | False
17 | >>> check_if_balance('')
18 | True
19 | """
20 | table = Counter()
21 | for i in string:
22 |
23 | index = str(ord(i))[0]
24 | if i in '{[(':
25 | table[index] += 1
26 |
27 | elif i in ')}]':
28 | table[index] -= 1
29 |
30 | for i in table.values():
31 | if i !=-0:
32 | return False
33 | return True
34 |
35 |
36 |
37 | if __name__ == "__main__":
38 | import doctest
39 | doctest.testmod()
40 |
41 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/check_if_3_numbers_sum_to_zero.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Determine if an Array of integers contains 3 numbers that sum to 0 """
7 |
8 | from collections import defaultdict
9 |
10 | def find_3_number(array):
11 | """
12 | >>> find_3_number([1,5,56,11,-3,-12])
13 | 1 11 -12
14 | True
15 | >>> find_3_number([] )
16 | False
17 | """
18 | hash_ = defaultdict()
19 | for i in array:
20 | hash_[i] = 1
21 |
22 | for i, x in enumerate(array):
23 | for y in array[i+1:]:
24 | if -(x+y) in hash_:
25 | print x, y, -(x+y)
26 | return True
27 |
28 | return False
29 |
30 |
31 |
32 |
33 | if __name__ == "__main__":
34 | import doctest
35 | doctest.testmod()
36 |
37 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/check_non_overlapping_intervals.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """
7 | given an array of intervals, return max number of non-overlapping intervals
8 | """
9 |
10 | from collections import defaultdict
11 |
12 | def non_overlapping(array):
13 | """
14 | >>> non_overlapping([(1,2), (2,5), (1, 6)])
15 | [[(1, 2), (2, 5)]]
16 | >>> non_overlapping([(1,4), (2,5), (3, 6)])
17 | []
18 | """
19 | total = []
20 |
21 | for i, t in enumerate(array):
22 | start = t[0]
23 | end = t[1]
24 | for tt in array[i+1:] :
25 | if end <= tt[0]:
26 | total.append([(start, end), (tt[0], tt[1])])
27 |
28 | return total
29 |
30 |
31 |
32 | if __name__ == "__main__":
33 | import doctest
34 | doctest.testmod()
35 |
36 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/count_unique_words_On2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | import collections
6 | import string
7 | import sys
8 |
9 |
10 | def count_unique_word():
11 |
12 | words = collections.defaultdict(int)
13 |
14 | strip = string.whitespace + string.punctuation + string.digits + "\"'"
15 |
16 | for filename in sys.argv[1:]:
17 | with open(filename) as file:
18 | for line in file:
19 | for word in line.lower().split():
20 | word = word.strip(strip)
21 | if len(word) > 2:
22 | words[word] = +1
23 |
24 | for word in sorted(words):
25 | print("'{0}' occurs {1} times.".format(word, words[word]))
26 |
27 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/delete_duplicate_char_str.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ find and delete all the duplicate characters in a string """
6 |
7 | from collections import Counter
8 |
9 | def delete_unique(str1):
10 | """
11 | >>> delete_unique("Trust no one")
12 | 'on'
13 | >>> delete_unique("Mulder?")
14 | ''
15 | """
16 |
17 | str_strip = ''.join(str1.split())
18 | repeat = Counter()
19 |
20 | for c in str_strip:
21 | repeat[c] += 1
22 |
23 | result = ''
24 | for c, count in repeat.items():
25 | if count > 1:
26 | result += c
27 |
28 | return result
29 |
30 |
31 | def removing_duplicates_seq(str1):
32 | """
33 | >>> delete_unique("Trust no one")
34 | 'on'
35 | >>> delete_unique("Mulder?")
36 | ''
37 | """
38 | seq = str1.split()
39 | result = set()
40 | for item in seq:
41 | if item not in result:
42 | #yield item
43 | result.add(item)
44 | return result
45 |
46 |
47 | if __name__ == "__main__":
48 | import doctest
49 | doctest.testmod()
50 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/fibonacci.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def fib_generator():
7 | a, b = 0, 1
8 |
9 | while True:
10 | yield b
11 | a, b = b, a+b
12 |
13 |
14 | def fib(n):
15 | """
16 | >>> fib(2)
17 | 1
18 | >>> fib(5)
19 | 5
20 | >>> fib(7)
21 | 13
22 | """
23 | if n < 3:
24 | return 1
25 |
26 | a, b = 0, 1
27 | count = 1
28 |
29 | while count < n:
30 | count += 1
31 | a, b = b, a+b
32 |
33 | return b
34 |
35 |
36 | def fib_rec(n):
37 | """
38 | >>> fib_rec(2)
39 | 1
40 | >>> fib_rec(5)
41 | 5
42 | >>> fib_rec(7)
43 | 13
44 | """
45 | if n < 3:
46 | return 1
47 | return fib_rec(n - 1) + fib_rec(n - 2)
48 |
49 |
50 |
51 |
52 | if __name__ == "__main__":
53 | import doctest
54 | doctest.testmod()
55 |
56 | fib = fib_generator()
57 | print(next(fib))
58 | print(next(fib))
59 | print(next(fib))
60 | print(next(fib))
61 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_0_MxN_replace_cols_rows.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def find_0_MxN(m):
7 | """ find 0s in a matrix and replace the col and row to 0s:
8 | >>> m1 = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
9 | >>> find_0_MxN(m1)
10 | [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
11 | >>> m2 = [[1, 2, 3, 4], [0, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
12 | >>> find_0_MxN(m2)
13 | [[0, 2, 3, 4], [0, 0, 0, 0], [0, 10, 11, 12], [0, 14, 15, 16]]
14 | """
15 | index = []
16 |
17 | for row in range(len(m)):
18 | for col in range(len(m[0])):
19 | if m[row][col] == 0:
20 | index.append((row, col))
21 | for i in index:
22 | row = i[0]
23 | col = i[1]
24 | for i in range(len(m)):
25 | m[row][i] = 0
26 | for i in range(len(m[0])):
27 | m[i][col] = 0
28 |
29 | return m
30 |
31 |
32 | if __name__ == "__main__":
33 | import doctest
34 | doctest.testmod()
35 |
36 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_dice_probabilities.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """
6 | given 2 dice, determine number of ways to sum S if all dice are rolled
7 | """
8 |
9 | from collections import Counter, defaultdict
10 |
11 | def find_dice_probabilities(S=5, n_faces=6):
12 | if S > 2*n_faces or S < 2:
13 | return None
14 |
15 | cdict = Counter()
16 | ddict = defaultdict(list)
17 |
18 | for dice1 in range(1, n_faces+1):
19 | for dice2 in range(1, n_faces+1):
20 | t = [dice1, dice2]
21 | cdict[dice1+dice2] += 1
22 | ddict[dice1+dice2].append( t)
23 |
24 | return [cdict[S], ddict[S]]
25 |
26 |
27 |
28 |
29 |
30 | if __name__ == "__main__":
31 | results = find_dice_probabilities()
32 | assert(results[0] == len(results[1]))
33 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_edit_distance.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ computes the edit distance between two strings """
7 |
8 |
9 | def find_edit_distance(str1, str2):
10 | """
11 | >>> s = 'sunday'
12 | >>> t = 'saturday'
13 | >>> find_edit_distance(s, t)
14 | 3
15 | """
16 |
17 | m = len(str1)
18 | n = len(str2)
19 | diff = lambda c1, c2: 0 if c1 == c2 else 1
20 |
21 | E = [[0] * (n + 1) for i in range(m + 1)]
22 |
23 | for i in range(m + 1):
24 | E[i][0] = i
25 |
26 | for j in range(1, n + 1):
27 | E[0][j] = j
28 |
29 | for i in range(1, m + 1):
30 | for j in range(1, n + 1):
31 | E[i][j] = min(E[i-1][j] + 1, E[i][j-1] + 1, E[i-1][j-1] + diff(str1[i-1], str2[j-1]))
32 |
33 | return E[m][n]
34 |
35 |
36 |
37 | if __name__ == "__main__":
38 | import doctest
39 | doctest.testmod()
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_first_non_repetead_char.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import Counter
6 |
7 | def find_non_rep_char(s1):
8 | """
9 | >>> s1 = 'aabbcceff'
10 | >>> find_non_rep_char(s1)
11 | e
12 | >>> find_non_rep_char('ccc')
13 | """
14 |
15 | aux_dict = Counter()
16 |
17 | for i in s1:
18 | aux_dict[i] += 1
19 |
20 | for k, v in aux_dict.items():
21 | if v < 2:
22 | print k
23 |
24 |
25 |
26 | if __name__ == "__main__":
27 | import doctest
28 | doctest.testmod()
29 |
30 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_gcd.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | def finding_gcd(a, b):
8 | """ implements the greatest common divider algorithm """
9 | while(b != 0):
10 | result = b
11 | a, b = b, a % b
12 | return result
13 |
14 |
15 | def test_finding_gcd():
16 | number1 = 21
17 | number2 = 12
18 | assert(finding_gcd(number1, number2) == 3)
19 | print('Tests passed!')
20 |
21 | if __name__ == "__main__":
22 | test_finding_gcd()
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_if_substr.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def find_substr(s1, s2):
7 |
8 | if len(s1) < len(s2):
9 | bs = s2
10 | ss = s1
11 | else:
12 | bs = s1
13 | ss = s2
14 |
15 | ps = 0
16 |
17 | for c in bs:
18 |
19 | if ss[ps] == c:
20 | ps += 1
21 | else:
22 | ps = 0
23 |
24 | if ps == len(ss)-1:
25 | return True
26 |
27 | return False
28 |
29 |
30 |
31 | if __name__ == "__main__":
32 | s1 = 'buffy is a vampire slayer'
33 | s2 = 'vampire'
34 | s3 = 'angel'
35 | assert(find_substr(s2, s1) == True)
36 | assert(find_substr(s3, s1) == False)
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_if_unique_char.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | import collections
8 |
9 | def find_if_unique_chars(word):
10 | """
11 | >>> find_if_unique_chars('abcde')
12 | True
13 | >>> find_if_unique_chars('abcae')
14 | False
15 | """
16 |
17 | unique = True
18 |
19 | counter = collections.Counter()
20 |
21 | for c in word:
22 | if not counter[c]:
23 | counter[c] += 1
24 | else:
25 | unique = False
26 |
27 | return unique
28 |
29 |
30 | if __name__ == "__main__":
31 | import doctest
32 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_largest_sum.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | """
8 | You are given an array of integers (both positive and negative).
9 | Find the contiguous sequence with the largest sum.
10 | """
11 |
12 |
13 | def find_largest_sum(array):
14 | """
15 | >>> find_largest_sum([-1, 2, -3, 5, 3, 1, -16, 7, 1, -13, 1])
16 | 9
17 | >>> find_largest_sum([])
18 | 0
19 | >>> find_largest_sum([1])
20 | 1
21 | """
22 |
23 | sum_ = 0
24 | sum_here = 0
25 |
26 | for i in array:
27 |
28 | sum_here += i
29 |
30 | if sum_here < 0:
31 | sum_here = 0
32 |
33 | if sum_ < sum_here:
34 | sum_ = sum_here
35 |
36 | return sum_
37 |
38 |
39 |
40 | if __name__ == "__main__":
41 | import doctest
42 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_longest_inc_subseq.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ find the longest continuous increasing subsequence"""
6 |
7 |
8 | def find_long_con_inc(seq):
9 | """
10 | >>> find_long_con_inc([1, -2, 3, 5, 1, -1, 4, -1, 6])
11 | [-2, 3, 5]
12 | >>> find_long_con_inc([1, 3, -2, 3, 5, 6])
13 | [-2, 3, 5, 6]
14 | >>> find_long_con_inc([1, 3, 4, -13, 2, 5, 8, -1, 2,-17])
15 | [-13, 2, 5, 8]
16 | """
17 |
18 | res, aux = [], []
19 | seq.append(-float('infinity'))
20 |
21 | for i, n in enumerate(seq[:-1]):
22 | aux.append(n)
23 | if n > seq[i+1]:
24 | if len(res) < len(aux):
25 | res = aux[:]
26 | aux = []
27 |
28 | return res
29 |
30 |
31 |
32 | if __name__ == "__main__":
33 | import doctest
34 | doctest.testmod()
35 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_longest_str_unique_chars.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """
7 | given a string, find longest string with unique characters
8 | """
9 |
10 | def find_longest(string):
11 | """
12 | >>> find_longest('abfgrhgtrdsandwejfhdasjcbdsjvrejwghireeej')
13 | 'wejfhdas'
14 | >>> find_longest('abcabcabcabcdefabcccc')
15 | 'defabc'
16 | """
17 | maxs = ''
18 | result = ''
19 |
20 | for c in string:
21 | if c in result:
22 | if len(maxs) < len(result):
23 | maxs = result
24 | result = ''
25 | else:
26 | result += c
27 |
28 | if result and len(maxs) < len(result):
29 | maxs = result
30 |
31 | return maxs
32 |
33 |
34 |
35 | if __name__ == "__main__":
36 | import doctest
37 | doctest.testmod()
38 |
39 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_non_repeating_number.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from collections import defaultdict
7 |
8 |
9 | def find_unique_number(array):
10 | """
11 | >>> find_unique_number([1, 3, 6, 1, 5, 6, 9, 3, 7])
12 | [1, 6, 3]
13 | >>> find_unique_number([1, 3, 5, 6, 9, 7])
14 | []
15 | """
16 |
17 | table = defaultdict()
18 | total = []
19 |
20 | for i in array:
21 | if i in table:
22 | total.append(i)
23 | else:
24 | table[i] = 1
25 |
26 | return total
27 |
28 |
29 |
30 |
31 | if __name__ == "__main__":
32 | import doctest
33 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_product_without_division.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """Given an array of numbers, replace each number with the product of all
6 | the numbers in the array except the number itself *without* using division
7 | """
8 |
9 |
10 | def find_product_without_division(seq):
11 | """
12 | >>> seq = [2,3,4]
13 | >>> find_product_without_division(seq)
14 | [12, 8, 6]
15 | """
16 |
17 | forw = []
18 | bacw = []
19 |
20 | for i in range(len(seq)):
21 |
22 | prod_f, prod_b = 1, 1
23 |
24 | for next in range(i+1, len(seq)):
25 | prod_f *= seq[next]
26 |
27 | for before in range(0, i):
28 | prod_b *= seq[before]
29 |
30 | forw.append(prod_f)
31 | bacw.append(prod_b)
32 |
33 | for i in range(len(seq)):
34 | seq[i] = forw[i] * bacw[i]
35 |
36 | return seq
37 |
38 |
39 |
40 | if __name__ == "__main__":
41 | import doctest
42 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/find_top_N_recurring_words.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from collections import Counter
6 |
7 | def find_top_N_recurring_words(seq, N):
8 | """ find the top N recurring words in a file:
9 | 1) use a hash table to find counts
10 | 2) sort the list on base of the maximum counts
11 | 3) return the last N words
12 | """
13 |
14 | dcounter = Counter()
15 | for word in seq.split():
16 | dcounter[word] += 1
17 |
18 | return dcounter.most_common(N)
19 |
20 |
21 |
22 | if __name__ == "__main__":
23 | seq = 'buffy angel monster xander a willow gg buffy the monster super buffy angel'
24 | N = 3
25 | assert(find_top_N_recurring_words(seq, N) == [('buffy', 3), ('monster', 2), ('angel', 2)])
26 |
27 |
28 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/get_float_rep_bin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Given a real number between 0 and 1 (eg: 0.72), this method print the
7 | binary representation. If the Number cannot be represented accurately
8 | in binary, with at exit most 32 chars, print error:
9 | """
10 |
11 | def get_float_rep(num):
12 | if num >= 1 or num <= 0: return 'Error 1'
13 | result = '.'
14 | while num:
15 | if len(result) >= 32: return 'Error 2', result
16 | r = num*2
17 | if r >= 1:
18 | result += '1'
19 | num = r - 1
20 | else:
21 | result += '0'
22 | num = r
23 | return result
24 |
25 |
26 | if __name__ == "__main__":
27 | print get_float_rep(0.72) #('Error 2', '.1011100001010001111010111000010')
28 | print get_float_rep(0.1) # ('Error 2', '.0001100110011001100110011001100')
29 | print get_float_rep(0.5) #'.1'
30 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/max_subarray_stocks.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | def beating_stock(array):
8 |
9 | imin = 0
10 |
11 | # first deal is just buying in the next day (1)
12 | deal = [array[1] - array[imin], imin, 1]
13 |
14 | for i, d in enumerate(array):
15 |
16 | deal_here = d - array[imin]
17 |
18 | if deal_here > deal[0]:
19 | deal = [deal_here, imin, i]
20 |
21 | elif d < array[imin]:
22 | imin = i
23 |
24 | return deal[0], array[deal[1]], array[deal[2]]
25 |
26 |
27 | def beating_stock2(array):
28 |
29 | deal = 0
30 | min_value = array[0]
31 |
32 | for i, d in enumerate(array):
33 |
34 | deal_here = d - min_value
35 |
36 | if deal_here > deal:
37 | deal = deal_here
38 |
39 | else:
40 | if min_value > array[i]:
41 | min_value = array[i]
42 |
43 | return deal
44 |
45 |
46 |
47 | if __name__ == "__main__":
48 | array = [7, 2, 3, 6, 5, 8, 5, 3, 4]
49 |
50 | deal = beating_stock(array)
51 | print("Profit: %d, buying at %d, selling at %d." %(deal[0], deal[1], deal[2]))
52 |
53 | deal = beating_stock2(array)
54 | print "Profit: " + str(deal)
--------------------------------------------------------------------------------
/source_code/builtin_structures/number_of_zeros_factorial.txt:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | How to know how many 0 are in 100!
8 |
9 | You look for the primes that multiply to 10, i.e. 2 and 5.
10 |
11 | There are more 5 than 2s so you can count the fives.
12 |
13 | there is 100/5 = 20, so 20 5s. However, there are two 5s in 25, 50, 75 and 100.
14 |
15 | result: 20+4 = 24
--------------------------------------------------------------------------------
/source_code/builtin_structures/palindrome.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from collections import defaultdict
7 |
8 |
9 | def is_palindrome(array):
10 | """
11 | >>> is_palindrome('subi no onibus')
12 | True
13 | >>> is_palindrome('helllo there')
14 | False
15 | >>> is_palindrome('h')
16 | True
17 | >>> is_palindrome('')
18 | True
19 | """
20 | array = array.strip(" ")
21 | if len(array) < 2:
22 | return True
23 |
24 | if array[0] == array[-1]:
25 | return is_palindrome(array[1:-1])
26 | else:
27 | return False
28 |
29 |
30 | if __name__ == "__main__":
31 | import doctest
32 | doctest.testmod()
33 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/permutations_alphanumeric.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Write code to generate all possible case permutations of a given
7 | lower-cased string
8 | """
9 |
10 | def alpha_permutation(string):
11 | """
12 | >>> alpha_permutation('0ab')
13 | ['0Ab', '0Ab', '0ab', '0ab', '0Ba', '0Ba', '0ba', '0ba', 'ab0', 'a0b', 'a0b', 'b0a', 'b0a', 'ba0']
14 | >>> alpha_permutation('')
15 | ''
16 | """
17 |
18 | if len(string) < 2:
19 | return string
20 |
21 | result = []
22 |
23 | for i, c in enumerate(string):
24 | rest = string[i+1:] + string[:i]
25 | for cc in alpha_permutation(rest):
26 | if cc.isalpha():
27 | result.append(c.upper() + cc)
28 | result.append(c + cc)
29 |
30 | return result
31 |
32 |
33 |
34 | if __name__ == "__main__":
35 | import doctest
36 | doctest.testmod()
37 |
38 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/primes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """
7 | find prime factors of a number.
8 | """
9 |
10 | import math
11 | import random
12 |
13 | def find_prime_factors(n):
14 | """
15 | >>> find_prime_factors(14)
16 | [2, 7]
17 | >>> find_prime_factors(19)
18 | []
19 | """
20 |
21 | divisors = [d for d in range(2, n//2 + 1) if n % d == 0]
22 | primes = [d for d in divisors if is_prime(d)]
23 |
24 | return primes
25 |
26 |
27 | def is_prime(n):
28 | for j in range(2, int(math.sqrt(n))):
29 | if (n % j) == 0:
30 | return False
31 | return True
32 |
33 |
34 | """ return a n-bit prime """
35 | def generate_prime(number=3):
36 | while 1:
37 | p = random.randint(pow(2, number-2), pow(2, number-1)-1)
38 | p = 2 * p + 1
39 | if find_prime_factors(p):
40 | return p
41 |
42 |
43 |
44 | if __name__ == "__main__":
45 | import doctest
46 | doctest.testmod()
47 |
48 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/prod_other_ints.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def get_products_of_all_except_at_index(array):
7 | """
8 | >>> a = [1, 7, 3, 4]
9 | >>> get_products_of_all_except_at_index(a)
10 | [84, 12, 28, 21]
11 | """
12 | total = 1
13 | for n in array:
14 | total *= n
15 |
16 | new_array = []
17 | for n in array:
18 | if n is not 0:
19 | item = total/n
20 | new_array.append(item)
21 | else:
22 | new_array.append(n)
23 |
24 | return new_array
25 |
26 | if __name__ == "__main__":
27 | import doctest
28 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/ransom_note.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | from collections import Counter
8 |
9 | def check_if_ransom_note(magazines, note):
10 | count = Counter()
11 | pm, pn = 0, 0
12 |
13 | while pn < len(note) and pm < len(magazines):
14 | char_note = note[pn]
15 | if count[char_note]>0:
16 | count[char_note] -= 1
17 | pn += 1
18 | else:
19 | char_magazine = magazines[pm]
20 | count[char_magazine] += 1
21 | pm +=1
22 |
23 | return pn == len(note)
24 |
25 |
26 |
27 | if __name__ == "__main__":
28 |
29 | magazines1 = "avfegthhgrebvkdsvnijnvyijfdmckdsmovkmmfvskumvl;cdkmioswckofjbkreenyukjemjgnmkmvkmnvdkmvkr g gmvdvmldm vldfkmbldkmlvdkm"
30 | magazines2 = "adfsfa"
31 | note = "you should disobey"
32 |
33 | print(check_if_ransom_note(magazines1, note))
34 | print(check_if_ransom_note(magazines2, note))
35 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/reverse_string.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def revert(string):
7 | """
8 | >>> s = 'hello'
9 | >>> revert(s)
10 | 'olleh'
11 | >>> revert('')
12 | ''
13 | """
14 | return string[::-1]
15 |
16 |
17 |
18 | def reverse_string_inplace(s):
19 | """
20 | >>> s = 'hello'
21 | >>> reverse_string_inplace(s)
22 | 'olleh'
23 | >>> reverse_string_inplace('')
24 | ''
25 | """
26 | if s:
27 | s = s[-1] + reverse_string_inplace(s[:-1])
28 | return s
29 |
30 |
31 |
32 |
33 |
34 |
35 | if __name__ == "__main__":
36 | import doctest
37 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/builtin_structures/reverse_words.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def reversing_words(word):
7 | """
8 | >>> reversing_words('buffy is awesome')
9 | 'awesome is buffy'
10 | """
11 | new_word = []
12 |
13 | words = word.split(" ")
14 | for word in words[::-1]:
15 | new_word.append(word)
16 |
17 | return " ".join(new_word)
18 |
19 |
20 | def reversing_words2(s):
21 | """
22 | >>> reversing_words2('buffy is awesome')
23 | 'awesome is buffy'
24 | """
25 | words = s.split()
26 | return " ".join(reversed(words))
27 |
28 |
29 | def reversing_words3(s):
30 | """
31 | >>> reversing_words('buffy is awesome')
32 | 'awesome is buffy'
33 | """
34 | words = s.split(" ")
35 | words.reverse()
36 | return " ".join(words)
37 |
38 |
39 | if __name__ == "__main__":
40 | import doctest
41 | doctest.testmod()
42 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/rotate_NxN.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def rotate_NxN(m):
6 | n = len(m)
7 | for layer in range(n//2):
8 | first = layer
9 | last = n - 1 - layer
10 | for i in range(first, last):
11 | offset = i - first
12 | top = m[first][i]
13 | m[first][i] = m[last-offset][first]
14 | m[last-offset][first] = m[last][last-offset]
15 | m[last][last-offset] = m[i][last]
16 | m[i][last] = top
17 | return m
18 |
19 |
20 |
21 | def main():
22 | m = [[1,2],[3,4]]
23 | mr = [[3,1],[4,2]]
24 | assert(rotate_NxN(m) == mr)
25 | m2 = [[1,2,3],[4,5,6],[7,8,9]]
26 | print(rotate_NxN(m2))
27 |
28 | if __name__ == "__main__":
29 | main()
30 |
31 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/search_entry_matrix.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ Search an Entry in a Matrix where the Rows and columns are Sorted
7 | In this 2D matrix, every row is increasingly sorted from left to right,
8 | and every column is increasingly sorted from top to bottom.
9 | The runtime is O(m+n).
10 | """
11 |
12 | def find_elem_matrix_bool(m1, value):
13 |
14 | found = False
15 | row = 0
16 | col = len(m1[0]) - 1
17 |
18 | while row < len(m1) and col >= 0:
19 |
20 | if m1[row][col] == value:
21 | found = True
22 | break
23 | elif m1[row][col] > value:
24 | col-=1
25 | else:
26 | row+=1
27 |
28 | return found
29 |
30 |
31 |
32 | def test_find_elem_matrix_bool(module_name='this module'):
33 | m1 = [[1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]]
34 | assert(find_elem_matrix_bool(m1,8) == True)
35 | assert(find_elem_matrix_bool(m1,3) == False)
36 | m2 = [[0]]
37 | assert(find_elem_matrix_bool(m2,0) == True)
38 |
39 |
40 | if __name__ == "__main__":
41 | test_find_elem_matrix_bool()
42 |
43 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/simple_str_comprension.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from collections import Counter
7 |
8 | def str_comp(s):
9 | """
10 | >>> s1 = 'aabcccccaaa'
11 | >>> str_comp(s1)
12 | 'a2b1c5a3'
13 | >>> str_comp('')
14 | ''
15 | """
16 |
17 | count, last = 1, ''
18 | list_aux = []
19 | for i, c in enumerate(s):
20 | if last == c:
21 | count += 1
22 | else:
23 | if i != 0:
24 | list_aux.append(str(count))
25 | list_aux.append(c)
26 | count = 1
27 | last = c
28 | list_aux.append(str(count))
29 | return ''.join(list_aux)
30 |
31 |
32 | if __name__ == "__main__":
33 | import doctest
34 | doctest.testmod()
35 |
--------------------------------------------------------------------------------
/source_code/builtin_structures/sum_two_numbers_as_strings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """
7 | find the sum of two integers represented as strings,
8 | return the sum as string, i.e "123" and "456" would return "579"
9 | """
10 |
11 |
12 | def get_number(s):
13 | count = 1
14 | num = 0
15 | p = len(s) -1
16 | while p >= 0:
17 | num = num + int(s[p])*count
18 | count *= 10
19 | p -= 1
20 | return num
21 |
22 |
23 | def sum_string(s1, s2):
24 | """
25 | >>> sum_string('10', '5')
26 | '15'
27 | >>> sum_string('0', '1')
28 | '1'
29 | >>> sum_string('123', '456')
30 | '579'
31 | """
32 |
33 | n1 = get_number(s1)
34 | n2 = get_number(s2)
35 | return str(n2 + n1)
36 |
37 |
38 | if __name__ == "__main__":
39 | import doctest
40 | doctest.testmod()
41 |
42 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/searching/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/searching_and_sorting/searching/__init__.py
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/searching/find_max_unimodal_array.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | def find_max_unimodal_array(A):
6 | if len(A) <= 2 :
7 | return None
8 | left = 0
9 | right = len(A)-1
10 |
11 | while right > left +1:
12 |
13 | mid = (left + right)//2
14 | if A[mid] > A[mid-1] and A[mid] > A[mid+1]:
15 | return A[mid]
16 | elif A[mid] > A[mid-1] and A[mid] < A[mid+1]:
17 | left = mid
18 | else:
19 | right = mid
20 |
21 | return None
22 |
23 |
24 | def test_find_max_unimodal_array():
25 | seq = [1, 2, 5, 6, 7, 10, 12, 9, 8, 7, 6]
26 | assert(find_max_unimodal_array(seq) == 12)
27 | print('Tests passed!')
28 |
29 |
30 | if __name__ == "__main__":
31 | test_find_max_unimodal_array()
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/searching/find_sqrt_bin_search.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """ implement square root using binary search """
6 |
7 |
8 | def find_sqrt_bin_search(n, error=0.001):
9 | lower = n < 1 and n or 1
10 | upper = n < 1 and 1 or n
11 | mid = lower + (upper - lower) / 2.0
12 | square = mid * mid
13 | while abs(square - n) > error:
14 | if square < n:
15 | lower = mid
16 | else:
17 | upper = mid
18 | mid = lower + (upper - lower) / 2.0
19 | square = mid * mid
20 | return mid
21 |
22 |
23 | def test_ind_sqrt_bin_search():
24 | number = 9
25 | assert(find_sqrt_bin_search(number) == 3)
26 | print('Tests passed!')
27 |
28 |
29 | if __name__ == "__main__":
30 | test_ind_sqrt_bin_search()
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/searching/ordered_sequential_search.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | def ordered_sequential_search(seq, n):
8 | """ an example of sequential search in an ordered seq:
9 | it improves the performance if the item is not present """
10 | item = 0
11 | for item in seq:
12 | if item > n: return False
13 | if item == n: return True
14 | return False
15 |
16 |
17 | def test_ordered_sequential_search(module_name='this module'):
18 | seq = [1, 2, 4, 5, 6, 8, 10]
19 | n1 = 10
20 | n2 = 7
21 | assert(ordered_sequential_search(seq, n1) == True)
22 | assert(ordered_sequential_search(seq, n2) == False)
23 |
24 | s = 'Tests in {name} have {con}!'
25 | print(s.format(name=module_name, con='passed'))
26 |
27 |
28 | if __name__ == "__main__":
29 | test_ordered_sequential_search()
30 |
31 |
32 | """
33 | Case Best Case Worst Case Average Case
34 | item is present 1 n n/2
35 | item not present 1 n n/2
36 | """
37 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/searching/sequential_search.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def sequential_search(seq, n):
7 | """ an example of sequential search (for items stored in a collection) """
8 | for item in seq:
9 | if item == n: return True
10 | return False
11 |
12 |
13 | def test_sequential_search(module_name='this module'):
14 | seq = [1, 5, 6, 8, 3]
15 | n1 = 5
16 | n2 = 7
17 | assert(sequential_search(seq, n1) == True)
18 | assert(sequential_search(seq, n2) == False)
19 |
20 | s = 'Tests in {name} have {con}!'
21 | print(s.format(name=module_name, con='passed'))
22 |
23 |
24 | if __name__ == "__main__":
25 | test_sequential_search()
26 |
27 |
28 | """
29 | Case Best Case Worst Case Average Case
30 | item is present 1 n n2
31 | item is not present n n n
32 | """
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/1.dat:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/2.dat:
--------------------------------------------------------------------------------
1 | 3
2 | 5
3 | 6
4 | 7
5 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/3.dat:
--------------------------------------------------------------------------------
1 | 1
2 | 3
3 | 5
4 | 8
5 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/searching_and_sorting/sorting/__init__.py
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/bubble_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def bubble_sort(seq):
7 | """
8 | Implementation of bubble sort.
9 | O(n2) and thus highly ineffective.
10 | """
11 | size = len(seq) -1
12 | for num in range(size, 0, -1):
13 | for i in range(num):
14 | if seq[i] > seq[i+1]:
15 | temp = seq[i]
16 | seq[i] = seq[i+1]
17 | seq[i+1] = temp
18 | return seq
19 |
20 |
21 | def test_bubble_sort(module_name='this module'):
22 | seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8]
23 | assert(bubble_sort(seq) == sorted(seq))
24 |
25 |
26 | if __name__ == "__main__":
27 | test_bubble_sort()
28 |
29 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/count_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 | from collections import defaultdict
8 |
9 | def count_sort_dict(a):
10 | """ an example of counting sort using default dictionaries """
11 | b, c = [], defaultdict(list)
12 | for x in a:
13 | c[x].append(x) # we could have used key = lambda x:x
14 | for k in range(min(c), max(c) + 1):
15 | b.extend(c[k])
16 | return b
17 |
18 |
19 | def test_count_sort():
20 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
21 | assert(count_sort_dict(seq) == sorted(seq))
22 |
23 |
24 | if __name__ == "__main__":
25 | test_count_sort()
26 |
27 |
28 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/gnome_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def gnome_sort(seq):
7 | """ sort a sequence using the gnome sort alg """
8 | i = 0
9 | while i < len(seq):
10 | if i ==0 or seq[i-1] <= seq[i]:
11 | i += 1
12 | else:
13 | seq[i], seq[i-1] = seq[i-1], seq[i]
14 | i -= 1
15 | return seq
16 |
17 |
18 | def test_gnome_sort():
19 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
20 | assert(gnome_sort(seq) == sorted(seq))
21 |
22 |
23 | if __name__ == "__main__":
24 | test_gnome_sort()
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/heap.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | class Heap(object):
7 | def __init__(self, data):
8 | self.data = data
9 | for i in range(len(data)/2, -1, -1):
10 | self.__max_heapify__(i)
11 |
12 |
13 | def parent(self, i):
14 | return i >> 1
15 |
16 |
17 | def left_child(self, i):
18 | return (i << 1) + 1
19 |
20 |
21 | def right_child(self, i):
22 | return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed.
23 |
24 |
25 | def __max_heapify__(self, i):
26 | largest = i
27 | left = self.left_child(i)
28 | right = self.right_child(i)
29 | n = len(self.data)
30 | largest = (left < n and self.data[left] > self.data[i]) and left or i
31 | largest = (right < n and self.data[right] > self.data[largest]) and right or largest
32 | if i != largest:
33 | self.data[i], self.data[largest] = self.data[largest], self.data[i]
34 | self.__max_heapify__(largest)
35 |
36 |
37 | def extract_max(self):
38 | n = len(self.data)
39 | max_element = self.data[0]
40 | self.data[0] = self.data[n - 1]
41 | self.data = self.data[:n - 1]
42 | self.__max_heapify__(0)
43 | return max_element
44 |
45 |
46 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/insertion_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 |
7 |
8 | def insertion_sort(seq):
9 | """ sort a sequence using the insertion sort alg """
10 | for i in range(1, len(seq)):
11 | j = i
12 | while j > 0 and seq[j-1] > seq[j]:
13 | seq[j-1], seq[j] = seq[j], seq[j-1]
14 | j -= 1
15 | return seq
16 |
17 |
18 | def insertion_sort_rec(seq, i = None):
19 | """ sort a sequence using the recursive insertion sort alg """
20 | if i == None: i = len(seq) -1
21 | if i == 0: return i
22 | insertion_sort_rec(seq, i-1)
23 | j = i
24 | while j > 0 and seq[j-i] > seq[j]:
25 | seq[j-1], seq[j] = seq[j], seq[j-1]
26 | j -= 1
27 | return seq
28 |
29 |
30 | def test_insertion_sort():
31 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
32 | assert(insertion_sort(seq) == sorted(seq))
33 | assert(insertion_sort_rec(seq) == sorted(seq))
34 |
35 |
36 | if __name__ == "__main__":
37 | test_insertion_sort()
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/merge_and_sort_two_arrays.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | """
6 | You have two arrays with N integers in them. Merge those arrays using a
7 | recursive algorithm so that the integers in the final array are sorted.
8 | """
9 |
10 | def merge_arrays(a1, a2):
11 | """
12 | >>> merge_arrays([5, 4, 3], [6, 2, 9])
13 | [2, 3, 4, 5, 6, 9]
14 | >>> merge_arrays([2, 6], [6, 2])
15 | [2, 2, 6, 6]
16 | >>> merge_arrays([], [])
17 | []
18 | """
19 | # if they are not sorted yet
20 | a1.sort()
21 | a2.sort()
22 |
23 | merge = []
24 | p1, p2 = 0, 0
25 |
26 | while p1 < len(a1) and p2 < len(a2):
27 | if a1[p1] <= a2[p2]:
28 | merge.append(a1[p1])
29 | p1 += 1
30 | else:
31 | merge.append(a2[p2])
32 | p2 +=1
33 |
34 | if a1[p1:]:
35 | merge.extend(a1[p1:])
36 |
37 | if a2[p2:]:
38 | merge.extend(a2[p2:])
39 |
40 | return merge
41 |
42 |
43 | if __name__ == "__main__":
44 | import doctest
45 | doctest.testmod()
46 |
47 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/merge_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def merge_sort(array):
7 | """
8 | >>> merge_sort([3 ,5, 1, 2, 10, 6])
9 | [1, 2, 3, 5, 6, 10]
10 | """
11 | if len(array) < 2:
12 | return array
13 |
14 | mid = len(array)//2
15 | left = merge_sort(array[:mid])
16 | right = merge_sort(array[mid:])
17 |
18 | res = []
19 | i, j = 0, 0
20 | while i < len(left) and j < len(right):
21 | if left[i] <= right[j]:
22 | res.append(left[i])
23 | i += 1
24 | else:
25 | res.append(right[j])
26 | j += 1
27 |
28 | if left[i:]:
29 | res.extend(left[i:])
30 | if right[j:]:
31 | res.extend(right[j:])
32 | return res
33 |
34 |
35 |
36 | """ Merge sort for files """
37 | def merge_files(list_files):
38 | result = []
39 | final = []
40 | for filename in list_files:
41 | aux = []
42 | with open(filename, 'r') as file:
43 | for line in file:
44 | aux.append(int(line))
45 | result.append(aux)
46 | final.extend(result.pop())
47 | for l in result:
48 | final = merge(l, final)
49 | return final
50 |
51 |
52 | if __name__ == "__main__":
53 | import doctest
54 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/quick_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def qs(array):
7 | """
8 | >>> qs([4,1,6,2,7,9,3])
9 | [1, 2, 3, 4, 6, 7, 9]
10 | """
11 | if len(array) < 2:
12 | return array
13 |
14 | piv = len(array)//2
15 | piv_element = array[piv]
16 | new_array = array[:piv] + array[piv+1:]
17 |
18 | left = [a for a in new_array if a <= piv_element]
19 | right = [a for a in new_array if a > piv_element]
20 |
21 | return qs(left) + [array[piv]] + qs(right)
22 |
23 |
24 |
25 | # we can also divide them into two functions
26 | def partition(seq):
27 | pi,seq = seq[0],seq[1:]
28 | lo = [x for x in seq if x <= pi]
29 | hi = [x for x in seq if x > pi]
30 | return lo, pi, hi
31 |
32 | def quick_sort_divided(seq):
33 | """
34 | >>> quick_sort_divided([4,1,6,2,7,9,3])
35 | [1, 2, 3, 4, 6, 7, 9]
36 | """
37 | if len(seq) < 2:
38 | return seq
39 | lo, pi, hi = partition(seq)
40 | return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi)
41 |
42 |
43 |
44 | if __name__ == "__main__":
45 | import doctest
46 | doctest.testmod()
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/selection_sort.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | def selection_sort(seq):
7 | """ sort a sequence using the selection sort alg """
8 | for i in range(len(seq) -1, 0, -1):
9 | max_j = i
10 | for j in range(max_j):
11 | if seq[j] > seq[max_j]:
12 | max_j = j
13 | seq[i], seq[max_j] = seq[max_j], seq[i]
14 | return seq
15 |
16 |
17 | def test_selection_sort():
18 | seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
19 | assert(selection_sort(seq) == sorted(seq))
20 |
21 |
22 | if __name__ == "__main__":
23 | test_selection_sort()
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/source_code/searching_and_sorting/sorting/sort_anagrams_together.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ A method to sort an array so that all the anagrams are together.
7 | Since we only want the anagrams to be grouped, we can use a
8 | dictionary for this task. This algorithm is O(n).
9 | """
10 |
11 | from collections import defaultdict
12 |
13 | def sort_anagrams_together(l1):
14 | """
15 | >>> l1 = ['hat', 'ball', 'tha', 'cut', 'labl', 'hta', 'cool', 'cuy', 'uct']
16 | >>> sort_anagrams_together(l1)
17 | ['cuy', 'cut', 'uct', 'cool', 'ball', 'labl', 'hat', 'tha', 'hta']
18 | """
19 | result = []
20 |
21 | dict_aux = defaultdict(list)
22 | for word in l1:
23 | key = ''.join(sorted(word))
24 | dict_aux[key].append(word)
25 |
26 | for key in dict_aux:
27 | result.extend(dict_aux[key])
28 |
29 | return result
30 |
31 | if __name__ == "__main__":
32 | import doctest
33 | doctest.testmod()
34 |
35 |
--------------------------------------------------------------------------------
/source_code/trees/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AstinCHOI/Python-and-Algorithms-and-Data-Structures/c143f4248734b86f0b1783b6759ba8b9dbebf685/source_code/trees/__init__.py
--------------------------------------------------------------------------------
/source_code/trees/bunchclass.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | class BunchClass(dict):
6 | def __init__(self, *args, **kwds):
7 | super(BunchClass, self).__init__(*args, **kwds)
8 | self.__dict__ = self
9 |
10 |
11 | def main():
12 | """ {'right': {'right': 'Xander', 'left': 'Willow'}, 'left': {'right': 'Angel', 'left': 'Buffy'}}"""
13 | bc = BunchClass # notice the absence of ()
14 | tree = bc(left = bc(left="Buffy", right="Angel"), right = bc(left="Willow", right="Xander"))
15 | print(tree)
16 |
17 | if __name__ == "__main__":
18 | main()
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/source_code/trees/check_if_balanced.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 | from binary_search_tree import BST, Node
6 | from binary_tree import BT, Node
7 |
8 |
9 |
10 | def isBalanced(node, left=0, right=0):
11 | if not node:
12 | return (left - right) < 2
13 |
14 | return isBalanced(node.left, left+1, right) and \
15 | isBalanced(node.right, left, right+1)
16 |
17 |
18 |
19 |
20 | if __name__ == "__main__":
21 | bt = BST()
22 | for i in range(1, 10):
23 | bt.add(i)
24 |
25 | assert(isBalanced(bt.root) == True)
26 |
27 | bt = BT()
28 | for i in range(1, 10):
29 | bt.add(i)
30 |
31 | assert(isBalanced(bt.root) == False)
32 |
--------------------------------------------------------------------------------
/source_code/trees/check_largest_item.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | from binary_search_tree import BST, Node
7 |
8 | def largest(node):
9 |
10 | if node.right:
11 | return largest(node.right)
12 | return node.item
13 |
14 |
15 | if __name__ == "__main__":
16 |
17 |
18 | bst = BST()
19 | l = [10, 5, 6, 3, 8, 2, 1, 11, 9, 4]
20 | for i in l:
21 | bst.add(i)
22 |
23 | print(largest(bst.root))
24 |
--------------------------------------------------------------------------------
/source_code/trees/simple_tree.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | __author__ = "bt3"
4 |
5 |
6 | """ A class for a simple tree """
7 |
8 | class SimpleTree(object):
9 |
10 | def __init__(self, value=None, children = None):
11 | self.value = value
12 | self.children = children
13 | if self.children == None:
14 | self.children = []
15 |
16 | def __repr__(self, level=0):
17 | ret = "\t"*level+repr(self.value)+"\n"
18 | for child in self.children:
19 | ret += child.__repr__(level+1)
20 | return ret
21 |
22 |
23 |
24 | def main():
25 | """
26 | 'a'
27 | 'b'
28 | 'd'
29 | 'e'
30 | 'c'
31 | 'h'
32 | 'g'
33 | """
34 | st = SimpleTree('a', [SimpleTree('b', [SimpleTree('d'), SimpleTree('e')] ), SimpleTree('c', [SimpleTree('h'), SimpleTree('g')]) ])
35 | print(st)
36 |
37 |
38 | if __name__ == "__main__":
39 | main()
40 |
41 |
42 |
--------------------------------------------------------------------------------