2

I have the following working code for Python I produced. It´s a rewriting system based on Lindenmayer. The Output C is: +-LF+RFR+FL-F-+RF-LFL-FR+F+RF-LFL-FR+-F-LF+RFR+FL-+ which I can interpret to draw a space-filling curve. C is the starting letter and the process is performed n times.

C = 'L'
n = 2
Code = {ord('L'):'+RF-LFL-FR+',
ord('R'):'-LF+RFR+FL-'}

while n:
    C = C.translate(Code)
    n -=1

print C

Now I want, that the code is written automatically from a list. For example I have the list R=[['L', '+RF-LFL-FR+'], ['R', '-LF+RFR+FL-']] which should be automatically inserted in the code, so I can use it furthermore. The first element of every sub-list should be inserted in the ord() method and the second after the colon. Any suggestions?

I found a way via list comprehension. The List R is L=+RF-LFL-FR+, R=-LF+RFR+FL-. Now I ask if theres a more efficient way to get to the code?

R = ['L=+RF-LFL-FR+','R=-LF+RFR+FL-']
A = 'L'

for i in range(0,len(R)):
    R[i]=R[i].split('=')

print R

Start = []
Rule = []

for i in range(0,len(R)):
    Start.append(R[i][0])
    Rule.append(R[i][1])

#mapping via list comprehension
while n:
    A=''.join([Rule[Start.index(i)] if i in Start else i for i in A])
    n -=1

print A
  • Did you test your sample code? It does not execute. How is variable A initialized? – normanius Nov 22 '17 at 23:24
  • And why is the first attempt not feasible for you? You can convert the input list into a dictionary like this (python3): `Code = dict((ord(key), value) for (key, value) in dict(R).items())`, where `R=[['L', '+RF-LFL-FR+'], ['R', '-LF+RFR+FL-']]`. – normanius Nov 22 '17 at 23:43
  • Hey! I forgot to mention, that I have an "outer" input which defines A and R. I'm programming in Grasshopper for Rhino3D, where you can use external inputs. I inserted the two missing variables in the code. – Martin Friedrich Eichenauer Nov 23 '17 at 10:47
  • I'm a really newbie and I have to look up everything I want to programm, so the most obvious things I don't recognize sometimes. I tried your code and it's working perfect for me. Thanks! – Martin Friedrich Eichenauer Nov 23 '17 at 10:53
  • I tested both codes about speed, and the one I found is a bit faster. – Martin Friedrich Eichenauer Nov 23 '17 at 11:07
  • Have a look at my extended answer below. I found that my answer was a bit faster than yours. – normanius Nov 23 '17 at 23:28

1 Answers1

0

Apparently this seems to be working for you. The code runs on python3.

def fun1(n):
    axiom = 'L'
    rules = ['L=+RF-LFL-FR+','R=-LF+RFR+FL-']

    # Convert the rules into a translation table.
    rules = [ r.split('=') for r in rules ]
    table = dict((ord(key), value) for (key, value) in dict(rules).items())

    # Expand
    string = axiom
    for i in range(n):
        string = string.translate(table)
    return string

Edit: I found a second approach that makes use of the built-in map function:

def fun2(n):
    axiom = 'L'
    rules = ['L=+RF-LFL-FR+','R=-LF+RFR+FL-']

    # Convert the rules into a translation table.
    rules = [ r.split('=') for r in rules ]
    table = dict(rules)
    lookup = lambda c: table[c] if c in table else c

    string = axiom
    for i in range(n):
        # Map
        string = map(lookup, string)
        # "Reduce": from list of strings to string
        string = ''.join(string)
    return string

Timing: To check the runtime, I executed the candidates for n=10, which leads to a resulting string with about 3'500'000 characters. Your implementation (without the print ops of course) I named fun3(n). The results I measured using the %timeit command in ipython.

%timeit fun1(n=10)
10 loops, best of 3: 143 ms per loop

%timeit fun2(n=10)
10 loops, best of 3: 195 ms per loop

%timeit fun3(n=10)
10 loops, best of 3: 152 ms per loop

System: Python 3.5.2., MacBook Pro (Retina, 15-inch, Mid 2015), 2.8 GHz Intel Core i7.

Summary: My first suggestion and your implementation perform about equally as fast, with a slight advantage on my version, particularly if it comes to readability. The map approach does not pay off.

I also tried a fourth version where the output array is preallocated, however the code was getting involved and python's memory allocation logic outperformed my preallocation approach clearly by a factor of 2 in runtime. I did not further investigate on this.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
normanius
  • 8,629
  • 7
  • 53
  • 83