• Coding
  • [Exercise] Shortest Brainfuck print

Take a look at the 'Hello World' Bf program from Wikipedia:
+++++ +++++             initialize counter (cell #0) to 10
[                       use loop to set the next four cells to 70/100/30/10
    > +++++ ++              add  7 to cell #1
    > +++++ +++++           add 10 to cell #2 
    > +++                   add  3 to cell #3
    > +                     add  1 to cell #4
    <<<< -                  decrement counter (cell #0)
]                   
> ++ .                  print 'H'
> + .                   print 'e'
+++++ ++ .              print 'l'
.                       print 'l'
+++ .                   print 'o'
> ++ .                  print ' '
<< +++++ +++++ +++++ .  print 'W'
> .                     print 'o'
+++ .                   print 'r'
----- - .               print 'l'
----- --- .             print 'd'
> + .                   print '!'
> .                     print '\n'
The way it works is simple: the firtst loops sets 4 cells to the values 70/100/30/10.
Then the pointer goes through these cells, modifying their values to reach the desired ASCII value and prints it to the screen with '.'

The exercise consists of writing a program that takes a string as an input and outputs the shortest brainfuck program printing the string to the screen.

Hint: Make sure you understand correctly how the above Hello World program works, so you get a good grasp of the exercise. You'll probably have to set up some initial state (70/100/30/10 seems like a good idea, unless you think of something better). The rest consists of deciding which cell to modify next.
My commented answer. I applied the same reasoning as I did on the Delivery Center exercise. For each letter, I pick the closest cell and modify it. I know it's not an optimal way to do it.

If anyone's interested in joining efforts to improve this problem I'd be super happy :)
import operator

# get this string any way you want and assign it to this variable.
inputstring = "hello world"


def outputbf (state=[0, [70, 100, 30, 10]], letters=inputstring):

    # state[0] is an int representing the position of the pointer.
    # state[1] is an array holding the values of each cell at any given time.

    if not letters: return
    l = ord(letters[0])

    # An array of distances between letter and state[1].
    # I avoid using abs values now to know whether to print '+' or '-'
    cell_distances = [ l - x for x in state[1] ]


    
    # cell_pick[0] is the cell to be updated.
    # cell_pick[1] is the amount to be changed.
    # abs values are introduced now.
    cell_pick = min(enumerate([abs(x) for x in cell_distances]),
                    key=operator.itemgetter(1))


    # print the bf code that moves the pointer to the desired cell.
    mov_nr = cell_pick[0] - state[0]
    for i in xrange(abs(mov_nr)):
        print '>' if mov_nr > 0 else '<'

    # print the bf code that modifies the cell to desired value.
    for i in xrange(abs(cell_pick[1])):
        print '+' if cell_distances[cell_pick[0]] > 0 else '-'

    print '.'


    # update the value of the global_state
    state[0] = cell_pick[0]
    state[1][cell_pick[0]] = l

    return outputbf(state, letters[1:])


def init():
    print '''+++++ +++++             initialize counter (cell #0) to 10
[                       use loop to set the next four cells to 70/100/30/10
    > +++++ ++              add  7 to cell #1
    > +++++ +++++           add 10 to cell #2 
    > +++                   add  3 to cell #3
    > +                     add  1 to cell #4
    <<<< -                  decrement counter (cell #0)
]>'''

if __name__ == '__main__':
    init()
    outputbf()