sk5s 自主學習Time

進階程式設計

學習 Python 語法與一些 Python 基礎知識。

  • 課程名稱:進階程式設計
  • 教學程式語言:Python
  • 程式撰寫平台:Colaboratory
  • 課程內容:基礎 Python 程式語言教學

專案網頁:🌐 https://portfolio.sk5s.cyou/project/230203-advance-py/

目次

  1. 心得
  2. 作業1
  3. 作業2
  4. 作業3
  5. 作業4
  6. 作業5

心得

經過了一個學期的 Python 練習,我覺得我對於 Python 語法的熟悉度增加了。以前因為 Python 的設定流程較複雜,所以決定先學習 Javascript ,不過後來發現網路上有一些線上的 sandbox 可以免安裝執行 Python ,像是這次進階程式設計學習 Python 所使用的 Colaboratory 等工具,使開始學習 Python 的成本降低了,我可以更輕鬆的使用 Python 和練習。我覺得 Python 這個語言的使用範圍很廣,從控制單板電腦,到桌面應用程式,都可以使用 Python 來實作,而且 APCS 考試中,實作題也可以用 Python 來完成,也因為 Python 的使用者很多,所以網路上很容易可以找到相關教學與討論,學習上對新手比較友善,我覺得學習 Python 這個新的程式語言,是非常實用的,而我也想試著用 Python 來完成一些小專案。以下是課堂中的練習題。

作業1

成品及時展示:

思路說明

讀取操作者輸入的字母,依據不同字母執行不同指令(使用 if elif else 完成),每次輸入完字母後重新繪製地圖。

step 1

w, h = 10, 5   # 設定寬為 5,高為 3
i, j = 0, 0    # 初始化印刷位置
x, y = 2, 3  # 使用者初始位置
while i < h:     # 高度判斷條件
  j=0        # 初始化 j
  content = ""
  while j<w: # 寬度判斷條件
    content += "-"
    j+=1
  print(content)
  i+=1

step 2

w, h = 10, 5   # 設定寬為 5,高為 3
i, j = 0, 0    # 初始化印刷位置
x, y = 2, 3  # 使用者初始位置
while i < h:     # 高度判斷條件
  j=0        # 初始化 j
  content = ""
  while j<w: # 寬度判斷條件
    if i == x and j == y:
      content += "*"
    else:
      content += "-"
    j+=1
  print(content)
  i+=1

step 3

#from IPython.display import clear_output
w, h = 10, 5   # 設定寬為 5,高為 3
x, y = 2, 3  # 使用者初始位置
while True:
  #clear_output() # 清除前一步內容(若輸入條會消失請移除此行)
  i, j = 0, 0    # 初始化印刷位置
  print('當前座標: (', x, ',', y, ')')
  while i < h:     # 高度判斷條件
    j=0        # 初始化 j
    content = ""
    while j<w: # 寬度判斷條件
      if i == x and j == y:
        content += "*"
      else:
        content += "-"
      j+=1
    print(content)
    i+=1
  # 讀取使用者指令
  control = input('按 W/A/S/D 來移動星星(q 結束)!\n')
  control = control.lower()
  
  # 更新使用者位置
  if control == "w":   # w 往上
    x -= 1
  elif control == "s": # s 往下
    x += 1
  elif control == "a": # a 往左
    y -= 1
  elif control == "d": # d 往右
    y += 1
  elif control == "q": # q 結束
    break

作業2

說明:定義一個 function ,功能是將 tsv 字串,轉換為 csv 字串,並且把值按照數字大到小排列。

成品及時展示:

思路說明

先將tsv文字使用.split("\t")來分離成一個陣列,然後把每一個字串分別轉換成整數,再使用.sort(reverse=True)來排序陣列,最後用",".join(arr)來將陣列轉換成csv輸出。

主要程式

def tsv_to_csv(tsv):
  return ",".join(str_reverse_sort(tsv.split("\t")))
def str_reverse_sort(arr):
  n = [int(x) for x in arr]
  n.sort(reverse=True)
  strarr = [str(x) for x in n]
  return strarr
print(tsv_to_csv("2\t1\t11"))

讀取檔案

def read_data(path):
    with open(path) as f:
        data = f.read().rstrip().replace('\\t', '\t')
    return data

作業3

說明:請統計文章中,不同字所出現的次數為何。

  • ‘I don’t care’ 視為三個字,分別為I, don’t, care各一次。
  • play和plays 視為兩種字,同時出現時,各算一次。

成品及時展示:

思路說明

使用Counter模組。讀取檔案內容後,用.split()將內容以空格分開為陣列,在from collections import Counter後使用Counter(arr)得到計數結果,最後轉成字串輸出。

主要程式

from collections import Counter

def read_data(path):
    with open(path) as f:
        data = f.read().rstrip()
    return data

article = read_data('data/article2.txt')
print(Counter(article.split()))

加分題

article = read_data('data/bonus.txt')
l = article.split()
n = []
for i in range(len(l)-1):
  n.append(l[i] + " " + l[i+1])
print(Counter(n))

作業4

