熔毀防制

熔毀防制

學習練習

簡介

Crystal 有所謂的控制運算式,用來控制程式的執行方式,它們會接受真值或假值。 有一類運算子可以用來產生真值或假值,這些稱為相等與比較運算子。

控制哪些程式碼會執行、哪些不會的控制運算式主要有兩種,也就是決定會執行哪個分支。

這兩種是:if和unless運算式。

比較運算子

比較運算子用來比較值並回傳 true 或 false。這類運算子要求兩個型別相同的值才能比較。如果兩個值的型別不同,編譯器會拋出錯誤。 以下是比較運算子清單,以及它們產生 true 時的範例:

方法 說明 範例
< 小於 4 < 5
<= 小於或等於 4 <= 4
> 大於 3 > 1
>= 大於或等於 2 >= 2

相等運算子

相等運算子和比較運算子類似,但用來檢查兩個值是否相等。

==運算子會檢查兩個值是否相等,包括值的型別。如果兩個值相同,就回傳 true,否則回傳 false。 ==運算子可以拿任何型別的值和任何其他型別的值比較。 !=的運作方式相同,但值不相等時回傳 true,相等時回傳 false。

if敘述

if敘述用來檢查給定的條件是真值還是假值。如果條件為真值,if敘述裡的程式碼就會執行。if敘述以 end關鍵字結尾。

if 1 == 1
  puts "1 is equal to 1"
end
# => 1 is equal to 1

if 1 > 2
  puts "1 is greater than 2"
end
# => no output

unless敘述

unless敘述的運作方式和 if敘述非常相似,但如果條件為假值,它就會執行 unless敘述裡的程式碼。

unless 1 == 1
  puts "1 is not equal to 1"
end
# => no output

unless 1 > 2
  puts "1 is not greater than 2"
end
# => 1 is not greater than 2

else敘述

else敘述可以和 if、unless敘述搭配使用。如果 if分支或 unless分支沒有執行,就會執行 else敘述。

即使 `else`分支可以和 `unless,`搭配使用,也不建議這麼做,因為會降低可讀性。
建議改用帶有 else 分支的 `if !condition`。
if 1 == 1
  puts "1 is equal to 1"
else
  puts "1 is not equal to 1"
end
# => 1 is equal to 1

unless 1 < 2
  puts "1 is not greater than 2"
else
  puts "1 is greater than 2"
end
# => 1 is greater than 2

「串接式 if」敘述

elsif敘述可以和 if 敘述搭配使用。如果 if 分支沒有執行,而且 elsif敘述的條件為真值,就會執行 elsif敘述。 elsif敘述可以串接在一起,第一個為真值的條件會被執行。 if 敘述最後也可以有一個 else 敘述,如果前面的敘述都沒成立,就會執行它。

if 1 != 1
  puts "1 is not equal to 1"
elsif 1 > 2
  puts "1 is greater than 2"
else
  puts "1 is not equal to 1 and 1 is not greater than 2"
end
# => 1 is not equal to 1 and 1 is not greater than 2

型別與條件式

當變數被指定成不同型別時,變數會同時帶有這兩種型別。這是因為編譯器不知道哪個分支會被執行。這種多重指定也稱為 union,會在之後的概念中介紹。以下範例可以看到這種情況:

if 1 == 1
  a = 1
else
  a = "1"
end

typeof(a) # => Int32 | String

三元運算子

Crystal 有三元運算子,也就是單行的 if-else 敘述:condition ? expression_if_truthy : expression_if_falsey

1 == 1 ? puts("1 is equal to 1") : puts("1 is not equal to 1")
# => 1 is equal to 1

說明

在這個練習中,我們要為核子反應爐開發一套簡單的控制系統。

反應爐要產生電力,就必須處於_臨界_狀態。如果反應爐的狀態低於臨界,就可能受損;如果反應爐的狀態超過臨界,就可能過載,導致爐心熔毀。我們希望能降低熔毀的機率,並正確地管理反應爐的狀態。

以下三個任務都與撰寫程式碼來維持理想的反應爐狀態有關。

1. 檢查臨界狀態

控制系統第一件要做的事,就是檢查反應爐是否處於平衡的臨界狀態。當反應爐滿足以下條件時,就稱為處於臨界:

  • 溫度低於 800 K。
  • 每秒釋放的中子數大於 500。
  • 溫度與每秒釋放中子數的乘積小於 500000。

請實作方法Reactor.criticality_balanced?,它接受以克氏溫標計量的temperature和neutrons_emitted作為參數,並在符合臨界條件時回傳true,不符合時回傳false。

Reactor.criticality_balanced?(750, 600)
# => true

2. 判斷功率輸出範圍

反應爐開始產生電力之後,就必須判斷它的效率。效率可以分為 4 個等級:

  1. green -> 效率達 80% 以上,
  2. orange -> 效率低於 80%,但至少 60%,
  3. red -> 效率低於 60%,但仍有 30% 以上,
  4. black -> 效率低於 30%。

百分比數值可以用(generated_power/theoretical_max_power)*100計算,其中generated_power = voltage * current。請注意,百分比數值通常不會是整數,因此務必留意<和<=比較的正確用法。

請實作方法Reactor.reactor_efficiency,它有三個參數:voltage、current和theoretical_max_power。這個函式應回傳反應爐的效率等級:"green"、"orange"、"red"或"black"。

Reactor.reactor_efficiency(200,50,15000)
# => "orange"

3. 失效安全機制

你的最後一項任務,是建立一套失效安全機制,以避免過載與爐心熔毀。這套機制會判斷反應爐是低於、等於還是高於理想的臨界門檻。接著就能透過將控制棒插入(或移出)反應爐,來提升、降低或停止臨界程度。

請實作方法Reactor.fail_safe(),它接受 3 個參數:以克氏溫標計量的temperature、neutrons_produced_per_second和threshold,並輸出反應爐的狀態代碼。

  • 如果temperature * neutrons_produced_per_second小於threshold的 90%,請輸出狀態代碼 "LOW",表示必須移除控制棒才能產生電力。

  • 如果temperature * neutrons_produced_per_second落在threshold加減 10% 的範圍內,反應爐就處於_臨界_狀態,此時應輸出狀態代碼 "NORMAL",表示反應爐處於最佳狀態,控制棒也位於理想位置。

  • 如果temperature * neutrons_produced_per_second不在上述範圍內,反應爐正邁向爐心熔毀,必須傳遞狀態代碼 "DANGER",以立即關閉反應爐。

temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Crystal Exercism

準備好開始 熔毀防制 了嗎?

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