Logika wyrażeń w instrukcjach warunkowych

Logika matematyczna to jedna z bardziej przydatnych w programowaniu (i ogólnie informatyce) dziedzin matematyki. Dzięki prawom logiki działają wszystkie układy elektroniczne. W codzienności programisty może przydać się zwłaszcza podczas optymalizacji warunków logicznych.

Przykładowo, inspekcja kodu Ruby w środowisko IntelliJ za błąd uważa sterowanie przepływem za pomocą negatywnego warunku typu: if !condition ... . Taki pojedynczy warunek wystarczy w takim przypadku zamienić na: unless condition .... W przypadku bardziej rozbudowanych warunków przydają się znane z liceum prawa de Morgana.

I prawo de Morgana (zaprzeczenia koniunkcji)
~(p ^ q) <==> (~p v ~q)

Poniższy kod sprawdza, czy jest widoczny nagłówek. Nagłówek powinien mieć tytuł oraz podtytuł. Jeżeli obydwa tytuły są widoczne, uznajemy ze jest wyświetlony poprawnie. I tak następujące instrukcje warunkowe:

if !is_title_displayed || !is_subtitle_displayed
  puts 'Header not visible!'
end

można zamienić na:

unless (is_title_displayed && is_subtitle_displayed)
  puts 'Header not visible!'
end

Zobaczmy, jak to działa.

def check(p, q)
  if !p || !q
    puts 'Header not visible!'
  else
    puts 'Header is displayed.'
  end
end

def check_morgan(p, q)
  unless p && q
    puts 'Header not visible!'
  else
    puts 'Header is displayed.'
  end
end

Test, czy obydwie funkcje są sobie równoważne:

is_title_displayed=true
is_subtitle_displayed=true
check(is_title_displayed,is_subtitle_displayed)
=> Header is displayed.
check_morgan(is_title_displayed,is_subtitle_displayed)
=> Header is displayed.

is_title_displayed=true
is_subtitle_displayed=false
check(is_title_displayed,is_subtitle_displayed)
=> Header not visible!
check_morgan(is_title_displayed,is_subtitle_displayed)
=> Header not visible!

is_title_displayed=false
is_subtitle_displayed=true
check(is_title_displayed,is_subtitle_displayed)
=> Header not visible!
check_morgan(is_title_displayed,is_subtitle_displayed)
=> Header not visible!

is_title_displayed=false
is_subtitle_displayed=false
check(is_title_displayed,is_subtitle_displayed)
=> Header not visible!
check_morgan(is_title_displayed,is_subtitle_displayed)
=> Header not visible!

Obydwie metody zachowują się identycznie.

II prawo de Morgana (zaprzeczenia alternatywy)
~(p v q) <==> (~p ^ ~q)

Poniższy kod zwraca wartość true, gdy linia zawiera jakieś znaki i nie zawiera napisu "Serial number".

def validate(line)
  if !line.empty? && !line.include?('Serial Number')
    puts 'True'
  else
    puts 'False'
  end
end  

def validate_morgan(line)
  unless(line.empty? || line.include?('Serial Number'))
    puts 'True'
  else
    puts 'False'
  end
end

Oczywiście funkcje te można zapisać w krótszej formie, ale dla celu artykułu pozostawiam formę rozwiniętą, gdzie lepiej widać, do się dzieje.

Czas na sprawdzenie poprawności…

Prawidłowa linia:

line='QWERTY'
validate(line)
=> True
validate_morgan(line)
=> True

Nieprawidłowe linie:

line=''
validate(line)
=> False
validate_morgan(line)
=> False

line='Serial Number'
validate(line)
=> False
validate_morgan(line)
=> False

Funkcje są sobie równoważne.

 

Zasady logiki to jednak nie tylko prawa de Morgana. Warto przypomnieć sobie np. tablice tautologii.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *