{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### CS 200: Deep Recursion\n", "\n", "\n", "
\n",
"\n",
"In regular recursion, we would recurse over the top level elements of a list, string, or tuple.\n",
"\n",
"There are other recursive data structures that have multiple levels, for example, trees.\n",
"\n",
"A tree, like the UNIX file system, has a root node. Each node can contain terminals nodes, called \"leaves\", or other nodes or branches. These nodes are called children. The main node is the parent. For example, in a UNIX directory, .. refers to the parent directory and . refers to the child directory. If a UNIX program spawns a process, the new process is the child and the originating process is the parent. (In C, you use the fork
command to create a child process.)\n",
"\n",
"The recursive function must process each node and all the children nodes.\n",
"\n",
"Our first example procedure is maptree(proc, tree)
which creates a copy of the given tree, with each leaf node replaced by proc(leafnode)
\n",
"\n",
"The base case is when a node is empty, an integer, or some other leaf node.\n",
"\n",
"The recursive case is a list, in which the function is called recursively on each element of the list, and returns a copy of the list with appropriate modifications.\n",
"\n",
"The functions in this notebook are from recursion.py\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1', '2', '3', '4']"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(map(str,[1,2,3,4]))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, 9, 16]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(map(lambda x: x*x , [1,2,3,4]))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1', '2', '[3, 4]']"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(map(str, [1,2,[3,4]]))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"list"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type([])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def maptree(proc,tree):\n",
" if tree == []:\n",
" return tree\n",
" if not type(tree) == type([]):\n",
" return proc(tree)\n",
" result = []\n",
" for c in tree:\n",
" result.append(maptree(proc, c))\n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"l = [1,2,[3,4,[5,6],'a', 'b', []]]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, [3, 4, [5, 6], 'a', 'b', []]]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"l"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1', '2', ['3', '4', ['5', '6'], 'a', 'b', []]]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"maptree(str, l) ## convert every leaf into a string"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def square(x):\n",
" if type(x) == int:\n",
" return x*x\n",
" else:\n",
" return x"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, [9, 16, [25, 36], 'a', 'b', []]]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"maptree(square, l)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, [3, 4, [5, 6], 'a', 'b', []]]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"l"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[(1, 1),\n",
" (2, 2),\n",
" [(3, 3), (4, 4), [(5, 5), (6, 6)], ('a', 'a'), ('b', 'b'), []]]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"maptree(lambda x: (x,x), l)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"int"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(1)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, [9, 16, [25, 36], 'a', 'b', []]]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"maptree(lambda x: x*x if type(x) == type(1) else x, l)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will redefine maptree using a list comprehension"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def lcmaptree(proc,tree):\n",
" if tree == []:\n",
" return tree\n",
" if not type(tree) == type([]):\n",
" return proc(tree)\n",
" return [lcmaptree(proc,x) for x in tree]"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1', '2', ['3', '4', ['5', '6'], 'a', 'b', []]]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lcmaptree(str, l)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, [9, 16, [25, 36], 'a', 'b', []]]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lcmaptree(square, l)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[(1, 1),\n",
" (2, 2),\n",
" [(3, 3), (4, 4), [(5, 5), (6, 6)], ('a', 'a'), ('b', 'b'), []]]"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lcmaptree(lambda x: (x,x), l)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, [9, 16, [25, 36], 'a', 'b', []]]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lcmaptree(lambda x: x*x if type(x) == type(1) else x, l)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is a nested list comprehension version of maptree."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"def lclcmaptree(proc,tree):\n",
" return [[lclcmaptree(proc,x) for x in t] if type(t) == list\n",
" else t if t == [] else proc(t) for t in tree]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "'int' object is not iterable",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_653364/3129645351.py\u001b[0m in \u001b[0;36m