UNC-CH COMP 210

Mad Math Minute

The Universal Language of Math


FRACTRAN (John Conway)

FRACTRAN is an esoteric programming language invented by John Conway (Game of Life). It is know to be Turing complete; this means that for any program you can write in, say, Java you can write a program in FRACTRAN to compute the same function. Since FRACTRAN programs "compute" sequences of integers, this would involve some encoding schemes (as in the example to follow).

A FRACTRAN program is an ordered list of positive fractions together with an initial positive integer input n.

The program is run by updating the integer n as follows:

  1) for the first fraction f in the list for which nf is an integer, 
     replace n by nf 

  2) repeat this rule until no fraction in the list produces an 
     integer when multiplied by n, then halt.

Here is one program in FRACTRAN:

Executing it, this FRACTRAN program generates the following sequence of integers:

    2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290, 770, ... 
After starting with n=2, this sequence occasionally contains numbers which have powers of 2 when prime factored, and here are the powers of 2 that show up (in the order they occur):
   2^2 = 4, 2^3 = 8, 2^5 = 32, 2^7 = 128, 2^11 = 2048, 2^13 = 8192, 2^17 = 131072, 2^19 = 524288, …
The exponent part of these powers of two are the primes (in order): 2, 3, 5, 7, 11, 13, 17, etc.


John Horton Conway passed away in April 2020 (aged 82) from Covid-19.


Here is a video of a 2012 lecture he gave at Berkley on the Collatz Conjecture, and FRACTRAN:
(Conway himself) FRACTRAN: A Ridiculous Logical Langauage

Conway paper on FRACTRAN

wiki on FRACTRAN

FRACTRAN interpreter in Python

Project Euler problem 308

btw... Project Euler. Practice your programming thinking skills.

essay on FRACTRAN.


Mandelbrot and Fractals

Infinite Self-Similarity Try it, interactively

Try it, interactively


Number Systems



Rational numbers
are numbers that can be written in the form p/q, where p and q are integers and q≠0. The difference between rational numbers and fractions lies in the fact that fractions cannot have negative numerator or denominator. Hence, the numerator and denominator of a fraction are whole numbers (denominator ≠ 0), whereas in the case of rational numbers, the numerator and denominator are integers.

Real numbers
... are hard to define. We sort of know one when we see one. One nicely circular definition is: the Reals are the union of the Rationals and the Irrationals (as the diagram shows), and then of course, the Irrationals are defined as a Real that is not Rational.
We see from this attempt how the adjective real comes about; it was used in the 17th century by René Descartes, to distinguish real numbers from imaginary numbers (such as the square roots of −1).
Here are a pile of ways to do better in defining the Reals: https://proofwiki.org/wiki/Definition:Real_Number.
A real number can be defined as a number which is identified with a point on the real number line. The real number line then is an arbitrary infinite straight line each of whose points is identified with a real number such that the distance between any two real numbers is consistent with the length of the line between those two points. The Reals are characterized by that distance being arbitrarily small.
We commonly say the Reals are dense, meaning that between any two reals a and b, we will find another real c. In fact we find an infinite quantity of reals between any two others. This is an uncountable infinity (meaning there are more reals than there are integers).

Real Algebraic numbers
are a subset of the Reals. A real number is an algebraic number if it is a zero of a polynomial with integer coefficients; and its degree is the least of the degrees of the polynomials with it as a zero. For example, the rational number a/b (with a, b being non-zero integers) is an algebraic number of degree one, because it is a zero of bx-a. As another example, the golden ratio, (1+sqrt(5))/2, is an algebraic number, because it is a root of the polynomial x^2 − x − 1. That is, it is a value for x for which the polynomial evaluates to zero

Irrational numbers
are numbers that cannot be the result of dividing one integer by another integer (a ratio of two integers). We again get hints of our circular definition of the Reals. Irrational numbers have decimal expansions that neither terminate nor become periodic.

Transcendental numbers
If you are Real, and Irrational, and yet not Algebraic, then you are Transcendental. But some Complex numbers are Transcendental as well.
A transcendental number is a (possibly complex) number that is not the root of any integer polynomial. Every real transcendental number must also be irrational, since a rational number is the root of an integer polynomial of degree one.
The best known transcendental numbers are π, 𝜏 and e, but the set is uncountably infinite.

