From ad5fc0e6957e8abdef536b8f6820f4641f7ed99e Mon Sep 17 00:00:00 2001 From: Donovan Date: Fri, 21 Mar 2025 05:15:52 -0500 Subject: [PATCH] add docs to split_shuffle_tutorial.ipynb --- notebooks/split_shuffle_tutorial.ipynb | 132 ++++++++++++++++++++++--- src/user_keypad.py | 2 +- 2 files changed, 118 insertions(+), 16 deletions(-) diff --git a/notebooks/split_shuffle_tutorial.ipynb b/notebooks/split_shuffle_tutorial.ipynb index 79dbd53..84578ef 100644 --- a/notebooks/split_shuffle_tutorial.ipynb +++ b/notebooks/split_shuffle_tutorial.ipynb @@ -3,8 +3,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-21T09:22:33.939365Z", - "start_time": "2025-03-21T09:22:33.911673Z" + "end_time": "2025-03-21T10:15:10.166756Z", + "start_time": "2025-03-21T10:15:10.163120Z" } }, "cell_type": "code", @@ -17,30 +17,44 @@ ], "id": "1f073371d04d02ef", "outputs": [], - "execution_count": 1 + "execution_count": 37 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Keypad Split Shuffle\n", + "\n", + "The split shuffle algorithm aims to increase the number of observations required to decipher an nKode.\n", + "For more details, refer to the [Evil nKode](https://github.com/Arcanum-Technology/evil-nkode).\n", + "\n", + "The positions of the keypad properties are divided into two sets, with each set being shuffled collectively to form a new key." + ], + "id": "651d7d661f4128d" }, { "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2025-03-21T09:22:33.948436Z", - "start_time": "2025-03-21T09:22:33.943046Z" + "end_time": "2025-03-21T10:15:10.177990Z", + "start_time": "2025-03-21T10:15:10.172547Z" } }, "cell_type": "code", "source": [ "keypad_size = KeypadSize(numb_of_keys=5, props_per_key=4)\n", "props = [1, 10, 11, 100]\n", - "keypad = []\n", + "keypad_list = []\n", "for key_numb in range(1,keypad_size.numb_of_keys+1):\n", - " keypad.extend([key_numb * prop for prop in props])\n", + " keypad_list.extend([key_numb * prop for prop in props])\n", "\n", - "demo_interface = UserKeypad(keypad_size=keypad_size, keypad=np.array(keypad))\n", + "user_keypad = UserKeypad(keypad_size=keypad_size, keypad=np.array(keypad_list))\n", "display(Markdown(f\"\"\"\n", "## Example Keypad\n", "{keypad_size.numb_of_keys} X {keypad_size.props_per_key} keypad ({keypad_size.numb_of_keys} keys, {keypad_size.props_per_key} properties per key).\n", "\"\"\"))\n", - "display(Markdown(keypad_md_table(demo_interface.keypad, keypad_size)))" + "keypad_mat = user_keypad.keypad_matrix()\n", + "display(Markdown(keypad_md_table(user_keypad.keypad, keypad_size)))" ], "id": "initial_id", "outputs": [ @@ -65,15 +79,103 @@ "output_type": "display_data" } ], - "execution_count": 2 + "execution_count": 38 }, { - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-03-21T10:15:10.187564Z", + "start_time": "2025-03-21T10:15:10.184075Z" + } + }, "cell_type": "code", - "outputs": [], - "execution_count": null, - "source": "keypad_mat = demo_interface", - "id": "43db2b9d247f420d" + "source": [ + "np.random.shuffle(keypad_mat)\n", + "display(Markdown(\"\"\"\n", + "### Step 1\n", + "\n", + "Shuffle the keys\n", + "\"\"\"\n", + "))\n", + "display(Markdown(keypad_md_table(keypad_mat.reshape(-1), keypad_size)))" + ], + "id": "43db2b9d247f420d", + "outputs": [ + { + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\n### Step 1\n\nShuffle the keys\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ], + "text/markdown": "||position 0|position 1|position 2|position 3|\n|-|-|-|-|-|\n|key 0|1|10|11|100|\n|key 1|3|30|33|300|\n|key 2|2|20|22|200|\n|key 3|5|50|55|500|\n|key 4|4|40|44|400|" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 39 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-03-21T10:15:10.202941Z", + "start_time": "2025-03-21T10:15:10.198267Z" + } + }, + "cell_type": "code", + "source": [ + "display(Markdown(\"\"\"\n", + "### Step 2\n", + "\n", + "Choose half of the properties and randomly assign them to a new key as a group, then shuffle this group to another new key.\"\"\"\n", + "))\n", + "prop_permutation = np.random.permutation(keypad_size.props_per_key)[: keypad_size.props_per_key // 2]\n", + "print(f\"Selected Group: {prop_permutation}\")\n", + "key_permutation = np.random.permutation(keypad_size.numb_of_keys)\n", + "# shuffle the selected property sets to new keys as a group\n", + "keypad_mat[:, prop_permutation] = keypad_mat[key_permutation, :][:, prop_permutation]\n", + "display(Markdown(keypad_md_table(keypad_mat.reshape(-1), keypad_size)))" + ], + "id": "8c322a6c074392e6", + "outputs": [ + { + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\n### Step 2\n\nChoose half of the properties and randomly assign them to a new key as a group, then shuffle this group to another new key." + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected Group: [2 0]\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ], + "text/markdown": "||position 0|position 1|position 2|position 3|\n|-|-|-|-|-|\n|key 0|2|10|22|100|\n|key 1|4|30|44|300|\n|key 2|1|20|11|200|\n|key 3|5|50|55|500|\n|key 4|3|40|33|400|" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 40 } ], "metadata": { diff --git a/src/user_keypad.py b/src/user_keypad.py index 9fe36f3..ffe9276 100644 --- a/src/user_keypad.py +++ b/src/user_keypad.py @@ -61,7 +61,7 @@ class UserKeypad: # shuffle all keys keypad_mat = self.keypad_matrix() np.random.shuffle(keypad_mat) - # select half the property sets + # select half the property positions prop_permutation = np.random.permutation(self.keypad_size.props_per_key)[: self.keypad_size.props_per_key // 2] key_permutation = np.random.permutation(self.keypad_size.numb_of_keys) # shuffle the selected property sets to new keys as a group