Percursos
/
Crystal
Crystal
/
Exercícios
/
Mitigação de Fusão
Mitigação de Fusão

Mitigação de Fusão

Exercício de aprendizagem

Introdução

O Crystal tem aquilo a que se chama expressões de controlo. Estas servem para controlar a forma como o programa corre e assumem um valor verdadeiro ou falso. Existem operadores que podem ser usados para criar valores verdadeiros ou falsos: os operadores de igualdade e de comparação.

Existem duas expressões de controlo principais que determinam que código é executado e que código não é. Por outras palavras, que ramo é que corre.

Essas duas são: a expressão if e a expressão unless.

Operadores de comparação

Os operadores de comparação são usados para comparar valores e devolver um valor true ou false. Estes operadores exigem que sejam comparados dois valores do mesmo tipo. Se os valores não forem do mesmo tipo, o compilador dá um erro. Aqui está uma lista dos operadores de comparação e um exemplo de quando devolvem um valor true:

Método Descrição Exemplo
< menor que 4 < 5
<= menor ou igual que 4 <= 4
> maior que 3 > 1
>= maior ou igual que 2 >= 2

Operadores de igualdade

Os operadores de igualdade são semelhantes aos operadores de comparação, mas são usados para verificar se dois valores são iguais ou não.

O operador == verifica se dois valores são iguais, incluindo o tipo do valor. Se os valores forem iguais, devolve true; caso contrário, devolve false. O operador == pode comparar qualquer tipo de valor com qualquer outro tipo de valor. O != funciona da mesma forma, mas devolve true se os valores não forem iguais e false se forem iguais.

Instrução if

A condicional if é usada para verificar se uma determinada condição é verdadeira ou falsa. Se a condição for verdadeira, o código dentro da condicional if é executado. Uma condicional if termina com a palavra-chave 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

Instrução unless

A condicional unless funciona de forma muito semelhante à condicional if, mas executa o código dentro da condicional unless se a condição for falsa.

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

Instrução else

A instrução else pode ser usada em conjunto com as condicionais if e unless. A instrução else é executada se o ramo do if ou o ramo do unless não for executado.

Embora um ramo `else` possa ser usado em conjunto com `unless,` isso é desaconselhado porque prejudica a legibilidade.
Em vez disso, recomenda-se usar `if !condition` com um ramo else.
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

Instruções if em cascata

A instrução elsif pode ser usada em conjunto com a condicional if. A instrução elsif é executada se o ramo do if não for executado e a condição da instrução elsif for verdadeira. As instruções elsif podem ser encadeadas e a primeira condição verdadeira é a que é executada. Também pode haver uma instrução else no fim da condicional if, que corre se nenhuma das instruções anteriores tiver sido verdadeira.

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

Tipos com condicionais

Quando é atribuída a tipos diferentes, a variável passa a ter os dois tipos. Isto acontece porque o compilador não sabe que ramo será executado. Esta atribuição múltipla, também conhecida como união, será explicada em conceitos posteriores. Podes ver isto no exemplo seguinte:

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

typeof(a) # => Int32 | String

Operador ternário

O Crystal tem um operador ternário, uma instrução if-else de uma só linha: 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

Instruções

Neste exercício, vamos desenvolver um sistema de controlo simples para um reator nuclear.

Para um reator produzir potência, tem de estar num estado de criticidade. Se o reator estiver num estado abaixo da criticidade, pode ficar danificado. Se o estado do reator ultrapassar a criticidade, pode sobrecarregar e provocar uma fusão do núcleo. Queremos reduzir a probabilidade de fusão do núcleo e gerir corretamente o estado do reator.

As três tarefas seguintes estão todas relacionadas com a escrita de código para manter o estado ideal do reator.

1. Verifica a criticidade

A primeira coisa que um sistema de controlo tem de fazer é verificar se o reator está equilibrado na criticidade. Diz-se que um reator está crítico se cumprir as seguintes condições:

  • A temperatura é inferior a 800 K.
  • O número de neutrões emitidos por segundo é superior a 500.
  • O produto da temperatura pelo número de neutrões emitidos por segundo é inferior a 500000.

Implementa o método Reactor.criticality_balanced?, que recebe temperature, medida em kelvin, e neutrons_emitted como parâmetros, e devolve true se as condições de criticidade forem cumpridas, e false caso contrário.

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

2. Determina o intervalo de potência de saída

Assim que o reator começa a produzir potência, é preciso determinar a sua eficiência. A eficiência pode ser agrupada em 4 faixas:

  1. green -> eficiência de 80% ou mais,
  2. orange -> eficiência inferior a 80%, mas de pelo menos 60%,
  3. red -> eficiência abaixo de 60%, mas ainda 30% ou mais,
  4. black -> eficiência inferior a 30%.

O valor percentual pode ser calculado como (generated_power/theoretical_max_power)*100, em que generated_power = voltage * current. Tem em atenção que o valor percentual normalmente não é um número inteiro, por isso certifica-te de que usas corretamente as comparações < e <=.

Implementa o método Reactor.reactor_efficiency, com três parâmetros: voltage, current e theoretical_max_power. Esta função deve devolver a faixa de eficiência do reator: "green", "orange", "red" ou "black".

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

3. Mecanismo à prova de falhas

A tua última tarefa consiste em criar um mecanismo à prova de falhas para evitar a sobrecarga e a fusão do núcleo. Este mecanismo vai determinar se o reator está abaixo, no, ou acima do limiar ideal de criticidade. A criticidade pode então ser aumentada, diminuída ou interrompida inserindo (ou removendo) barras de controlo do reator.

Implementa o método Reactor.fail_safe(), que recebe 3 parâmetros: temperature, medida em kelvin, neutrons_produced_per_second e threshold, e devolve um código de estado para o reator.

  • Se temperature * neutrons_produced_per_second for inferior a 90% de threshold, devolve o código de estado "LOW", que indica que é preciso remover as barras de controlo para produzir potência.

  • Se temperature * neutrons_produced_per_second estiver dentro de mais ou menos 10% de threshold, o reator está em criticidade e deve ser devolvido o código de estado "NORMAL", que indica que o reator está em condições ótimas e que as barras de controlo estão numa posição ideal.

  • Se temperature * neutrons_produced_per_second não estiver dentro dos intervalos acima indicados, o reator vai entrar em fusão do núcleo e é preciso passar o código de estado "DANGER" para desligar imediatamente o reator.

temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"
Editar via GitHub A ligação abre numa nova janela ou separador
Crystal Exercism

Estás pronto para começar Mitigação de Fusão?

Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.