Reordering a list in python so that no neighboring elements are equal
As the Python version was not specified, I assume Python 3; for Python 2 you need to adjust the imports from itertools

There are a number of ways you can attack this problem. One way becomes apparent if we think of an input that has no solution, which would be if more than half + 1 (rounded up) of the elements would be equal to each other, e.g. you can find a solution for [1, 1, 1, 2, 2] but not for [1, 1, 1, 1, 2, 2].

The solution would be that you group the elements and sort them by decreasing group length, then interleave first half of the elements with the rest; so, if your list is [3, 2, 2, 1, 3, 1, 1], at first you need to somehow group them, then sort into decreasing order, so that you get for example [1, 1, 1, 3, 3, 2, 2]; then you split it into 2 almost equal parts: [1, 1, 1, 3] and [3, 2, 2], and interleave these into the result: [1, 3, 1, 2, 1, 2, 3].

There are many ways to write this algorithm, here is one, using Python standard library extensively:

from collections import Counter
from itertools import chain, repeat, starmap, zip_longest, islice

def funny_op(l):
    # use Counter to count the number of each distinct element, then
    # most_common() to sort them by decreasing frequency
    counts = Counter(l).most_common()

    # counts is a list of (element, count) pairs; with the example input
    # it could be [(1, 3), (3, 2), (2, 2)]

    # we then make an iterator that iterates over each distinct
    # element, by repeating each `element` `count` times
    sorted_els = chain.from_iterable(starmap(repeat, counts))

    # now, for example input sorted_els would be an iterator yielding 
    # 1, 1, 1, 3, 3, 2, 2

    # we split it into half; we round up so that the first
    # list gets the extra element
    halfway = (len(l) + 1) // 2

    # the elements that go to even indices

    even = list(islice(sorted_els, halfway))

    # and the remaining fill up the odd indices of the result list
    odd = sorted_els

    # then we interleave elements from even and odd. In case the 
    # original list had odd number of elements, there'd be an 
    # extra None, which we remove by islicing only len(l) elements;
    # and return the result as a list

    return list(islice(chain.from_iterable(zip_longest(even, odd)), len(l)))


To test:

print(funny_op([2, 2, 1, 1, 1]))


prints:

[1, 2, 1, 2, 1]