#!/usr/bin/env PYTHONHASHSEED=1234 python3 # Copyright 2014-2019 Brett Slatkin, Pearson Education Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Reproduce book environment import random random.seed(1234) import logging from pprint import pprint from sys import stdout as STDOUT # Write all output to a temporary directory import atexit import gc import io import os import tempfile TEST_DIR = tempfile.TemporaryDirectory() atexit.register(TEST_DIR.cleanup) # Make sure Windows processes exit cleanly OLD_CWD = os.getcwd() atexit.register(lambda: os.chdir(OLD_CWD)) os.chdir(TEST_DIR.name) def close_open_files(): everything = gc.get_objects() for obj in everything: if isinstance(obj, io.IOBase): obj.close() atexit.register(close_open_files) # Example 1 data = list(range(10**5)) index = data.index(91234) assert index == 91234 # Example 2 def find_closest(sequence, goal): for index, value in enumerate(sequence): if goal < value: return index raise ValueError(f'{goal} is out of bounds') index = find_closest(data, 91234.56) assert index == 91235 try: find_closest(data, 100000000) except ValueError: pass # Expected else: assert False # Example 3 from bisect import bisect_left index = bisect_left(data, 91234) # Exact match assert index == 91234 index = bisect_left(data, 91234.56) # Closest match assert index == 91235 # Example 4 import random import timeit size = 10**5 iterations = 1000 data = list(range(size)) to_lookup = [random.randint(0, size) for _ in range(iterations)] def run_linear(data, to_lookup): for index in to_lookup: data.index(index) def run_bisect(data, to_lookup): for index in to_lookup: bisect_left(data, index) baseline = timeit.timeit( stmt='run_linear(data, to_lookup)', globals=globals(), number=10) print(f'Linear search takes {baseline:.6f}s') comparison = timeit.timeit( stmt='run_bisect(data, to_lookup)', globals=globals(), number=10) print(f'Bisect search takes {comparison:.6f}s') slowdown = 1 + ((baseline - comparison) / comparison) print(f'{slowdown:.1f}x time')