{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Week09.ipynb","provenance":[],"authorship_tag":"ABX9TyPgaibSUCB2PNyH5LA2ezuv"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["#第九週上課內容"],"metadata":{"id":"9xoK4OIjIfZA"}},{"cell_type":"markdown","source":["###GitHub 教材參考資料\n","\n","[https://github.com/htchen/i2p-nthu/tree/master/程式設計一/Recursive](https://github.com/htchen/i2p-nthu/tree/master/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E4%B8%80/Recursive)\n"],"metadata":{"id":"05G1Fqg6GRZX"}},{"cell_type":"markdown","source":["##Example 1\n","**Binary representation**\n","\n","我們要來寫一個程式能把十進位整數值的二進位表示法顯示出來，譬如二進位的表示法 $101_2$ 其實就是 $1\\times 2^2 + 0\\times 2^1 + 1\\times 2^0$，相當於十進位的 $5$。從十進位數字轉成二進位表示法的運算要怎麼做呢，我們可以先用十進位來思考。譬如平常寫 $9487_{10}$ 其實相當於 $9\\times 10^3 + 4\\times 10^2 + 8\\times 10^1 + 7$。所以如果要得到個位數是多少，只要用 $9487\\%10$，就可以知道個位數是 $7$。那麼接下來如果要知道十位數是多少，其實只要先把十位數降成個位數，也就是 $9487/10$，然後無條件捨去得到 $948$，接著再用同樣伎倆 $948\\%10$ 就可以取得十位數。就這樣一直做下去就可以把每個位數都求出來。二進位運算其實完全一樣，只要把 $\\%10$ 改成 $\\%2$，然後把 $/10$ 改成 $/2$ 就可以。\n","\n","我們最早算出來的是個位數，但是個位數應該是要最後輸出的。如果我們用傳統的迴圈寫法，必須先儲存之前的結果，最後倒過來輸出。如果改成利用遞迴運算跟輸出，則可以利用不同時機運作的特性，來完成二進位的轉換。\n","\n","`f(n/2) * 2 + n%2`"],"metadata":{"id":"mviKuWaapY32"}},{"cell_type":"code","source":["%%writefile E09_01.c\n","#include <stdio.h>\n","void binary(unsigned int i)\n","{\n","  if (i > 0) {\n","\t\tbinary(i/2); \n","    printf(\"%u\", i%2);\n","  }\n","}\n","\n","int main(void)\n","{\n","    unsigned int n;\n","    scanf(\"%u\", &n);\n","    binary(n);\n","    return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7ZODSFC-pmP2","executionInfo":{"status":"ok","timestamp":1649761440351,"user_tz":-480,"elapsed":618,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"dbc54913-8b97-473c-f5b1-079bacdbd7c0"},"execution_count":37,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_01.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E09_01.c -o E09_01\n","./E09_01"],"metadata":{"id":"HMqFdYymQIzj","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649761449658,"user_tz":-480,"elapsed":3219,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"486dfba3-815c-4fae-a3bf-629d26eedcdf"},"execution_count":38,"outputs":[{"output_type":"stream","name":"stdout","text":["18\n","10010"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":38}]},{"cell_type":"markdown","source":["##Example 2\n","**Fibonacci number**\n","\n","$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, \\cdots$\n","\n","$F_n = F_{n-1} + F_{n-2}$\n","\n","$F_0 = 0$\n","\n","$F_1 = 1$"],"metadata":{"id":"Mp5lAOxDodYd"}},{"cell_type":"code","source":["%%writefile E09_02.c\n","#include <stdio.h> \n","int table[50]; \n","\n","int fib(int i)\n","{\n","  if (table[i] != 0) {\n","\t\treturn table[i]; \n","\t}\n","  if (i == 0) {\n","    return 0;\n","  }\n","  else if (i == 1) {\n","  \treturn 1;\n","\t} else {\n","    table[i] = fib(i-1) + fib(i-2); \n","    return table[i];\n","  }\n","}\n","\n","int main(void)\n","{\n","  int n;\n","  scanf(\"%d\", &n);\n","  printf(\"%d\\n\", fib(n));\n","  return 0;\n","}"],"metadata":{"id":"LZ8575uZo5hG","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649762736931,"user_tz":-480,"elapsed":264,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"373adc02-1dc1-4908-87e4-0e61ff2bb72b"},"execution_count":39,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_02.c\n"]}]},{"cell_type":"code","source":["%%writefile E09_02.c\n","#include <stdio.h> \n","\n","int fib(int n, int ans, int ans_prev)\n","{\n","  if (n == 1) {\n","    return ans;\n","  } else { \n","    return fib(n-1, ans+ans_prev, ans); \n","  }\n","}\n","\n","int main(void)\n","{\n","  int n;\n","  scanf(\"%d\", &n);\n","  printf(\"%d\\n\", fib(n, 1, 0));\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"fwEeDDsCkncZ","executionInfo":{"status":"ok","timestamp":1649764276884,"user_tz":-480,"elapsed":314,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"27794d9b-e0be-4b70-8296-810eef1e5c66"},"execution_count":65,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_02.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc -O2 E09_02.c -o E09_02\n","./E09_02\n"],"metadata":{"id":"f1ClwjOzsdsQ","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649764304755,"user_tz":-480,"elapsed":25546,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"b686720c-82c9-402c-b1ea-e7d2ca45a693"},"execution_count":66,"outputs":[{"output_type":"stream","name":"stdout","text":["\u001b[01m\u001b[KE09_02.c:\u001b[m\u001b[K In function ‘\u001b[01m\u001b[Kmain\u001b[m\u001b[K’:\n","\u001b[01m\u001b[KE09_02.c:15:3:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kignoring return value of ‘\u001b[01m\u001b[Kscanf\u001b[m\u001b[K’, declared with attribute warn_unused_result [\u001b[01;35m\u001b[K-Wunused-result\u001b[m\u001b[K]\n","   \u001b[01;35m\u001b[Kscanf(\"%d\", &n)\u001b[m\u001b[K;\n","   \u001b[01;35m\u001b[K^~~~~~~~~~~~~~~\u001b[m\u001b[K\n","40\n","102334155\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":66}]},{"cell_type":"markdown","source":["##Example 3\n","\n","**Prefix**\n","\n","Prefix representation:\n","```\n","* + 2 3 + 4 + - 5 6 - 17 18\n","```\n","\n","Postfix representation:\n","```\n","2 3 + 4 5 6 - 17 18 - + + *\n","```\n","\n","\n","Infix representation:\n","```\n","((2 + 3) * (4 + ((5 - 6) + (17 - 18))))\n","```\n","\n"],"metadata":{"id":"2HgZZI7vpHFE"}},{"cell_type":"code","source":["%%writefile E09_03.c\n","#include <stdio.h>\n","#include <ctype.h>\n","\n","int cal(void)\n","{\n","  int ans, op1, op2;\n","  char c = getchar();\n","  if (c == ' ') {\n","\t\treturn cal();\n","\t} else if (isdigit(c)) {\n","    ungetc(c, stdin);\n","    scanf(\"%d\", &ans);\n","    return ans;\n","  } else if(c == '+') {\n","  \top1 = cal();\n","    op2 = cal();\n","\t\treturn op1 + op2;\n","\t} else if(c == '-') {\n","  \top1 = cal();\n","    op2 = cal();  \n","\t\treturn op1 - op2;\n","\t} else if(c == '*') {\n","  \top1 = cal();\n","    op2 = cal();\n","\t\treturn op1 * op2;\n","\t}\n","}\n","\n","int main(void)\n","{\n","  printf(\"%d\\n\", cal());\n","  return 0;\n","}"],"metadata":{"id":"1rqwHlHmrEi9","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649765134691,"user_tz":-480,"elapsed":293,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"e947ae25-8c66-4b65-fcb5-3763d0baa696"},"execution_count":67,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_03.c\n"]}]},{"cell_type":"code","source":["%%writefile E09_03.c\n","#include <stdio.h>\n","#include <ctype.h>\n","\n","int cal(void)\n","{\n","  int ans, op1, op2;\n","  char c = getchar();\n","  if (c == ' ') {\n","\t\treturn cal();\n","\t} else if (isdigit(c)) {\n","    ungetc(c, stdin);\n","    scanf(\"%d\", &ans);\n","    printf(\"%d\", ans);\n","    return ans;\n","  } \n","  \n","  printf(\"(\");\n","  op1 = cal();\n","  printf(\" %c \", c);\n","  op2 = cal();  \n","  printf(\")\");\n","    \n","  if(c == '+') {\n","\t\treturn op1 + op2;\n","\t} else if(c == '-') {\n","\t\treturn op1 - op2;\n","\t} else if(c == '*') {\n","\t\treturn op1 * op2;\n","\t}\n","}\n","\n","int main(void)\n","{\n","  printf(\" = %d\\n\", cal());\n","  return 0;\n","}\n","\n","// ((2 + 3) * (4 + ((5 - 6) + (17 - 18))))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"4mllPj9Rt8qF","executionInfo":{"status":"ok","timestamp":1649767326425,"user_tz":-480,"elapsed":246,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"fa841b75-5db0-4ac3-8d53-771b36fbaa87"},"execution_count":76,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_03.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E09_03.c -o E09_03\n","./E09_03"],"metadata":{"id":"3yZlwmmjsiKP","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649767344942,"user_tz":-480,"elapsed":13205,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"8d823f38-7d78-44d4-ad1a-7ae022e11acf"},"execution_count":77,"outputs":[{"output_type":"stream","name":"stdout","text":["* + 2 3 + 4 + - 5 6 - 17 18\n","((2 + 3) * (4 + ((5 - 6) + (17 - 18)))) = 10\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":77}]},{"cell_type":"markdown","source":["##Example 4\n","\n","**Binary Search**\n","\n","在一個排序過後的數列中找尋某個指定的數。\n","\n","因為數列是已經排序過的，所以我們可以先取排列在中間的值，看這個值跟我們所要找的數是不是一樣大。若是一樣大，那我們就找到了；若是這個值比較我們要找的小，那我們可以從比它大的那一群數中再找；反之，則從比它小的那一群繼續找。如此一步一步取區間內中間位置的值比對，這樣的方法的時間複雜度是 $O(\\log_2 N)$。\n","\n"],"metadata":{"id":"7co6TxbjrUL2"}},{"cell_type":"code","source":["%%writefile E09_04.c\n","#include <stdio.h>\n","int data[] = {2, 5, 10, 15, 17, 24, 25, 28, 32, 35};\n","void find(int n, int left, int right);\n","\n","int main(void)\n","{\n","  int number;\n","  printf(\"Enter a number between 1 and 40 you want to find:\\n\");\n","  scanf(\"%d\", &number);\n","  find(number, 0, 9);\n","}\n","\n","void find(int number, int left, int right)\n","{\n","  int middle= left + (right - left) / 2;\n","  if (left > right) {\n","    printf(\"%d is not in the data.\\n\", number);\n","  } else if (data[middle] == number) {\n","    printf(\"%d is at position %d.\\n\", number, middle);\n","  } else if (data[middle] > number) {\n","    find(number, left, middle - 1);\n","  } else {\n","    find(number, middle + 1, right);\n","  }\n","\n","}"],"metadata":{"id":"bNrwKmsysNfy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649768357852,"user_tz":-480,"elapsed":248,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"0c138062-f088-475e-9853-3f05b212cbef"},"execution_count":78,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_04.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E09_04.c -o E09_04\n","./E09_04"],"metadata":{"id":"puvNtlHWssLK","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649768376691,"user_tz":-480,"elapsed":3291,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"7953bd1c-b544-4423-acc4-c6cde93319a3"},"execution_count":80,"outputs":[{"output_type":"stream","name":"stdout","text":["Enter a number between 1 and 40 you want to find:\n","28\n","28 is at position 7.\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":80}]},{"cell_type":"markdown","source":["##Example 5\n","\n","**Merge Sort**\n","前一個搜尋的例子，我們假設資料已經從小到大排序好了。但是如果是要在一組未排序的資料中找值，二元搜尋方法就行不通了，唯一的方法是一個一個檢查。\n","\n","我們可以先對未排序的資料先排序 (sort) ，再用 binary search 。這樣的優缺點和前面的方法相反，在搜尋的數字少時，因為一開始需要 sort ，所以會多花時間；但是當尋找的數字多時，binary search 的速度優勢就會佔上風。而 sort 的方法有很多種，底下要介紹的是一種做法是 merge sort："],"metadata":{"id":"eAEfEJkitIw9"}},{"cell_type":"code","source":["%%writefile E09_05.c\n","#include <stdio.h>\n","#include <stdlib.h>\n","#define MAXN 1000000\n","\n","int A[MAXN], buffer[MAXN];\n","void merge(int starta, int lena, int startb, int lenb){\n","  int i = 0, j = 0, k = 0;\n","  while(i < lena && j < lenb) {\n","    if(A[starta+i] < A[startb+j]) {\n","      buffer[k++] = A[starta + i++];\n","    } else {\n","      buffer[k++] = A[startb + j++];\n","    }\n","  }\n","  while(i < lena) {\n","    buffer[k++] = A[starta + i++];\n","  }\n","  while(j < lenb) {\n","    buffer[k++] = A[startb + j++];\n","  }\n","}\n","\n","void merge_sort(int left, int right)\n","{\n","  int i, mid;\n","  if (left >= right) return; \n","  mid = left + (right-left)/2;   \n","  merge_sort(left, mid); // A[left...mid] is sorted\n","  merge_sort(mid+1, right); // A[mid+1...right] is sorted\n","  merge(left, mid-left+1, mid+1, right-mid); \n","  for(i=0; i < right-left+1; i++){  \t\n","    A[left+i] = buffer[i];\n","  }\n","}\n","\n","int main(){\n","    int n, i;\n","    /*\n","    scanf(\"%d\", &n);\n","    for(i=0; i<n; i++){\n","      scanf(\"%d\", &A[i]);\n","    }*/\n","    n = 500000;\n","    for (i=0; i<n; i++) {\n","      A[i] = rand()%n;\n","    }    \n","    printf(\"Before sorting: \");\n","    for (i=10000; i<10010; ++i) {\n","      printf(\"%d \", A[i]);\n","    }\n","\n","    merge_sort(0, n-1);\n","    printf(\"\\nAfter sorting: \");\n","    for (i=10000; i<10010; ++i) {\n","      printf(\"%d \", A[i]);\n","    }\n","\n","    for (i=1; i<n; ++i) {\n","      if (A[i-1]>A[i]) {\n","        printf(\"\\nWrong!\\n\");\n","      }\n","    }\n","    printf(\"\\nCorrect.\\n\");\n","\n","    return 0;\n","}"],"metadata":{"id":"CUD4U1iTuWSa","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649770166236,"user_tz":-480,"elapsed":260,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"82af5453-6d3d-434b-a2e7-c23903e96d1d"},"execution_count":95,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E09_05.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E09_05.c -o E09_05\n","./E09_05"],"metadata":{"id":"dn61T8gVudiD","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1649770170789,"user_tz":-480,"elapsed":1328,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"33796c69-cbf4-4bed-c87e-36c90ed1b155"},"execution_count":96,"outputs":[{"output_type":"stream","name":"stdout","text":["Before sorting: 57537 48410 273756 177667 85312 32062 54136 467229 456846 9902 \n","After sorting: 9965 9967 9969 9969 9970 9972 9973 9973 9973 9974 \n","Correct.\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":96}]}]}