#!/usr/bin/env ruby
# frozen_string_literal: true
require 'set'
# в комментариях через x, y обозначаются элементы множеств X, Y,
# а в коде вместо X используется имя переменной x, чтобы вывод
# скрипта не замусоривался предупреждениями о том, что изменено
# значение константы (в Ruby имена с заглавных букв используются
# для констант).
def relation_is_func?(xset, yset, rset)
# проверка того, что в отношении R (которое представляет собой
# множество упорядоченных пар (x,y)) "задействованы" все элементы
# x из X, причём ровно по одному разу.
# получаем это так:
# rset.map(&:keys) даёт нам массив из одноэлементных массивов
# ключей. для первого примера ниже он получается таким:
# [[2], [1], [3], [4]]
# полученный массив из массивов мы делаем "плоским"
# (используя метод Array#flatten), получаем соответственно массив
# [2, 1, 3, 4]
# методом Set#to_a преобразуем множество X в массив. из первого
# примера ниже это даёт нам такой массив:
# [1, 2, 3, 4]
# rset.map(&:keys).flatten - xset.to_a
# даёт нам разность полученных массивов, т.е. те элементы первого
# массива, которых нет во втором массиве. для первого примера
# она пуста:
# []
# метод Array#empty? делает проверку того, что эта разность пустая.
# т.е. мы убеждаемся в том, что в тех парах (x,y), что принадлежат
# отношению R, нет таких x, которые не содержатся во множестве X.
x_is_correct = (rset.map(&:keys).flatten - xset.to_a).empty?
# аналогичная процедура для множества Y: убеждаемся в том, что
# в тех парах (x,y), что принадлежат отношению R, нет таких y,
# которые не содержатся во множестве Y. поскольку упорядоченные
# пары (x,y) у нас представлены хэшами { x => y }, то вместо ключей
# тут мы должны брать значения хэшей:
# rset.map(&:values)
# остальное аналогично вышеописанному
y_is_correct = (rset.map(&:values).flatten - yset.to_a).empty?
# метод Array#sort сортирует массив.
# для второго примера ниже получаем:
# rset.map(&:keys).flatten.sort даёт нам
# [1, 2, 2, 3, 4]
# xset.to_a.sort даёт
# [1, 2, 3, 4]
# здесь: rset.map(&:keys).flatten.sort == xset.to_a.sort
# мы проверяем, равны ли массивы. для второго примера они
# не равны (элементу 2 из X сопоставлены 2 элемента из Y, b и c),
# для третьего примера тоже равенства не получается,
# rset.map(&:keys).flatten.sort даёт нам
# [1, 2, 4]
# т.е. элементу 3 из X у нас ничего не сопоставлено в Y, массивы
# не равны.
r_is_correct = rset.map(&:keys).flatten.sort == xset.to_a.sort
# проверка того, что все три условия выполняются.
# если истина, то получаем 'Function.',
# в противном случае 'Not function.'
x_is_correct && y_is_correct && r_is_correct ? 'Function.' : 'Not function.'
end
x = Set[1, 2, 3, 4]
y = Set['a', 'b', 'c', 'd', 'e']
# отношение R между X и Y задано как множество хэшей. Хэши состоят
# в данном случае из одной пары "ключ - значение". В качестве ключа
# выступает элемент X, в качестве значения - элемент Y. Таким образом,
# получаем реализацию упорядоченой пары (x,y).
r = Set[{ 2 => 'b' }, { 1 => 'b' }, { 3 => 'b' }, { 4 => 'a' }]
# проверка того, что отношение R есть отображение (функция).
relation_is_func?(x, y, r) #=> "Function."
x = Set[1, 2, 3, 4]
y = Set['a', 'b', 'c', 'd', 'e']
r = Set[{ 1 => 'b' }, { 2 => 'b' }, { 3 => 'b' }, { 4 => 'b' }, { 2 => 'c' }]
relation_is_func?(x, y, r) #=> "Not function."
x = Set[1, 2, 3, 4]
y = Set['a', 'b', 'c', 'd', 'e']
r = Set[{ 1 => 'c' }, { 2 => 'a' }, { 4 => 'b' }]
relation_is_func?(x, y, r) #=> "Not function."