Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Creating a factoring calculator

Hey Codea,

I'm attempting to code a program that will factor polynomials. Firstly, though, I have created a program that finds the factors of the inputted number. If you know how to factor, this basically will be part of the "x-box" method. This is just the beginning of a big project I have in mind.

-- Factor

function setup()

        parameter.integer("n", 0, 300, 0) 
        parameter.action("Factors", factor)
        print("Factors of "..n.." are: ")
        factorsList = { }
end

function factor()

    i = 1
    while(i <= n) do
        if(n%i==0) then
            print(i)
            table.insert(factorsList, i)
        end
        i = i + 1
    end
    drawFactors = true
end

function draw()

    background(40, 40, 50)
    fill(172, 22, 22, 255)
    rect(WIDTH/4, HEIGHT/4, 500, 400)
    fill(255, 255, 255, 255)
    fontSize(50)
    text(n, WIDTH/2+50, 550)
    for i = 1, #factorsList do
        text(factorsList[i], WIDTH/2-50, HEIGHT/2)
    end
end

I would like to draw the factors in a list format (with commas and such), however, they are overlapping each other. Also, in the print command, I want to have it in pairs. I'm trying to do for i,v in pairs(factorsList) do print(i,v) end but v doesn't have any value. Is there a way to have pairs with a single variable like i? So if the input was 10, the output (print and/or text) should read 1 10, 2 5.

