The expressive simplicity of python using tasks from combinatorics as an example
Anyone familiar with the basics of probability theory should remember what urn schemes are and about than this table:

And so TK - write four generators that, taking a string s consisting of unique characters and a sample size of k , return a string - a sample with / without repetition of k characters of string sorder is important / not important.
The result is the following code:
import itertools
from functools import partial
import unittest
def template(s, k, assertion, reducer):
n = len(s)
assert assertion(n, k)
if k == 0:
yield ""
elif k == 1:
for c in s:
yield c
else:
k-=1
for i, c in enumerate(s):
new_s = reducer(s, i)
if not assertion(len(new_s), k):
break
for res in template(new_s, k, assertion, reducer):
yield c+res
assertion_norep = lambda n, k: n > 0 and n >= k and k >= 0
assertion_rep = lambda n, k: n > 0 and k >= 0
permutation_norep = partial(template, assertion=assertion_norep, reducer=lambda s, i: s[:i]+s[i+1:])
permutation_rep = partial(template, assertion=assertion_rep, reducer=lambda s, i: s)
combination_norep = partial(template, assertion=assertion_norep, reducer=lambda s, i: s[i+1:])
combination_rep = partial(template, assertion=assertion_rep, reducer=lambda s, i: s[i:])
class TestCombinatoricGenerators(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_string = "abcdefg"
cls.k = 5
def test_permutation_norep(self):
self.assertEquals(set(permutation_norep(self.test_string, self.k)),
set(map(''.join, itertools.permutations(self.test_string, self.k))))
def test_permutation_rep(self):
self.assertEquals(set(permutation_rep(self.test_string, self.k)),
set(map(''.join, itertools.product(self.test_string, repeat=self.k))))
def test_combination_norep(self):
self.assertEquals(set(combination_norep(self.test_string, self.k)),
set(map(''.join, itertools.combinations(self.test_string, self.k))))
def test_combination_rep(self):
self.assertEquals(set(combination_rep(self.test_string, self.k)),
set(map(''.join, itertools.combinations_with_replacement(self.test_string, self.k))))
if __name__ == '__main__':
unittest.main()Since python is a language of an even higher level of abstraction than c / c ++, it therefore makes it easier and more expressive to write code that would look more bulky and confusing in other languages. To newbies in python, I would like to draw attention to a few points:
- return after yield
- Recursive generator
- Strategy Template
- Using lambda functions
PS
I can add that I did not immediately come up with a similar solution using a common "template" function. First, I wrote all the functions separately, and then highlighted the general and the different.