def build_final_pic_array(final_order, slice_map):
    '''
    Takes final_order array, which lists the slices in the order they should be combined (identifying
    each by its key number) and builds the final slice_map according. Passes that final slice array to 
    show_image to get the picture
    '''

    start = final_order[0]
    for n in final_order:
    if(n != start):
slice_map[start] += slice_map[n]

imageutils.show_image(slice_map[start])


def stitch_list(sub_list, start, end, final_order_list):

    '''
    Recursive function that takes the list of tuples which shows the slice pairings that ought 
    to be glued and turns all those pair tuples into one continuous list, from leftmost slice to 
    rightmost. Basically, any tuple (key1, key2) would be added to the end of a tuple (keyX, key1)
    and to the front of a tuple (key2, keyY). 

    Uses recursion to stitch the tuples together like this. Returns the final stitched list.
    '''
    start_is_key2 = [key for key in final_order_list if key[1] == start]
    end_is_key1 = [key for key in final_order_list if key[0] == end]

    if(start_is_key2 == [] and end_is_key1 == []):
    return sub_list

    new_sub_list = []
    if(start_is_key2 != []):
    new_start_tup = start_is_key2[0]
new_start = new_start_tup[0]
new_sub_list.append(new_start)
else:ether(master_repository, slice_map)




if __name__ == '__main__':

    slice_map = get_all_images()

    slice_similarity_control(slice_map)
					first_index = first_slice_index
					second_index = second_slice_index
					if left_overlap_score <= right_overlap_score:
						best_overlap_score = left_overlap_score
						first_on_left = True
					else:
						best_overlap_score = right_overlap_score
						first_on_left = False

		if first_on_left:
			slices[first_index] += slices[second_index]
			slices.pop(second_index)
		else:
			slices[second_index] += slices[first_index]
			slices.pop(first_index)
	return slices[0]

if __name__ == '__main__':
	"""
	Constructs and opens the image formed by the slices in DATA_LOCATION.
	"""
	DATA_LOCATION = 'shredded/destination'
	slices = []
	for file in imageutils.files_in_directory(DATA_LOCATION):
		image_slice = imageutils.load_image(file)
		slices.append(image_slice)
	final_image = reconstruct_slices(slices)
	imageutils.show_image(final_image)


	images = [] #the holder for image data
	for file in [doc for doc in os.listdir(PATH_NAME)]: #importing all images into images
		images.append(iu.load_image(PATH_NAME + file))

	""" Named tuple that contains score information, orientation, and an image """
	Score = collections.namedtuple('Score', ['score','onleft', 'image'])

	###the below could have been modularized a bit more and be decomposed into different functions###

	""" Iterates until there is only one image left and merges most similar images """
	while (len(images) > 1):
		for image in images:
			images.remove(image)
			bestScore = Score(-1, True, None) #True for image on left
			for otherimage in images:
				if otherimage == None:
					break
				currminscore = findCurrScore(image, otherimage)

				if (bestScore.score == -1 or currminscore.score < bestScore.score): 
					bestScore = currminscore

			images.remove(bestScore.image)
			newimage = merge(image, bestScore.image, bestScore.onleft)
			images.append(newimage)

	for image in images:
		iu.show_image(image)
	print(len(images))

                    if first_overlap_score <= second_overlap_score:
                        best_overlap_score = first_overlap_score
                        first_slice_on_left = True
                    else:
                        best_overlap_score = second_overlap_score
                        first_slice_on_left = False
                first_slice_index = first_slice_index
        if first_slice_on_left:
            slices[first_index] += slices[second_index]
            slices.pop(second_index)
        else:
            slices[second_index] += slices[first_index]
            slices.pop(first_index)

    return slices[0]
    
"""
TA Grading Comment:
Yeesh. A little messy. I get it was the last one and you wanted to knock it out.
"""

if __name__ == '__main__':
    DATA_FILES = 'shredded/destination'

    slices = list()
    for f in imageutils.files_in_directory(DATA_FILES):
        piece = imageutils.load_image(f)
        slices.append(piece)

    imageutils.show_image(reconstruct_slices(slices))
		# loop through the matrix and find the smallest entry
		min_dist_entry = (-1, -1)
		min_dist = INFINITY
		for i in range(INITIAL_SLICE_COUNT):
			for j in range(INITIAL_SLICE_COUNT):
				dist = distances[i][j]
				if dist < min_dist:
					min_dist = dist
					min_dist_entry = (i, j)
		
		# Now stitch the slices together:
		print("Stitching slices {0} and {1} together (in that order, from left to right)".format(min_dist_entry[0], min_dist_entry[1]))
		new_cluster = cluster[min_dist_entry[0]] + cluster[min_dist_entry[1]]
		cluster[min_dist_entry[0]] = new_cluster
		cluster[min_dist_entry[1]] = new_cluster
		final_stitchings.append(tuple([min_dist_entry[0], min_dist_entry[1]]))
		stitched_image = stitch_images(all_image_slices[min_dist_entry[0]], all_image_slices[min_dist_entry[1]])
		for index in new_cluster:
			all_image_slices[index] = stitched_image

		if stitching == INITIAL_SLICE_COUNT - 2:
			imageutils.show_image(stitched_image)
			break

		# Now update the distance matrix:
		for x in range(INITIAL_SLICE_COUNT):
			distances[x][min_dist_entry[1]] = INFINITY
			distances[min_dist_entry[0]][x] = INFINITY
		distances[min_dist_entry[0]][min_dist_entry[1]] = INFINITY
		distances[min_dist_entry[1]][min_dist_entry[0]] = INFINITY
# Both args are imageutils pixels. Returns a float.
def pixDiff(pix1, pix2):
  return sqrt(sum([abs(com[0]-com[1]) for com in zip(pix1, pix2)]))
  
