Swift L-System Algae

329 Views Asked by At

So this is just something I'm doing for fun in the IBM Swift sandbox. I did a L-system algae in Scala recently and though it would be cool to do it in Swift to see how the language compares.

https://github.com/I2obiN/L-System-Algorithms-and-Fractals/blob/master/algae.scala

That's the Scala one to show you what I'm aiming for, and this is what I have in Swift;

/**
  * Created by t.hood on 26/01/16
  * L-System Algae
  *
  */

 import Foundation

 // Mapping function for string

 func stringmap(x: String) -> String {
 var str = x;

     // Replace characters in string
     str = x.stringByReplacingOccurrencesOfString("A", withString: "AB") +
     str.stringByReplacingOccurrencesOfString("B", withString: "A");

  // Return mapped string;
  return str;
 }

 func lsys() {

 // Declarations

 var iteration : Int = 2;
 var x = 0;
 var lsystem: String = "A";
 let charA: Character = "A";
 let charB: Character = "B";

 while(x != iteration) {

 print(lsystem)

  // Iterate through characters in string
  for chars in lsystem.characters {
    lsystem = stringmap(lsystem);
  }

  // Inc count ..
  x+=1

 }
}

 // Run ..
 lsys();

The problem I'm having is in my mapping function. I need it to map x, print the result, then do the next map on str. The problem is I have the operator + between both maps and I can't get swift to print str after the first operation.

Anyone any ideas on how to get around this? If I could print str after the first replacements I think it would work.

1

There are 1 best solutions below

0
On

I created a project in Xcode so I could use the debugger to see what's going on. Here's what I found.

I moved your print statement into the for loop so it would show the value of lsystem every time the loop executed.

The while loop executes twice, when x == 0 and 1 The first time through the while loop lsystem == 'A', so the for loop executes once. In stringmap(), the 'A' becomes 'ABA'. 'ABA' is printed. The second time through the while loop, the for loop gets executed three times. For loop 1: 'ABA' is sent to stringmap() and 'ABBABAAA' is returned. For loop 2: 'ABBABAAA' is sent to stringmap() and 'ABBBABBABABABAAAAAAAA' is returned. For loop 3: 'ABBBABBABABABAAAAAAAA' is sent to stringmap() and 'ABBBBABBBABBABBABBABABABABABABABABAAAAAAAAAAAAAAAAAAAAA' is returned.

I modified your stringmap() function to iterate through the string character by character and apply the grammar to each character, appending each change to a new string that was then returned to lsys().

Seven iterations of the while loop returned this, which agrees with what I see in the Wikipedia article about L-system. Iteration 0: A Iteration 1: AB Iteration 2: ABA Iteration 3: ABAAB Iteration 4: ABAABABA Iteration 5: ABAABABAABAAB Iteration 6: ABAABABAABAABABAABABA Iteration 7: ABAABABAABAABABAABABAABAABABAABAAB

Here's the code. This worked in a playground on my iMac, I'd expect it to work in the IBM Swift sandbox too.

func stringmap(x: String) -> String
{
    var returnString = ""

    for char in x.characters
    {
        switch (char)
        {
        case "A" :
            returnString += "AB"
            break
        case "B":
            returnString += "A"
            break
        default:
            break
        }
    }
    return returnString
}


func lsys()
{

    // Declarations

    let iteration : Int = 7;
    var x = 0;
    var lsystem: String = "A";

    print("Iteration \(x): \(lsystem)")

    while(x != iteration)
    {
        lsystem = stringmap(lsystem)
        x++
        print("Iteration \(x): \(lsystem)")

    }
}

lsys()