If It's True
Sometimes you want code to run only when a certain condition is met. Swift's if statement does exactly that — it's the gateway from data into decisions.
An if statement checks a condition — an expression that's either true or false — and runs one block of code if it's true, and optionally a different block (else) if it's false.
let sides = 4 if sides == 4 { // this block runs only when sides equals 4 print("This is a quadrilateral") } else { // this block runs for any other value print("Not a quadrilateral") }
Notice the == (two equals signs). In Swift, = means "assign a value" while == means "are these equal?" — it's a common beginner trap.
Here are all of Swift's comparison operators:
a == b // equal to a != b // not equal to a < b // less than a <= b // less than or equal to a > b // greater than a >= b // greater than or equal to
Conditions that evaluate to true or false are called Boolean expressions, named after the 19th-century mathematician George Boole who invented the algebra of logic.
Only two values. A Boolean can be one of exactly two things:trueorfalse. No "maybe", no "sort of", no "null". This two-valued logic is the foundation of all digital circuits — every electronic device you use is built from billions of tiny switches, each one in one of exactly two states. Boolean logic is also the foundation of mathematical proof: a statement is either true or it isn't.
Comparison makes a Boolean. Writingsides == 4doesn't do anything by itself — it just produces a value, eithertrueorfalse. Theifstatement then looks at that value and decides which block to run. You can even store the result:let isQuad = (sides == 4)— nowisQuadis a Boolean variable you can reuse.
Same-type rule. Swift is strict about types — you can only compare values of the same type.5 == 5.0is a compile error because5is anIntand5.0is aDouble. To compare them, convert one:Double(5) == 5.0. You'll see this again in Section 02 when we start mixing integer inputs with decimal values.
| Concept | Connection |
|---|---|
| Logic & Reasoning | Boolean expressions are the foundation of mathematical logic. A condition is either true or false — there's no middle ground — mirroring two-valued logic in proofs and set theory. Swift's ==, !=, <, >, <=, >= are direct translations of the mathematical comparison symbols =, ≠, <, >, ≤, ≥. |
Classify an Angle
Write code that classifies an angle as acute, right, or obtuse based on its value in degrees. Then we'll meet Input() — an interactive value that lets you test every angle without editing your code.
- Acute: less than 90°
- Right: exactly 90°
- Obtuse: greater than 90° and less than 180°
New tool: Input()
Up to this point, whenever you wanted to test with a different value you had to edit your code:
let angle = 45 // change this number every time you want to try a different angle
Swift Playgrounds gives you a better way: Input(). It creates an interactive slider or text field right next to your code that you can drag or type into, and your code re-runs automatically with the new value. No more editing!
let angle = Input(number: 45, id: "angle")
There are three flavours of Input, one per type:
let count = Input(number: 5, id: "count") // Int — whole numbers let side = Input(decimal: 3.5, id: "side") // Double — decimals let name = Input(text: "square", id: "name") // String — text
The first parameter is the default value (what Input shows before you change it), and id is the label Swift uses to identify this particular input on screen — give each input a unique id.
Playing with types. Notice that each flavour ofInputproduces a value of a different type:Input(number:)gives you anInt,Input(decimal:)gives you aDouble, andInput(text:)gives you aString. This matters because Swift is strict — you can't compare aDoublewith anIntdirectly. For whole-number angles like 45 or 90, useInput(number:). For lengths like 3.6 or 10.5, useInput(decimal:).
Unique ids. EachInputin your program needs its ownid— otherwise Swift can't tell them apart. Use descriptive names like"angle","side a","sides", so when you're looking at the interactive controls you know which one is which.
Boundary cases. When classifying a continuous range (angles from 0° to 180°), think carefully about the boundaries. Is 90° "acute" or "right"? Is 180° "obtuse" or "straight"? Pick explicit rules (right = exactly 90°, obtuse = strictly between 90° and 180°) and make yourif/else ifchain match them exactly. Off-by-one or boundary bugs are among the most common errors in classification code.
Try your code with the values 45, 90, and 120 by dragging the Input slider.
let angle = Input(number: 45, id: "angle") if angle < 90 { print("Acute") } else if angle == 90 { print("Right") } else { print("Obtuse") }
What about angles above 180°? This solution labels anything> 90as "Obtuse" — including 200° or 350°, which are actually reflex angles. Section 05 ("And & Or") extends this classification to the full 0°–360° range using compound conditions likeangle > 90 && angle < 180. For this exercise, assume the angle is between 0° and 180°.
| Concept | Connection |
|---|---|
| Geometry — Angle Classification | Angles are classified by measure: acute (0°–90°), right (90°), obtuse (90°–180°), straight (180°), reflex (180°–360°). Identifying angle types is fundamental to geometry. The Swift if/else if chain mirrors the mutually exclusive categories — an angle can only fall into one. |
Else If
When you have more than two possible outcomes, chain multiple conditions with else if. Swift checks them in order and takes the first branch that's true.
You already used else if in Section 02 to handle three angle types. Let's look at the pattern more carefully — and use Input() so you can test any number of sides interactively.
let sides = Input(number: 5, id: "sides") if sides == 3 { print("Triangle") } else if sides == 4 { print("Quadrilateral") } else if sides == 5 { print("Pentagon") } else if sides == 6 { print("Hexagon") } else { print("Other polygon") }
Top-to-bottom, first match wins. Swift evaluates each condition in order from top to bottom. As soon as it finds one that's true, it runs that block and skips all the rest. That means order matters — if two conditions could both be true, only the first one runs. You'll see this matter a lot in the triangle and quadrilateral classifiers coming up.
Mutually exclusive vs. overlapping. The polygon example is mutually exclusive:sidescan only be one value, so only one branch can ever match. The triangle classifier in Section 04 is overlapping: an equilateral triangle is also isosceles (by definition). In the overlapping case, the order of yourelse ifchain decides which label you give it — more specific categories must come first.
Always think about theelse. The finalelsecatches everything that didn't match. If you forget it, inputs you haven't thought of will silently do nothing. A common trick is to put a sanity-check print in the finalelse, so you'll notice when an unexpected value sneaks through.
| Concept | Connection |
|---|---|
| Geometry — Polygon Classification | Polygons are classified by number of sides: 3 = triangle, 4 = quadrilateral, 5 = pentagon, 6 = hexagon, 7 = heptagon, 8 = octagon, … Each classification is a mutually exclusive category — a shape can only have one number of sides. The if/else if/else chain mirrors this partition exactly. |
Triangle Classifier
Given three side lengths (using Input(decimal:) so you can try different combinations), classify the triangle as equilateral, isosceles, or scalene, and check whether it's also a right triangle.
- Equilateral: all three sides equal (e.g. 5, 5, 5)
- Isosceles: at least two sides equal (e.g. 5, 5, 8)
- Scalene: all three sides different (e.g. 3, 4, 5)
You can also check if the triangle is a right triangle using the Pythagorean theorem: a² + b² = c², where c is the longest side. Test with (3, 4, 5), (5, 5, 5), and (5, 5, 8).
You'll need && (AND) and || (OR) to combine side comparisons. We'll formalise these logical operators in Section 05 — for now, just know that a == b && b == c means "all three are equal" and a == b || b == c || a == c means "at least two are equal".
Triangle inequality. Not every triple of positive numbers is a valid triangle! For three sides to form a triangle, each side must be shorter than the sum of the other two:a + b > c,a + c > b,b + c > a. Try (1, 2, 10) — those three lengths can't close into a triangle, because the longest side is longer than the other two combined. This is a built-in property of geometric space, not just a rule someone made up.
Order of checks matters here. Every equilateral triangle is also isosceles (isosceles means "at least two sides equal", and equilateral means "all three equal" — which certainly includes "at least two"). So if you check isosceles first, an equilateral triangle will be labelled "isosceles" — technically true but not specific enough. Check the most specific category first (equilateral), then the less specific one (isosceles), then the default (scalene). This is the same pattern you'll use for the quadrilateral classifier in Section 06.
Squaring vs.pow(). To testa² + b² = c², you can writea*a + b*b == c*c— just multiply the variable by itself. Swift does have apow()function, but for simple squaring,x*xis clearer and slightly faster.
Double comparison is exact. When you compare twoDoublevalues with==, Swift checks whether they're exactly equal bit-for-bit. If you try(0.1 + 0.2) == 0.3, you'll getfalsedue to how decimal fractions are stored in binary. For this exercise's whole-number test cases (3, 4, 5) it's fine, but for real-world floating-point geometry you'd check whether the difference is smaller than a tiny "epsilon" value.
let a = Input(decimal: 3, id: "side a") let b = Input(decimal: 4, id: "side b") let c = Input(decimal: 5, id: "side c") // ── 1. Triangle inequality check ───────────────────── if a + b <= c || a + c <= b || b + c <= a { print("Not a valid triangle!") } else { // ── 2. Side classification (most specific first) ──── if a == b && b == c { print("Equilateral") } else if a == b || b == c || a == c { print("Isosceles") } else { print("Scalene") } // ── 3. Right triangle check (find the longest side) ─ var longest = a var x = b var y = c if b > longest { longest = b x = a y = c } if c > longest { longest = c x = a y = b } if x*x + y*y == longest*longest { print("Also a right triangle!") } }
Why the extra "longest side" hunt? The Pythagorean theorema² + b² = c²only holds whencis the longest side (the hypotenuse). If your inputs are (5, 3, 4), you need to recognise that 5 is the longest and compare3² + 4² = 5². If you just naively used whichever variable you calledc, you'd miss right triangles whose longest side is in a different variable.
| Concept | Connection |
|---|---|
| Geometry — Triangles | Triangle classification by sides: equilateral (all equal), isosceles (two equal), scalene (all different). The triangle inequality (each side shorter than the sum of the other two) is a necessary condition for three lengths to form a triangle. The Pythagorean theorem a² + b² = c² identifies right triangles when c is the hypotenuse. |
And & Or
Swift's logical operators let you combine conditions: && (AND), || (OR), and ! (NOT). Use them to classify an angle across the full 0°–360° range.
a && b // AND: true only if BOTH a and b are true a || b // OR: true if AT LEAST ONE of a or b is true !a // NOT: inverts the truth value
Truth tables — the complete specification of each operator:
// AND (&&) // a | b | a && b // true | true | true // true | false | false // false | true | false // false | false | false // OR (||) // a | b | a || b // true | true | true // true | false | true // false | true | true // false | false | false // NOT (!) // a | !a // true | false // false | true
Given an angle in degrees, classify it as one of:
- Zero angle (= 0°)
- Acute (0° < angle < 90°)
- Right (= 90°)
- Obtuse (90° < angle < 180°)
- Straight (= 180°)
- Reflex (180° < angle < 360°)
- Full rotation (= 360°)
Compound inequalities. In mathematical notation you'd write "90° < angle < 180°" — a single expression with two inequalities. Swift doesn't allow that directly; you have to split it into two parts joined by&&:angle > 90 && angle < 180. Same idea, different syntax. The&&is essential — it says "both conditions must be true for the angle to count as obtuse".
Short-circuit evaluation. Swift is lazy with&&and||: if the first operand already settles the answer, the second is never evaluated. Fora && b, ifaisfalse, the whole expression isfalseno matter whatbis — so Swift skipsb. Same fora || b: ifaistrue, the whole expression istrue, sobis skipped. This matters when the second operand has side effects or might crash (e.g. dividing by zero) — you can use short-circuiting to guard against it.
De Morgan's laws. Here's a pair of logical identities that every programmer learns eventually:In English: "not both" equals "either not the first or not the second". Useful when you want to invert a compound condition — instead of wrapping everything in
!(a && b) == !a || !b!(a || b) == !a && !b!(...), you can distribute the!inside and flip&&to||(or vice versa).
let angle = Input(number: 135, id: "angle") if angle == 0 { print("Zero angle") } else if angle > 0 && angle < 90 { print("Acute") } else if angle == 90 { print("Right") } else if angle > 90 && angle < 180 { print("Obtuse") } else if angle == 180 { print("Straight") } else if angle > 180 && angle < 360 { print("Reflex") } else if angle == 360 { print("Full rotation") } else { print("Out of range (0°–360°)") }
Why no redundant bounds checks? Notice that the "Obtuse" branch only checksangle > 90 && angle < 180— it doesn't also checkangle != 90. That's because Swift already handledangle == 90in the previous branch, and "first match wins" means we never reach "Obtuse" if the angle was exactly 90. Theelse ifchain lets you trust that earlier conditions have already been ruled out.
| Concept | Connection |
|---|---|
| Logic & Reasoning — Boolean Algebra | Angles are classified across the full 0°–360° range. Compound inequalities (e.g. 90° < angle < 180°) represent intervals on the number line — a key IM1 concept. Boolean operators &&, ||, ! correspond exactly to the logical connectives ∧, ∨, ¬ in mathematical logic, and De Morgan's laws are the basis for simplifying any Boolean expression. |
Quadrilateral Checker
Given four side lengths and two booleans describing whether the sides are parallel and whether the angles are right angles, classify the shape.
- Square: all sides equal + both pairs parallel + right angles
- Rhombus: all sides equal + both pairs parallel, but not right angles
- Rectangle: opposite sides equal + both pairs parallel + right angles
- Parallelogram: opposite sides equal + both pairs parallel (no angle requirement)
- Trapezoid: at least one pair of parallel sides
- Irregular quadrilateral: none of the above
The quadrilateral hierarchy. Quadrilaterals form a nested hierarchy of increasingly specific shapes:So:
- Every square is a rhombus (all sides equal) AND a rectangle (all angles 90°)
- Every rhombus is a parallelogram (opposite sides parallel)
- Every rectangle is a parallelogram
- Every parallelogram is a trapezoid (has at least one pair of parallel sides)
- Every trapezoid is a quadrilateral (4 sides)
square ⊂ rhombus ⊂ parallelogram ⊂ trapezoid ⊂ quadrilateral, and alsosquare ⊂ rectangle ⊂ parallelogram. A square lives in the intersection of "rhombus" and "rectangle".
Subclass checks must come first. Because a square is also a rhombus, rectangle, parallelogram, and trapezoid, checking "is it a square?" must come before "is it a rhombus?", which must come before "is it a parallelogram?", and so on. This is the same "most specific first" rule you used in the triangle classifier (Section 04) — an equilateral triangle is also an isosceles triangle, so you checked equilateral first.
Intermediate variables make complex conditions readable. Rather than writingtop == right && right == bottom && bottom == leftinline three times, store it in a named variable:let allSidesEqual = .... Now yourifstatements read like English:if allSidesEqual && bothParallel && rightAngles. This is a key technique for keeping classifier code understandable.
// Four side lengths (in canvas units) let top = Input(decimal: 80, id: "top") let right = Input(decimal: 80, id: "right") let bottom = Input(decimal: 80, id: "bottom") let left = Input(decimal: 80, id: "left") // Two boolean properties (change these to test different shapes) let horizontalParallel = true // top ∥ bottom let verticalParallel = true // left ∥ right let rightAngles = true // all four corners = 90° // ── Derived properties (named Booleans) ────────────── let allSidesEqual = top == right && right == bottom && bottom == left let oppositeSidesEqual = top == bottom && left == right let bothPairsParallel = horizontalParallel && verticalParallel let somePairParallel = horizontalParallel || verticalParallel // ── Classify (most specific first!) ────────────────── if allSidesEqual && bothPairsParallel && rightAngles { print("Square") } else if allSidesEqual && bothPairsParallel { print("Rhombus") } else if oppositeSidesEqual && bothPairsParallel && rightAngles { print("Rectangle") } else if oppositeSidesEqual && bothPairsParallel { print("Parallelogram") } else if somePairParallel { print("Trapezoid") } else { print("Irregular quadrilateral") }
What was wrong with the "withoutrightAngles" version? If you only checked side lengths and parallelism, you couldn't distinguish a square from a rhombus — they share those properties. TherightAnglesflag is what separates them: a square has right angles, a rhombus doesn't. Same for rectangle vs parallelogram. This is why real geometry tools need to look at angles, not just side lengths, to classify quadrilaterals fully.
| Concept | Connection |
|---|---|
| Geometry — Quadrilaterals | Quadrilaterals form a hierarchy: square ⊂ (rhombus ∩ rectangle) ⊂ parallelogram ⊂ trapezoid ⊂ quadrilateral. Boolean logic mirrors set inclusion — a square satisfies all conditions that a rectangle satisfies, plus more. The order of classification checks encodes the "most specific first" principle from set theory. |
Right Angle Test
Given three angles of a triangle (as Input(number:)), write a program that verifies they sum to 180°, checks for a right angle, and checks for equiangularity.
- Verifies that all three angles sum to 180° (prints a warning if not)
- Checks whether the triangle is right-angled (has at least one 90° angle)
- Checks whether it is equiangular (all three angles equal)
Test with (90, 45, 45), (60, 60, 60), (30, 60, 90), and (60, 60, 70) — the last one should fail the sum test.
The triangle angle sum theorem. For any triangle in flat (Euclidean) space, the three interior angles always sum to exactly 180°. This is one of the most important theorems in elementary geometry — it's what distinguishes flat geometry from spherical or hyperbolic geometry (where the sum would be more or less than 180°). A triple of angles that doesn't sum to 180° cannot form a triangle in the plane.
Validation first, then classification. Notice the structure: first check whether the input even makes sense (do the angles sum to 180°?), then classify if it does. This "guard early, process later" pattern is a universal programming technique — don't waste time classifying bad input, and don't let bogus results leak out. You used the same pattern in Section 04 with the triangle inequality check.
Equiangular ↔ equilateral. For triangles specifically, "all angles equal" is logically equivalent to "all sides equal". If all three angles are the same, they must each be 60° (because 60 + 60 + 60 = 180), and that forces all three sides to be the same length. This equivalence is unique to triangles — for other polygons, equiangular and equilateral are independent properties (a rectangle is equiangular but not equilateral; a rhombus is equilateral but not equiangular).
Independent checks need nestedifs, notelse if. A triangle can be both right-angled and equiangular only if... well, it can't (a 90° angle prevents equiangularity). But more generally, a triangle could have multiple classifications — right AND isosceles, for example. When classifications aren't mutually exclusive, use separateifstatements rather than anelse ifchain, so each check runs independently.
let a1 = Input(number: 90, id: "angle 1") let a2 = Input(number: 45, id: "angle 2") let a3 = Input(number: 45, id: "angle 3") // Guard: do the angles sum to 180°? if a1 + a2 + a3 != 180 { print("Warning: angles don't sum to 180°") } else { // Two independent classifications — neither excludes the other if a1 == 90 || a2 == 90 || a3 == 90 { print("Right triangle") } if a1 == a2 && a2 == a3 { print("Equiangular (therefore equilateral)") } }
A 45-45-90 triangle. The test case (90, 45, 45) is a right isosceles triangle — half of a square cut along its diagonal. It has one 90° angle (hence "right"), and two equal 45° angles (hence "isosceles"). Both properties are true at the same time, which is why the twoifstatements need to be independent rather than chained withelse if.
| Concept | Connection |
|---|---|
| Geometry — Triangle Angle Sum | The angle sum property of triangles states that the three interior angles always sum to 180° in Euclidean (flat) geometry. An equiangular triangle has three 60° angles and must also be equilateral — the "equiangular ↔ equilateral" equivalence is a defining property of triangles, not shared by other polygons. |
Colour by Rule
Draw a row of squares using a loop, and colour each square based on a rule: squares in positions divisible by 3 get one colour, positions divisible by 2 (but not 3) get another, and the rest get a third colour.
The modulo operator%. Swift's%gives the remainder after division.7 % 3is1(because 7 = 2·3 + 1).i % 3 == 0is true exactly wheniis divisible by 3. This is the single most useful operator for number theory: divisibility, parity (odd vs even viai % 2), cyclic patterns (i % nwraps around everynsteps), and any "every Nth thing" pattern.
Order matters:% 3must come before% 2. The number 6 is divisible by both 2 and 3, so bothi % 3 == 0andi % 2 == 0are true for it. With anif/else ifchain, only the first matching branch runs — so if you check% 3first, 6 gets the "divisible by 3" colour; if you check% 2first, 6 gets the "divisible by 2" colour. The exercise asks for the first behaviour, so the% 3check comes first. Same principle as "most specific first" from Sections 04 and 06.
Counting from 1 vs. from 0. Swift'sfor i in 1...12counts from 1 to 12 inclusive. If you wrotefor i in 0..<12you'd get 0 through 11. For this exercise, the "position" of the square is 1-indexed (human counting), so1...12is more natural. Be careful which convention you use — array indices in Swift are 0-indexed, but human "position in a sequence" is usually 1-indexed.
import UIKit let count: Int = Input(number: 12, id: "count") let size: Double = 40 let gap: Double = 10 let startX: Double = -240 for i in 1...count { // Pick a colour based on divisibility let color: UIColor if i % 3 == 0 { color = .blue // 3, 6, 9, 12, … } else if i % 2 == 0 { color = .yellow // 2, 4, 8, 10, … (not also divisible by 3) } else { color = .red // 1, 5, 7, 11, … } // Draw a filled square at the computed x position var square = Pen() square.penColor = color square.fillColor = color square.goto( x: startX + Double(i - 1) * (size + gap), y: -size / 2 ) for _ in 1...4 { square.addLine(distance: size) square.turn(degrees: 90) } addShape(pen: square) }
Why create a newsquarepen each loop? Each square needs its own colour and its own starting position. Creating a freshPen()inside the loop guarantees both — the colour is set once per square, andgotojumps the new pen to the right x position before drawing. This is the "one pen per shape" pattern you learned in Chapter II (Shape Properties with Variables).
| Concept | Connection |
|---|---|
| Number — Divisibility | The modulo operator checks divisibility — a key number theory concept. Multiples of 3 and multiples of 2 create overlapping sets (their intersection is multiples of 6). The union and intersection of these sets can be described using Boolean logic, and the order of else if checks determines which label overlapping elements receive. |
Polygon Properties
Write a program that, given Inputs for the number of sides and the side length of a regular polygon, calculates and prints key properties, then draws the polygon. Drag the sliders to explore any regular polygon from a triangle to a hexagon to a decagon.
Calculate and print all of these:
- The exterior angle (
360° ÷ n) - The interior angle (
180° − exterior) - The perimeter (
n × side length) - Whether the polygon is convex (always true for regular polygons — use an
ifto check and explain why)
Then use a loop (from Chapter III) to draw the polygon with the calculated exterior angle as the turn.
The two angle formulas. For a regular polygon withnsides:For a triangle (
- Each exterior angle =
360° ÷ n. If you walked all the way around the polygon, your total turning would be exactly 360° (one full rotation) — divide that evenly acrossncorners.- Each interior angle =
180° − exterior=180° − (360° ÷ n). The interior angle and exterior angle at each vertex sum to 180° because together they form a straight line.n = 3): exterior = 120°, interior = 60°. For a square: 90° and 90° (the only regular polygon where they're equal). For a hexagon: 60° and 120°. For a decagon: 36° and 144°.
Why are all regular polygons convex? A polygon is convex when every interior angle is less than 180°. For a regularn-gon, the interior angle is180° − (360° ÷ n)=180 × (1 − 2/n). Forn ≥ 3,2/n ≤ 2/3, so the interior angle is at most180 × (1 − 0) = 180°and at least180 × (1 − 2/3) = 60°. It's strictly less than 180° for any finiten, so the polygon is convex. A concave polygon would have at least one "dent" where an interior angle exceeds 180° — that can only happen in irregular polygons.
Int vs Double: why do we castn?Input(number:)gives you anInt(whole number), but360.0 / 3in Swift won't automatically produce aDoubleif both sides areInt. You need360.0 / Double(n)to force floating-point division. This is the same type-casting trick you learned in Chapter III when computing angles for regular polygons —Double(n)converts an integer to a decimal so the division produces aDoubleresult.
Preview of Chapter V. Notice how this code "hardcodes" the specific polygon — you have to rerun it to draw a different shape. In the next chapter, you'll learn to package this logic into a reusable function likedrawRegularPolygon(sides:, sideLength:)that you can call with any arguments. For now,Inputgets you most of the interactivity without the full function syntax.
let n = Input(number: 7, id: "sides") let sideLength = Input(decimal: 60, id: "side length") // Calculate properties let exteriorAngle = 360.0 / Double(n) let interiorAngle = 180.0 - exteriorAngle let perimeter = Double(n) * sideLength print("Exterior angle: \(exteriorAngle)°") print("Interior angle: \(interiorAngle)°") print("Perimeter: \(perimeter)") // Convexity check if interiorAngle < 180 { print("Convex — all interior angles are less than 180°") } else { print("Not convex") } // Draw the polygon (using the loop from Chapter III) for _ in 1...n { pen.addLine(distance: sideLength) pen.turn(degrees: exteriorAngle) }
String interpolation with\(). Inside a string literal,\(expression)inserts the value of that expression."Perimeter: \(perimeter)"becomes"Perimeter: 420.0"(or whatever the current value is). This is Swift's equivalent of printf formatting — clean, type-safe, and readable. You can use any expression inside the parentheses, not just a variable name.
| Concept | Connection |
|---|---|
| Geometry — Regular Polygons | All interior angles of a regular polygon are equal to 180° − (360° ÷ n). A polygon is convex when all interior angles are less than 180° — a condition satisfied by all regular polygons with n ≥ 3. The relationship between n, interior angle, exterior angle, and perimeter is the classic set of regular polygon formulas from IM1 geometry. |