2018年9月15日 星期六

商競程式105模_解題記錄

試題連結 (商業類技藝技賽_105年_程式設計_模擬題)  2018/9/16 建置
9/16 完成 p11、p21       10/06 完成 p21、p22 、 p41 、 p42

10/19 完成 p31   10/22 完成 p32   另 p12也OK

用VB10寫在Form_Load,讀檔統一如下,然後呼叫fxx,每題讀檔就不重複


讀檔寫檔

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Hide()
        FileOpen(1, "in1.txt", 1)
        FileOpen(2, "in2.txt", 1)
        FileOpen(3, "out.txt", 2)
        For fn = 1 To 2
            If fn = 2 Then PrintLine(3)
            Dim n As Short = LineInput(fn)
            For k = 1 To n
                Dim s As String = LineInput(fn)
                PrintLine(3, fxx(s)) '根據測資可能一次兩列或傳fn讀多行
                ' fxx(s1,s2) 或 fxx(fn,s)
            Next
        Next
        End
    End Sub
   ...
   每一題 解題部份
   Function fxx( s as ... ) as ...
   ...
End Class

P11 數學問題-質數
每檔n筆<=5, x<65536 ,直接呼叫 isp,可以不需建質數表 

  Function fxx(ByVal s As String) As String
 
    Dim x As Integer = s
     If isp(x) Then
         Return "T" '是質數
     Else
         Return "F"  '非質數
     End If
  End Function

  Function isp(ByVal k As Integer) As Boolean
        If k < 2 Then Return False
        For i = 2 To Math.Sqrt(k)
            If k Mod i = 0 Then Return False
        Next
        Return True
  End Function


P12 數學問題-大數運算
A除B,求商 :A,B<= 60位數的整數,B>0,A沒規定 {有可能<0},
以neg記錄正負,以正數處理,若為neg,印出才加印負號

form_load 每筆讀入2列:被除數s1及除數s2,傳入 fxx( s1,s2)

  Const MaxN As Integer = 65 '最多 60位數
    Dim A(MaxN), B(MaxN), C(MaxN) As Integer
    Dim an, bn, cn As Integer
    Function fxx(ByVal s1 As String, ByVal s2 As String) As String
        'A 被除數,有可能為負數 、 B>0的正數 A÷B 求商
        Dim neg As Boolean = False 'A是否為負數
        s1 = Trim(s1) : s2 = Trim(s2)
        If Mid(s1, 1, 1) = "-" Then
            neg = True
            s1 = Mid(s1, 2)
        End If
        s2n(s1, A, an) '將「被除數」s1轉成陣列 A 
        s2n(s2, B, bn) '將「除數」正數s2轉成陣列 B 
        If bn = 1 And B(0) = 1 Then ' 若B為1,直接印出S1
            fxx = p2f(A, an)
            Return IIf(neg, "-", "") & fxx
        End If
        bdiv()  '呼叫大數除法 a÷b 存入 c
        Return IIf(neg, "-", "") & p2f(C, cn) ' 印 c => fxx
    End Function

   Function p2f(ByVal x() As Integer, ByVal xn As Integer) As String
        ' 倒著印陣列 X(),元素個數 xn
        If xn = 0 Then Return "0"
        p2f = ""
        For i = xn - 1 To 0 Step -1
            p2f &= x(i)
        Next
    End Function

   Sub s2n(ByVal xs As String, ByRef x() As Integer, ByRef xn As Integer)
        ' 將字串倒轉成 整數陣列
        Dim i As Integer = 0
        xn = xs.Length
        For j = xn To 1 Step -1
            x(i) = Mid(xs, j, 1)
            i += 1
        Next
        x(xn) = 0
    End Sub

   Sub bdiv()  '將 a÷b 存入 c
        Dim aw As Integer = bn + 1
        Dim i, cnt As Integer
        For k = an - bn To 0 Step -1
            cnt = 0
            Do While ncmp(k, aw)
                '  Print(3, k & ":" &  aw)
                cnt += 1
                bsub(k, aw)
                Dim os1 As String = p2f(A, an), os2 As String = p2f(B, bn)
                '  PrintLine(3, " a,b " & os1 & " , " & os2)
            Loop
            C(k) = cnt
        Next
        For i = an - bn To 0 Step -1
            If C(i) <> 0 Then Exit For
        Next
        cn = i + 1
    End Sub

    Function ncmp(ByVal ak As Integer, ByVal aw As Integer) As Boolean
        ncmp = True ' A 陣列 a(ak+aw-1) ~ a(ak) 共 aw 位, 與 b 陣列比較大小
        '先消去 a(ak+aw-1) 起的前導 0  、有需要?
        Dim i As Integer
        For i = aw - 1 To 0 Step -1
            If A(i + ak) <> 0 Then Exit For
        Next
        aw = i + 1
        If aw <> bn Then Return (aw > bn)
        For i = bn - 1 To 0 Step -1
            If A(i + ak) <> B(i) Then Return (A(i + ak) >= B(i))
        Next
        Return True
    End Function

    Function bsub(ByVal ak As Integer, ByVal aw As Integer) As Integer
      ' A 陣列 a(ak+aw-1) ~ a(ak) 共 aw 位, 減去 b 陣列, 去前導0 傳回新寬度 
        Dim i As Integer
        For k = 0 To bn - 1
            i = k + ak
            If A(i) < B(k) Then  '往前1位 借10
                A(i + 1) -= 1
                A(i) += 10
            End If
            A(i) -= B(k)
        Next
        '消去 a(ak+aw-1) 起的前導 0
        Do While aw > 0 AndAlso A(aw + ak - 1) = 0
            aw -= 1
        Loop
        bsub = aw

    End Function

