 License Public Domain
 Lines 140
PointSort (4)
##### Related PointSort, C++, Priority Queue Project Euler 28 SnortSnort Snort Snort Project Euler 28: Wacky Python Solution
##### Permissions Owner: jsimones Group Owner: SnortSnort Viewable by Everyone Editable by All Siafoo Users

# Stou's I/O and sorting assignment 0

 Language Python
# 's
`  1"""  2Simple I/O "Assignment"  3  4The "assignment":  5  61. Load a file of arbitrary length that is composed of 3 tab-separated columns  7   with floating point numbers representing x, y, z coordinates of points. Lines  8   starting with the pound character (i.e. #) are comments and your program  9   should ignore them. 10 112. Accept file on the command lines: 12   \$ ./a.out some_data.dat 13 143. Use STL sort to sort all data points beyond the first by their distance from 15   the first data point (shortest to longest). 16 174. Output sorted list as x y z distance use only 4 significant figures (output 18   only once we can compare speed and correctness with a script later). 19 205. (bonus) Implement your own sorting method and compare to STL method. 21 226. (bonus) Try some of the Boost libraries 23 247. (bonus) Accept command line arguments to pick algorithm, sort order, data 25   points. Try Boost Program Options 26 27Python suggestions: 28 291. Use the standard sorting routine and define your own comparator function 30 31Oh and I suggest sticking to the standard libraries (STL and Python)... if you 32decide to use stuff from Boost and numpy it would probably be good to implement 33your own too and compare them. 34 35""" 36import sys 37import numpy as np 38 39def set_options(opt_list, func_dict): 40    opt_dict = {} 41 42    if '-xyz' in opt_list: 43        i = opt_list.index('-xyz') 44        xyz = float(opt_list[i+1]), float(opt_list[i+2]), float(opt_list[i+3]) 45        opt_dict['xyz0'] = xyz 46    else: 47        opt_dict['xyz0'] = None 48 49    if '-d' in opt_list: 50        i = opt_list.index('-d') 51        opt_dict['distfunc'] = func_dict[opt_list[i+1]] 52    else: 53        opt_dict['distfunc'] = calc_dist1 54 55    if '-s' in opt_list: 56        i = opt_list.index('-s') 57        opt_dict['sortfunc'] = func_dict[opt_list[i+1]] 58    else: 59        opt_dict['sortfunc'] = dist_sort1 60 61    return opt_dict 62 63def get_coords(file, delim='\t', skip=['#', '\n']): 64    """ 65    Return a list of x,y,z tuples from the coordinates listed in file. Lines 66    starting with # and empty lines are ignored. 67 68    file : file 69        An open file object containing x,y,z data. 70    delim : str 71        String on which split each line of data into x,y,z components. 72    skip : list 73        List of strings. A line will be skipped if it begins with any of these. 74 75    """ 76    xyz = [] 77    for line in file: 78        if any(line.startswith(i) for i in skip): 79            continue 80        xyz.append(tuple(float(i) for i in line.split(delim))) 81    return xyz 82 83def calc_dist1(xyz, xyz0=None): 84    """ 85    Add a distance column to the input coordinate list. 86 87    xyz : list 88        List of x,y,z tuples. 89    xyz0 : list 90        x,y,z location from which to calculated distance to all other points. 91 92    """ 93    if xyz0 is None: 94        x0, y0, z0 = xyz 95    else: 96        x0, y0, z0 = xyz0 97 98    xyzr = [] 99    for x, y, z in xyz:100        r = ((x - x0)**2 + (y - y0)**2 + (z - z0)**2)**0.5101        xyzr.append((x, y, z, r))102103    return xyzr104105def calc_dist2(xyz, xyz0=None):106    """107    numpy version of calc_dist1.108109    """110    xyz = np.array(xyz)111112    if xyz0 is None:113        x0, y0, z0 = xyz114    else:115        x0, y0, z0 = xyz0116117    r = ((xyz[:,0] - x0)**2 + (xyz[:,1] - y0)**2 + (xyz[:,2] - z0)**2)**0.5118    return np.c_[xyz, r]119120def dist_sort1(xyzr):121    """122    Sort points by distance using the built-in sorted function.123124    xyzr : list125        List of x,y,z,r tuples.126127    """128    def keyfunc(xyzr):129        return xyzr[-1]130131    return sorted(xyzr, key=keyfunc)132133def dist_sort2(xyzr):134    """135    Sort using argsort array method, then use fancy indexing to return the136    sorted xyzr array.137138    """139    try:140        idx = xyzr[:,3].argsort()141    except AttributeError:142        xyzr = np.array(xyzr)143        idx = xyzr[:,3].argsort()144    return xyzr[idx]145146def pretty_print(xyzr):147    """148    Print the contents of xyzr, a list of 4-tuples.149150    """151    for x, y, z, r in xyzr:152        print '%.4f\t%.4f\t%.4f\t%.4f' % (x, y, z, r)153154def main():155    """156    Command line options157    --------------------158    -xyz <x> <y> <z> :159        Coordinates of the desired reference point for distance calculations.160    -d <distfunc>:161        Choose which function in func_dict to use when opt_dict['distfunc'] is162        called.163    -s <sortfunc>:164        Choose which function in func_dict to use when opt_dict['sortfunc'] is165        called.166167    """168    filename = sys.argv169    opt_dict = set_options(sys.argv[1:], func_dict)170171    file = open(filename, 'r')172    xyz = get_coords(file)173    file.close()174175    xyzr = opt_dict['distfunc'](xyz, opt_dict['xyz0'])176    xyzr = opt_dict['sortfunc'](xyzr)177    pretty_print(xyzr)178179func_dict = {'calc_dist1': calc_dist1, 'calc_dist2': calc_dist2,180             'dist_sort1': dist_sort1, 'dist_sort2': dist_sort2}181182if __name__ == '__main__':183    main()`