Complex numbers
A complex number is an element of a number system that extends the real numbers with a specific element denoted i, called the imaginary unit and satisfying the equation i^2 = − 1 . Every complex number can be expressed in the form a + bi, where a and b are real numbers.
Complex numbers allow solutions to all polynomial equations, even those that have no solutions in real numbers. More precisely, the fundamental theorem of algebra asserts that every non-constant polynomial equation with real or complex coefficients has a solution which is a complex number.
For example, the equation (x+1)^2 = −9 has no real solution, since the square of a real number cannot be negative, but has the two non-real complex solutions −1+3i and −1−3i .
As another example, the complex number 1+i is algebraic because it is a root of x4 + 4.


Pearl Hacks 2024 Director

Apply here (bit.ly/PH24APPLY) to be a Pearl Hacks Director!

DEADLINE: Wednesday, Apr. 5th, 2023 11:59 PM EST

** NO computer science experience required. People of all genders and majors are 
welcome to apply, but you must be a UNC student!

Pearl Hacks is a beginner-friendly hackathon at UNC for women and gender 
non-conforming students. Get involved with the technology field and leadership 
experience by applying to join our Board! This is also a great way to get 
involved with UNC computer science!

Pearl Hacks is where you can help under-represented people, specifically 
women and gender non-conforming students, pursue their interests in technology. 
Pearl Hacks is a growing organization, looking for motivated students like 
you to take Pearl Hacks to new heights. Your work will directly impact 
the experience of hundreds of people from across the US.

Learn more about our positions: https://bit.ly/PH24BOARD

Asymptotic Analysis Practice

In a programming assignment, you are asked to implement a function named subd (in python). The function’s parameters are of type list[str] and dict[str, int]. The purpose of the function is to return a new dictionary whose keys are the intersection of items in the list and keys in the dictionary parameter.

The resulting dictionary’s values are copies of the dictionary parameter’s of the same key.

Example usage:

>>> subd(["a", "c", "d"], {"a": 1, "b": 2, "c": 3})
{"a": 1, "c": 3}

Consider these two ways to implement this function

def subd_v1(al: list[str], ad: dict[str, int]) -> dict[str, int]:
   result: dict[str, int] = {}
   for key in ad:
      if key in al:
         result[key] = ad[key]
   return result

def subd_v2(al: list[str], ad: dict[str, int]) -> dict[str, int]:
   result: dict[str, int] = {}
   for key in al:
      if key in ad:
         result[key] = ad[key]
   return result

Are these two functions equivalent? Is one as good as the other? Or would one be preferable over the other? Why, or why not?

Note that a dictionary in Python is a hashmap.



Conway's Game of Life

It's a cellular automaton
This means it's another abstract model of computation, like a Turing machine, generative grammars, lambda-calculus, or Post production systems.
Try playing it

John Horton Conway

Try playing it, another one

Turing complete

Divide 1/998001

The result is a string of digits after the decimal point with the pattern 000 001 002 003 .... up to 999


except ...                                         ^ 998

OK then, now try 1/9801


Slow and Fast Multiplication
Remember multiplying in school? Ever think about the worst-case time complexity of the method you learned?

You can think of integer arithmetic as a COMP-210-style ADT, where the values of the type -- the values being operated on -- are the counting numbers, and the operations of the type are add, sub, div, mult, etc.

If you want to mult two numbers with D digits each, what is O(mult), the worst case time complexity to multiply?
   mult(3282,7153)  ,   in school we write it like this      3282
                                                           x 7153
                                                           ------ 
We dont really think about our multiplying being "slow" because we rarely manually multiply two number with more than 4 or 5 digits each. Remember, "slow" and "inefficient" algorithms are just fine for small problems. But what if you need to do this problem? We sharpen a box of pencils, get a loooong, wiiiiiddeeee piece of paper, and a vat of coffee, and settle in for a few days or weeks (well, really, we don't try to do this with our school-taught manual algorithm).

And then, what if we need to multiply two numbers with a hundred thousand digits each?
Or a million digits each? Processes in cryptography and security require this.


Karatsuba algorithm is O(N^1.585)
Karatsuba algorithm is O(N^1.585), or O(N^(log 3))
Java code for it

In 1962, this algorithm for fast multiply was found and published. It disproved a conjecture (supposition, not a proof) by Kolmogorov that any multiply algorithm for two N digit numbers needed O(N^2) steps.

Schönhage–Strassen algorithm is O(n logN loglogN)
Java code for it

In 1971 these mathemeticians came up with a faster multiply, and they also proved that there was a O(N log N) algorithm possible... but they were not able to find such as algorithm.

Now (in 2019) van der Hoven and Harvey have found an O(N log N) algorithm, as proven to exist in 1971.



What is the volume of lunch?