學習軌道
/
Java
Java
/
練習
/
星際傳輸
星際傳輸

星際傳輸

中等

簡介

每毫秒都有數以兆計的訊息在地球與鄰近星系之間飛速穿梭。 但要在這麼遙遠的距離上傳輸訊息,可不是件容易的事。 惱人的太陽閃焰、時空扭曲、游離的作用力,甚至太空蝴蝶輕拍一下翅膀,都可能在傳輸過程中讓某個位元隨機改變。

現在想像一下後果:

  • 星際股市因為「buy low」變成「sell now」而徹底崩盤。
  • 因為「save new worm hole」變成「cave new worm hole」,而與 Kepler Whirl system 失去聯繫。
  • 或者把牛仔表情符號 🤠 換成小丑表情符號 🤡,讓整個宇宙陷入存在主義式的恐懼。

偵測損毀的訊息不只是重要,而是攸關存亡。 接收端_必須_在災難發生之前知道出了問題。

但該怎麼做呢? 來自宇宙各地的科學家和工程師已經與這個問題搏鬥了億萬年。 龐大的宇宙級 AI 超級叢集不停消化這些資料。 直到某一天,一個傳說重現了:一個古老卻強大的方法,在除錯論壇上被人悄悄提起,被見識過太多事情的工程師低聲傳頌……

同位位元!

這個方法如此簡單、如此強大,或許正好能拯救星際通訊。

說明

你的任務是協助實作

  • 發送器,負責計算傳輸序列
  • 接收器,負責解碼

同位位元是偵測傳輸錯誤的簡單做法。 發送器和接收器一次只能傳輸和接收_正好_ 8 個位元(包含同位位元)。 同位位元的設定方式,是讓每次傳輸中的 1 位元數量為_偶數_,而且同位位元永遠是從右邊數來的第一個位元。 所以如果接收器收到 11000001、01110101 或 01000000(也就是含有奇數個 1 位元的傳輸),就知道發生了錯誤。

不過,訊息很少這麼短;當訊息較長時,就必須拆成序列來傳輸。

舉例來說,假設訊息是 11000000 00000001 11000000 11011110(或十六進位的 C0 01 C0 DE)。

由於每次傳輸正好包含 8 個位元,其中只能放入 7 個位元的資料以及同位位元。 因此,每 7 個位元的資料後面都必須插入一個同位位元:

11000000 00000001 11000000 11011110
      ↑       ↑       ↑       ↑          (7th bits)

這個訊息的傳輸序列如下:

1100000_ 0000000_ 0111000_ 0001101_ 1110
       ↑        ↑        ↑        ↑      (parity bits)

序列中第一個傳輸的資料(1100000)有 2 個 1 位元(偶數),所以同位位元是 0。 第一個傳輸就變成 11000000(或十六進位的 C0)。

下一個傳輸的資料(0000000)有 0 個 1 位元(又是偶數),所以同位位元同樣是 0。 第二個傳輸因此變成 00000000(或十六進位的 00)。

接下來兩個傳輸的資料(0111000 和 0001101)有 3 個 1 位元。 它們的同位位元設為 1,讓整個傳輸含有偶數個 1 位元。 它們會以 01110001 和 00011011 傳輸(或十六進位的 71 和 1B)。

最後一個傳輸(1110)只有 4 個位元的資料。 由於一次正好傳輸 8 個位元,而同位位元是最右邊的位元,因此會補上 3 個 0 位元,再加上同位位元,湊成 8 個位元。 現在看起來像這樣(其中_代表同位位元):

1110 000_
     ↑↑↑   (added 0 bits)

這裡的 1 位元數量又是奇數,所以同位位元是 1。 序列中最後一個傳輸變成 11100001(或十六進位的 E1)。

這個訊息完整的傳輸序列是 11000000 00000000 01110001 00011011 11100001(或十六進位的 C0 00 71 1B E1)。

實作

雖然我們處理的是位元組資料,但輸入和輸出都是 List<Integer>(而非 byte[]),這樣就不需要為了 128 到 255 的位元組而轉型或轉換負值。


出處

Kah Goh連結會在新視窗或分頁中開啟
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Java Exercism

準備好開始 星際傳輸 了嗎?

註冊 Exercism,透過 26 個概念158 個練習 和真人引導來學習並精通 Java,全部免費。