# Computes the sum of the differences amonst all the pixels in the
# rightmost edge of lhs and leftmost edge of rhs. Both args are 
# tuples of imageutils pixels. Returns a float.
@lru_cache(maxsize=None)
def colDiff(lhs, rhs):
  return sum([pixDiff(pixs[0], pixs[1]) for pixs in zip(lhs, rhs)])

if __name__ == '__main__':
  strips = [list(map(tuple, imageutils.load_image(file))) for file in imageutils.files_in_directory(dir)]
  """
  TA Grading Comment:
  file is a keyword watch out
  
  True = False
  """
  while len(strips) > 1:
    besti, bestj, bestDiff = 0, 0, -1
    for i in range(len(strips)):
      for j in range(len(strips)):
        if i == j: continue
        diff = colDiff(strips[i][-1], strips[j][0])
        if bestDiff == -1 or diff < bestDiff:
          bestDiff, besti, bestj = diff, i, j
    strips[besti] += strips[bestj]
    strips.pop(bestj)
  imageutils.show_image(strips[0])
use any 3rd party libraries (outside of Pillow, which we've provided
through the imageutils module)

Best of luck! Now go find that Holy Grail.
"""
import imageutils
import itertools


if __name__ == '__main__':
    images = []
    for filename in imageutils.files_in_directory('shredded/grail4'):
        images.append(imageutils.load_image(filename))
    imageutils.show_all_images(images)
    reassembled_image = reassemble(images)
    imageutils.show_image(reassembled_image)

'''
***** alternatively, for pixel_similarity1 you can use the fact that pixels are tuples:

return sum([(component[0] - component[1])**2 for component in zip(p1, p2)])

'''
def pixel_similarity1(pixel1, pixel2):
    return (pixel1.red - pixel2.red)**2 + (pixel1.green - pixel2.greem)**2 + (pixel1.blue - pixel2.blue)**2 + (pixel1.alpha - pixel2.alpha)**2

'''
***** nice list comprehension and use of sum/zip functions
'''
def column_similarity(c1, c2):
    return sum([pixel_similarity1(p1, p2) for p1, p2 in zip(c1, c2)])
            best_score = sim
            best_pair = (pair[0], pair[1])
    return best_pair


def stitch(imgs):
    """
    FUNCTION: stitch

    Stitches together all the shreds specified in imgs by searching for the
    pairs with highest similarity and iteratively reassembling the image.

    @params: imgs: dict mapping a unique key to a 2D array representing an
    image slice.
    @return: reassembled image represented via 2D array.
    """
    while len(imgs) > 1:
        pair = get_best_pair(imgs)
        stitched = imgs[pair[0]] + imgs[pair[1]]  # Combine the pair of slices.
        del imgs[pair[0]]  # Delete the slices we just used ...
        del imgs[pair[1]]
        # ...and create a unique key & store the new slice
        imgs["({})-({})".format(*pair)] = stitched
    return imgs.popitem()[1]

if __name__ == '__main__':
    # Associate each 2D array with a unique key
    imgs = {i: imageutils.load_image(filename) for i, filename in enumerate(
        imageutils.files_in_directory("./shredded/grail20"))}
    imageutils.show_image(stitch(imgs))
		highestOne.append(column)


def mergeClosestSlices(slices):
	"""
	Gets the two closest slices and merges them together
	"""
	lowestSimilarity = 9999999999999
	for left in slices:
		for right in slices:
			if left != right:
				currSim = sliceSimilarity(left, right)
				if currSim < lowestSimilarity:
					lowestSimilarity = currSim
					leftHigh = left
					rightHigh = right
	mergeSlices(leftHigh, rightHigh)
	slices.remove(rightHigh)


if __name__ == '__main__':
	slices = []
	for image in imageutils.files_in_directory("shredded/destination"):
		slices.append(imageutils.load_image(image))
	while len(slices) > 1:
		mergeClosestSlices(slices)
	imageutils.show_image(slices[0])


		
    while(num_slices > 1):
        highest = 442.0
        for i_ind, i in enumerate(slices):
            for j_ind, j in enumerate(slices):
                if i != j:
                    sim = slice_similarity(i, j)
                    if sim < highest:
                        highest = sim 
                        highest_ind[0] = i_ind
                        highest_ind[1] = j_ind
        slices[highest_ind[0]] = slices[highest_ind[0]] + slices[highest_ind[1]]
        slices.remove(slices[highest_ind[1]])
        num_slices -= 1
    return slices[0]

if __name__ == '__main__':
    """
    Opens directory of image slices and translates into list pixel arrays, 
    then stiches together original image and opens it
    """
    file_names = imageutils.files_in_directory('shredded/destination')

    slices = []
    for file in file_names:
        pixels = imageutils.load_image(file)
        slices.append(pixels)
    imageutils.show_image(stitch(slices))


#great functional programming on this one!
            simLeft  = compare(piece, elem)
            simRight = compare(elem, piece)

            if simLeft < colLeft:
                left = elem
                colLeft = simLeft

            if simRight < colRight:
                right = elem
                colRight = simRight

        if colLeft < colRight:
            newSlice = combine(left, piece)
            imageutils.save_image(newSlice, left)

        else:
            newSlice = combine(piece, right)
            imageutils.save_image(newSlice, right)

        imageutils.save_image(newSlice, 'shredded\\test\\' + str(100 - len(slices)) + '.png')

    return slices[0]

if __name__ == '__main__':
    slices = []
    for filename in imageutils.files_in_directory(DATA_LOCATION):
        slices += [filename]

    picture = buildPicture(slices)
    imageutils.show_image(imageutils.load_image(picture))