Code Sketch


Visualizing Prime Factorization
By: Lalit Pant [2]
Category: Math
def isPrime(n: Int): Boolean = {
    if (n == 1) return false
    
    for (i <- 2 to n/2) {
        if (n %i == 0) {
            return false
        }
    }
    return true
}

def twoFactors(n: Int): (Int, Int) = {
    for (i <- 2 to n/2) {
        if (n % i == 0) {
            return (i, n / i)
        }
    }
    throw new IllegalStateException("Problemo - twoFactors()!")
}

var Siz = 40.0
val FontSize = 20

def rect(w: Double, h: Double) {
    forward(h); right()
    forward(w); right()
    forward(h); right()
    forward(w); right()
}

def square(n: Double) {
    rect(n, n)
}

def showNumberHelper(n: Int)(borderMaker: => Unit) {
    borderMaker
    
    val ts = textExtent(n.toString, FontSize)
    
    penUp()
    forward(ts.height + (Siz - ts.height)/2)
    right()
    forward((Siz - ts.width)/2)
    penDown()
    
    saveStyle()
    setPenColor(blue)
    write(n.toString)
    restoreStyle()

    penUp()
    back((Siz - ts.width)/2)
    left()
    back(ts.height + (Siz - ts.height)/2)
    penDown()
}

def showNumberInBox(n: Int) {
    showNumberHelper(n) {
        square(Siz)
    } 
}

def showNumberInL(n: Int) {
    showNumberHelper(n) {
        forward(Siz)
        back(Siz)
        right()
        forward(Siz)
        back(Siz)
        left()
    } 
}

def showNumber(n: Int) {
    showNumberHelper(n) {}
}

def showFactorTree(f: (Int, Int)) {
    val (f1, f2) = (f._1, f._2)
    
    // left leg
    left(135)
    forward(Siz)
    
    // goto box starting position
    penUp()
    forward(math.sqrt(Siz * Siz * 2))
    right(135)
    penDown()

    // make tree for the first factor
    factorTree(f1)
    
    // back to starting point
    penUp()
    right(45)
    forward(math.sqrt(Siz * Siz * 2) + Siz)
    left(45)
    penDown()

    // right leg
    right(135)
    forward(Siz)

    // goto box starting position
    penUp()
    right(45)
    forward(Siz)
    right(180)
    penDown()

    // make tree for the second factor
    factorTree(f2)

    // go back to the starting point
    // this is not strictly necessary for this command because
    // (a) the factorTree call above is the last thing that this 
    // command does, and
    // (b) the ealier factorTree call does not recurse (because 
    // f1 is always a prime)
    // be we go back to the starting point anyway - in keeping
    // with the convention that a command leaves the turtle 
    // where it picked it up from
    penUp()
    forward(Siz)
    left(45)
    forward(Siz)
    right(45)
    penDown()
}

def showFactorStairs(f: (Int, Int)) {
    val (f1, f2) = (f._1, f._2)
    
    penUp()
    left()
    forward(Siz)
    right()
    penDown()
    
    showNumber(f1)
    
    penUp()
    right()
    forward(Siz)
    left()

    right(180)
    forward(Siz)
    left(180)

    penDown()

    cdiv(f2)
}

def factorTree(n: Int) {
    if (isPrime(n)) {
        showNumberInBox(n)
    }
    else {
        showNumberInBox(n)
        showFactorTree(twoFactors(n))
    }
}

def cdiv(n: Int) {
    if (isPrime(n)) {
        showNumberInL(n)
    }
    else {
        showNumberInL(n)
        showFactorStairs(twoFactors(n))
    }
}

def title(s: String) {
    val ts = textExtent(s, FontSize)
    penUp()
    forward(100)
    left()
    forward(ts.width/2)
    penDown()
    
    saveStyle()
    setPenColor(blue)
    setPenThickness(4)
    write(s)
    restoreStyle()
    
    penUp()
    back(ts.width/2)
    right()
    back(100)
    penDown()
}


val pageStyle = "color:white;background:#016491;margin:15px;"
val headerStyle = "text-align:center;font-size:110%;color:yellow;"

def pgHeader(hdr: String) =
    <p style={headerStyle}>
        {xml.Unparsed(hdr)}
        <hr/>
    </p>


val pg = Page(
    name = "",
    body = 
        <body style={pageStyle}>
            {pgHeader("Visualizing Factors and Factorization")}
            <p>
                Wanna see how you can factorize any number and come
                up with its prime factorization?
            </p>
            
            <p>
                Enter a number below and click <em>Factorize</em>
            </p>
            
        </body>,
    code = {
        clear()
        clearOutput()
        stAddField("Number", 12)
        stAddButton ("Factorize") {
            val n = stFieldValue("Number", 12)
            val ts = textExtent(n.toString, FontSize)
            Siz = if (ts.width > Siz) ts.width + 10 else Siz
            clear()
// invisible()
            setAnimationDelay(100)
            setPenFontSize(FontSize)

            penUp()
            forward(100)
            left()
            forward(Siz * 4)
            right()
            penDown()
            
            title("Factor Tree Method")
            factorTree(n)

            penUp()
            right()
            forward(Siz * 8)
            left()
            penDown()

            title("Continuous Division Method")
            cdiv(n)
            
        }
    }
)

val story = Story(pg)
stClear()
stPlayStory(story)