From 61ba85f4b0fcca1872843f90f1b45f2cfa08ad5b Mon Sep 17 00:00:00 2001 From: lukew3 Date: Fri, 16 Oct 2020 20:53:33 -0400 Subject: [PATCH 1/7] makeReadme.py added and generators with newloine chars fixed --- README.md | 69 +++++++++++++++++++++++++++++----------- makeReadme.py | 25 +++++++++++++++ mathgenerator/mathgen.py | 65 +++++++++++++++++++++++++------------ 3 files changed, 121 insertions(+), 38 deletions(-) create mode 100644 makeReadme.py diff --git a/README.md b/README.md index 45ffcec..dfc7d41 100644 --- a/README.md +++ b/README.md @@ -30,21 +30,54 @@ problem, solution = mathgen.genById(0) | Id | Skill | Example problem | Example Solution | Function Name | |------|-----------------------------------|--------------------|-----------------------|--------------------------| -| 0 | Addition | 1+5= | 6 | addition | -| 1 | Subtraction | 9-4= | 5 | subtraction | -| 2 | Multiplication | 4*6= | 24 | multiplication | -| 3 | Division | 4/3= | 1.33333333 | division | -| 4 | Binary Complement 1s | 1010= | 0101 | binaryComplement1s | -| 5 | Modulo Division | 10%3= | 1 | moduloDivision | -| 6 | Square Root | sqrt(25)= | 5 | squareRootFunction | -| 7 | Power Rule Differentiation | 4x^3 | 12x^2 | powerRuleDifferentiation | -| 8 | Square | 4^2 | 16 | square | -| 9 | LCM (Least Common Multiple) | LCM of 14 and 9 = | 126 | lcm | -| 10 | GCD (Greatest Common Denominator) | GCD of 18 and 18 = | 18 | gcd | -| 11 | Basic Algebra | 9x + 7 = 10 | 1/3 | basicAlgebra | -| 12 | Logarithm | log3(3) | 1 | log | -| 13 | Easy Division | 270/15 = | 18 | intDivision | -| 14 | Decimal to Binary | Binary of a= | b | decimalToBinary | -| 15 | Binary to Decimal | Decimal of a= | b | binaryToDecimal | -| 16 | Fraction Division | (a/b)/(c/d)= | x/y | fractionDivision | -| 17 | Int 2x2 Matrix Multiplication | k * [[a,b],[c,d]]= | [[k*a,k*b],[k*c,k*d]] | intMatrix22Multiplication| +| 0 | Addition | 29+33= | 62 | addition | +| 1 | Subtraction | 62-7= | 55 | subtraction | +| 2 | Multiplication | 93*1= | 93 | multiplication | +| 3 | Division | 59/47= | 1.2553191489361701 | division | +| 4 | Binary Complement 1s | 001110000 | 110001111 | binaryComplement1s | +| 5 | Modulo Division | 89%34= | 21 | moduloDivision | +| 6 | Square Root | sqrt(16)= | 4 | squareRoot | +| 7 | Power Rule Differentiation | 4x^3 | 12x^2 | powerRuleDifferentiation | +| 8 | Square | 12^2= | 144 | square | +| 9 | LCM (Least Common Multiple) | LCM of 10 and 1 = | 10 | lcm | +| 10 | GCD (Greatest Common Denominator) | GCD of 12 and 5 = | 1 | gcd | +| 11 | Basic Algebra | 8x + 7 = 10 | 3/8 | basicAlgebra | +| 12 | Logarithm | log3(729) | 6 | log | +| 13 | Easy Division | 378/21 = | 18 | intDivision | +| 14 | Decimal to Binary | Binary of 4= | 100 | decimalToBinary | +| 15 | Binary to Decimal | 10011 | 19 | binaryToDecimal | +| 16 | Fraction Division | (1/2)/(4/3) | 3/8 | fractionDivision | +| 17 | Integer Multiplication with 2x2 Matrix | 2 * [[0, 7], [7, 7]] = | [[0,14],[14,14]] | intMatrix22Multiplication | +| 18 | Area of Triangle | Area of triangle with side lengths: 9 14 15 = | 61.644140029689765 | areaOfTriangle | +| 19 | Triangle exists check | Does triangle with sides 33, 6 and 43 exist? | No | doesTriangleExist | +| 20 | Midpoint of the two point | (-15,-10),(-5,2)= | (-10.0,-4.0) | midPointOfTwoPoint | +| 21 | Factoring Quadratic | x^2-17x+72 | (x-9)(x-8) | factoring | +| 22 | Third Angle of Triangle | Third angle of triangle with angles 4 and 31 = | 145 | thirdAngleOfTriangle | +| 23 | Solve a System of Equations in R^2 | 4x - 8y = 48, 3x - 8y = 40 | x = 8, y = -2 | systemOfEquations | +| 24 | Distance between 2 points | Find the distance between (-9, -20) and (18, -19) | sqrt(730) | distance2Point | +| 25 | Pythagorean Theorem | The hypotenuse of a right triangle given the other two lengths 18 and 13 = | 22.20 | pythagoreanTheorem | +| 26 | Linear Equations | -11x + -16y = -302 +1x + 20y = 250 | x = 10, y = 12 | linearEquations | +| 27 | Prime Factorisation | Find prime factors of 55 | [5, 11] | primeFactors | +| 28 | Fraction Multiplication | (4/9)*(8/10) | 16/45 | fractionMultiplication | +| 29 | Angle of a Regular Polygon | Find the angle of a regular polygon with 15 sides | 156.0 | angleRegularPolygon | +| 30 | Combinations of Objects | Number of combinations from 13 objects picked 1 at a time | 13 | combinations | +| 31 | Factorial | 2! = | 2 | factorial | +| 32 | Surface Area of Cube | Surface area of cube with side = 13m is | 1014 m^2 | surfaceAreaCubeGen | +| 33 | Surface Area of Cuboid | Surface area of cuboid with sides = 5m, 3m, 7m is | 142 m^2 | surfaceAreaCuboidGen | +| 34 | Surface Area of Cylinder | Surface area of cylinder with height = 15m and radius = 7m is | 967 m^2 | surfaceAreaCylinderGen | +| 35 | Volum of Cube | Volume of cube with side = 11m is | 1331 m^3 | volumeCubeGen | +| 36 | Volume of Cuboid | Volume of cuboid with sides = 6m, 1m, 10m is | 60 m^3 | volumeCuboidGen | +| 37 | Volume of cylinder | Volume of cylinder with height = 26m and radius = 15m is | 18378 m^3 | volumeCylinderGen | +| 38 | Surface Area of cone | Surface area of cone with height = 46m and radius = 14m is | 2730 m^2 | surfaceAreaConeGen | +| 39 | Volume of cone | Volume of cone with height = 7m and radius = 11m is | 886 m^3 | volumeConeGen | +| 40 | Common Factors | Common Factors of 91 and 51 = | [1] | commonFactors | +| 41 | Intersection of Two Lines | Find the point of intersection of the two lines: y = 6/4x + 5 and y = -7/2x + 3 | (-2/5, 22/5) | intersectionOfTwoLines | +| 42 | Permutations | Number of Permutations from 13 objects picked 4 at a time = | 17160 | permutations | +| 43 | Cross Product of 2 Vectors | [-14, 13, 20] X [-5, -18, 19] = | [607, 166, 317] | vectorCross | +| 44 | Compare Fractions | Which symbol represents the comparison between 8/3 and 6/7? | > | compareFractions | +| 45 | Simple Interest | Simple interest for a principle amount of 6128 dollars, 5% rate of interest and for a time period of 5 years is = | 1532.0 | simpleInterest | +| 46 | Multiplication of two matrices | Multiply [[-20, -14, -88, -62, 39, 94, 21, 75, 26], [89, -67, -80, -60, 32, -23, -79, 11, -69], [13, -75, -66, 3, 67, -79, -49, 6, 36], [-44, -84, 68, -27, -86, -95, -71, -77, -62], [45, 58, 89, 82, 30, -83, -23, 51, 95], [11, 46, 100, -15, 60, -34, 85, 50, -44], [93, -100, -62, 63, -73, -64, 90, -15, 23], [-8, 91, -22, 53, -42, 25, 32, -26, 31], [-60, 90, 75, -42, 19, 33, -30, 74, 13]] and [[-80, 54, -39, 37, -99], [31, -28, -31, 64, 73], [-21, -34, -28, -21, -76], [-94, 55, 66, 0, 17], [-28, 25, -65, -74, 100], [76, 74, -96, -98, -5], [-90, -70, -66, -71, -35], [65, 49, -100, 72, -23], [-95, -97, -31, -84, -86]] | [[15409, 6508, -21665, -10161, 5326], [9859, 17962, 3267, 12768, 3119], [-8761, 1272, 8611, 738, 3881], [4489, -5790, 29652, 11947, -5940], [-22167, -8208, -1142, 6747, -10714], [-4628, -5167, -15527, 1404, 243], [-29240, -2432, 11103, 615, -22487], [-5498, -5038, 1462, -100, 2495], [18214, -3238, -15548, 3691, 6061]] | matrixMultiplication | +| 47 | Cube Root | cuberoot of 711 upto 2 decimal places is: | 8.93 | CubeRoot | +| 48 | Power Rule Integration | 3x^1 | (3/1)x^2 + c | powerRuleIntegration | +| 49 | Fourth Angle of Quadrilateral | Fourth angle of quadrilateral with angles 94 , 101, 102 = | 63 | fourthAngleOfQuadrilateral | diff --git a/makeReadme.py b/makeReadme.py new file mode 100644 index 0000000..7ca8f2c --- /dev/null +++ b/makeReadme.py @@ -0,0 +1,25 @@ +#To use, paste at bottom of mathgen.py code, change line variable and remove all table rows in README.md except for the top 2 and run mathgen.py + +wList = getGenList() +allRows = [] +f=open('mathgen.py') +lines=f.readlines() +line = 720 #This has to be changed depending on which line the first generator appears on +for item in wList: + myGen = item[2] + prob, sol = myGen() + prob = str(prob).rstrip("\n") + sol = str(sol).rstrip("\n") + instName = lines[line] + def_name = instName[:instName.find('=')].strip() + row = [myGen.id, myGen.title, prob, sol, def_name] + line+=1 + allRows.append(row) + +g=open('../README.md', "a") +for row in allRows: + tableLine = "| " + str(row[0]) + " | " + str(row[1]) + " | " + str(row[2]) + " | " + str(row[3]) + " | " + str(row[4]) + " |\n" + g.write(tableLine) +g.close() + +print("New README.md table generated") diff --git a/mathgenerator/mathgen.py b/mathgenerator/mathgen.py index 1041a55..d00ea30 100644 --- a/mathgenerator/mathgen.py +++ b/mathgenerator/mathgen.py @@ -224,7 +224,7 @@ def areaOfTriangleFunc(maxA=20, maxB=20, maxC=20): c = random.randint(1, maxC) s = (a+b+c)/2 area = (s*(s-a)*(s-b)*(s-c)) ** 0.5 - problem = "Area of triangle with side lengths: "+ str(a) +" "+ str(b) +" "+ str(c) + " = " + problem = "Area of triangle with side lengths: "+ str(a) +" "+ str(b) +" "+ str(c) + " = " solution = area return problem, solution @@ -234,7 +234,7 @@ def isTriangleValidFunc(maxSideLength = 50): sideC = random.randint(1, maxSideLength) sideSums = [sideA + sideB, sideB + sideC, sideC + sideA] sides = [sideC, sideA, sideB] - exists = True & (sides[0] < sideSums[0]) & (sides[1] < sideSums[1]) & (sides[2] < sideSums[2]) + exists = True & (sides[0] < sideSums[0]) & (sides[1] < sideSums[1]) & (sides[2] < sideSums[2]) problem = f"Does triangle with sides {sideA}, {sideB} and {sideC} exist?" if exists: solution = "Yes" @@ -267,7 +267,7 @@ def factoringFunc(range_x1 = 10, range_x2 = 10): if (b == "+1"): b = "+" - + if (b == ""): problem = f"x^2{c}" else: @@ -277,7 +277,7 @@ def factoringFunc(range_x1 = 10, range_x2 = 10): x2 = intParser(x2) solution = f"(x{x1})(x{x2})" return problem, solution - + def thirdAngleOfTriangleFunc(maxAngle=89): angle1 = random.randint(1, maxAngle) angle2 = random.randint(1, maxAngle) @@ -362,13 +362,13 @@ def linearEquationsFunc(n = 2, varRange = 20, coeffRange = 20): for _ in range(n): coeff = [ random.randint(-coeffRange, coeffRange) for i in range(n) ] res = sum([ coeff[i] * soln[i] for i in range(n)]) - + prob = ["{}{}".format(coeff[i], vars[i]) if coeff[i] != 0 else "" for i in range(n)] while "" in prob: prob.remove("") prob = " + ".join(prob) + " = " + str(res) problem.append(prob) - + problem = "\n".join(problem) return problem, solution @@ -417,8 +417,8 @@ def regularPolygonAngleFunc(minVal = 3,maxVal = 20): problem = f"Find the angle of a regular polygon with {sideNum} sides" exteriorAngle = round((360/sideNum),2) solution = 180 - exteriorAngle - return problem, solution - + return problem, solution + def combinationsFunc(maxlength=20): def factorial(a): @@ -434,9 +434,9 @@ def combinationsFunc(maxlength=20): solution= int(factorial(a)/(factorial(b)*factorial(a-b))) problem= "Number of combinations from {} objects picked {} at a time ".format(a,b) - + return problem, solution - + def factorialFunc(maxInput = 6): a = random.randint(0, maxInput) n = a @@ -470,7 +470,7 @@ def surfaceAreaCuboid(maxSide = 20, unit = 'm'): a = random.randint(1, maxSide) b = random.randint(1, maxSide) c = random.randint(1, maxSide) - + problem = f"Surface area of cuboid with sides = {a}{unit}, {b}{unit}, {c}{unit} is" ans = 2 * (a*b + b*c + c*a) solution = f"{ans} {unit}^2" @@ -567,7 +567,7 @@ def intersectionOfTwoLinesFunc( else: x = f"{x.numerator}/{x.denominator}" return x - + m1 = (random.randint(minM, maxM), random.randint(minDenominator, maxDenominator)) m2 = (random.randint(minM, maxM), random.randint(minDenominator, maxDenominator)) b1 = random.randint(minB, maxB) @@ -625,7 +625,7 @@ def compareFractionsFunc(maxVal=10): solution="<" else: solution="=" - + problem = f"Which symbol represents the comparison between {a}/{b} and {c}/{d}?" return problem,solution @@ -648,7 +648,7 @@ def matrixMultiplicationFunc(maxVal=100): a.append([]) for c in range(n): a[r].append(random.randint(-maxVal,maxVal)) - + b=[] for r in range(n): b.append([]) @@ -666,8 +666,8 @@ def matrixMultiplicationFunc(maxVal=100): for t in range(n): temp+=a[r][t]*b[t][c] res[r].append(temp) - problem= f"Multiply \n{a_string}\n and \n\n{b_string}" #consider using a, b instead of a_string, b_string if the problem doesn't look right - solution= matrixMultiplicationFuncHelper(res) + problem= f"Multiply {a} and {b}" #consider using a, b instead of a_string, b_string if the problem doesn't look right + solution= res#matrixMultiplicationFuncHelper(res) return problem, solution def matrixMultiplicationFuncHelper(inp): @@ -703,7 +703,7 @@ def powerRuleIntegrationFunc(maxCoef = 10, maxExp = 10, maxTerms = 5): solution = solution + " + c" return problem, solution - + def fourthAngleOfQuadriFunc(maxAngle = 180): angle1 = random.randint(1, maxAngle) angle2 = random.randint(1, 240-angle1) @@ -741,8 +741,7 @@ doesTriangleExist = Generator("Triangle exists check", 19, "Does triangle with s midPointOfTwoPoint=Generator("Midpoint of the two point", 20,"((X1,Y1),(X2,Y2))=","((X1+X2)/2,(Y1+Y2)/2)",MidPointOfTwoPointFunc) factoring = Generator("Factoring Quadratic", 21, "x^2+(x1+x2)+x1*x2", "(x-x1)(x-x2)", factoringFunc) thirdAngleOfTriangle = Generator("Third Angle of Triangle", 22, "Third Angle of the triangle = ", "angle3", thirdAngleOfTriangleFunc) -systemOfEquations = Generator("Solve a System of Equations in R^2", 23, "2x + 5y = 13, -3x - 3y = -6", "x = -1, y = 3", - systemOfEquationsFunc) +systemOfEquations = Generator("Solve a System of Equations in R^2", 23, "2x + 5y = 13, -3x - 3y = -6", "x = -1, y = 3", systemOfEquationsFunc) distance2Point = Generator("Distance between 2 points", 24, "Find the distance between (x1,y1) and (x2,y2)","sqrt(distanceSquared)", distanceTwoPointsFunc) pythagoreanTheorem = Generator("Pythagorean Theorem", 25, "The hypotenuse of a right triangle given the other two lengths a and b = ", "hypotenuse", pythagoreanTheoremFunc) linearEquations = Generator("Linear Equations", 26, "2x+5y=20 & 3x+6y=12", "x=-20 & y=12", linearEquationsFunc) #This has multiple variables whereas #23 has only x and y @@ -754,7 +753,7 @@ factorial = Generator("Factorial", 31, "a! = ", "b", factorialFunc) surfaceAreaCubeGen = Generator("Surface Area of Cube", 32, "Surface area of cube with side a units is","b units^2", surfaceAreaCube) surfaceAreaCuboidGen = Generator("Surface Area of Cuboid", 33, "Surface area of cuboid with sides = a units, b units, c units is","d units^2", surfaceAreaCuboid) surfaceAreaCylinderGen = Generator("Surface Area of Cylinder", 34, "Surface area of cylinder with height = a units and radius = b units is","c units^2", surfaceAreaCylinder) -volumeCubeGen = Generator("Volum of Cube", 35, "Volume of cube with side a units is","b units^3", volumeCube) +volumeCubeGen = Generator("Volum of Cube", 35, "Volume of cube with side a units is","b units^3", volumeCube) volumeCuboidGen = Generator("Volume of Cuboid", 36, "Volume of cuboid with sides = a units, b units, c units is","d units^3", volumeCuboid) volumeCylinderGen = Generator("Volume of cylinder", 37, "Volume of cylinder with height = a units and radius = b units is","c units^3", volumeCylinder) surfaceAreaConeGen = Generator("Surface Area of cone", 38, "Surface area of cone with height = a units and radius = b units is","c units^2", surfaceAreaCone) @@ -769,3 +768,29 @@ matrixMultiplication = Generator("Multiplication of two matrices", 46, "Multipl CubeRoot = Generator("Cube Root",47,"Cuberoot of a upto 2 decimal places is","b",cubeRootFunc) powerRuleIntegration = Generator("Power Rule Integration", 48, "nx^m=", "(n/m)x^(m+1)", powerRuleIntegrationFunc) fourthAngleOfQuadrilateral = Generator("Fourth Angle of Quadrilateral",49,"Fourth angle of Quadrilateral with angles a,b,c =","angle4",fourthAngleOfQuadriFunc) + +wList = getGenList() +#print(wList) +allRows = [] +f=open('mathgen.py') +lines=f.readlines() +line = 720 +for item in wList: + myGen = item[2] + prob, sol = myGen() + prob = str(prob).rstrip("\n") + sol = str(sol).rstrip("\n") + instName = lines[line] + def_name = instName[:instName.find('=')].strip() + print(def_name) + row = [myGen.id, myGen.title, prob, sol, def_name] + print(row) + line+=1 + allRows.append(row) + +g=open('../README.md', "a") +for row in allRows: + tableLine = "| " + str(row[0]) + " | " + str(row[1]) + " | " + str(row[2]) + " | " + str(row[3]) + " | " + str(row[4]) + " |\n" + g.write(tableLine) + #print(tableLine) +g.close() From 7e9f8a4d2b19e5ed168cca1498a6c26958d5123d Mon Sep 17 00:00:00 2001 From: "sakshi.kst" Date: Sat, 17 Oct 2020 18:30:57 +0530 Subject: [PATCH 2/7] Sum of Angles of Polygon function added --- README.md | 1 + mathgenerator/mathgen.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/README.md b/README.md index dfc7d41..d39ce06 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,4 @@ problem, solution = mathgen.genById(0) | 47 | Cube Root | cuberoot of 711 upto 2 decimal places is: | 8.93 | CubeRoot | | 48 | Power Rule Integration | 3x^1 | (3/1)x^2 + c | powerRuleIntegration | | 49 | Fourth Angle of Quadrilateral | Fourth angle of quadrilateral with angles 94 , 101, 102 = | 63 | fourthAngleOfQuadrilateral | +| 50 | Sum of Angles of Polygon | Sum of angles of polygon with 4 sides = | 360 | sumOfAnglesOfPolygon | \ No newline at end of file diff --git a/mathgenerator/mathgen.py b/mathgenerator/mathgen.py index 1041a55..52ee492 100644 --- a/mathgenerator/mathgen.py +++ b/mathgenerator/mathgen.py @@ -714,6 +714,13 @@ def fourthAngleOfQuadriFunc(maxAngle = 180): solution = angle4 return problem, solution +def sumOfAnglesOfPolygonFunc(maxSides = 12): + side = random.randint(3, maxSides) + sum = (side - 2) * 180 + problem = f"Sum of angles of polygon with {side} sides = " + solution = sum + return problem, solution + # || Class Instances #Format is: @@ -769,3 +776,4 @@ matrixMultiplication = Generator("Multiplication of two matrices", 46, "Multipl CubeRoot = Generator("Cube Root",47,"Cuberoot of a upto 2 decimal places is","b",cubeRootFunc) powerRuleIntegration = Generator("Power Rule Integration", 48, "nx^m=", "(n/m)x^(m+1)", powerRuleIntegrationFunc) fourthAngleOfQuadrilateral = Generator("Fourth Angle of Quadrilateral",49,"Fourth angle of Quadrilateral with angles a,b,c =","angle4",fourthAngleOfQuadriFunc) +sumOfAnglesOfPolygon = Generator("Sum of Angles of Polygon", 50, "Sum of angles of polygon with n sides = ", "sum", sumOfAnglesOfPolygonFunc) From 08fc9d0663e90b96ee9d7cb7451aa3ee5c212576 Mon Sep 17 00:00:00 2001 From: YuvalG Date: Sat, 17 Oct 2020 20:05:47 +0300 Subject: [PATCH 3/7] Add flake8 as linter --- .github/workflows/tests.yaml | 44 +- Makefile | 9 +- dev-requirements.txt | 5 +- .../__pycache__/__init__.cpython-37.pyc | Bin 164 -> 0 bytes .../__pycache__/mathgen.cpython-37.pyc | Bin 19103 -> 0 bytes mathgenerator/mathgen.py | 500 ++++++++++-------- tests/test_mathgen.py | 92 ++-- 7 files changed, 358 insertions(+), 292 deletions(-) delete mode 100644 mathgenerator/__pycache__/__init__.cpython-37.pyc delete mode 100644 mathgenerator/__pycache__/mathgen.cpython-37.pyc diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 3252576..cc6cf9d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,21 +1,23 @@ -name: Run tests - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install -U pip - python -m pip install -r dev-requirements.txt - - name: Test - run: make test +name: Run tests + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install -U pip + python -m pip install -r dev-requirements.txt + - name: Linter + run: make lint + - name: Test + run: make test diff --git a/Makefile b/Makefile index dbf1f17..bd04e35 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,7 @@ -test: - python -m pytest --verbose -s tests +FLAKE_FLAGS = --ignore=E501,F401,F403,F405 + +lint: + python -m flake8 $(FLAKE_FLAGS) + +test: + python -m pytest --verbose -s tests diff --git a/dev-requirements.txt b/dev-requirements.txt index a965899..6e46af4 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,2 +1,3 @@ -pytest -hypothesis \ No newline at end of file +pytest +hypothesis +flake8 \ No newline at end of file diff --git a/mathgenerator/__pycache__/__init__.cpython-37.pyc b/mathgenerator/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 893336fc37f23c5d8be2b5e049b532e5ed6e2ea6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164 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 diff --git a/mathgenerator/mathgen.py b/mathgenerator/mathgen.py index 7bf36d8..b8d9033 100644 --- a/mathgenerator/mathgen.py +++ b/mathgenerator/mathgen.py @@ -4,6 +4,7 @@ import fractions genList = [] + # || Generator class class Generator: def __init__(self, title, id, generalProb, generalSol, func): @@ -20,52 +21,59 @@ class Generator: def __call__(self, **kwargs): return self.func(**kwargs) + # || Non-generator Functions def genById(id): generator = genList[id][2] return(generator()) + def getGenList(): return(genList) # || Generator Functions -def additionFunc(maxSum = 99, maxAddend = 50): + +def additionFunc(maxSum=99, maxAddend=50): a = random.randint(0, maxAddend) - b = random.randint(0, min((maxSum-a), maxAddend)) #The highest value of b will be no higher than the maxsum minus the first number and no higher than the maxAddend as well - c = a+b + b = random.randint(0, min((maxSum - a), maxAddend)) # The highest value of b will be no higher than the maxsum minus the first number and no higher than the maxAddend as well + c = a + b problem = str(a) + "+" + str(b) + "=" solution = str(c) return problem, solution -def subtractionFunc(maxMinuend = 99, maxDiff = 99): + +def subtractionFunc(maxMinuend=99, maxDiff=99): a = random.randint(0, maxMinuend) - b = random.randint(max(0, (a-maxDiff)), a) - c = a-b + b = random.randint(max(0, (a - maxDiff)), a) + c = a - b problem = str(a) + "-" + str(b) + "=" solution = str(c) return problem, solution -def multiplicationFunc(maxRes = 99, maxMulti = 99): + +def multiplicationFunc(maxRes=99, maxMulti=99): a = random.randint(0, maxMulti) - b = random.randint(0, min(int(maxMulti/a), maxRes)) - c = a*b + b = random.randint(0, min(int(maxMulti / a), maxRes)) + c = a * b problem = str(a) + "*" + str(b) + "=" solution = str(c) return problem, solution -def divisionFunc(maxRes = 99, maxDivid = 99): + +def divisionFunc(maxRes=99, maxDivid=99): a = random.randint(0, maxDivid) b = random.randint(0, min(maxRes, maxDivid)) - c = a/b + c = a / b problem = str(a) + "/" + str(b) + "=" solution = str(c) return problem, solution -def binaryComplement1sFunc(maxDigits = 10): + +def binaryComplement1sFunc(maxDigits=10): question = '' answer = '' - for i in range(random.randint(1,maxDigits)): + for i in range(random.randint(1, maxDigits)): temp = str(random.randint(0, 1)) question += temp answer += "0" if temp == "1" else "1" @@ -74,22 +82,25 @@ def binaryComplement1sFunc(maxDigits = 10): solution = answer return problem, solution -def moduloFunc(maxRes = 99, maxModulo= 99): + +def moduloFunc(maxRes=99, maxModulo=99): a = random.randint(0, maxModulo) b = random.randint(0, min(maxRes, maxModulo)) - c = a%b + c = a % b problem = str(a) + "%" + str(b) + "=" solution = str(c) return problem, solution -def squareRootFunc(minNo = 1, maxNo = 12): + +def squareRootFunc(minNo=1, maxNo=12): b = random.randint(minNo, maxNo) - a = b*b + a = b * b problem = "sqrt(" + str(a) + ")=" solution = str(b) return problem, solution -def powerRuleDifferentiationFunc(maxCoef = 10, maxExp = 10, maxTerms = 5): + +def powerRuleDifferentiationFunc(maxCoef=10, maxExp=10, maxTerms=5): numTerms = random.randint(1, maxTerms) problem = "" solution = "" @@ -103,23 +114,26 @@ def powerRuleDifferentiationFunc(maxCoef = 10, maxExp = 10, maxTerms = 5): solution += str(coefficient * exponent) + "x^" + str(exponent - 1) return problem, solution -def squareFunc(maxSquareNum = 20): + +def squareFunc(maxSquareNum=20): a = random.randint(1, maxSquareNum) b = a * a problem = str(a) + "^2" + "=" solution = str(b) return problem, solution + def gcdFunc(maxVal=20): a = random.randint(1, maxVal) b = random.randint(1, maxVal) x, y = a, b while(y): - x, y = y, x % y + x, y = y, x % y problem = f"GCD of {a} and {b} = " solution = str(x) return problem, solution + def lcmFunc(maxVal=20): a = random.randint(1, maxVal) b = random.randint(1, maxVal) @@ -132,11 +146,13 @@ def lcmFunc(maxVal=20): solution = str(d) return problem, solution -def basicAlgebraFunc(maxVariable = 10): + +def basicAlgebraFunc(maxVariable=10): a = random.randint(1, maxVariable) b = random.randint(1, maxVariable) c = random.randint(b, maxVariable) # calculate gcd + def calculate_gcd(x, y): while(y): x, y = y, x % y @@ -145,44 +161,49 @@ def basicAlgebraFunc(maxVariable = 10): x = f"{(c - b)//i}/{a//i}" if (c - b == 0): x = "0" - elif a == 1 or a == i : + elif a == 1 or a == i: x = f"{c - b}" problem = f"{a}x + {b} = {c}" solution = x return problem, solution + def logFunc(maxBase=3, maxVal=8): a = random.randint(1, maxVal) b = random.randint(2, maxBase) - c = pow(b,a) - problem = "log"+str(b)+"("+str(c)+")" + c = pow(b, a) + problem = "log" + str(b) + "(" + str(c) + ")" solution = str(a) return problem, solution + def divisionToIntFunc(maxA=25, maxB=25): - a = random.randint(1,maxA) - b = random.randint(1,maxB) - divisor = a*b - dividend=random.choice([a,b]) + a = random.randint(1, maxA) + b = random.randint(1, maxB) + divisor = a * b + dividend = random.choice([a, b]) problem = f"{divisor}/{dividend} = " - solution=int(divisor/dividend) - return problem,solution + solution = int(divisor / dividend) + return problem, solution + def DecimalToBinaryFunc(max_dec=99): a = random.randint(1, max_dec) b = bin(a).replace("0b", "") - problem = "Binary of "+str(a)+"=" + problem = "Binary of " + str(a) + "=" solution = str(b) return problem, solution -def BinaryToDecimalFunc(max_dig=10): - problem='' - for i in range(random.randint(1,max_dig)): - temp = str(random.randint(0, 1)) - problem += temp - solution=int(problem, 2); - return problem, solution +def BinaryToDecimalFunc(max_dig=10): + problem = '' + for i in range(random.randint(1, max_dig)): + temp = str(random.randint(0, 1)) + problem += temp + + solution = int(problem, 2) + return problem, solution + def divideFractionsFunc(maxVal=10): a = random.randint(1, maxVal) @@ -193,6 +214,7 @@ def divideFractionsFunc(maxVal=10): d = random.randint(1, maxVal) while (c == d): d = random.randint(1, maxVal) + def calculate_gcd(x, y): while(y): x, y = y, x % y @@ -208,33 +230,36 @@ def divideFractionsFunc(maxVal=10): solution = x return problem, solution -def multiplyIntToMatrix22(maxMatrixVal = 10, maxRes = 100): + +def multiplyIntToMatrix22(maxMatrixVal=10, maxRes=100): a = random.randint(0, maxMatrixVal) b = random.randint(0, maxMatrixVal) c = random.randint(0, maxMatrixVal) d = random.randint(0, maxMatrixVal) - constant = random.randint(0, int(maxRes/max(a,b,c,d))) + constant = random.randint(0, int(maxRes / max(a, b, c, d))) problem = f"{constant} * [[{a}, {b}], [{c}, {d}]] = " solution = f"[[{a*constant},{b*constant}],[{c*constant},{d*constant}]]" return problem, solution -def areaOfTriangleFunc(maxA=20, maxB=20, maxC=20): - a = random.randint(1, maxA) - b = random.randint(1, maxB) - c = random.randint(1, maxC) - s = (a+b+c)/2 - area = (s*(s-a)*(s-b)*(s-c)) ** 0.5 - problem = "Area of triangle with side lengths: "+ str(a) +" "+ str(b) +" "+ str(c) + " = " - solution = area - return problem, solution -def isTriangleValidFunc(maxSideLength = 50): +def areaOfTriangleFunc(maxA=20, maxB=20, maxC=20): + a = random.randint(1, maxA) + b = random.randint(1, maxB) + c = random.randint(1, maxC) + s = (a + b + c) / 2 + area = (s * (s - a) * (s - b) * (s - c)) ** 0.5 + problem = "Area of triangle with side lengths: " + str(a) + " " + str(b) + " " + str(c) + " = " + solution = area + return problem, solution + + +def isTriangleValidFunc(maxSideLength=50): sideA = random.randint(1, maxSideLength) sideB = random.randint(1, maxSideLength) sideC = random.randint(1, maxSideLength) sideSums = [sideA + sideB, sideB + sideC, sideC + sideA] sides = [sideC, sideA, sideB] - exists = True & (sides[0] < sideSums[0]) & (sides[1] < sideSums[1]) & (sides[2] < sideSums[2]) + exists = True & (sides[0] < sideSums[0]) & (sides[1] < sideSums[1]) & (sides[2] < sideSums[2]) problem = f"Does triangle with sides {sideA}, {sideB} and {sideC} exist?" if exists: solution = "Yes" @@ -242,51 +267,56 @@ def isTriangleValidFunc(maxSideLength = 50): solution = "No" return problem, solution + def MidPointOfTwoPointFunc(maxValue=20): - x1=random.randint(-20,maxValue) - y1=random.randint(-20,maxValue) - x2=random.randint(-20,maxValue) - y2=random.randint(-20,maxValue) - problem=f"({x1},{y1}),({x2},{y2})=" - solution=f"({(x1+x2)/2},{(y1+y2)/2})" - return problem,solution + x1 = random.randint(-20, maxValue) + y1 = random.randint(-20, maxValue) + x2 = random.randint(-20, maxValue) + y2 = random.randint(-20, maxValue) + problem = f"({x1},{y1}),({x2},{y2})=" + solution = f"({(x1+x2)/2},{(y1+y2)/2})" + return problem, solution -def factoringFunc(range_x1 = 10, range_x2 = 10): - x1 = random.randint(-range_x1, range_x1) - x2 = random.randint(-range_x2, range_x2) - def intParser(z): - if (z == 0): - return "" - if (z > 0): - return "+" + str(z) - if (z < 0): - return "-" + str(abs(z)) - b = intParser(x1 + x2) - c = intParser(x1 * x2) +def factoringFunc(range_x1=10, range_x2=10): + x1 = random.randint(-range_x1, range_x1) + x2 = random.randint(-range_x2, range_x2) + + def intParser(z): + if (z == 0): + return "" + if (z > 0): + return "+" + str(z) + if (z < 0): + return "-" + str(abs(z)) + + b = intParser(x1 + x2) + c = intParser(x1 * x2) + + if (b == "+1"): + b = "+" + + if (b == ""): + problem = f"x^2{c}" + else: + problem = f"x^2{b}x{c}" + + x1 = intParser(x1) + x2 = intParser(x2) + solution = f"(x{x1})(x{x2})" + return problem, solution - if (b == "+1"): - b = "+" - - if (b == ""): - problem = f"x^2{c}" - else: - problem = f"x^2{b}x{c}" - x1 = intParser(x1) - x2 = intParser(x2) - solution = f"(x{x1})(x{x2})" - return problem, solution - def thirdAngleOfTriangleFunc(maxAngle=89): - angle1 = random.randint(1, maxAngle) - angle2 = random.randint(1, maxAngle) - angle3 = 180 - (angle1 + angle2) - problem = f"Third angle of triangle with angles {angle1} and {angle2} = " - solution = angle3 - return problem, solution + angle1 = random.randint(1, maxAngle) + angle2 = random.randint(1, maxAngle) + angle3 = 180 - (angle1 + angle2) + problem = f"Third angle of triangle with angles {angle1} and {angle2} = " + solution = angle3 + return problem, solution -def systemOfEquationsFunc(range_x = 10, range_y = 10, coeff_mult_range=10): + +def systemOfEquationsFunc(range_x=10, range_y=10, coeff_mult_range=10): # Generate solution point first x = random.randint(-range_x, range_x) y = random.randint(-range_y, range_y) @@ -331,17 +361,19 @@ def systemOfEquationsFunc(range_x = 10, range_y = 10, coeff_mult_range=10): # Add random (non-zero) multiple of equations to each other -def distanceTwoPointsFunc(maxValXY = 20, minValXY=-20): - point1X = random.randint(minValXY, maxValXY+1) - point1Y = random.randint(minValXY, maxValXY+1) - point2X = random.randint(minValXY, maxValXY+1) - point2Y = random.randint(minValXY, maxValXY+1) + +def distanceTwoPointsFunc(maxValXY=20, minValXY=-20): + point1X = random.randint(minValXY, maxValXY + 1) + point1Y = random.randint(minValXY, maxValXY + 1) + point2X = random.randint(minValXY, maxValXY + 1) + point2Y = random.randint(minValXY, maxValXY + 1) distanceSq = (point1X - point2X) ** 2 + (point1Y - point2Y) ** 2 solution = f"sqrt({distanceSq})" problem = f"Find the distance between ({point1X}, {point1Y}) and ({point2X}, {point2Y})" return problem, solution -def pythagoreanTheoremFunc(maxLength = 20): + +def pythagoreanTheoremFunc(maxLength=20): a = random.randint(1, maxLength) b = random.randint(1, maxLength) c = (a**2 + b**2)**0.5 @@ -349,29 +381,31 @@ def pythagoreanTheoremFunc(maxLength = 20): solution = f"{c:.0f}" if c.is_integer() else f"{c:.2f}" return problem, solution -def linearEquationsFunc(n = 2, varRange = 20, coeffRange = 20): + +def linearEquationsFunc(n=2, varRange=20, coeffRange=20): if n > 10: print("[!] n cannot be greater than 10") return None, None vars = ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g'][:n] - soln = [ random.randint(-varRange, varRange) for i in range(n) ] + soln = [random.randint(-varRange, varRange) for i in range(n)] problem = list() solution = ", ".join(["{} = {}".format(vars[i], soln[i]) for i in range(n)]) for _ in range(n): - coeff = [ random.randint(-coeffRange, coeffRange) for i in range(n) ] - res = sum([ coeff[i] * soln[i] for i in range(n)]) - + coeff = [random.randint(-coeffRange, coeffRange) for i in range(n)] + res = sum([coeff[i] * soln[i] for i in range(n)]) + prob = ["{}{}".format(coeff[i], vars[i]) if coeff[i] != 0 else "" for i in range(n)] while "" in prob: prob.remove("") prob = " + ".join(prob) + " = " + str(res) problem.append(prob) - + problem = "\n".join(problem) return problem, solution + def primeFactorsFunc(minVal=1, maxVal=200): a = random.randint(minVal, maxVal) n = a @@ -389,6 +423,7 @@ def primeFactorsFunc(minVal=1, maxVal=200): solution = f"{factors}" return problem, solution + def multiplyFractionsFunc(maxVal=10): a = random.randint(1, maxVal) b = random.randint(1, maxVal) @@ -398,6 +433,7 @@ def multiplyFractionsFunc(maxVal=10): b = random.randint(1, maxVal) while (c == d): d = random.randint(1, maxVal) + def calculate_gcd(x, y): while(y): x, y = y, x % y @@ -412,32 +448,33 @@ def multiplyFractionsFunc(maxVal=10): solution = x return problem, solution -def regularPolygonAngleFunc(minVal = 3,maxVal = 20): + +def regularPolygonAngleFunc(minVal=3, maxVal=20): sideNum = random.randint(minVal, maxVal) problem = f"Find the angle of a regular polygon with {sideNum} sides" - exteriorAngle = round((360/sideNum),2) + exteriorAngle = round((360 / sideNum), 2) solution = 180 - exteriorAngle - return problem, solution - + return problem, solution + + def combinationsFunc(maxlength=20): def factorial(a): - d=1 + d = 1 for i in range(a): - a=(i+1)*d - d=a + a = (i + 1) * d + d = a return d - a= random.randint(10,maxlength) - b=random.randint(0,9) + a = random.randint(10, maxlength) + b = random.randint(0, 9) + solution = int(factorial(a) / (factorial(b) * factorial(a - b))) + problem = "Number of combinations from {} objects picked {} at a time ".format(a, b) - - solution= int(factorial(a)/(factorial(b)*factorial(a-b))) - problem= "Number of combinations from {} objects picked {} at a time ".format(a,b) - return problem, solution - -def factorialFunc(maxInput = 6): + + +def factorialFunc(maxInput=6): a = random.randint(0, maxInput) n = a problem = str(a) + "! = " @@ -452,31 +489,35 @@ def factorialFunc(maxInput = 6): solution = str(b) return problem, solution -def surfaceAreaCube(maxSide = 20, unit = 'm'): + +def surfaceAreaCube(maxSide=20, unit='m'): a = random.randint(1, maxSide) problem = f"Surface area of cube with side = {a}{unit} is" ans = 6 * a * a solution = f"{ans} {unit}^2" return problem, solution -def volumeCube(maxSide = 20, unit = 'm'): + +def volumeCube(maxSide=20, unit='m'): a = random.randint(1, maxSide) problem = f"Volume of cube with side = {a}{unit} is" ans = a * a * a solution = f"{ans} {unit}^3" return problem, solution -def surfaceAreaCuboid(maxSide = 20, unit = 'm'): + +def surfaceAreaCuboid(maxSide=20, unit='m'): a = random.randint(1, maxSide) b = random.randint(1, maxSide) c = random.randint(1, maxSide) - + problem = f"Surface area of cuboid with sides = {a}{unit}, {b}{unit}, {c}{unit} is" - ans = 2 * (a*b + b*c + c*a) + ans = 2 * (a * b + b * c + c * a) solution = f"{ans} {unit}^2" return problem, solution -def volumeCuboid(maxSide = 20, unit = 'm'): + +def volumeCuboid(maxSide=20, unit='m'): a = random.randint(1, maxSide) b = random.randint(1, maxSide) c = random.randint(1, maxSide) @@ -485,7 +526,8 @@ def volumeCuboid(maxSide = 20, unit = 'm'): solution = f"{ans} {unit}^3" return problem, solution -def surfaceAreaCylinder(maxRadius = 20, maxHeight = 50,unit = 'm'): + +def surfaceAreaCylinder(maxRadius=20, maxHeight=50, unit='m'): a = random.randint(1, maxHeight) b = random.randint(1, maxRadius) problem = f"Surface area of cylinder with height = {a}{unit} and radius = {b}{unit} is" @@ -493,7 +535,8 @@ def surfaceAreaCylinder(maxRadius = 20, maxHeight = 50,unit = 'm'): solution = f"{ans} {unit}^2" return problem, solution -def volumeCylinder(maxRadius = 20, maxHeight = 50, unit = 'm'): + +def volumeCylinder(maxRadius=20, maxHeight=50, unit='m'): a = random.randint(1, maxHeight) b = random.randint(1, maxRadius) problem = f"Volume of cylinder with height = {a}{unit} and radius = {b}{unit} is" @@ -501,7 +544,8 @@ def volumeCylinder(maxRadius = 20, maxHeight = 50, unit = 'm'): solution = f"{ans} {unit}^3" return problem, solution -def surfaceAreaCone(maxRadius = 20, maxHeight = 50,unit = 'm'): + +def surfaceAreaCone(maxRadius=20, maxHeight=50, unit='m'): a = random.randint(1, maxHeight) b = random.randint(1, maxRadius) slopingHeight = math.sqrt(a**2 + b**2) @@ -510,14 +554,16 @@ def surfaceAreaCone(maxRadius = 20, maxHeight = 50,unit = 'm'): solution = f"{ans} {unit}^2" return problem, solution -def volumeCone(maxRadius = 20, maxHeight = 50, unit = 'm'): + +def volumeCone(maxRadius=20, maxHeight=50, unit='m'): a = random.randint(1, maxHeight) b = random.randint(1, maxRadius) problem = f"Volume of cone with height = {a}{unit} and radius = {b}{unit} is" - ans = int(math.pi * b * b * a * (1/3)) + ans = int(math.pi * b * b * a * (1 / 3)) solution = f"{ans} {unit}^3" return problem, solution + def commonFactorsFunc(maxVal=100): a = random.randint(1, maxVal) b = random.randint(1, maxVal) @@ -537,6 +583,7 @@ def commonFactorsFunc(maxVal=100): solution = arr return problem, solution + def intersectionOfTwoLinesFunc( minM=-10, maxM=10, minB=-10, maxB=10, minDenominator=1, maxDenominator=6 ): @@ -567,7 +614,7 @@ def intersectionOfTwoLinesFunc( else: x = f"{x.numerator}/{x.denominator}" return x - + m1 = (random.randint(minM, maxM), random.randint(minDenominator, maxDenominator)) m2 = (random.randint(minM, maxM), random.randint(minDenominator, maxDenominator)) b1 = random.randint(minB, maxB) @@ -590,21 +637,24 @@ def intersectionOfTwoLinesFunc( solution = f"({fractionToString(intersection_x)}, {fractionToString(intersection_y)})" return problem, solution + def permutationFunc(maxlength=20): - a = random.randint(10,maxlength) - b = random.randint(0,9) - solution= int(math.factorial(a)/(math.factorial(a-b))) - problem= "Number of Permutations from {} objects picked {} at a time = ".format(a,b) + a = random.randint(10, maxlength) + b = random.randint(0, 9) + solution = int(math.factorial(a) / (math.factorial(a - b))) + problem = "Number of Permutations from {} objects picked {} at a time = ".format(a, b) return problem, solution + def vectorCrossFunc(minVal=-20, maxVal=20): a = [random.randint(minVal, maxVal) for i in range(3)] b = [random.randint(minVal, maxVal) for i in range(3)] - c = [a[1]*b[2] - a[2]*b[1], - a[2]*b[0] - a[0]*b[2], - a[0]*b[1] - a[1]*b[0]] + c = [a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]] return str(a) + " X " + str(b) + " = ", str(c) + def compareFractionsFunc(maxVal=10): a = random.randint(1, maxVal) b = random.randint(1, maxVal) @@ -616,79 +666,84 @@ def compareFractionsFunc(maxVal=10): while (c == d): d = random.randint(1, maxVal) - first=a/b - second=c/d + first = a / b + second = c / d - if(first>second): - solution=">" - elif(first second): + solution = ">" + elif(first < second): + solution = "<" else: - solution="=" - - problem = f"Which symbol represents the comparison between {a}/{b} and {c}/{d}?" - return problem,solution + solution = "=" + + problem = f"Which symbol represents the comparison between {a}/{b} and {c}/{d}?" + return problem, solution + + +def simpleInterestFunc(maxPrinciple=10000, maxRate=10, maxTime=10): + a = random.randint(1000, maxPrinciple) + b = random.randint(1, maxRate) + c = random.randint(1, maxTime) + d = (a * b * c) / 100 + problem = "Simple interest for a principle amount of " + str(a) + " dollars, " + str(b) + "% rate of interest and for a time period of " + str(c) + " years is = " + solution = round(d, 2) + return problem, solution -def simpleInterestFunc(maxPrinciple = 10000, maxRate = 10, maxTime = 10): - a = random.randint(1000, maxPrinciple) - b = random.randint(1, maxRate) - c = random.randint(1, maxTime) - d = (a*b*c)/100 - problem = "Simple interest for a principle amount of " + str(a) +" dollars, " + str(b) + "% rate of interest and for a time period of " + str(c) + " years is = " - solution = round(d, 2) - return problem, solution def matrixMultiplicationFunc(maxVal=100): - m= random.randint(2, 10) - n= random.randint(2, 10) - k= random.randint(2, 10) - #generate matrices a and b - a=[] + m = random.randint(2, 10) + n = random.randint(2, 10) + k = random.randint(2, 10) + # generate matrices a and b + a = [] for r in range(m): a.append([]) for c in range(n): - a[r].append(random.randint(-maxVal,maxVal)) - - b=[] + a[r].append(random.randint(-maxVal, maxVal)) + + b = [] for r in range(n): b.append([]) for c in range(k): b[r].append(random.randint(-maxVal, maxVal)) - res= [] - a_string= matrixMultiplicationFuncHelper(a) - b_string= matrixMultiplicationFuncHelper(b) + res = [] + a_string = matrixMultiplicationFuncHelper(a) + b_string = matrixMultiplicationFuncHelper(b) for r in range(m): res.append([]) for c in range(k): - temp= 0 + temp = 0 for t in range(n): - temp+=a[r][t]*b[t][c] + temp += a[r][t] * b[t][c] res[r].append(temp) - problem= f"Multiply \n{a_string}\n and \n\n{b_string}" #consider using a, b instead of a_string, b_string if the problem doesn't look right - solution= matrixMultiplicationFuncHelper(res) + problem = f"Multiply \n{a_string}\n and \n\n{b_string}" # consider using a, b instead of a_string, b_string if the problem doesn't look right + solution = matrixMultiplicationFuncHelper(res) return problem, solution + def matrixMultiplicationFuncHelper(inp): - m= len(inp) - n= len(inp[0]) - string= "" + m = len(inp) + n = len(inp[0]) + string = "" for i in range(m): for j in range(n): - string+=f"{inp[i][j]: 6d}" - string+=" " - string+="\n" + string += f"{inp[i][j]: 6d}" + string += " " + string += "\n" return string -def cubeRootFunc(minNo = 1, maxNo = 1000): + +def cubeRootFunc(minNo=1, maxNo=1000): b = random.randint(minNo, maxNo) - a = b**(1/3) + a = b**(1 / 3) problem = "cuberoot of " + str(b) + " upto 2 decimal places is:" - solution = str(round(a,2)) + solution = str(round(a, 2)) return problem, solution -def powerRuleIntegrationFunc(maxCoef = 10, maxExp = 10, maxTerms = 5): + +def powerRuleIntegrationFunc(maxCoef=10, maxExp=10, maxTerms=5): numTerms = random.randint(1, maxTerms) problem = "" solution = "" @@ -699,32 +754,33 @@ def powerRuleIntegrationFunc(maxCoef = 10, maxExp = 10, maxTerms = 5): coefficient = random.randint(1, maxCoef) exponent = random.randint(1, maxExp) problem += str(coefficient) + "x^" + str(exponent) - solution += "("+str(coefficient) +"/"+str(exponent) +")x^" + str(exponent +1) + solution += "(" + str(coefficient) + "/" + str(exponent) + ")x^" + str(exponent + 1) solution = solution + " + c" return problem, solution - -def fourthAngleOfQuadriFunc(maxAngle = 180): + +def fourthAngleOfQuadriFunc(maxAngle=180): angle1 = random.randint(1, maxAngle) - angle2 = random.randint(1, 240-angle1) - angle3 = random.randint(1, 340-(angle1 + angle2)) + angle2 = random.randint(1, 240 - angle1) + angle3 = random.randint(1, 340 - (angle1 + angle2)) sum_ = angle1 + angle2 + angle3 angle4 = 360 - sum_ problem = f"Fourth angle of quadrilateral with angles {angle1} , {angle2}, {angle3} =" solution = angle4 return problem, solution - -def quadraticEquation(maxVal=100): - a = random.randint(1,maxVal) - c = random.randint(1,maxVal) - b = random.randint(round(math.sqrt(4*a*c))+1,round(math.sqrt(4*maxVal*maxVal))) - - problem = "Zeros of the Quadratic Equation {}x^2+{}x+{}=0".format(a,b,c) - D = math.sqrt(b*b-4*a*c) - - solution = str([round((-b+D)/(2*a), 2),round((-b-D)/(2*a), 2)]) - return problem,solution + +def quadraticEquation(maxVal=100): + a = random.randint(1, maxVal) + c = random.randint(1, maxVal) + b = random.randint(round(math.sqrt(4 * a * c)) + 1, round(math.sqrt(4 * maxVal * maxVal))) + + problem = "Zeros of the Quadratic Equation {}x^2+{}x+{}=0".format(a, b, c) + + D = math.sqrt(b * b - 4 * a * c) + + solution = str([round((-b + D) / (2 * a), 2), round((-b - D) / (2 * a), 2)]) + return problem, solution def hcfFunc(maxVal=20): @@ -732,15 +788,17 @@ def hcfFunc(maxVal=20): b = random.randint(1, maxVal) x, y = a, b while(y): - x, y = y, x % y + x, y = y, x % y problem = f"HCF of {a} and {b} = " solution = str(x) return problem, solution # || Class Instances -#Format is: -# = Generator("<Title>", <id>, <generalized problem>, <generalized solution>, <function name>) +# Format is: +# <title> = Generator("<Title>", <id>, <generalized problem>, <generalized solution>, <function name>) + + addition = Generator("Addition", 0, "a+b=", "c", additionFunc) subtraction = Generator("Subtraction", 1, "a-b=", "c", subtractionFunc) multiplication = Generator("Multiplication", 2, "a*b=", "c", multiplicationFunc) @@ -749,48 +807,48 @@ binaryComplement1s = Generator("Binary Complement 1s", 4, "1010=", "0101", binar moduloDivision = Generator("Modulo Division", 5, "a%b=", "c", moduloFunc) squareRoot = Generator("Square Root", 6, "sqrt(a)=", "b", squareRootFunc) powerRuleDifferentiation = Generator("Power Rule Differentiation", 7, "nx^m=", "(n*m)x^(m-1)", powerRuleDifferentiationFunc) -square = Generator("Square", 8,"a^2", "b", squareFunc) +square = Generator("Square", 8, "a^2", "b", squareFunc) lcm = Generator("LCM (Least Common Multiple)", 9, "LCM of a and b = ", "c", lcmFunc) gcd = Generator("GCD (Greatest Common Denominator)", 10, "GCD of a and b = ", "c", gcdFunc) basicAlgebra = Generator("Basic Algebra", 11, "ax + b = c", "d", basicAlgebraFunc) log = Generator("Logarithm", 12, "log2(8)", "3", logFunc) -intDivision = Generator("Easy Division", 13,"a/b=","c",divisionToIntFunc) -decimalToBinary = Generator("Decimal to Binary",14,"Binary of a=","b",DecimalToBinaryFunc) -binaryToDecimal = Generator("Binary to Decimal",15,"Decimal of a=","b",BinaryToDecimalFunc) +intDivision = Generator("Easy Division", 13, "a/b=", "c", divisionToIntFunc) +decimalToBinary = Generator("Decimal to Binary", 14, "Binary of a=", "b", DecimalToBinaryFunc) +binaryToDecimal = Generator("Binary to Decimal", 15, "Decimal of a=", "b", BinaryToDecimalFunc) fractionDivision = Generator("Fraction Division", 16, "(a/b)/(c/d)=", "x/y", divideFractionsFunc) intMatrix22Multiplication = Generator("Integer Multiplication with 2x2 Matrix", 17, "k * [[a,b],[c,d]]=", "[[k*a,k*b],[k*c,k*d]]", multiplyIntToMatrix22) areaOfTriangle = Generator("Area of Triangle", 18, "Area of Triangle with side lengths a, b, c = ", "area", areaOfTriangleFunc) -doesTriangleExist = Generator("Triangle exists check", 19, "Does triangle with sides a, b and c exist?","Yes/No", isTriangleValidFunc) -midPointOfTwoPoint=Generator("Midpoint of the two point", 20,"((X1,Y1),(X2,Y2))=","((X1+X2)/2,(Y1+Y2)/2)",MidPointOfTwoPointFunc) +doesTriangleExist = Generator("Triangle exists check", 19, "Does triangle with sides a, b and c exist?", "Yes/No", isTriangleValidFunc) +midPointOfTwoPoint = Generator("Midpoint of the two point", 20, "((X1,Y1),(X2,Y2))=", "((X1+X2)/2,(Y1+Y2)/2)", MidPointOfTwoPointFunc) factoring = Generator("Factoring Quadratic", 21, "x^2+(x1+x2)+x1*x2", "(x-x1)(x-x2)", factoringFunc) thirdAngleOfTriangle = Generator("Third Angle of Triangle", 22, "Third Angle of the triangle = ", "angle3", thirdAngleOfTriangleFunc) systemOfEquations = Generator("Solve a System of Equations in R^2", 23, "2x + 5y = 13, -3x - 3y = -6", "x = -1, y = 3", systemOfEquationsFunc) -distance2Point = Generator("Distance between 2 points", 24, "Find the distance between (x1,y1) and (x2,y2)","sqrt(distanceSquared)", distanceTwoPointsFunc) +distance2Point = Generator("Distance between 2 points", 24, "Find the distance between (x1,y1) and (x2,y2)", "sqrt(distanceSquared)", distanceTwoPointsFunc) pythagoreanTheorem = Generator("Pythagorean Theorem", 25, "The hypotenuse of a right triangle given the other two lengths a and b = ", "hypotenuse", pythagoreanTheoremFunc) -linearEquations = Generator("Linear Equations", 26, "2x+5y=20 & 3x+6y=12", "x=-20 & y=12", linearEquationsFunc) #This has multiple variables whereas #23 has only x and y +linearEquations = Generator("Linear Equations", 26, "2x+5y=20 & 3x+6y=12", "x=-20 & y=12", linearEquationsFunc) # This has multiple variables whereas #23 has only x and y primeFactors = Generator("Prime Factorisation", 27, "Prime Factors of a =", "[b, c, d, ...]", primeFactorsFunc) fractionMultiplication = Generator("Fraction Multiplication", 28, "(a/b)*(c/d)=", "x/y", multiplyFractionsFunc) -angleRegularPolygon = Generator("Angle of a Regular Polygon",29,"Find the angle of a regular polygon with 6 sides","120",regularPolygonAngleFunc) -combinations = Generator("Combinations of Objects",30, "Combinations available for picking 4 objects at a time from 6 distinct objects ="," 15", combinationsFunc) +angleRegularPolygon = Generator("Angle of a Regular Polygon", 29, "Find the angle of a regular polygon with 6 sides", "120", regularPolygonAngleFunc) +combinations = Generator("Combinations of Objects", 30, "Combinations available for picking 4 objects at a time from 6 distinct objects =", " 15", combinationsFunc) factorial = Generator("Factorial", 31, "a! = ", "b", factorialFunc) -surfaceAreaCubeGen = Generator("Surface Area of Cube", 32, "Surface area of cube with side a units is","b units^2", surfaceAreaCube) -surfaceAreaCuboidGen = Generator("Surface Area of Cuboid", 33, "Surface area of cuboid with sides = a units, b units, c units is","d units^2", surfaceAreaCuboid) -surfaceAreaCylinderGen = Generator("Surface Area of Cylinder", 34, "Surface area of cylinder with height = a units and radius = b units is","c units^2", surfaceAreaCylinder) -volumeCubeGen = Generator("Volum of Cube", 35, "Volume of cube with side a units is","b units^3", volumeCube) -volumeCuboidGen = Generator("Volume of Cuboid", 36, "Volume of cuboid with sides = a units, b units, c units is","d units^3", volumeCuboid) -volumeCylinderGen = Generator("Volume of cylinder", 37, "Volume of cylinder with height = a units and radius = b units is","c units^3", volumeCylinder) -surfaceAreaConeGen = Generator("Surface Area of cone", 38, "Surface area of cone with height = a units and radius = b units is","c units^2", surfaceAreaCone) -volumeConeGen = Generator("Volume of cone", 39, "Volume of cone with height = a units and radius = b units is","c units^3", volumeCone) -commonFactors = Generator("Common Factors", 40, "Common Factors of {a} and {b} = ","[c, d, ...]",commonFactorsFunc) +surfaceAreaCubeGen = Generator("Surface Area of Cube", 32, "Surface area of cube with side a units is", "b units^2", surfaceAreaCube) +surfaceAreaCuboidGen = Generator("Surface Area of Cuboid", 33, "Surface area of cuboid with sides = a units, b units, c units is", "d units^2", surfaceAreaCuboid) +surfaceAreaCylinderGen = Generator("Surface Area of Cylinder", 34, "Surface area of cylinder with height = a units and radius = b units is", "c units^2", surfaceAreaCylinder) +volumeCubeGen = Generator("Volum of Cube", 35, "Volume of cube with side a units is", "b units^3", volumeCube) +volumeCuboidGen = Generator("Volume of Cuboid", 36, "Volume of cuboid with sides = a units, b units, c units is", "d units^3", volumeCuboid) +volumeCylinderGen = Generator("Volume of cylinder", 37, "Volume of cylinder with height = a units and radius = b units is", "c units^3", volumeCylinder) +surfaceAreaConeGen = Generator("Surface Area of cone", 38, "Surface area of cone with height = a units and radius = b units is", "c units^2", surfaceAreaCone) +volumeConeGen = Generator("Volume of cone", 39, "Volume of cone with height = a units and radius = b units is", "c units^3", volumeCone) +commonFactors = Generator("Common Factors", 40, "Common Factors of {a} and {b} = ", "[c, d, ...]", commonFactorsFunc) intersectionOfTwoLines = Generator("Intersection of Two Lines", 41, "Find the point of intersection of the two lines: y = m1*x + b1 and y = m2*x + b2", "(x, y)", intersectionOfTwoLinesFunc) -permutations= Generator("Permutations",42, "Total permutations of 4 objects at a time from 10 objects is","5040", permutationFunc) +permutations = Generator("Permutations", 42, "Total permutations of 4 objects at a time from 10 objects is", "5040", permutationFunc) vectorCross = Generator("Cross Product of 2 Vectors", 43, "a X b = ", "c", vectorCrossFunc) -compareFractions=Generator("Compare Fractions",44,"Which symbol represents the comparison between a/b and c/d?",">/</=",compareFractionsFunc) +compareFractions = Generator("Compare Fractions", 44, "Which symbol represents the comparison between a/b and c/d?", ">/</=", compareFractionsFunc) simpleInterest = Generator("Simple Interest", 45, "Simple interest for a principle amount of a dollars, b% rate of interest and for a time period of c years is = ", "d dollars", simpleInterestFunc) -matrixMultiplication = Generator("Multiplication of two matrices", 46, "Multiply two matrices A and B", "C", matrixMultiplicationFunc) -CubeRoot = Generator("Cube Root",47,"Cuberoot of a upto 2 decimal places is","b",cubeRootFunc) +matrixMultiplication = Generator("Multiplication of two matrices", 46, "Multiply two matrices A and B", "C", matrixMultiplicationFunc) +CubeRoot = Generator("Cube Root", 47, "Cuberoot of a upto 2 decimal places is", "b", cubeRootFunc) powerRuleIntegration = Generator("Power Rule Integration", 48, "nx^m=", "(n/m)x^(m+1)", powerRuleIntegrationFunc) -fourthAngleOfQuadrilateral = Generator("Fourth Angle of Quadrilateral",49,"Fourth angle of Quadrilateral with angles a,b,c =","angle4",fourthAngleOfQuadriFunc) +fourthAngleOfQuadrilateral = Generator("Fourth Angle of Quadrilateral", 49, "Fourth angle of Quadrilateral with angles a,b,c =", "angle4", fourthAngleOfQuadriFunc) quadraticEquationSolve = Generator("Quadratic Equation", 50, "Find the zeros {x1,x2} of the quadratic equation ax^2+bx+c=0", "x1,x2", quadraticEquation) hcf = Generator("HCF (Highest Common Factor)", 51, "HCF of a and b = ", "c", hcfFunc) diff --git a/tests/test_mathgen.py b/tests/test_mathgen.py index ace72a5..af38bff 100644 --- a/tests/test_mathgen.py +++ b/tests/test_mathgen.py @@ -1,46 +1,46 @@ -from math import sqrt -from mathgenerator.mathgen import * - -from hypothesis import strategies as st, given, assume - - -@given(maxSum=st.integers(min_value=1), maxAddend=st.integers(min_value=1)) -def test_additionFunc(maxSum, maxAddend): - assume(maxSum > maxAddend) - problem, solution = additionFunc(maxSum, maxAddend) - assert eval(problem[:-1]) == int(solution) - - -@given(maxMinuend=st.integers(min_value=1), maxDiff=st.integers(min_value=1)) -def test_subtractionFunc(maxMinuend, maxDiff): - assume(maxMinuend > maxDiff) - problem, solution = subtractionFunc(maxMinuend, maxDiff) - assert eval(problem[:-1]) == int(solution) - - -@given(maxRes=st.integers(min_value=1), maxMulti=st.integers(min_value=1)) -def test_multiplicationFunc(maxRes, maxMulti): - assume(maxRes > maxMulti) - problem, solution = multiplicationFunc(maxRes, maxMulti) - assert eval(problem[:-1]) == int(solution) - - -@given(maxRes=st.integers(min_value=1), maxDivid=st.integers(min_value=1)) -def test_divisionFunc(maxRes, maxDivid): - assume(maxRes > maxDivid) - problem, solution = divisionFunc(maxRes, maxDivid) - assert eval(problem[:-1]) == float(solution) - - -@given(maxRes=st.integers(min_value=1), maxModulo=st.integers(min_value=1)) -def test_moduloFunc(maxRes, maxModulo): - assume(maxRes > maxModulo) - problem, solution = moduloFunc(maxRes, maxModulo) - assert eval(problem[:-1]) == int(solution) - - -@given(minNo=st.integers(min_value=1), maxNo=st.integers(min_value=1, max_value=2 ** 50)) -def test_squareRootFunc(minNo, maxNo): - assume(maxNo > minNo) - problem, solution = squareRootFunc(minNo, maxNo) - assert eval(problem[:-1]) == float(solution) +from math import sqrt +from mathgenerator.mathgen import * + +from hypothesis import strategies as st, given, assume + + +@given(maxSum=st.integers(min_value=1), maxAddend=st.integers(min_value=1)) +def test_addition(maxSum, maxAddend): + assume(maxSum > maxAddend) + problem, solution = addition.func(maxSum, maxAddend) + assert eval(problem[:-1]) == int(solution) + + +@given(maxMinuend=st.integers(min_value=1), maxDiff=st.integers(min_value=1)) +def test_subtraction(maxMinuend, maxDiff): + assume(maxMinuend > maxDiff) + problem, solution = subtraction.func(maxMinuend, maxDiff) + assert eval(problem[:-1]) == int(solution) + + +@given(maxRes=st.integers(min_value=1), maxMulti=st.integers(min_value=1)) +def test_multiplication(maxRes, maxMulti): + assume(maxRes > maxMulti) + problem, solution = multiplication.func(maxRes, maxMulti) + assert eval(problem[:-1]) == int(solution) + + +@given(maxRes=st.integers(min_value=1), maxDivid=st.integers(min_value=1)) +def test_division(maxRes, maxDivid): + assume(maxRes > maxDivid) + problem, solution = division.func(maxRes, maxDivid) + assert eval(problem[:-1]) == float(solution) + + +@given(maxRes=st.integers(min_value=1), maxModulo=st.integers(min_value=1)) +def test_moduloDivision(maxRes, maxModulo): + assume(maxRes > maxModulo) + problem, solution = moduloDivision.func(maxRes, maxModulo) + assert eval(problem[:-1]) == int(solution) + + +@given(minNo=st.integers(min_value=1), maxNo=st.integers(min_value=1, max_value=2 ** 50)) +def test_squareRoot(minNo, maxNo): + assume(maxNo > minNo) + problem, solution = squareRoot.func(minNo, maxNo) + assert eval(problem[:-1]) == float(solution) From 801ac79b00f757f2e66650f133463ef98a70917b Mon Sep 17 00:00:00 2001 From: Luke Weiler <lukew25073@gmail.com> Date: Sat, 17 Oct 2020 13:54:51 -0400 Subject: [PATCH 4/7] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d39ce06..dfc7d41 100644 --- a/README.md +++ b/README.md @@ -81,4 +81,3 @@ problem, solution = mathgen.genById(0) | 47 | Cube Root | cuberoot of 711 upto 2 decimal places is: | 8.93 | CubeRoot | | 48 | Power Rule Integration | 3x^1 | (3/1)x^2 + c | powerRuleIntegration | | 49 | Fourth Angle of Quadrilateral | Fourth angle of quadrilateral with angles 94 , 101, 102 = | 63 | fourthAngleOfQuadrilateral | -| 50 | Sum of Angles of Polygon | Sum of angles of polygon with 4 sides = | 360 | sumOfAnglesOfPolygon | \ No newline at end of file From 74c3cab7db1d040d6975e6dcbc8a08029c55f6be Mon Sep 17 00:00:00 2001 From: MaxwellJpg <70202524+MaxwellJpg@users.noreply.github.com> Date: Sat, 17 Oct 2020 19:00:21 +0100 Subject: [PATCH 5/7] Update README.md corrected line 81, function id 48. Integrated denominator should be power + 1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f3ab03..a8c09dc 100644 --- a/README.md +++ b/README.md @@ -78,5 +78,5 @@ problem, solution = mathgen.genById(0) | 45 | Simple Interest | Simple interest for a principle amount of 6128 dollars, 5% rate of interest and for a time period of 5 years is = | 1532.0 | simpleInterest | | 46 | Multiplication of two matrices | Multiply [[-20, -14, -88, -62, 39, 94, 21, 75, 26], [89, -67, -80, -60, 32, -23, -79, 11, -69], [13, -75, -66, 3, 67, -79, -49, 6, 36], [-44, -84, 68, -27, -86, -95, -71, -77, -62], [45, 58, 89, 82, 30, -83, -23, 51, 95], [11, 46, 100, -15, 60, -34, 85, 50, -44], [93, -100, -62, 63, -73, -64, 90, -15, 23], [-8, 91, -22, 53, -42, 25, 32, -26, 31], [-60, 90, 75, -42, 19, 33, -30, 74, 13]] and [[-80, 54, -39, 37, -99], [31, -28, -31, 64, 73], [-21, -34, -28, -21, -76], [-94, 55, 66, 0, 17], [-28, 25, -65, -74, 100], [76, 74, -96, -98, -5], [-90, -70, -66, -71, -35], [65, 49, -100, 72, -23], [-95, -97, -31, -84, -86]] | [[15409, 6508, -21665, -10161, 5326], [9859, 17962, 3267, 12768, 3119], [-8761, 1272, 8611, 738, 3881], [4489, -5790, 29652, 11947, -5940], [-22167, -8208, -1142, 6747, -10714], [-4628, -5167, -15527, 1404, 243], [-29240, -2432, 11103, 615, -22487], [-5498, -5038, 1462, -100, 2495], [18214, -3238, -15548, 3691, 6061]] | matrixMultiplication | | 47 | Cube Root | cuberoot of 711 upto 2 decimal places is: | 8.93 | CubeRoot | -| 48 | Power Rule Integration | 3x^1 | (3/1)x^2 + c | powerRuleIntegration | +| 48 | Power Rule Integration | 3x^1 | (3/2)x^2 + c | powerRuleIntegration | | 49 | Fourth Angle of Quadrilateral | Fourth angle of quadrilateral with angles 94 , 101, 102 = | 63 | fourthAngleOfQuadrilateral | From 49ed99a3f9d042352ba8fb2b738e0c3da56a817f Mon Sep 17 00:00:00 2001 From: lukew3 <lukew25073@gmail.com> Date: Sat, 17 Oct 2020 14:06:00 -0400 Subject: [PATCH 6/7] Fixed createFibList indentation error --- mathgenerator/mathgen.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mathgenerator/mathgen.py b/mathgenerator/mathgen.py index 3c91834..02b4c1d 100644 --- a/mathgenerator/mathgen.py +++ b/mathgenerator/mathgen.py @@ -713,16 +713,16 @@ def fourthAngleOfQuadriFunc(maxAngle = 180): problem = f"Fourth angle of quadrilateral with angles {angle1} , {angle2}, {angle3} =" solution = angle4 return problem, solution - + def quadraticEquation(maxVal=100): a = random.randint(1,maxVal) c = random.randint(1,maxVal) b = random.randint(round(math.sqrt(4*a*c))+1,round(math.sqrt(4*maxVal*maxVal))) - + problem = "Zeros of the Quadratic Equation {}x^2+{}x+{}=0".format(a,b,c) D = math.sqrt(b*b-4*a*c) - + solution = str([round((-b+D)/(2*a), 2),round((-b-D)/(2*a), 2)]) return problem,solution @@ -797,18 +797,18 @@ def surdsComparisonFunc(maxValue = 100, maxRoot = 10): elif first < second: solution = "<" return problem, solution - + def fibonacciSeriesFunc(minNo=1): n = random.randint(minNo,20) def createFibList(n): - l=[] - for i in range(n): - if i<2: - l.append(i) - else: - val = l[i-1]+l[i-2] - l.append(val) - return l + l=[] + for i in range(n): + if i<2: + l.append(i) + else: + val = l[i-1]+l[i-2] + l.append(val) + return l fibList=createFibList(n) problem = "The Fibonacci Series of the first "+str(n)+" numbers is ?" solution = fibList @@ -821,7 +821,7 @@ def basicTrigonometryFunc(angles=[0,30,45,60,90],functions=["sin","cos","tan"]): problem=f"What is {function}({angle})?" expression='math.'+function+'(math.radians(angle))' result_fraction_map={0.0:"0",0.5:"1/2",0.71:"1/√2",0.87:"√3/2",1.0:"1",0.58:"1/√3",1.73:"√3"} - + solution=result_fraction_map[round(eval(expression),2)] if round(eval(expression),2)<=99999 else "∞" #for handling the ∞ condition return problem,solution @@ -895,4 +895,4 @@ confidenceInterval = Generator("Confidence interval For sample S", 54, "With X% surdsComparison = Generator("Comparing surds", 55, "Fill in the blanks a^(1/b) _ c^(1/d)", "</>/=", surdsComparisonFunc) fibonacciSeries = Generator("Fibonacci Series",56,"fibonacci series of first a numbers","prints the fibonacci series starting from 0 to a",fibonacciSeriesFunc) basicTrigonometry=Generator("Trigonometric Values",57,"What is sin(X)?","ans",basicTrigonometryFunc) -sumOfAnglesOfPolygon = Generator("Sum of Angles of Polygon", 58, "Sum of angles of polygon with n sides = ", "sum", sumOfAnglesOfPolygonFunc) \ No newline at end of file +sumOfAnglesOfPolygon = Generator("Sum of Angles of Polygon", 58, "Sum of angles of polygon with n sides = ", "sum", sumOfAnglesOfPolygonFunc) From f323be51ae5281ad142095782177bc9d08ff52cc Mon Sep 17 00:00:00 2001 From: lukew3 <lukew25073@gmail.com> Date: Sat, 17 Oct 2020 14:14:57 -0400 Subject: [PATCH 7/7] remove pycache --- .../__pycache__/__init__.cpython-37.pyc | Bin 164 -> 0 bytes .../__pycache__/mathgen.cpython-37.pyc | Bin 29724 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 mathgenerator/__pycache__/__init__.cpython-37.pyc delete mode 100644 mathgenerator/__pycache__/mathgen.cpython-37.pyc diff --git a/mathgenerator/__pycache__/__init__.cpython-37.pyc b/mathgenerator/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 893336fc37f23c5d8be2b5e049b532e5ed6e2ea6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164 zcmZ?b<>g{vU|`t!q%$5wKL!yn%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_`8r$0 zgche36~_cP$GD^xXP4v`!~_)OXQd{W6vqS<B_@|-Ca1>aCYEHRr{<*=C6?qDq4DD5 dGxIV_;^XxSDsOSv<mRW8=A_zztoaOb3ILz#EKdLc diff --git a/mathgenerator/__pycache__/mathgen.cpython-37.pyc b/mathgenerator/__pycache__/mathgen.cpython-37.pyc deleted file mode 100644 index 82bcec4b454f2a62c9cf0b2088c33baea54dfaef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29724 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 E0A7mq+5i9m