72 lines
1.6 KiB
Python
72 lines
1.6 KiB
Python
|
|
'''Cantor set – strings as both model and display.'''
|
|||
|
|
|
|||
|
|
from itertools import (chain, islice)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# cantorLines :: Int -> String
|
|||
|
|
def cantorLines(n):
|
|||
|
|
'''N levels of cantor segmentation,
|
|||
|
|
obtained and displayed in the
|
|||
|
|
form of lines of block characters.
|
|||
|
|
'''
|
|||
|
|
return '\n'.join(
|
|||
|
|
[''.join(x) for x in islice(
|
|||
|
|
iterate(cantor)(
|
|||
|
|
[3 ** (n - 1) * '█']
|
|||
|
|
), n
|
|||
|
|
)]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# cantor :: [String] -> [String]
|
|||
|
|
def cantor(xs):
|
|||
|
|
'''A cantor line derived from its predecessor.'''
|
|||
|
|
def go(s):
|
|||
|
|
m = len(s) // 3
|
|||
|
|
blocks = s[0:m]
|
|||
|
|
return [
|
|||
|
|
blocks, m * ' ', blocks
|
|||
|
|
] if '█' == s[0] else [s]
|
|||
|
|
return concatMap(go)(xs)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# MAIN ----------------------------------------------------
|
|||
|
|
# main :: IO ()
|
|||
|
|
def main():
|
|||
|
|
'''Testing cantor line generation to level 5'''
|
|||
|
|
|
|||
|
|
print(
|
|||
|
|
cantorLines(5)
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# GENERIC -------------------------------------------------
|
|||
|
|
|
|||
|
|
|
|||
|
|
# concatMap :: (a -> [b]) -> [a] -> [b]
|
|||
|
|
def concatMap(f):
|
|||
|
|
'''A concatenated list over which a function has been mapped.
|
|||
|
|
The list monad can be derived by using a function f which
|
|||
|
|
wraps its output in a list,
|
|||
|
|
(using an empty list to represent computational failure).'''
|
|||
|
|
return lambda xs: list(
|
|||
|
|
chain.from_iterable(map(f, xs))
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# iterate :: (a -> a) -> a -> Gen [a]
|
|||
|
|
def iterate(f):
|
|||
|
|
'''An infinite list of repeated
|
|||
|
|
applications of f to x.
|
|||
|
|
'''
|
|||
|
|
def go(x):
|
|||
|
|
v = x
|
|||
|
|
while True:
|
|||
|
|
yield v
|
|||
|
|
v = f(v)
|
|||
|
|
return lambda x: go(x)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# MAIN ---
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
main()
|