Why?
- Thinking about a sequence of odd numbers where numbers divisible by 3 are not part of it I came to a sequence starting with 5, 7, 11, 13, 17, 19, ...
- The interesting property of this sequence is that the sequence of differences between the individual elements are 2,4,2,4,2,...
How?
- I'm not a math expert (unfortunately) but I could imagine that there is a quite simple formula to get this.
- However I thought that using different combinations of defined functions a script could do the favour for me.
Result?
- Formula:
(((-1)**(x-1))+1)+2
-> Simplified ->-1**(x-1) + 3
(now clear to you?) - You have to look for the sequence [4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2]
Out of scope:
- Does not check for using lambda functions only and "x" only in the lambda functions.
- The Python script does not simplify functions like changing ((x+1)+1) to x+2 - would be an interesting recipe - by the way :)
Please note
- You should not add other functions than lambda.
- You should always use "x" in your formular.
- Be aware that the actual setup runs a few minutes (about 3 minutes) and you can imagine - surely - that adding further functions will definitely increase the runtime.
Side effects?
- Quite funny to produce a sequence of nines with
(((-1)**(2*x))+2)**2
. - If you apply the first binomial theorem (a+b)^2 = a^2 + 2ab + b^2 then you see why!
What I have learned from this?
- The biggest nightmare I did have with the Sequence class because of not knowing how to generate unique elements of this in a set (__eq__ and __hash__ are required); and I have to ensure that the hash code is calculated once only.
- The 'combineFunctions' was interesting to me. I have never used 'inspect.getsource' before.
- A few minutes does not sound much but for developing all times with more than 30 seconds are not comfortable. There are just 325 sequences and to investigate for certain sequences you probably have to have some more formula. Maybe I would have to take another approach for that.
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 | """
@author Thomas Lehmann
@file sequenceBuilder.py
@brief generates sequences throughout different combinations of functions
"""
import sys
import itertools
import inspect
import re
class Sequence(object):
""" represents a sequence and the used formula """
def __init__(self, sequence, formula):
""" storing one sequence and the relating formula """
self.sequence = sequence
self.formula = formula
self.hashCode = hash(tuple(self.sequence))
def __eq__(self, other):
""" required for unique elements in set container """
return self.hashCode == other.hashCode
def __lt__(self, other):
""" required for sorting only """
for a,b in zip(self.sequence, other.sequence):
if a < b: return True
if a > b: return False
return False
def __hash__(self):
""" required for unique elements in set container """
return self.hashCode
def __repr__(self):
return "%s - %s" % (self.sequence, self.formula)
class SequenceBuilder(object):
def __init__(self):
""" initializes for empty containers only """
self.registeredFunctions = []
self.sequences = set()
def add(self, function):
""" adds a function to the list of functions
@param function is expected to be a lambda expression
"""
self.registeredFunctions.append(function)
def createSequences(self, fromPosition, toPosition):
""" using the permutation of all functions to generate sequences
@param fromPosition start position/index/value
@param toPosition end position/index/value
"""
self.sequences = set()
for r in range(1,len(self.registeredFunctions)):
for functions in itertools.permutations(self.registeredFunctions, r):
position = fromPosition
sequence = []
while position <= toPosition:
value = position
for function in functions:
value = function(value)
sequence.append(value)
position += 1
self.sequences.add(Sequence(sequence[0:], self.combineFunctions(functions)))
def combineFunctions(self, functions):
""" generates a combined formula as used for the calculation
@param functions the list of individual functions (lambda code)
@return the combined formula
@note out of scope is the simplification (like: (x+1)+1 => x+2)
"""
expression = ""
for function in reversed(functions):
match = re.match(".*\((?P<expression>lambda.*)\).*", inspect.getsource(function))
if match:
functionCode = match.group("expression")
functionCode = functionCode[functionCode.find(":")+1:].strip()
if not len(expression):
expression = functionCode
else:
expression = expression.replace("x", "("+functionCode+")")
return expression
def main():
""" application entry point """
print("Sequence builder v0.1")
print("...Using Python %s" % sys.version.replace("\n", " - "))
builder = SequenceBuilder()
builder.add(lambda x: x-1)
builder.add(lambda x: x-2)
builder.add(lambda x: x+1)
builder.add(lambda x: x+2)
builder.add(lambda x: 2*x)
builder.add(lambda x: x**2)
builder.add(lambda x: (-1)**x)
# takes a while...
builder.createSequences(1, 20)
print("...%d sequences found:" % len(builder.sequences))
for sequence in sorted(builder.sequences):
print(sequence)
if __name__ == "__main__":
main()
|
In one comment you see the extract of the full output!
1 comment
Thomas Lehmann (author)
12 years, 1 month ago
#
|
flag