aboutsummaryrefslogtreecommitdiff
path: root/src/PatternFinder.kt
blob: fb660f5d093d8ac836d76cd959f3b06724eda32d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import java.lang.Math.floor
import java.lang.Math.max
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager

data class Expression(val expression: String)

fun main(args:Array<String>) {
    while (true) {
        println("---------------------------")
        println("Separate numbers by comma.")
        print("Enter numbers: ")

        val inputNumbers = readLine()!!.split(",").map { it.trim().toDouble() }
        val formula = findFormula(inputNumbers)
        println("Formula: $formula")
        println("Pattern: " + continuePattern(formula))
    }
}

private fun findFormula(numbers: List<Double>): String {
    // Find difference between numbers
    val differences = listOf(
            numbers[1] - numbers[0],
            numbers[2] - numbers[1]
    )

    var incrementsByDifference = true
    var increment = 0.0
    if (differences[0] != differences[1]) // If the pattern doesn't increment by difference
        incrementsByDifference = false
    else
        increment = differences[0]

    // Start-value
    val nAsExponent = nAsExponent(differences, numbers)
    val startValueDifference = when {
        incrementsByDifference -> differences[0]             // xn
        nAsExponent            -> getBase(differences) // x^n
        else                   -> 1.0                        // n^x
    }

    val startValue = numbers[0] - startValueDifference

    // Exponents
    var base = "n"
    var exponent = ""
    if (nAsExponent(differences, numbers)) {
        base = getBase(differences).cleanRedundancy() + "^"
        exponent = "n"
    } else if (!incrementsByDifference) {
        base = "n^"
        exponent = getExponent(numbers[1], startValue).cleanRedundancy()
    }

    // Add the pieces together
    var formula = increment.cleanRedundancy()
    formula += base + exponent + startValue.cleanRedundancy().addSign()

    return formula
}

private fun continuePattern(formula: String): String {
    var output = ""
    for (i in 1..20) {
        val expression = Expression(formula.replace("n", i.toString()))
        output += expression.calculate().cleanRedundancy() + ", "
    }

    return output.cleanRedundancy()
}

fun Double.cleanRedundancy(): String {
    return when {
        this == 0.0         -> return ""
        floor(this) == this -> this.toInt().toString()
        else                -> return this.toString()
    }
}

fun String.cleanRedundancy(): String {
    return if (this.endsWith(", "))
        this.substring(0, this.length - 3)
    else
        this
}

fun String.addSign(): String {
    return if (!this.startsWith("-"))
        "+" + this
    else
        this
}

fun Expression.calculate(): Double {
    val addSubSign = max(expression.indexOf("+"), expression.indexOf("-"))
    val addSub = expression.substring(addSubSign + 1, expression.length).toDouble()
    val numbers = expression.substring(0, addSubSign)
            .split(Regex("[*^]")).map { it.toDouble() }

    if (expression.contains("*"))
        return numbers[0] * numbers[1] + addSub
    else if (expression.contains("^"))
        return Math.pow(numbers[0], numbers[1]) + addSub
    return 0.0
}

private fun getBase(differences: List<Double>): Double {
    return differences[1] / differences[0]
}

private fun getExponent(secondNumber: Double, startValue: Double): Double {
    return Math.log(secondNumber - startValue) / Math.log(2.0)
}

private fun nAsExponent(differences: List<Double>, numbers: List<Double>): Boolean {
    val base = getBase(differences)
    return  Math.log(numbers[1] - (base - 1)) / Math.log(base)  == 2.0
}