Jump to content

Intersecting number wheels: Difference between revisions

→‎Python: Functional composition: Added a functionally composed variant (map-accumulation of a recursion)
m (→‎{{header|Haskell}}: Allowed for ill-formed wheel sets (unknown wheel names))
(→‎Python: Functional composition: Added a functionally composed variant (map-accumulation of a recursion))
Line 738:
Generates:
1 3 5 1 4 3 1 4 5 1 3 4 1 3 5 1 4 3 1 4 ...</pre>
 
===Python: Functional composition===
Defining a unit rotation of the wheel set as a recursive descent, and taking
a map-accumulation of this recursion
over a list of specific length and arbitrary content.
{{Trans|Haskell}}
{{Works with|Python|3.7}}
<lang python>'''Intersecting number wheels'''
 
from functools import reduce
from itertools import cycle, islice
 
 
# clockWorkTick :: Dict -> (Dict, Char)
def clockWorkTick(wheelMap):
'''The new state of the wheels, tupled with the
digit found, both resulting from a recursive
descent from a single click of the first
wheel, terminating at the first digit found.'''
def click(wheels, name):
wheel = wheels[name]
v = wheel[0]
wheels.update({name: leftRotate(wheel)})
return (Tuple if isDigit(v) else curry(click))(
wheels
)(v)
return click(wheelMap, 'A')
 
 
# leftRotate :: [a] -> [a]
def leftRotate(xs):
''' A list shifted cyclically towards
the left by one position.
'''
return list(islice(cycle(xs), 1, 1 + len(xs)))
 
 
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''First twenty values from each set of test wheels.'''
 
for wheels, series in [
mapAccumL(compose(const)(clockWorkTick))(
dict(kvs)
)(' ' * 20) for kvs in [
[('A', "123")],
[('A', "1B2"), ('B', "34")],
[('A', "1DD"), ('D', "678")],
[('A', "1BC"), ('B', "34"), ('C', "5B")]
]
]:
print((wheels, ''.join(series)))
 
 
# GENERIC -------------------------------------------------
 
# Tuple (,) :: a -> b -> (a, b)
def Tuple(x):
'''Constructor for a pair of values,
possibly of two different types.
'''
return lambda y: (
x + (y,)
) if isinstance(x, tuple) else (x, y)
 
 
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
 
 
# const :: a -> b -> a
def const(k):
'''The latter of two arguments,
with the first discarded.
'''
return lambda _: k
 
 
# curry :: ((a, b) -> c) -> a -> b -> c
def curry(f):
'''A curried function derived
from an uncurried function.
'''
return lambda x: lambda y: f(x, y)
 
 
# isDigit :: Char -> Bool
def isDigit(c):
'''True if the character c is a digit.'''
return c.isdigit() and (1 == len(c))
 
 
# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumL(f):
'''A tuple of an accumulation and a list derived by a
combined map and fold,
with accumulation from left to right.
'''
def go(a, x):
tpl = f(a[0])(x)
return (tpl[0], a[1] + [tpl[1]])
return lambda acc: lambda xs: (
reduce(go, xs, (acc, []))
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>
({'A': ['3', '1', '2']}, '12312312312312312312')
({'A': ['2', '1', 'B'], 'B': ['4', '3']}, '13214213214213214213')
({'A': ['D', '1', 'D'], 'D': ['7', '8', '6']}, '16718617816718617816')
({'A': ['C', '1', 'B'], 'B': ['3', '4'], 'C': ['5', 'B']}, '13514314513413514314')</pre>
 
=={{header|REXX}}==
9,659

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.