Comments

  • dave1707dave1707 Mod
    edited November 2016 Posts: 7,532

    @Zacharias Here's your code modified a little.

    -- Factor
    
    function setup()
        parameter.integer("n", 0, 300, 0,factor) 
        factorsList = {}
    end
    
    function factor()
        factorsList = {}
        i = 1
        while(i <= n) do
            if(n%i==0) then
                table.insert(factorsList, i)
            end
            i = i + 1
        end
    end
    
    function draw()
        background(40, 40, 50)
        fill(172, 22, 22, 255)
        fontSize(25)
        text(n,WIDTH/2,HEIGHT-30)
        for i = 1, #factorsList do
            text(factorsList[i], WIDTH/2, HEIGHT-30*i-60)
        end
    end
    
  • @dave1707 Thanks a lot! It serves its purpose well. Now I just have to figure how to use this with factoring polynomials. Should be fun :tongue:

  • IgnatzIgnatz Mod
    edited November 2016 Posts: 5,396

    @Zacharias - your loop only needs to run from 2 (1 is always a factor) to the square root of n. That should make it much faster.

    For example, take the number 24. Loop from 2 to 4 (integer of square root of 5).

    2 is a factor, so 12 must be as well (since 24/2=12).

    3 is a factor, so 8 must be too.

    4 is a factor, so 6 must be too

    Factors are 1, 2, 3, 4, 6, 8, 12

    NB if you are going to want to factor primes, there are faster methods.

  • @Zacharias I believe a good way to do is something I learned last year in math class, I don't know if it is the best way or it even works, but search up the Gausse-Jordan method. It deals with matrices and solving and factoring polynomials. That's how I know graphing calculators are able to do that.

  • @Ignatz I see what you mean. When I figure out how to do the rest of the factoring and what not, I'll come back and optimize it.

    @CamelCoder Thanks for the suggestion. It looks complex, and I'd like to use my already obtained knowledge of math for what I'm coding. Feel free to try it out, though.

  • edited November 2016 Posts: 15

    [resolved]

  • edited November 2016 Posts: 15

    [resolved]

  • Posts: 50

    Going back to Ignatz's idea, I'd go from 2 up to the square root on n, which gives you the first half of the factors, and then take that list and work backwards through it, dividing n by each factor, to get the second half of the list. Much, much faster than going all the way up to n if n is large.

  • Alright thanks @Ceres and @Ignatz. I'll try and use those instructions and implement them into the code. Will update code here.
  • So I added pseudo code to clarify parts and added some aesthetic (not much) to the program. I'm confused with changing the loop to 2, math.sqrt(ac) and what to do inside, so I left it for later. Here is what I have:

    -- Factor
    
    function setup()
        --DISPLAY
        displayMode(STANDARD)
        supportedOrientations(LANDSCAPE_ANY)
        --PARAMETERS
        parameter.integer("a", 1, 1, 1)
        parameter.integer("b", 0, 50, 5)
        parameter.integer("c", 0, 50, 6)
        parameter.text("term", "x")
        parameter.action("Factor", factor)
        --LISTS
        factorsList = {}
        drawFactors = {}
        --VARIABLES
        local ac
        local factor1
        local factor2
    end
    
    function factor()
    
        ac = a * c
        factorsList = {} -- list of factors
        drawFactors = {} -- list of factors to draw
    
        --DETERMING FACTORS OF AC AND INPUTTING FACTORS IN A LIST
        i = 1
        while(i <= ac) do
            if(ac%i==0) then
                table.insert(factorsList, i)
                table.insert(drawFactors, i)
            end
            i = i + 1
        end
        --DETERMINING FACTORS FOR FACTORED FORM
        for i=1, #drawFactors do 
            factor1 = tonumber(factorsList[#factorsList])
            factor2 = tonumber(factorsList[#factorsList-(#factorsList-1)])
    
            if((factor1 + factor2 == b) and (factor1 * factor2 == ac)) then
                return
            else
                table.remove(factorsList, #factorsList)
                table.remove(factorsList, #factorsList-(#factorsList-1))
            end
        end
    end
    
    function draw()
        background(40, 40, 50)
    
        for i = 1, #drawFactors do
            --LIST OF FACTORS
            fill(236, 236, 236 , 255)
            fontSize(25)
            text("Factors of "..ac, WIDTH/2-225, HEIGHT/2+350)
            text(drawFactors[i], WIDTH/2-225, HEIGHT-30*i-60)
            --AC AND B IN X, AND POLYNOMIAL/FACTORED FORMS AT BOTTOM
            fill(172, 22, 22, 255)
            fontSize(50)
            text(""..ac.."", WIDTH/2, HEIGHT/2+75) --in the X 
            text(""..b.."", WIDTH/2, HEIGHT/2-75)  -- in the X
            fontSize(35)
            text(""..term.."^2 + "..b..term.." + "..c.."", WIDTH/2, HEIGHT/2-225) -- polynomial
            text("("..term.." + "..factor1..")("..term.." + "..factor2..")", WIDTH/2, HEIGHT/2-300) --factored
            --FACTORS FOR FACTORED FORM OF POLYNOMIAL
            fill(41, 184, 20, 255)
            fontSize(50)
            text(""..factor1.."", WIDTH/2-75, HEIGHT/2) -- in the X
            text(""..factor2.."", WIDTH/2+75, HEIGHT/2) -- in the X
        end
    
        --"POLYNOMIAL:/FACTORED:" AT BOTTOM
        fill(236, 236, 236, 255)
        fontSize(35)
        text("Your polynomial: ", WIDTH/2-225, HEIGHT/2-225)
        text("Factored: ", WIDTH/2-173, HEIGHT/2-300)
        --X LINES IN MIDDLE
        lineCapMode(ROUND)
        smooth()
        strokeWidth(7)
        line(WIDTH/2+100, HEIGHT/2+150, WIDTH/2-100, HEIGHT/2-150)
        line(WIDTH/2-100, HEIGHT/2+150, WIDTH/2+100, HEIGHT/2-150)
    end
    
  • I also need to do complex polynomial so where a > 1. That program can only solve simple polynomials.

  • I was sort of getting a headache from making my game, i really do hate 3D. I thought I would take a break and make my own version of this calculator. I added a UI just because I didn't like the parameters. The UI is sort of bad because I in all spent about an hour on this program, so it will probably have errors. I would like to post the code, but I do not know how to post code on this forum. Can u please tell me what to do so I can post it

  • dave1707dave1707 Mod
    edited November 2016 Posts: 7,532

    @CamelCoder To post code in the forum, just select all of your code then copy it. After that, just paste the code in the forum. Put 3 ~'s on a line before and after your code so it formats correctly.

  • edited November 2016 Posts: 237
    That's what I did, but it said that my body (the post) had too many characters in it
    
  • dave1707dave1707 Mod
    Posts: 7,532

    @CamelCoder If your code is too big then you can post it in github, or split your code into 2 or more posts.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @CamelCoder - but there is little point in posting your code if it is rushed and has errors and doesn't work properly. Why would we want to look at it?

  • dave1707dave1707 Mod
    edited December 2016 Posts: 7,532

    Here's an example that uses the quadratic equation to solve for X. Just change the X2, X1, X0 values and see the results as you change the values. An example is shown when the program is started.

    EDIT: Corrected an error.

    supportedOrientations(PORTRAIT_ANY)
    
    function setup()
        fontSize(30)
        parameter.text("X2",0)
        parameter.text("X1",0)
        parameter.text("X0",0)
        X2=8    -- for example only
        X1=2
        X0=-15
    end
    
    function draw()
        background(0)
        fill(255)       
        X2=tonumber(X2)
        if X2=="" or X2==nil then
            X2=0
        end   
        strA=X2.."x^2"
        X1=tonumber(X1)
        if X1=="" or X1==nil then
            X1=0
        end   
        strB=X1.."x"
        if X1>=0 then
            strB="+"..X1.."x"
        end    
        X0=tonumber(X0)
        if X0=="" or X0==nil then
            X0=0
        end
        strC=X0
        if X0>=0 then
            strC="+"..X0
        end  
        solve()  
        text(strA..strB..strC.." = 0",WIDTH/2,HEIGHT-100)
        text(str1,WIDTH/2,HEIGHT-200)
        text(str2,WIDTH/2,HEIGHT-250)
    end
    
    function solve()
        if X2=="" or X1=="" or X0=="" then
            str1,str2="",""    
        else
            str1="x = "..(-X1+math.sqrt(X1*X1-4*X2*X0))/(2*X2)
            str2="x = "..(-X1-math.sqrt(X1*X1-4*X2*X0))/(2*X2)
        end
    end
    
  • edited December 2016 Posts: 237

    @Ignatz Although it was rushed, I found it to have few errors. I don't know the cause because I didn't look into it that much. It still works great for the most part. [Edit] I fixed the error it had, now I hope you think it is worth looking at.
    Here is the first part:

    --# Main
    -- MyFactorCalc
    displayMode(FULLSCREEN)
    supportedOrientations(ANY)
    function setup()
        vara,varb,varc,var=readLocalData("vara",1),readLocalData("varb",2),readLocalData("varc",1),""
        txt,bpos,cpos,counter="",readLocalData("bpos",true),readLocalData("cpos",true),readLocalData("counter",120)
        arrows={upArrow={},downArrow={}}
        for i=1,6 do table.insert(arrows.upArrow,Arrow{size=vec2(70,35)})
        table.insert(arrows.downArrow,Arrow{size=vec2(70,35),angle=180}) end
        factorButton=TextButton{text=string.upper("Factor"),pos=vec2(WIDTH/2,HEIGHT/8),
        fill=color(255, 0, 186, 255),font="Baskerville-Bold",fontSize=80}
        establishArrowFuncs()
    end
    function draw()
        var=string.char(counter)
        if cpos then varc=math.abs(varc) else varc=-math.abs(varc)end
        if bpos then varb=math.abs(varb) else varb=-math.abs(varb)end
        background(255, 255, 255, 255)
        textMode(CENTER)
        textAlign(CENTER)
        fill(0, 45, 255, 255)
        textWrapWidth(500)
        fontSize(30)
        text("Modify the variables, then click factor to factor the formula.",WIDTH/2,HEIGHT-100)
        fontSize(50)
        font("AmericanTypewriter-Bold")
        fill(0)
        local s=getString(vara,varb,varc,var)
        text(s,WIDTH/2,HEIGHT*3/4)
        textWrapWidth(-1)
        text(txt,WIDTH/2,HEIGHT/4)
        drawSelections()
        for i,v in pairs(arrows) do
            for n,m in ipairs(v) do
                if m.counter and m.counter>1.2 then
                    if math.floor(m.counter*25)%2==0 then m.func(BEGAN) end
                end
            end
        end
        factorButton:draw()
    end
    function factor(a,b,c)
        txt="Factoring..."
        local signb,signc=sign(b),sign(c)
        local mm=math.greatestCommonFactor(a,b)
        local m=math.abs(math.greatestCommonFactor(mm,c))
        a,b,c=a/m,b/m,c/m
        local ac=a*c
        local factors=math.findAllFactors(ac)
        local sol
        for i,v in ipairs(factors) do
            for n,m in ipairs(factors) do
                if i~=n or #factors==1 then
                    if m+v==b and m*v==ac then
                        sol=vec2(m,v)
                    elseif -m+v==b and -m*v==ac then
                        sol=vec2(-m,v)
                    elseif m-v==b and m*-v==ac then
                        sol=vec2(m,-v)
                    elseif -m-v==b and -m*-v==ac then
                        sol=vec2(-m,-v)
                    end
                end
            end
        end
        if sol then
            local function func(a,b,sol,s)
                local gcf=math.greatestCommonFactor
                local aa=gcf(a,sol.x)
                local bb=gcf(b,sol.y)
                local cc=gcf(a,sol.y)
                local dd=gcf(b,sol.x)
                local ab=math.abs(aa)+math.abs(bb)
                local cd=math.abs(cc)+math.abs(dd)
                local soll=vec2(aa,bb)
                if not s or s==1 then
                if ab<cd and sign(cc)~=-1 or sign(aa)==-1 then soll=vec2(cc,dd) end elseif s==2 then
                soll=vec2(cc,dd) end
                return soll:unpack()
            end
            local tt
            ::place::
            local aa,cc=func(a,c,vec2(sol.y,sol.x),tt)
            local f=a/aa
            local ff=sol.x/aa
            if cc*ff~=c and ff==-1 then
                ff=2
            end
            if sign(aa)==-1 then
                aa=-aa
                f=-f
                ff=-ff
            end
            if not (aa*f==a and (cc*f)+(aa*ff)==b and cc*ff==c) then
                tt=2
                goto place
            end
            txt=getFactoredString(aa,cc,f,ff,m)
        else txt="NOT FACTORABLE"
            if m~=1 then
                txt=tostring(m).."("..getString(a,b,c,var)..")"
            end
        end
    end
    
    function drawSelections()
        local tab={
        {txt="a",tag="math.floor(vara)"},{txt="+/-",tag="stringSign(varb)"},
        {txt="b",tag="math.floor(math.abs(varb))"},{txt="+/-",tag="stringSign(varc)"},
        {txt="c",tag="math.floor(math.abs(varc))"},{txt="var.",tag="var"}}
        for i,v in ipairs(tab) do
            pushStyle()
            local a=color(255,0,0)
            if i==2 or i==3 then a=color(0,0,255) 
            elseif i==4 or i==5 then a=color(67, 255, 0, 255) 
            elseif i==6 then a=color(0, 255, 223, 255) end
            fill(0)
            fontSize(30)
            textMode(CENTER)
            local pos=vec2(WIDTH*i/(#tab+1),HEIGHT/2+150)
            text(tostring(v.txt),pos:unpack())
            pos.y=HEIGHT/2-30
            fill(a)
            rectMode(CENTER)
            rect(pos.x,pos.y,100,100)
            fill(255)
            font("Baskerville-SemiBold")
            fontSize(55)
            text(tostring(loadstring("return "..v.tag)()),pos:unpack())
            arrows.upArrow[i].pos.x=pos.x
            arrows.upArrow[i].pos.y=pos.y+90
            arrows.upArrow[i]:draw()
            arrows.downArrow[i].pos.x=pos.x
            arrows.downArrow[i].pos.y=pos.y-90
            arrows.downArrow[i]:draw()
            popStyle()
        end
    end
    
    function establishArrowFuncs()
        local s=ENDED
        arrows.upArrow[1].func=function(a)if a==s then vara=vara+1;saveLocalData("vara",vara) end end
        arrows.downArrow[1].func=function(a)if a==s then vara=math.max(vara-1,1)saveLocalData("vara",vara) end end
        arrows.upArrow[2].func=function(a)if a==s then bpos=not bpos;saveLocalData("bpos",bpos) end end
        arrows.downArrow[2].func=function(a)if a==s then bpos=not bpos;saveLocalData("bpos",bpos) end end
        arrows.upArrow[3].func=function(a)if a==s then varb=math.abs(varb)+1;saveLocalData("varb",varb) end end
        arrows.downArrow[3].func=function(a)if a==s then varb=math.max(math.abs(varb)-1,0)saveLocalData("varb",varb) end end
        arrows.upArrow[4].func=function(a)if a==s then cpos=not cpos;saveLocalData("cpos",cpos) end end
        arrows.downArrow[4].func=function(a)if a==s then cpos=not cpos;saveLocalData("cpos",cpos) end end
        arrows.upArrow[5].func=function(a)if a==s then varc=math.abs(varc)+1;saveLocalData("varc",varc) end end
        arrows.downArrow[5].func=function(a)if a==s then varc=math.max(math.abs(varc)-1,0)saveLocalData("varc",varc) end end
        arrows.downArrow[6].func=function(a)if a==s then
                counter=counter+1
                if counter>122 then counter=97 end
                saveLocalData("counter",counter)
            end
        end
        arrows.upArrow[6].func=function(a)if a==s then
                counter=counter-1
                if counter<97 then counter=122 end
                saveLocalData("counter",counter)
            end
        end
    end
    
    function touched(t)
        for i,v in pairs(arrows) do
            for n,m in ipairs(v) do
                if m:touched(t) then txt="" end
            end
        end
        factorButton:touched(t)
        if factorButton.state==ENDED then
            factor(vara,varb,varc)
        end
    end
    
    function orientationChanged(o)
        if factorButton then factorButton.pos=vec2(WIDTH/2,HEIGHT/8) end
    end
    
  • edited December 2016 Posts: 237

    Here is the second part:

    --# Math
    function math.findAllFactors(n)
        local factors={}
        for i=1,math.abs(n) do
            local a=n/i
            if a==math.floor(a) then
                table.insert(factors,math.floor(i*sign(a)))
                if a==i then
                    table.insert(factors,math.floor(i*sign(a)))
                end
            end
        end
        return factors
    end
    
    function math.greatestCommonFactor(a,b)
        local ans=1
        for i,v in pairs(math.findAllFactors(a)) do
            for n,m in pairs(math.findAllFactors(b)) do
                if v==m or -v==-m then
                    ans=v
                elseif -v==m or v==-m then
                    ans=-v
                end
            end
        end
        return ans
    end
    
    function sign(x)
        if x==x and x~=0 then
            return x/math.abs(x)
        end
        return(0)
    end
    --# String
    function stringSign(a) if a<0 then return "-" end return "+" end
    
    function getString(a,b,c,x)
        local space=string.rep(" ",2)
        local s=""
        local function concatVals(n,pow)
            if n~=0 then
                local a=tostring(math.floor(math.abs(n)))
                local p=""
                local t=stringSign(n)
                if pow>=1 then
                if a=="1" then a="" end
                p=x if pow==2 then p=p.."²"t="" end end
                s=s..t..space..a..p..space
            end
        end
        concatVals(a,2)
        concatVals(b,1)
        concatVals(c,0)
        return s
    end
    
    function getFactoredString(fo,fi,li,lo,m)
        local space=string.rep(" ",2)
        local s=""
        if m~=1 then s=s..tostring(m) end
        if fi~=0 then s=s.."(" end
        if fo~=1 then s=s..tostring(math.floor(fo)) end
        s=s..var
        if fi~=0 then s=s..space..stringSign(fi)..space..tostring(math.floor(math.abs(fi)))..")" end
        if lo~=0 then s=s.."(" end
        if li~=1 then s=s..tostring(math.floor(li)) end
        s=s..var
        if lo~=0 then s=s..space..stringSign(lo)..space..tostring(math.floor(math.abs(lo)))..")" end
        if string.sub(s,1+string.len(m),math.ceil(string.len(s)/2))
            ==string.sub(s,math.ceil(string.len(s)/2)+1,string.len(s)) then
            s=string.sub(s,1,math.ceil(string.len(s)/2)).."²"
        end
        return s
    end
    --# Arrow
    Arrow=class()
    
    function Arrow:init(args)args=args or {}
        self.strokeWidth=args.strokeWidth or 20
        self.stroke=args.stroke or color(0, 0, 0, 255)
        self.ang=args.angle or 0
        self.size=args.size or vec2(200,200)
        self.pos=args.pos or vec2(0,0)
        self.lineCapMode=args.lineCapMode or ROUND
        self.func=args.func or function()end
        self.counter=nil
    end
    
    function Arrow:draw()
        pushMatrix()
        pushStyle()
        translate(self.pos.x,self.pos.y)
        rotate(self.ang)
        lineCapMode(self.lineCapMode)
        strokeWidth(self.strokeWidth)
        stroke(self.stroke)
        for i=-1,1,2 do
            line(self.size.x/2*i,-self.size.y/2,0,self.size.y/2)
        end
        if self.counter then self.counter = self.counter + DeltaTime end
        popStyle()
        popMatrix()
    end
    
    function Arrow:touched(touch)
        local shift=vec2(0,10)
        if touch.x>self.pos.x-self.size.x/2-shift.x and touch.y>self.pos.y-self.size.y/2-shift.y and touch.x<self.pos.x+self.size.x/2+shift.x
            and touch.y<self.pos.y+self.size.y/2+shift.y then
            if touch.state==BEGAN then self.counter=0 elseif touch.state==ENDED then self.counter=nil end
            self.func(touch.state)
            return true
        end
        return false
    end
    --# TextButton
    TextButton=class()
    
    function TextButton:init(args)args=args or {}
        self.font=args.font or nil
        self.fontSize=args.fontSize or 50
        self.fill=args.fill or color(0)
        self.txt=args.text or ""
        self.pos=args.pos or vec2(0,0)
        self.w,self.h=0,0
    end
    
    function TextButton:draw()
        pushStyle()
        textMode(CENTER)
        textAlign(CENTER)
        fill(self.fill)
        if self.font then font(self.font) end
        fontSize(self.fontSize)
        self.w,self.h=textSize(self.txt)
        text(self.txt,self.pos:unpack())
        popStyle()
    end
    
    function TextButton:touched(t)
        if t.x>self.pos.x-self.w/2 and t.x<self.pos.x+self.w/2 and t.y>self.pos.y-self.h/2 and t.y<self.pos.y+self.h/2 then
            self.state=t.state
        else
            self.state=nil
        end
    end
    
  • dave1707dave1707 Mod
    Posts: 7,532

    @CamelCoder Nice job. One question, you don't allow the first variable for x^2 to be negative.

  • @dave1707 Thanks! Ya, I just didn't want to mess up the technique I used. Honestly, what I did was just thought about how I would factor a normal equation, and told the computer to do the same. That's probably why it's not too efficient. If you want, feel free to change it, I think that the leading coefficient shouldn't be negative.

  • dave1707dave1707 Mod
    Posts: 7,532

    @CamelCoder I'm not going to modify your code, but the leading coefficient could be negative as much as it could be positive. If the leading coefficient is negative, then there are 2 sets of answers. They're the same set of numbers, just with the signs flipped. Maybe I'll try writing something similar and see what I come up with. It's always good to see different coding styles.

  • IgnatzIgnatz Mod
    Posts: 5,396

    Assuming you wrote this for fun, I have no criticism, because it's good practice - but if intended for practical use, I would far rather enter a series of numbers such as 43,-345,12,3 and have the program factor them. This allows as many numbers as you like, positive or negative, and if you want to enter 187, you don't have to press an arrow key 187 separate times.

  • dave1707dave1707 Mod
    Posts: 7,532

    @Ignatz I think 99% of the programs written here are for fun or by new coders just trying to learn how to write programs. If it's a program someone wants to make some money from, they may write it in Codea, but they're not going to post it here. Any program written can be improved upon by someone else. Pressing the up or down arrows to change a number could take awhile depending on the number, but it was an interesting idea anyways. Maybe a change could be if you press and hold the up/down arrows, the number starts changing until you lift your finger.

  • edited December 2016 Posts: 237

    @Ignatz I didn't intend on making a UI aside from the parameters, but I just wanted to go a bit further, that's why it is awful. I will modify the code to make it possible to hold the arrow and zoom through the numbers. [Edit] I have added the ability to hold on the arrows to get to the number quicker

  • dave1707dave1707 Mod
    Posts: 7,532

    Here's another version. Tap a box and input the values then tap Solve.

    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
        rectMode(CENTER)
        fontSize(30)
        ans={}
        tab={}
        table.insert(tab,box(400,600,150,50,0,"x^2"))
        table.insert(tab,box(525,600,100,50,0,"x"))
        table.insert(tab,box(625,600,100,50,0,""))
        table.insert(tab,box(WIDTH/2,500,150,50,"","Solve"))
    end
    
    function draw()
        background(0)
        fill(255)
        for a,b in pairs(tab) do
            b:draw()
        end
        if #ans==0 then
            text("No solution found.",WIDTH/2,HEIGHT/2)
        else
            for a,b in pairs(ans) do
                v1=string.format("%d",b.x)
                v2=string.format("%+d",b.y)
                v3=string.format("%d",b.z)
                v4=string.format("%+d",b.w)
                text("("..v1.."x"..v2..") ("..v3.."x"..v4..")",WIDTH/2,HEIGHT/2-a*50+100)
            end
        end
    end
    
    function touched(t)
        for a,b in pairs(tab) do
            b:touched(t)
        end
    end
    
    function keyboard(k)
        for a,b in pairs(tab) do
            b:keyboard(k)
        end    
    end
    
    function solve()
        ans={}
        t1=vals(a)
        t2=vals(c)
        cnt=0
        for a1=1,#t1 do
            for a2=1,#t2 do 
                for b1=1,#t1 do
                    for b2=1,#t2 do
                        aa=t1[a1]*t1[b1]
                        bb=t1[a1]*t2[b2]+t1[b1]*t2[a2]
                        cc=t2[a2]*t2[b2]
                        if aa==a and bb==b and cc==c then
                            cnt=cnt+1
                            if a<0 and cnt<3 or a>0 and cnt<2 then
                                table.insert(ans,vec4(t1[a1],t2[a2],t1[b1],t2[b2]))
                            end
                        end
                    end
                end
            end
        end  
    end
    
    function vals(v)
        local t={}
        for z=1,math.abs(v) do
            if math.abs(v)%z==0 then
                table.insert(t,z)
                if v<0 then
                    table.insert(t,-z)
                end
            end
        end
        return t    
    end
    
    box=class()
    
    function box:init(x,y,w,h,v,s)
        self.x=x
        self.y=y
        self.w=w
        self.h=h
        self.v=v
        self.s=s
        self.sel=false
    end
    
    function box:draw()
        fill(255)
        if self.sel then
            fill(0, 255, 88, 255)
        end
        rect(self.x,self.y,self.w,self.h)
        fill(0, 141, 255, 255)
        str=""
        if string.sub(self.v,1,1)~="-" then
            str="+"
            if self.s=="x^2" or self.s=="Solve" then
                str=""
            end
        end
        text(str..self.v..self.s,self.x,self.y)
    end
    
    function box:touched(t)
        if t.state==BEGAN then
            ans={}
            self.sel=false
            if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
                    t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
                if self.s=="Solve" then
                    a=tonumber(tab[1].v)
                    b=tonumber(tab[2].v)
                    c=tonumber(tab[3].v)
                    hideKeyboard()
                    if a==nil or b==nil or c==nil then
                        return
                    end
                    solve()
                else
                    self.sel=true
                    self.v=""
                    showKeyboard()
                end
            end
        end
    end
    
    function box:keyboard(k)
        if k>="0" and k<="9" or k=="-" or k=="+" or k==BACKSPACE then
            if self.sel then            
                if k==BACKSPACE then
                    self.v=string.sub(self.v,1,#self.v-1)
                end
                self.v=self.v..k
            end
        end
    end
    
  • @dave1707 I'm sorry to say, but every equation I would type in would give me no solution found.

  • dave1707dave1707 Mod
    Posts: 7,532

    @CamelCoder Try 3x^2+13x-10 or 6x^2+11x-10 or -6x^2+19x-15.

  • I'm glad my little post sparked some inspiration. @CamelCoder I enjoyed your UI. I have lots of diff ideas of projects and learning how to do UI like yours seems prudent. Thanks @dave1707 for that program. Some don't work but it's definitely better than mine

  • dave1707dave1707 Mod
    Posts: 7,532

    @Zacharias I didn't post the program to be better than yours, I posted it to show a different style and for others to learn from it. Everyone has a different style of coding and I still learn from others even though I've been coding for what seems like forever. You said some don't work, but not every equation will have factors. Do you have any examples of equations that should work and don't. As for your code sparking interest, yes it did. I'm working on a program that will factor equations such as x^3+x^2+x+#=0 and even higher orders.

  • @dave1707 Oh I know that. I just admire your work. And I just realized right now I wasn't changing a to 1 in your code. Totally my fault (I was checking your code late at night). Great work on the factoring by grouping. The code works! (:
  • dave1707dave1707 Mod
    Posts: 7,532

    Here's a program that will factor third order equations like 1x3-5x2+2x+8 . Just enter 1,-5,2,8 in the parameter text area and press Factor. I included 6 examples to try. If there are more factors then the screen will show, just slide them up. I didn't spend a lot of time making it fancy, so if you want you can do it.

    function setup()
        print("-24,72,-18,-30")
        print("15,109,25,-21")
        print("6,-33,-27,54")
        print("1,-5,2,8")
        print("1,-3,-4,12")
        print("455,675,145,-75")
        dy=0
        sh={}
        tab={}
        delay=0
        fontSize(30)
        p2=string.char(194)..string.char(178)
        p3=string.char(194)..string.char(179)
        parameter.text("nbrs")
        parameter.action("Factor",createTab)
        fill(255)
    end
    
    function factor()
        t1=vals(tab[4])
        t2=vals(tab[1])
        solve()
        yy={}
        for z=1,#n1 do
            tt=order(n1[z],n2[z],n3[z])
            table.insert(yy,toInt(tt[1]).."  "..toInt(tt[2]).."  "..toInt(tt[3]))
        end 
        table.sort(yy)
        h=""
        sh={}
        for z=1,#yy do
            if yy[z]~=h then
                table.insert(sh,yy[z])
                h=yy[z]
            end
        end
    end
    
    function createTab()
        tab={}
        sh={}
        delay=0
        str=""
        for z=1,#nbrs do
            val=string.sub(nbrs,z,z)
            if val=="," then
                table.insert(tab,tonumber(str))
                str=""
            else
                str=str..val 
            end         
        end
        table.insert(tab,tonumber(str))
        nbrs=""
    end
    
    function draw()
        background(0)
        if #tab>0 then
            delay=delay+1
            fill(255)
            s2,s3,s4="","",""
            if tab[2]>=0 then
                s2="+"
            end
            if tab[3]>=0 then
                s3="+"
            end
            if tab[4]>=0 then
                s4="+"
            end
            text(tab[1].."x"..p3..s2..tab[2].."x"..p2..s3..tab[3].."x"..s4..tab[4],
                    WIDTH/2,HEIGHT-50+dy)
            if #sh==0 then
                text("Factoring, please wait...",WIDTH/2,HEIGHT/2)
            end
            for a,b in pairs(sh) do
                text(a.."   "..b,WIDTH/2,HEIGHT-70-a*50+dy)
            end
        else
            text("If factors go off bottom, slide them up.",WIDTH/2,HEIGHT/2)
        end
        if delay==4 then
            showKeyboard()
            hideKeyboard()
            factor()
        end
    end
    
    function order(a,b,c)
        local tab={a}
        if b.x<=a.x then
            table.insert(tab,1,b)
        else
            table.insert(tab,2,b)
        end
        if c.x<=tab[1].x then
            table.insert(tab,1,c)
        elseif c.x<=tab[2].x then
            table.insert(tab,2,c)
        else
            table.insert(tab,3,c)
        end
        return tab
    end
    
    function toInt(a)
        aa=math.tointeger(a.x)
        bb=math.tointeger(a.y)
        bp=""
        if bb>=0 then
            bp="+"
        end
        return("("..aa.."x"..bp..bb..")")
    end
    
    function solve()
        n1,n2,n3={},{},{}
        for a=1,#t2 do
          for b=1,#t1 do
            for c=1,#t2 do
              for d=1,#t1 do
                for e=1,#t2 do
                  for f=1,#t1 do
                    aa=t2[a]*t2[c]*t2[e]
                    bb=t2[e]*t2[a]*t1[d]+t2[e]*t2[c]*t1[b]+t1[f]*t2[a]*t2[c]                            
                    cc=t2[e]*t1[b]*t1[d]+t1[f]*t2[a]*t1[d]+t1[f]*t2[c]*t1[b]                            
                    dd=t1[b]*t1[d]*t1[f]
                    if aa==tab[1] and bb==tab[2] and 
                            cc==tab[3] and dd==tab[4] then
                        table.insert(n1,vec2(t2[a],t1[b]))
                        table.insert(n2,vec2(t2[c],t1[d]))
                        table.insert(n3,vec2(t2[e],t1[f]))
                    end
                  end
                end
              end                
            end
          end
        end
    end
    
    function vals(v)
        local t={}
        for z=1,math.abs(v) do
            if math.abs(v)%z==0 then
                table.insert(t,-z)
                table.insert(t,z)
            end
        end
        return t    
    end
    
    function touched(t)
        if t.state==MOVING then
            dy=dy+t.deltaY
            if dy<0 then
                dy=0
            end
        end
    end
    
  • @dave1707 with your quadratic factoring calculator, you didn't allow for -ve value, so I just (inelegantly) tweaked it:


    --# Main displayMode(FULLSCREEN) supportedOrientations(LANDSCAPE_ANY) function setup() rectMode(CENTER) fontSize(30) ans={} tab={} table.insert(tab,box(400,600,150,50,0,"x^2")) table.insert(tab,box(525,600,100,50,0,"x")) table.insert(tab,box(625,600,100,50,0,"")) table.insert(tab,box(WIDTH/2,500,150,50,"","Solve")) end function draw() background(0) fill(255) for a,b in pairs(tab) do b:draw() end if #ans==0 then text("No solution found.",WIDTH/2,HEIGHT/2) else for a,b in pairs(ans) do v1=string.format("%d",b.x) v2=string.format("%+d",b.y) v3=string.format("%d",b.z) v4=string.format("%+d",b.w) text("("..v1.."x"..v2..") ("..v3.."x"..v4..")",WIDTH/2,HEIGHT/2-a*50+100) end end end function touched(t) for a,b in pairs(tab) do b:touched(t) end end function keyboard(k) for a,b in pairs(tab) do b:keyboard(k) end end function solve() ans={} t1=vals(a) t2=vals(c) cnt=0 for a1=1,#t1 do for a2=-#t1,#t2 do for b1=-#t1,#t1 do for b2=-#t2,#t2 do aa=t1[a1]*t1[b1] bb=t1[a1]*t2[b2]+t1[b1]*t2[a2] cc=t2[a2]*t2[b2] if aa==a and bb==b and cc==c then cnt=cnt+1 if a<0 and cnt<3 or a>0 and cnt<2 then table.insert(ans,vec4(t1[a1],t2[a2],t1[b1],t2[b2])) end end end end end end end function vals(v) local t={} t[0]=0 for z=1,math.abs(v) do if math.abs(v)%z==0 then table.insert(t,z) if v<0 then table.insert(t,-z) end end end for i=1,#t do t[-i]=-t[i] end return t end box=class() function box:init(x,y,w,h,v,s) self.x=x self.y=y self.w=w self.h=h self.v=v self.s=s self.sel=false end function box:draw() fill(255) if self.sel then fill(0, 255, 88, 255) end rect(self.x,self.y,self.w,self.h) fill(0, 141, 255, 255) str="" if string.sub(self.v,1,1)~="-" then str="+" if self.s=="x^2" or self.s=="Solve" then str="" end end text(str..self.v..self.s,self.x,self.y) end function box:touched(t) if t.state==BEGAN then ans={} self.sel=false if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then if self.s=="Solve" then a=tonumber(tab[1].v) b=tonumber(tab[2].v) c=tonumber(tab[3].v) hideKeyboard() if a==nil or b==nil or c==nil then return end solve() else self.sel=true self.v="" showKeyboard() end end end end function box:keyboard(k) if k>="0" and k<="9" or k=="-" or k=="+" or k==BACKSPACE then if self.sel then if k==BACKSPACE then self.v=string.sub(self.v,1,#self.v-1) end self.v=self.v..k end end end
  • dave1707dave1707 Mod
    Posts: 7,532

    @MattthewLXXIII Thanks for the fix. I think I ran into that error when I did the next program for third order equations. The way I fixed it there was in the function vals() where I always created - values instead of checking for v<0 before creating them.

Sign In or Register to comment.