P21 字串-前綴字串(Prefix) and 後綴字串(Postfix)
  一次讀兩列 s1,s2 再傳入 fxx
  兩字串較小長度len起至1,分別判定左k個字是否等於右k個字

  Function fxx(ByVal s1 As String, ByVal s2 As String) As String
     Dim n1 As Integer = s1.Length, n2 As Integer = s2.Length
     Dim len As Integer = Math.Max(n1, n2)
     Dim k As Integer = len
     For k = len To 1 Step -1
         If Strings.Left(s1, k) = Strings.Right(s2, k) Then Exit For
     Next
     Return k 
  End Function




P22 字串-行、字數、字元數

       因要讀多行,傳入 檔號fn,在fxx(fn) 讀檔處理
    Function fxx(ByVal fn As Integer) As String
        Dim a, b, c As Integer '列、字、字元
        Do Until EOF(fn)
            Dim line = LineInput(fn)
            a += 1           '加1列
            c += line.Length '  這列的字元數
            Dim dat() = line.Split(" ")
            b += dat.Length  '  這列的 字數(word)以空白隔開
        Loop
        Return a & "," & b & "," & c
    End Function


P31 樹-是否為堆積樹(Heap tree)
  判斷是否為堆積樹 {Min_Heap、Max_Heap皆算}

  Function fxx(ByVal s As String) As String
 
      f = "T"
        Dim dat() = s.Split(",")
        Dim m As Integer = dat.Length
        Dim a(m) As Integer
        For i = 0 To UBound(dat)
            a(i + 1) = dat(i)
        Next
        If Not h1(a, m) And Not h2(a, m) Then Return "F" '不是 Max_Heap 且 不是 Min_Heap 才傳回 F
  End Function
   Function h1(ByVal a() As Integer, ByVal m As Integer) As Boolean ' Max_Heap ?
        h1 = True
        For p = m \ 2 To 1 Step -1
            If a(p) <= a(2 * p) Then Return False
            If 2 * p + 1 <= m AndAlso a(p) <= a(2 * p + 1) Then Return False '有可能 沒有 2p+1
         Next
    End Function

    Function h2(ByVal a() As Integer, ByVal m As Integer) As Boolean ' Min_Heap ?
        h2 = True
         For p = m \ 2 To 1 Step -1
            If a(p) >= a(2 * p) Then Return False
            If 2 * p + 1 <= m AndAlso a(p) >= a(2 * p + 1) Then Return False '有可能沒有 2p+1
        Next

    End Function



