Skip to content

Commit 290ecf5

Browse files
committed
Add testing and text to notebook
1 parent 2eab35f commit 290ecf5

File tree

1 file changed

+108
-74
lines changed

1 file changed

+108
-74
lines changed

source-code/functional-programming/persistent_binary_search_tree.ipynb

Lines changed: 108 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,49 @@
291291
" return flatten(left(tree)) + (value(tree), ) + flatten(right(tree))"
292292
]
293293
},
294+
{
295+
"cell_type": "markdown",
296+
"id": "d93d4c6e-d88f-49b1-b189-17017c7de51c",
297+
"metadata": {},
298+
"source": [
299+
"The implementation of `flatten` would be much simpler if we would use Python `list` rather than `tuple`, but given the fact that we want to program in a functional style, we make sure the data structures are immutable."
300+
]
301+
},
302+
{
303+
"cell_type": "code",
304+
"execution_count": 21,
305+
"id": "113acbc3-b18b-4ef5-b993-1ab5d8b3a043",
306+
"metadata": {},
307+
"outputs": [],
308+
"source": [
309+
"def visualize_tree(tree, indent=''):\n",
310+
" '''Print a visualization of a tree to standard output\n",
311+
" \n",
312+
" Parameters\n",
313+
" ----------\n",
314+
" tree: tuple[Any, tuple | None, tuple | None] | None\n",
315+
" binary search tree to visualize\n",
316+
" '''\n",
317+
" if is_empty(tree):\n",
318+
" print(f'{indent}empty tree')\n",
319+
" else:\n",
320+
" print(f'{indent}{value(tree)}')\n",
321+
" if not is_empty(left(tree)):\n",
322+
" print(f'{indent} left:')\n",
323+
" visualize_tree(left(tree), indent + ' ')\n",
324+
" if not is_empty(right(tree)):\n",
325+
" print(f'{indent} right:')\n",
326+
" visualize_tree(right(tree), indent + ' ')"
327+
]
328+
},
329+
{
330+
"cell_type": "markdown",
331+
"id": "fa4074a4-e15b-4388-958e-7497a11eba64",
332+
"metadata": {},
333+
"source": [
334+
"# Testing"
335+
]
336+
},
294337
{
295338
"cell_type": "markdown",
296339
"id": "b86c0c7a-d2c2-4e3a-8b70-108868d83f85",
@@ -301,140 +344,131 @@
301344
},
302345
{
303346
"cell_type": "code",
304-
"execution_count": 9,
347+
"execution_count": 28,
305348
"id": "2c595c38-71e1-4df1-8016-99b632373817",
306349
"metadata": {},
307-
"outputs": [
308-
{
309-
"data": {
310-
"text/plain": [
311-
"True"
312-
]
313-
},
314-
"execution_count": 9,
315-
"metadata": {},
316-
"output_type": "execute_result"
317-
}
318-
],
350+
"outputs": [],
319351
"source": [
320-
"is_empty(empty())"
352+
"assert is_empty(empty()), 'empty tree is not empty'"
321353
]
322354
},
323355
{
324356
"cell_type": "markdown",
325357
"id": "ccd1eec7-7eea-4193-9323-053d1638d3d9",
326358
"metadata": {},
327359
"source": [
328-
"Store the successive trees in a list that are obtained by inserting values into it, flatten them and print the result."
360+
"Store the successive trees in a list that are obtained by inserting values into it, that illustrates that this implementation of binary search trees is indeed persistent, and hence purely functional."
329361
]
330362
},
331363
{
332364
"cell_type": "code",
333-
"execution_count": 14,
365+
"execution_count": 23,
334366
"id": "9bf2469e-c918-450e-bae0-86afa77dd371",
335367
"metadata": {},
336368
"outputs": [
337369
{
338370
"name": "stdout",
339371
"output_type": "stream",
340372
"text": [
341-
"4 into None\n",
342-
"1 into (4, None, None)\n",
343-
"7 into (4, (1, None, None), None)\n",
344-
"-3 into (4, (1, None, None), (7, None, None))\n",
345-
"1 into (4, (1, (-3, None, None), None), (7, None, None))\n",
346-
"8 into (4, (1, (-3, None, None), None), (7, None, None))\n",
347-
"4 into (4, (1, (-3, None, None), None), (7, None, (8, None, None)))\n",
348-
"9 into (4, (1, (-3, None, None), None), (7, None, (8, None, None)))\n",
349-
"-3 into (4, (1, (-3, None, None), None), (7, None, (8, None, (9, None, None))))\n",
350373
"None\n",
351-
"(4,)\n",
352-
"(1, 4)\n",
353-
"(1, 4, 7)\n",
354-
"(-3, 1, 4, 7)\n",
355-
"(-3, 1, 4, 7)\n",
356-
"(-3, 1, 4, 7, 8)\n",
357-
"(-3, 1, 4, 7, 8)\n",
358-
"(-3, 1, 4, 7, 8, 9)\n",
359-
"(-3, 1, 4, 7, 8, 9)\n"
374+
"(4, None, None)\n",
375+
"(4, (1, None, None), None)\n",
376+
"(4, (1, None, None), (7, None, None))\n",
377+
"(4, (1, (-3, None, None), None), (7, None, None))\n",
378+
"(4, (1, (-3, None, None), None), (7, None, None))\n",
379+
"(4, (1, (-3, None, None), None), (7, None, (8, None, None)))\n",
380+
"(4, (1, (-3, None, None), None), (7, None, (8, None, None)))\n",
381+
"(4, (1, (-3, None, None), None), (7, None, (8, None, (9, None, None))))\n",
382+
"(4, (1, (-3, None, None), None), (7, None, (8, None, (9, None, None))))\n"
360383
]
361384
}
362385
],
363386
"source": [
364387
"new_values = (4, 1, 7, -3, 1, 8, 4, 9, -3)\n",
365388
"trees = [empty()]\n",
366389
"for new_value in new_values:\n",
367-
" print(f'{new_value} into {trees[-1]}')\n",
368390
" trees.append(insert(trees[-1], new_value))\n",
369391
"for tree in trees:\n",
370-
" print(flatten(tree))"
392+
" print(tree)"
393+
]
394+
},
395+
{
396+
"cell_type": "markdown",
397+
"id": "c88e781a-303e-4ac4-933c-f9b3d9c39255",
398+
"metadata": {},
399+
"source": [
400+
"In order to test the implementation, you should note that when a correct binary search tree is flattened, the resulting tuple ir ordered, i.e, its elements are in ascending order. To test this, we implement the function `is_ordered`."
371401
]
372402
},
373403
{
374404
"cell_type": "code",
375-
"execution_count": 14,
376-
"id": "41b1e508-407c-4fb5-aa40-45943825a7dd",
405+
"execution_count": 26,
406+
"id": "d3da91e3-4658-43bc-a980-f611cf65bd35",
377407
"metadata": {},
378408
"outputs": [],
379409
"source": [
380-
"t = insert(insert(insert(insert(empty(), 3), 5), 1), 2)"
410+
"def is_ordered(elements):\n",
411+
" '''Check whether the elements of a tuple are orded\n",
412+
" \n",
413+
" Parameters\n",
414+
" ----------\n",
415+
" elements: tuple[Any] | None\n",
416+
" tuple to check\n",
417+
" \n",
418+
" Returns\n",
419+
" -------\n",
420+
" bool\n",
421+
" True if the tuple's elements are in order, False otherwise; None, that represents\n",
422+
" the elements of an empty tree is also consired ordered\n",
423+
" '''\n",
424+
" return (elements is None or len(elements) <= 1 or\n",
425+
" (elements[0] <= elements[1]) and is_ordered(elements[1:])) "
381426
]
382427
},
383428
{
384-
"cell_type": "code",
385-
"execution_count": 15,
386-
"id": "8b71169d-3660-4024-b23b-1a77037ea922",
429+
"cell_type": "markdown",
430+
"id": "e81e0471-68d8-440c-bf74-9d408fbd517d",
387431
"metadata": {},
388-
"outputs": [
389-
{
390-
"data": {
391-
"text/plain": [
392-
"(1, 2, 3, 5)"
393-
]
394-
},
395-
"execution_count": 15,
396-
"metadata": {},
397-
"output_type": "execute_result"
398-
}
399-
],
400432
"source": [
401-
"flatten(t)"
433+
"We can now test the implementation."
402434
]
403435
},
404436
{
405437
"cell_type": "code",
406-
"execution_count": 20,
407-
"id": "d3da91e3-4658-43bc-a980-f611cf65bd35",
438+
"execution_count": 27,
439+
"id": "7ea1284c-8ca6-49b3-b051-263e3109d0f7",
408440
"metadata": {},
409441
"outputs": [],
410442
"source": [
411-
"def is_ordered(xs):\n",
412-
" return len(xs) <= 1 or (xs[0] <= xs[1]) and is_ordered(xs[1:]) "
443+
"new_values = (4, 1, 7, -3, 1, 8, 4, 9, -3)\n",
444+
"trees = [empty()]\n",
445+
"for new_value in new_values:\n",
446+
" trees.append(insert(trees[-1], new_value))\n",
447+
"for tree in trees:\n",
448+
" assert is_ordered(flatten(tree)), f'{tree} is not ordered'"
449+
]
450+
},
451+
{
452+
"cell_type": "markdown",
453+
"id": "36904405-5769-41db-9e8e-5314d50aa42b",
454+
"metadata": {},
455+
"source": [
456+
"Check whether the visualization works as expected."
413457
]
414458
},
415459
{
416460
"cell_type": "code",
417-
"execution_count": 10,
418-
"id": "113acbc3-b18b-4ef5-b993-1ab5d8b3a043",
461+
"execution_count": 16,
462+
"id": "41b1e508-407c-4fb5-aa40-45943825a7dd",
419463
"metadata": {},
420464
"outputs": [],
421465
"source": [
422-
"def visualize_tree(xs, indent=''):\n",
423-
" if is_empty(xs):\n",
424-
" print(f'{indent}empty tree')\n",
425-
" else:\n",
426-
" print(f'{indent}{value(xs)}')\n",
427-
" if not is_empty(left(xs)):\n",
428-
" print(f'{indent} left:')\n",
429-
" visualize_tree(left(xs), indent + ' ')\n",
430-
" if not is_empty(right(xs)):\n",
431-
" print(f'{indent} right:')\n",
432-
" visualize_tree(right(xs), indent + ' ')"
466+
"tree = insert(insert(insert(insert(empty(), 3), 5), 1), 2)"
433467
]
434468
},
435469
{
436470
"cell_type": "code",
437-
"execution_count": 11,
471+
"execution_count": 22,
438472
"id": "df17e319-80d1-45c1-8fe9-bf81626ea48d",
439473
"metadata": {},
440474
"outputs": [
@@ -453,7 +487,7 @@
453487
}
454488
],
455489
"source": [
456-
"visualize_tree(t)"
490+
"visualize_tree(tree)"
457491
]
458492
}
459493
],

0 commit comments

Comments
 (0)