Creating a factoring calculator

@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.

@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.

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.

@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.

@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

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.

@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

@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! (:

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

@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.