說明:

  • 輸入
    每個檔案總共 $N$ 行,$N$ 為正整數,$1 \leq N < 1000$。
    每行資料包含兩個值 $p$, $i$,以單一半形空格相接。
    $p$ 代表購買人姓名,$i$ 代表購買物品,此二值可能包含中文或英文,保證期間無空白存在。

  • 輸出
    請根據不同購買者分別建立以其姓名為檔名之文字檔。
    每個檔案中有數行,每行包含兩個值 $i$ 與 $c$,中間以單一半形空格相接。
    $i$ 為該購買者所購買之物品,$c$ 為與該物品總購買數量。

小題1

成品及時展示:

思路說明

使用Counter模組。讀取檔案內容後,使用.split("\n")得到檔案中每一行的陣列,再用.split()將每一行內容用空白分開。接者,將相同人名的物件放在同一個陣列中,在from collections import Counter後使用Counter(arr)得到計數結果,並儲存此結果到檔案中。

def read_data(path):
    with open(path) as f:
        data = f.read().rstrip()
    return data
from collections import Counter
import os
output_perfix = "output"

os.makedirs(output_perfix)

files = ['file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', 'file5.txt']


fileName = files[4]
rows = read_data(fileName).split("\n")
table = {}
for r in rows:
  x = r.split()
  if x[0] in table:
    table[x[0]]["items"].append(x[1])
  else:
    table[x[0]] = {"items": [],"counter": {}}
    table[x[0]]["items"].append(x[1])
for p in table:
  table[p]["counter"] = Counter(table[p]["items"])
for p in table:
  content = ""
  for x in table[p]["counter"]:
    if content != "":content += "\n"
    content += x + " " + str(table[p]["counter"][x])
  f = open(output_perfix + "/" + p + ".txt", "w")
  f.write(content)
  f.close()

小題2

說明: 定義一個叫做 SalaryDistribution 的 class ,底下定義四個 method:

  • min: 回傳 salaries 的最小值
  • max: 回傳 salaries 的最大值
  • median: 回傳 salaries 的中位數
    • 中位數:由小排到大之後,長度 $N$ 為奇數時取第 $(N+1)/2$ 個數字,為偶數則取第 $N/2$ 個數字
  • mean: 回傳 salaries 的算數平均數

成品及時展示:

思路說明

建立class SalaryDistribution,在其中定義__init__minmaxmedianmean這幾個 function 。

class SalaryDistribution:
  def __init__(self,salaries):
    self.salaries = salaries
    self.salaries.sort()
  def min(self):
    return min(self.salaries)
  def max(self):
    return max(self.salaries)
  def median(self):
    if len(self.salaries) == 0:
      return self.salaries[0]
    if len(self.salaries) % 2:
      index = len(self.salaries) // 2
    else:
      index = len(self.salaries) // 2 - 1
    return self.salaries[index]
  def mean(self):
    total = 0
    for n in self.salaries:
      total += n
    return total / len(self.salaries)

def read_test_data(file_path):
    f = open(file_path)
    test_data = []
    for number in f.read().rstrip().split(' '):
        test_data.append(int(number))
    return test_data

作業5

說明:

輸入說明

共一行,該行包含 $N$ 個數字 $C_0 \dots C_{N_1}$ ,$1 \leq N \le 20$ ,代表目前序列中的車輛編號,每個編號間一個空白相隔。 保證 $C_0 \dots C_{N-1}$ 由不重複之連續正整數組成,且最小車輛編號必定為 $1$ 。

輸出說明

針對每筆測資,請輸出 successfail,代表當前順序是否可以讓所有人平安離開停車場。

成品及時展示:

主要程式

import requests
ret = requests.get('https://gist.githubusercontent.com/CloudeWu/beafd531151dc9938f3b3c4f16285b1d/raw/a5dd4cd8cb3b168fce275c33fe1ed51c007ad9d1/HW6_%25E6%25B8%25AC%25E8%25B3%2587.txt')
if not ret.ok:
    print('網路好像有點問題,晚點再試試看!')
else:
    testcases = [ [int(char) for char in line.split(' ')] for line in ret.text.split('\n')]

#params
printOutDetail = False
testCase = 2

def printDetail(text):
  global printOutDetail
  if printOutDetail:
    print(text)

testData = testcases[testCase-1].copy()
parking = []
outside = []
state = 2
newItem = 0
lowest = min(testData)
while ((len(parking) != 0 or len(testData) != 0) and state == 2):
  if len(testData) == newItem and len(parking) == 0:
    state = 1

  if len(parking) and parking[-1] == lowest:
    outside.append(parking[-1])
    printDetail(str(parking[-1])+" 號從停車場離開")
    lowest += 1
    parking.pop()
  elif len(testData) > newItem and testData[newItem] == lowest:
    outside.append(testData[newItem])
    printDetail(str(testData[newItem])+" 號直接離開")
    lowest += 1
    newItem += 1
  elif len(testData) > newItem:
    if len(parking) and min(parking) <= testData[newItem]:
      state = 0
    parking.append(testData[newItem])
    printDetail(str(testData[newItem])+" 號進入停車場")
    newItem += 1

if state == 0:
  print("fail")
else:
  print("success")