P32 樹-中序表示法
  二元搜尋樹的中序表示法,每檔只有一組資料

    Class bt   '一個節點,內含三個資料  {註:也可以分開建三個陣列}
        Public Property lt As Integer = -1 '左樹
        Public Property dt As Integer '資料
        Public Property rt As Integer = -1 '右樹
    End Class
    Dim nd(30) As bt  '最多 30 個節點 ,編號 0~100
    '註:二搜樹的中序其實就是 由小到大,偷工的做法就是排序即可
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        FileOpen(1, "in1.txt", OpenMode.Input)
        FileOpen(2, "in2.txt", OpenMode.Input)
        FileOpen(3, "out.txt", OpenMode.Output)
        For fn = 1 To 2
            If fn = 2 Then PrintLine(3)
            Dim m As Short = LineInput(fn)  '共有 m 個節點
            '一個檔只有一組資料
            PrintLine(3, fxx(m, fn)) '傳 m 個節點, 檔號fn
        Next ' fn
        End
    End Sub
    Function fxx(ByVal m As Integer, ByVal fn As Integer) As String
        nd(0) = New bt   '要記得 需 New bt 才可使用
        nd(0).dt = LineInput(fn)  '第1個 root
        For j = 1 To m - 1
            nd(j) = New bt
            Dim k As Integer = LineInput(fn)
            nd(j).dt = k
            Dim p = 0
            Do While True
                If k < nd(p).dt Then  '往左
                    If nd(p).lt = -1 Then
                        nd(p).lt = j
                        Exit Do
                    Else
                        p = nd(p).lt
                    End If
                Else   '往右
                    If nd(p).rt = -1 Then
                        nd(p).rt = j
                        Exit Do
                    Else
                        p = nd(p).rt
                    End If
                End If
            Loop
        Next j
        fxx = ""
        'For j = 0 To m - 1   '印出參考  ( 左、值、右 )
        '  PrintLine(3, j & "  " & nd(j).lt & ":" & nd(j).dt & ":" & nd(j).rt)
        'Next
        fxx = ""
        fst = True : ino_t(0, fxx)   '印中序
        ' fst = True : pre_t(0,fxx)   '印前序
        ' fst = True : pos_t(0,fxx)   '印後序
    End Function

   Dim fst As Boolean  '是否印出的第1個節點, 不加,號

    Sub ino_t(ByVal p As Integer, ByRef fxx As String)  '中序
        If nd(p).lt <> -1 Then ino_t(nd(p).lt, fxx)
        If fst Then fst = False Else fxx &= ","
        fxx &= nd(p).dt
        If nd(p).rt <> -1 Then ino_t(nd(p).rt, fxx)
    End Sub

   Sub pre_t(ByVal p As Integer, ByRef fxx As String)  '前序
        If nd(p).lt <> -1 Then pre_t(nd(p).lt, fxx)
        If fst Then fst = False Else fxx &= ","
        fxx &= nd(p).dt
        If nd(p).rt <> -1 Then pre_t(nd(p).rt, fxx)
    End Sub

    Sub pos_t(ByVal p As Integer, ByRef fxx As String)  '後序
        If nd(p).lt <> -1 Then pos_t(nd(p).lt, fxx)
        If nd(p).rt <> -1 Then pos_t(nd(p).rt, fxx)
        If fst Then fst = False Else fxx &= ","
        fxx &= nd(p).dt
    End Sub



P41 其他-尋找對稱字串
  若字串長度為 k , 只需判別 k\2次  {  (1,k),(2,k-1)…(k\2,k-k\2+1)  } 是否皆相同


    Function fxx(ByVal s As String) As String
        fxx = ""
        Dim sn As Integer = s.Length
        ' 從最長開始 取一段 長度k = lt~rt 是否為迴文
        For k = sn To 1 Step -1 '長度從 sn開始至1 各試有沒有迴文
            For lt = sn - k + 1 To 1 Step -1
                Dim rt As Integer = k - lt + 1
                If padr(Mid(s, lt, k), k) Then Return k
            Next
        Next
    End Function

    Function padr(ByVal s As String, ByVal k As Integer) As Boolean
        '長度為 k 的字串 s 是否迴文
        For i = k \ 2 To 1 Step -1  '前後  各1字元比較
            If Mid(s, i, 1) <> Mid(s, k + 1 - i, 1) Then Return False
        Next
        Return True
    End Function

P42 其他-十進制數轉成二進制數
  可使用內建函數轉二、八、十六進位,也可自寫函數
 str = Convert.ToString( d, x ) '將十進位d轉為x進位{x為2、8、16)傳回字串

 d = Convert.ToInt32(str, x) ' 將x進位字串str轉為十進位 傳回數值

  Function fxx(ByVal s As String) As String
        Dim dat() = s.Split(",")  '需注意 原始資料的 逗號左右 是否有空白
        Dim a As Integer = StrReverse(Trim(dat(0)))
        Dim b As Integer = StrReverse(Trim(dat(1)))
        Dim sum As Integer = StrReverse((a + b) & "")
        ' Debug.Print(3, sum & ":") '十進位的結果
        fxx = d2b(sum)   '自訂轉換函數
   'fxx = Convert.ToString(sum, 2) '也可用Convert,但好像只有2,8,16可以
    End Function

    Function d2b(ByVal sum As Integer) As String
        d2b = ""
        If sum = 0 Then Return "0"
        Do Until sum = 0
            d2b = sum Mod 2 & d2b
            sum \= 2
        Loop
    End Function





0 意見:

張貼留言