HàPhan 河

Fun with Prime Numbers

Wikipedia says:

A prime number (or a prime) is a natural number greater than 1 that cannot be formed by multiplying two smaller natural numbers. A natural number greater than 1 that is not prime is called a composite number. For example, 5 is prime because the only ways of writing it as a product, 1 × 5 or 5 × 1, involve 5 itself. However, 6 is composite because it is the product of two numbers (2 × 3) that are both smaller than 6.

Therefore, to check if a number is prime, we need to check for it's divisibility on all numbers less that it, start from 2 through the square root of it.

extension Int {
    var isPrime: Bool {
        if self < 2 { return false }
        var x = 2
        while (x * x <= self) {
            if self % x == 0 { return false }
            x += 1
        }
        return true
    }
}

In episode 7 of Vietnamese version of The Brain gameshow, a young student was challenged to find a password to unlock a treasure. The password was hidden on a board of 1380 numbers with 5 in length. In those 1380 numbers, there were 7 prime numbers formed a polygons with only 2 diagonal lines that are perpendicular(90 degrees). The password is at the intersection of those 2 lines. See picture below

Screen-Shot-2019-12-11-at-10.52.40-AM

He solved the problem in 30 minutes. What a genius boy.

From my viewpoint as a software engineer, I'm trying to figure out the most efficient way to implement his brain to resolve this problem. :)

The only way to solve is to scan the 2D matrix and find 7 prime numbers. Then find the intersection of perpendicular diagonals. If we use the function isPrime above for every number, our algorithm with do duplicated works. How about pre-generate a set of prime numbers that are less than 100000

extension Int {
    var lowerPrimes: [Int] {
        var isPrimeArray = Array(repeating: true, count: self + 1)

        var currentPrime = 2
        while currentPrime <= Int(sqrt(Float(self))) {
            for i in stride(from: currentPrime * currentPrime, through: self, by: currentPrime) {
                isPrimeArray[i] = false
            }
            repeat {
                currentPrime += 1
            } while (isPrimeArray[currentPrime] == false && currentPrime < self + 1)
        }


        //display all result with list
        var result: [Int] = []

        for i in 2..<isPrimeArray.count {
            if isPrimeArray[i] {
                result.append(i)
            }
        }

        return result
    }
}

Let me describe a abit about function above. Start from currentPrime = 2, we mark all numbers greater than 2 * 2 that's divisible by 2 follow this formula: 4 + 2 * i. Then increase currentPrime till it's not appear on the mark list. Repeate previous step.
After done the process we will have list of primes.

Continue with our algorithm, with every number just take constant time to check isPrime. Space complexity here is O(n) - n is largest posible number of the board, and time complexity is O(p x q) - board's size.

func findPassword(_ board: [[Int]]) -> Int {
    let boardMax = board.reduce([], +).max()!
    let primes = Set(boardMax.lowerPrimes)
    
    var polygons: [(Int, Int)] = []
    
    for i in 0..<board.count {
        for j in 0..<board[0].count {
            if primes.contains(board[i][j]) { polygons.append((i,j)) }
        }
    }
    
    let sortedX = polygons.sorted { $0.0 < $1.0 }
    let sortedY = polygons.sorted { $0.1 < $1.1 }
    
    print(polygons)
    
    var x: Int = -1
    for i in 1..<sortedX.count {
        if sortedX[i].0 == sortedX[i-1].0 {
            x = sortedX[i].0
        }
    }
    
    var y: Int = -1
    for i in 1..<sortedY.count {
        if sortedY[i].1 == sortedY[i-1].1 {
            y = sortedY[i].1
        }
    }
    
    if x == -1 || y == -1 {
        return -1
    }
    
    return board[x][y]
}

And this is the game's board

func generateBoard() -> [[Int]] {
    var board = Array(repeating: Array(repeating: 4, count: 41), count: 47)
    
    //password
    board[20][14] = 17845
    
    //primes
    board[20][7] = 1489
    board[25][9] = 587
    board[14][11] = 3167
    board[3][14] = 2137
    board[33][14] = 823
    board[7][17] = 977
    board[20][21] = 9341
    
    return board
}

Summary, to have his brain we need to remember all prime numbers that are lower than 10000... HOW???

https://www.mathsisfun.com/numbers/prime-numbers-to-10k.html

Happy coding.

Comments