E-tutor [程式設計][C_AR183-易] 數字跑馬燈

簡介

題目來源:e-tutor平台
[C_AR183-易] 數字跑馬燈

數字跑馬燈,這題在輸入資料與如何處理資料這部分比較麻煩,讀進字串後還要切割,甚至還需要把字串轉整數,需要多個步驟。

讓我們先了解題目內容

問題描述:

請讀入二行資料,第一行是一串空白隔開的數字 ( 個數 N <= 20 ),假設這是要顯示的跑馬燈,第二行是一串讓跑馬燈資訊左右轉動的命令,可以指定這一串數字向左或者向右轉的次數,當一個數字從第一個位置向左轉出時,會移動到最後一個數字,反之亦然,一個數字從最後一個位置向右轉出時,會移動到第一個數字。下面例子說明跑馬燈轉動的過程:假設讀入的一串數字如下:

20 -5 -18 6 18 22 5 7 12 51 19

讀入的轉動命令為 L 5 R 13 R 2 L 7,L 表示向左移動,R 表示向右移動,所以 L 5 表示向左移動 5 個位置,R 13 表示向右移動 13 個位置等,則這些命令依序轉動過程如下:

L 5 → 22 5 7 12 51 19 20 -5 -18 6 18

R 13 → 6 18 22 5 7 12 51 19 20 -5 -18

R 2 → -5 -18 6 18 22 5 7 12 51 19 20

L 7 → 12 51 19 20 -5 -18 6 18 22 5 7

最後一行即是全部轉動完畢之後,要輸出的結果。

Input:

輸入資料有兩行,第一行是由空白隔開的一串數字 ( 最多 20 個 ),第二行是一串左轉或右轉的命令,命令之間由空白字元隔開,每個命令包含一個 L 或 R 字元 ( 皆為大寫字元 ),接著一個整數 S ( S >= 0 ) ,表示往左或者往右轉動 S 個位置。最多 25 個命令。

Output:

輸出該串數字經過這一連串的轉動命令之後的結果。

範例:


解題想法:

先處理輸入資料,把輸入的數字先存起來,再用兩個陣列儲存命令,一個是只有經過切割字串,另一個則是切割完後轉整數,資料分開後再去計算所有的左轉和右轉互相抵銷,到底該往哪個方向移動位置,接著不要去更動到原本的數字陣列,使用不同的輸出方式輸出答案。

第一步、處理題目所需的輸入格式

1.使用 vector 功能建立二個一維的字串陣列,分別為 NumberArray、Direction

2.使用 vector 功能建立一個一維的整數陣列,為 Integer

3.宣告題目所需的輸入,宣告兩個字串,分別為 number、command

※記得要 include < string >

為什麼題目所需資料要用字串讀取而不是用整數讀取?

題目沒有固定輸入 N 個整數和說明每次命令有多長

因此可能每次都不一樣長度

在這種情況下,就可以採用讀取字串,最後再一併切割

第二步、讀入字串並且切割字串

在處理字串前先 include < sstream > 引入 sstream 功能

1.字串 number

   使用 getline 讀入字串才不會使 enter 也讀入

   宣告 token 字串
 
   使用 sstream 功能,把 ss 當成是轉換器,拿 number 字串丟入轉換器

   設定一個迴圈

   只要在 number 字串裡有空白字元就把它當斷點切割丟到 token

   再把 token 丟到儲存所有數字的字串陣列 NumberArray 裡

2.字串 command

   同上步驟,使用 sstream 功能,轉換器名稱為 ss1,拿 command 字串丟入轉換器

   設定一個迴圈

   只要在 command 字串裡有空白字元就把它當斷點切割丟到 token

   再把 token 丟到儲存所有命令的字串陣列 Direction裡



3.字串 command 轉整數

   這邊與以上兩個切割字串有些微的不同

   多了一個轉整數的步驟

   一樣先做以上步驟,轉換器名稱為 ss2

   設定一個迴圈

   只要在 command 字串裡有空白字元就把它當斷點切割丟到 token

   再設定一個轉換器命名為 stmp,把 token 放進去

   宣告一個整數 v
 
   經過轉換器把切割下來的 token 轉成整數放進 Integer 陣列裡

   為什麼要創建兩個不同型別陣列分別用來儲存 command 字串所切割的東西?
 
   command 字串是由英文與數字組成的字串

   要先判斷英文是 " L " 或者 " R " 才能決定左移或右移

   因此我的想法為分別分開存在不同陣列
 
   取用時才不用在一個一個分開轉整數

   需要找尋左移或右移資料時,找 Direction 陣列元素單數個

   需要找尋移動位置數時,找 Integer 陣列元素偶數個

第三步、計算到底需要左移或右移幾個位置

1.宣告整數 move 來記錄

2.設定迴圈
 
   假設 i 等於 0,只要小於 Direction 陣列的大小,則 i = i + 2

   這個迴圈跑的次數為指令的數量

   i = i + 2,原因是前面有提到的,找尋左移或右移的命令時,要找 Direction 陣列元素單數個

3.如果 Direction 陣列元素單數個為 " L "

   則 move 等於 move 加上 Integer [ i + 1 ]乘 -1
 
4.如果 Direction 陣列元素單數個為 " R "
 
   則 move 等於 move 加上 Integer [ i + 1 ] 乘 1

5.最後在迴圈外

   move 等於 NumberArray 除以 move 取餘數

為什麼 move 要加上 Integer 陣列第 i + 1 個元素?

Direction 陣列第 i 個元素為奇數,因此同樣的 i 引用到 Integer 陣列並且把 i 將上 1

正好是 Integer 陣列的偶數元素,也就是我們所需要取的移動位置

為什麼取得移動位置後要乘 -1 或者乘 1?

為了方便計算總共移動幾格與移動哪個方向

假設把向右移幾格當成正數,向左移幾格當成負數

正負數就是一個負數的概念

右移乘正數 1,左移成負數 -1

為什麼最後還要把 move 變成 NumberArray 除以 move 取餘數?

假設今天所有數字只有 5 個

結果計算出來的命令結果為右移 23 格

那麼其實等於只有右移 3 格

其他的 20 格執行完會繞回原本位置

第四步、輸出答案

計算完移動方向與位置後不用更動數字陣列嗎?

只需要再輸出部分動手腳就不用去更動數字陣列

假設現在有一個 5 格的陣列

必須要向右移動三格


移動一格

移動二格

移動三格

比較原始順序

如果要在不要動到原始陣列的情況下

只要從陣列的第三個元素開始輸出就可以了

1.宣告整數 count 為計數器

   用來計算共輸出幾個數字

2.設定迴圈,迴圈的起始值 i 為 NumberArray 的大小減去 move

  也就是從第幾個元素開始輸出

3.如果 i 等於 NumberArray 的大小,也就是跑到陣列最尾巴時

  就把 i 歸零回到陣列最前面還沒輸出元素

4.其餘的狀況

   4-1.如果計數器等於 NumberArray 的大小減一,最後一個數時

          就輸出數字換行並且跳出迴圈

 
   4-2.其餘狀況,輸出數字加空白字元就好了

          並且讓計數器加一才知道已經輸出幾個了

以下為完整程式碼

留言

這個網誌中的熱門文章

E-tutor [程式設計][C_CH10-中] The 3n + 1 problem

E-tutor [程式設計][C_MM244-難] 複數的加減乘法