Perfect shuffle: Difference between revisions
Content added Content deleted
(→{{header|Python}}: Added a more functional version of the first code example.) |
|||
Line 1,520: | Line 1,520: | ||
</lang> |
</lang> |
||
More functional version of the same code: |
|||
<lang python>from functools import partial |
|||
from itertools import chain |
|||
from operator import eq |
|||
from typing import (Callable, |
|||
Iterable, |
|||
Iterator, |
|||
List, |
|||
TypeVar) |
|||
T = TypeVar('T') |
|||
def main(): |
|||
print("Deck length | Shuffles ") |
|||
for length in (8, 24, 52, 100, 1020, 1024, 10000): |
|||
deck = list(range(length)) |
|||
shuffles_needed = spin_number(deck, shuffle) |
|||
print(f"{length:<11} | {shuffles_needed}") |
|||
def shuffle(deck: List[T]) -> List[T]: |
|||
"""[1, 2, 3, 4] -> [1, 3, 2, 4]""" |
|||
half = len(deck) // 2 |
|||
return list(chain.from_iterable(zip(deck[:half], deck[half:]))) |
|||
def spin_number(source: T, |
|||
function: Callable[[T], T]) -> int: |
|||
""" |
|||
Applies given function to the source |
|||
until the result becomes equal to it, |
|||
returns the number of calls |
|||
""" |
|||
is_equal_source = partial(eq, source) |
|||
spins = repeat_call(function, source) |
|||
return next_index(is_equal_source, |
|||
spins, |
|||
start=1) |
|||
def repeat_call(function: Callable[[T], T], |
|||
value: T) -> Iterator[T]: |
|||
"""(f, x) -> f(x), f(f(x)), f(f(f(x))), ...""" |
|||
while True: |
|||
value = function(value) |
|||
yield value |
|||
def next_index(predicate: Callable[[T], bool], |
|||
iterable: Iterable[T], |
|||
start: int = 0) -> int: |
|||
""" |
|||
Returns index of the first element of the iterable |
|||
satisfying given condition |
|||
""" |
|||
for index, item in enumerate(iterable, start=start): |
|||
if predicate(item): |
|||
return index |
|||
if __name__ == "__main__": |
|||
main() |
|||
</lang> |
|||
{{Out}} |
|||
<pre>Deck length | Shuffles |
|||
8 | 3 |
|||
24 | 11 |
|||
52 | 8 |
|||
100 | 30 |
|||
1020 | 1018 |
|||
1024 | 10 |
|||
10000 | 300</pre> |
|||
Reversed shuffle or just calculate how many shuffles are needed: |
Reversed shuffle or just calculate how many shuffles are needed: |
||
<lang python>def mul_ord2(n): |
<lang python>def mul_ord2(n): |