Last active
January 16, 2021 14:02
-
-
Save deeplook/145fe207e5475f76268dc2ab3b287e45 to your computer and use it in GitHub Desktop.
This is a generator which creates sequences of integers as often presented in so-called *IQ tests* (or CCAT, Criteria Cognitive Aptitude Test) where people are asked to tell the next element after a given sequence of numbers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Integer series generator\n", | |
| "\n", | |
| "This is a generator which creates sequences of integers as often presented in so-called *IQ tests* (or CCAT, Criteria Cognitive Aptitude Test) where people are asked to tell the next element after a given sequence of numbers. Usually the tacit assumption is made that the next element is calculated from the previous one or two elements only.\n", | |
| "\n", | |
| "The implementation here is more general and allows to create $n$ new elements from $m$ previous ones, where $n >= 1, m >= 0$. Creating more than one next element will likely make the test much more difficult when not presenting longer sequences to identify the pattern more easily. The sequence will stop as soon as a `None` value is found." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def series(func, start=None):\n", | |
| " \"\"\"Apply a function repeatedly to a sequence to yield next elements.\n", | |
| " \n", | |
| " This will generate a series of integers by applying a function\n", | |
| " to one or more of the last elements of an existing sequence. The\n", | |
| " process continues forever or stops as soon as the function does\n", | |
| " return a None.\n", | |
| " \n", | |
| " The start sequence can be empty or a single integer, or a tuple\n", | |
| " of integers. The function passed must accept 0, or more integers\n", | |
| " in named positional variables, and not have a variable argument\n", | |
| " notation like in `func(*vars)`. This function is applied to the\n", | |
| " tail of the sequence with a length equal to the number of input\n", | |
| " variables. The value(s) it returns become the next element(s) to\n", | |
| " be added to the sequence and must be a single integer or a tuple\n", | |
| " of integers.\n", | |
| " \n", | |
| " Examples:\n", | |
| " \n", | |
| " >>> def inc(n): return n + 1\n", | |
| " >>> gen = series(inc, start=0)\n", | |
| " >>> [next(gen) for i in range(10)]\n", | |
| " [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n", | |
| " \n", | |
| " >>> def add(n, m): return n + m\n", | |
| " >>> gen = series(add, start=(0, 1))\n", | |
| " >>> [next(gen) for i in range(10)]\n", | |
| " [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n", | |
| " \n", | |
| " >>> def multi(n, m): return n + m, n + m + 1\n", | |
| " >>> gen = series(multi, start=(0, 1))\n", | |
| " >>> [next(gen) for i in range(16)]\n", | |
| " [0, 1, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128]\n", | |
| " \"\"\"\n", | |
| " # Build initial sequence from start value if given.\n", | |
| " if start is None:\n", | |
| " seq = []\n", | |
| " elif type(start) == tuple:\n", | |
| " seq = list(start)\n", | |
| " else:\n", | |
| " seq = [start]\n", | |
| "\n", | |
| " # Yield initial elements, if given.\n", | |
| " for el in seq:\n", | |
| " if el is None:\n", | |
| " return\n", | |
| " else:\n", | |
| " yield el\n", | |
| "\n", | |
| " # Call given function on last element(s) of sequence and \n", | |
| " # yield them, until hitting None or forever.\n", | |
| " num_vars = func.__code__.co_argcount\n", | |
| " while True:\n", | |
| " if num_vars == 0:\n", | |
| " nxt = func()\n", | |
| " if nxt is None:\n", | |
| " return\n", | |
| " else:\n", | |
| " nxt = func(*seq[-num_vars:])\n", | |
| " if nxt is None:\n", | |
| " return\n", | |
| " elif type(nxt) == int:\n", | |
| " seq.append(nxt)\n", | |
| " del seq[0]\n", | |
| " yield nxt \n", | |
| " elif type(nxt) in (tuple, list):\n", | |
| " for n in nxt:\n", | |
| " if n is None:\n", | |
| " return\n", | |
| " else:\n", | |
| " seq.append(n)\n", | |
| " del seq[0]\n", | |
| " yield n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Functions\n", | |
| "\n", | |
| "Most of these functions are intended to create a series of integers with increasing values, depending on some number of previously generated integers. " | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# zero arguments\n", | |
| "def const(): return 1\n", | |
| "\n", | |
| "# one argument\n", | |
| "def inc(n): return n + 1\n", | |
| "def double(n): return n * 2\n", | |
| "def alt(n): return 1 - n % 2\n", | |
| "def myst(n): return n * 2 if n % 2 else n + 1\n", | |
| "\n", | |
| "# multiple arguments\n", | |
| "def add(n, m): return n + m\n", | |
| "def sub(n, m): return m - n\n", | |
| "def mul(n, m): return m * n\n", | |
| "def diff(n, m): return m + 2 if (m - n) % 2 else m + 1\n", | |
| "\n", | |
| "# multiple results\n", | |
| "def id2(n, m): return n, m\n", | |
| "def add_multi(n, m): return n + m, n + m + 1\n", | |
| "def add_copy(n, m): return [n + m] * m\n", | |
| "\n", | |
| "# finite series\n", | |
| "def lt5(n): return n + 1 if n + 1 <= 4 else None" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Example sequences" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# pip install more-itertools\n", | |
| "from more_itertools import take" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]" | |
| ] | |
| }, | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(const))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" | |
| ] | |
| }, | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(inc, start=0))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]" | |
| ] | |
| }, | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(double, start=1))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]" | |
| ] | |
| }, | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(alt, start=1))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 2, 3, 6, 7, 14, 15, 30, 31]" | |
| ] | |
| }, | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(myst, start=0))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]" | |
| ] | |
| }, | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(add, start=(0, 1)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 1, 0, -1, -1, 0, 1, 1, 0]" | |
| ] | |
| }, | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(sub, start=(0, 1)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 2, 2, 4, 8, 32, 256, 8192, 2097152, 17179869184]" | |
| ] | |
| }, | |
| "execution_count": 11, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(mul, start=(1, 2)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 3, 4, 6, 7, 9, 10, 12, 13]" | |
| ] | |
| }, | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(diff, start=(0, 1)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 2, 1, 2, 1, 2, 1, 2, 1, 2]" | |
| ] | |
| }, | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(id2, start=(1, 2)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 14, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128]" | |
| ] | |
| }, | |
| "execution_count": 14, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(16, series(add_multi, start=(0, 1)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[1, 2, 3, 3, 6, 6, 6, 12, 12, 12, 12, 12, 12]" | |
| ] | |
| }, | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(13, series(add_copy, start=(1, 2)))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 16, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, 1, 2, 3, 4]" | |
| ] | |
| }, | |
| "execution_count": 16, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "take(10, series(lt5, start=0))" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.8.0" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment