Compare commits

..

16 Commits
main ... lab3

Author SHA1 Message Date
Artem-Darius Weber e603842e7c feat: add sorting examples for numbers, words, and people in sort_sort_by.rb
2 days ago
Artem-Darius Weber d7c500f202 docs: remove outdated example comment for sort and sort_by in main.rb
2 days ago
Artem-Darius Weber 8ccf7239f9 feat: add select and reduce methods to HtmlTree class; update examples in main.rb
2 days ago
Artem-Darius Weber 6f9cd89526 docs: remove outdated comments from main.rb
3 days ago
Artem-Darius Weber b1d90eab30 docs: add comments for clarity in indices_sorted_by_descending_values method
3 days ago
Artem-Darius Weber 9032b20783 refactor: simplify indices_sorted_by_descending_values method; add HtmlTree class for parsing and traversing HTML
2 weeks ago
Artem-Darius Weber c9a56f66f4 docs: update README.md with method descriptions for ArrayProcessor; add a.txt with sample data
1 month ago
Artem-Darius Weber 820a41173c feat: implement ArrayProcessor class with chunk, include?, reduce, member?, and filter methods; add tests and documentation
1 month ago
Artem-Darius Weber 205b10ff9d release:feat: add interactive menu for task selection and input methods
1 month ago
Artem-Darius Weber f015f43c99 feat: add prime_divisors function to retrieve prime divisors of a number
1 month ago
Artem-Darius Weber b9453a87e8 feat: add minimal_even_element function to retrieve the smallest even element from an array
1 month ago
Artem-Darius Weber 988d9c83dd feat: add elements_between_first_and_last_max function to retrieve elements between first and last maximum values
1 month ago
Artem-Darius Weber a50ef4122e feat: add elements_between_first_and_second_max function to retrieve elements between first and second maximum values
1 month ago
Artem-Darius Weber 44e77f3679 feat: rename task1 function to indices_sorted_by_descending_values for clarity
1 month ago
Artem-Darius Weber 8a8d9cfdd8 feat: implement task1 function to return indices of array elements in decreasing order
1 month ago
Artem-Darius Weber 8d8cc46bde ref: delete lab[1-2] files from lab3 branch
4 months ago

@ -9,7 +9,6 @@ Abstract:
Content:
[Lab 1: Hello world, user interface and number funcations](https://git.djft.ru/darius-atlas/kubsu-sm5-ruby/src/branch/main/lab1)
[Lab 2: Person classes](https://git.djft.ru/darius-atlas/kubsu-sm5-ruby/src/branch/main/lab2)
---

@ -1,102 +0,0 @@
# Lab 1
---
## 01. Hello world
Task:
Установить компилятор и текстовый редактор. Реализовать и
вызвать Hello World c комментарием. (ну как всегда)
```bash
ruby 01_hello_world.rb
```
Returns:
```
Hello, world!
```
## 02. User interface
Task:
Принять имя пользователя как аргумент программы.
Поздороваться с пользователем с использованием форматирования
строки. Спросить какой язык у пользователя любимый, в случае, если это
ruby, ответить что пользователь подлиза, иначе обязательно ответить, что
скоро будет ruby и поставить различные комментарии для нескольких
языков.
```bash
ruby 02_user_interface.rb darius
```
## 03. User interface with ruby and os commands execution
Task:
3.Продолжение предыдущего задания. Попросить пользователя
ввести команду языка ruby. И команду OC. Выполнить команду руби и
команду операционной системы.
```bash
ruby 03_fork_02_with_exec_pasted_command.rb darius
```
## 04. Number funcations
Task:
«Работа с числами». Составить 3 метода для работы с цифрами или делителей числа на основании варианта. Каждый метод отдельный коммит.
- Метод 1. Найти количество четных чисел, не взаимно простых с данным
- Метод 2. Найти максимальную цифры числа, не делящуюся на 3.
- Метод 3. Найти произведение максимального числа, не взаимно простого с данным, не делящегося на наименьший делитель исходно числа, и суммы цифр числа, меньших 5.
```bash
ruby 04_number_funcs.rb
```
## 05. Number items operations
Task:
Написать методы, которые находят минимальный, элементы,
номер первого положительного элемента. Каждая операция в отдельном
методе. Решить задачу с помощью циклов(for и while).
```bash
ruby 05_number_items_operations.rb
```
## 06. Command line file arguments
Task:
Написать программу, которая принимает как аргумент два
значения. Первое значение говорит, какой из методов задачи 1
выполнить, второй говорит о том, откуда читать список аргументом
должен быть написан адрес файла. Далее необходимо прочитать массив
и выполнить метод.
```bash
ruby 06_command_line_file_arguments.rb min numbers.txt
```
```bash
ruby 06_command_line_file_arguments.rb first_positive numbers.txt
```
```bash
ruby 06_command_line_file_arguments.rb first_positive_index numbers.txt
```
---
Author: Artem-Darius Weber
Licence: MIT

@ -1,16 +0,0 @@
require_relative '../src/02_user_interface.rb'
RSpec.describe "Main" do
before do
allow(STDIN).to receive(:gets).and_return("ruby\n")
end
it "greets the user and checks Ruby as language" do
expect { main() }.to output("Hello my catgirl test_user! \nWhat is your love language?\nruby\nc++\npy\nПодлиза \n").to_stdout
end
it "handles unknown language input" do
allow(STDIN).to receive(:gets).and_return("java\n")
expect { main() }.to output(/Неизвестный язык: java/).to_stdout
end
end

@ -1,34 +0,0 @@
require_relative '../src/03_fork_02_with_exec_pasted_command.rb'
RSpec.describe "Main" do
before do
allow(STDIN).to receive(:gets).and_return("ruby\n", "puts 'Hello from Ruby!'\n", "echo 'Hello from shell!'\n")
allow(ARGV).to receive(:[]).with(0).and_return("test_user")
end
it "greets the user and processes ruby input" do
expect { main() }.to output(/Hello my catgirl test_user! \nWhat is your love language?\nruby\nc++\npy\одлиза \n/).to_stdout
end
it "executes valid ruby command" do
allow(STDIN).to receive(:gets).and_return("ruby\n", "puts 'Hello from Ruby!'\n")
expect { main() }.to output(/Hello from Ruby!/).to_stdout
end
it "handles ruby command execution error" do
allow(STDIN).to receive(:gets).and_return("ruby\n", "invalid_ruby_code\n")
expect { main() }.to output(/Ошибка выполнения команды Ruby: undefined local variable or method `invalid_ruby_code'/).to_stdout
end
it "executes shell command" do
allow(STDIN).to receive(:gets).and_return("ruby\n", "puts 'Hello from Ruby!'\n", "echo 'Hello from shell!'\n")
expect(main()).to include("Hello from shell!")
end
it "returns correct output for unknown programming language" do
allow(STDIN).to receive(:gets).and_return("java\n")
expect { main() }.to output(/Неизвестный язык: java/).to_stdout
end
end

@ -1,2 +0,0 @@
puts "Hello, world!"

@ -1,30 +0,0 @@
#!/usr/bin/env ruby
LANGUAGES = [
"ruby",
"c++",
"py"
]
def main()
user_name = ARGV[0]
puts "Hello my catgirl #{user_name}! \nWhat is your love language?"
LANGUAGES.each { |language| puts "#{language}", " " }
user_lang = STDIN.gets.chomp
case user_lang
when "ruby"
puts "Подлиза \n"
when "c++"
puts "MATLAB скушал? \n"
when "TS/JS"
puts "Фронтендер, Фууу! \n"
when "py"
puts "Девопсер, иди ДАГИ писать \n"
else
puts "Неизвестный язык: #{user_lang}"
end
end
main()

@ -1,39 +0,0 @@
#!/usr/bin/env ruby
LANGUAGES = [
"ruby",
"c++",
"py"
]
def main()
user_name = ARGV[0]
puts "Hello my catgirl #{user_name}! \nWhat is your love language?"
LANGUAGES.each { |language| puts "#{language}", " " }
user_lang = STDIN.gets.chomp
case user_lang
when "ruby"
puts "Подлиза \n"
when "c++"
puts "MATLAB скушал? \n"
when "TS/JS"
puts "Фронтендер, Фууу! \n"
when "py"
puts "Девопсер, иди ДАГИ писать \n"
end
puts "Введите команду на языке Ruby для выполнения:"
ruby_command = STDIN.gets.chomp
begin
eval(ruby_command)
rescue Exception => e
puts "Ошибка выполнения команды Ruby: #{e.message}"
end
puts "Введите команду операционной системы для выполнения:"
os_command = STDIN.gets.chomp
system(os_command)
end
main()

@ -1,67 +0,0 @@
require 'prime'
# @param n [Integer] Число, для которого нужно найти количество четных, не взаимно простых чисел.
# @return [Integer] Количество четных чисел, не взаимно простых с данным числом.
# @example
# count_even_non_coprimes(30) # => 14
def count_even_non_coprimes(n)
(1...n).count do |num|
num.even? && n.gcd(num) != 1
end
end
# @param n [Integer] Число, цифры которого нужно проверить.
# @return [Integer, nil] Максимальная цифра числа, не делящаяся на 3, или nil, если таких цифр нет.
# @example
# max_digit_not_divisible_by_three(483726) # => 8
def max_digit_not_divisible_by_three(n)
n.digits.select { |digit| digit % 3 != 0 }.max
end
# @param n [Integer] Число, для которого нужно найти наименьший делитель.
# @return [Integer] Наименьший делитель числа.
# @example
# smallest_divisor(30) # => 2
def smallest_divisor(n)
(2..n).find { |i| n % i == 0 }
end
# @param n [Integer] Число, для которого нужно найти подходящее максимальное число.
# @return [Integer, nil] Максимальное число, не взаимно простое с данным, не делящееся на наименьший делитель, или nil, если таких чисел нет.
# @example
# max_non_coprime_not_divisible_by_smallest_divisor(30) # => 28
def max_non_coprime_not_divisible_by_smallest_divisor(n)
divisor = smallest_divisor(n)
(1...n).select { |num| n.gcd(num) != 1 && num % divisor != 0 }.max
end
# @param n [Integer] Число, цифры которого нужно просуммировать.
# @return [Integer] Сумма цифр числа, меньших 5.
# @example
# sum_of_digits_less_than_five(483726) # => 9
def sum_of_digits_less_than_five(n)
n.digits.select { |digit| digit < 5 }.sum
end
# @param n [Integer] Число, для которого проводится вычисление.
# @return [Integer] Произведение максимального числа и суммы цифр числа.
# @example
# product_of_max_and_sum(30) # => 252
def product_of_max_and_sum(n)
max_number = max_non_coprime_not_divisible_by_smallest_divisor(n)
sum_digits = sum_of_digits_less_than_five(n)
max_number * sum_digits
end
puts count_even_non_coprimes(30) # => 14
puts max_digit_not_divisible_by_three(483726) # => 8
puts product_of_max_and_sum(30) # => 252

@ -1,68 +0,0 @@
def find_min_element_for(arr)
min_element = arr[0]
for element in arr
min_element = element if element < min_element
end
min_element
end
def find_min_element_while(arr)
min_element = arr[0]
index = 0
while index < arr.size
min_element = arr[index] if arr[index] < min_element
index += 1
end
min_element
end
def find_first_positive_index_for(arr)
for index in 0...arr.size
return index if arr[index] > 0
end
nil
end
def find_first_positive_index_while(arr)
index = 0
while index < arr.size
return index if arr[index] > 0
index += 1
end
nil
end
def find_first_positive_for(arr)
for element in arr
return element if element > 0
end
nil
end
def find_first_positive_while(arr)
index = 0
while index < arr.size
return arr[index] if arr[index] > 0
index += 1
end
nil
end
# INPUT
array = [-10, -5, 0, 3, 5, -2]
puts "Минимальный элемент (for): #{find_min_element_for(array)}"
puts "Минимальный элемент (while): #{find_min_element_while(array)}"
puts "Индекс первого положительного элемента (for): #{find_first_positive_index_for(array)}"
puts "Индекс первого положительного элемента (while): #{find_first_positive_index_while(array)}"
puts "Первый положительный элемент (for): #{find_first_positive_for(array)}"
puts "Первый положительный элемент (while): #{find_first_positive_while(array)}"

@ -1,62 +0,0 @@
def find_min_element(arr)
min_element = arr[0]
arr.each do |element|
min_element = element if element < min_element
end
min_element
end
def find_first_positive_index(arr)
arr.each_with_index do |element, index|
return index if element > 0
end
nil
end
def find_first_positive(arr)
arr.each do |element|
return element if element > 0
end
nil
end
def main
method_name = ARGV[0]
file_path = ARGV[1]
if method_name.nil? || file_path.nil?
puts "Неправльный формат ввода. Использование: ruby program.rb <method_name> <file_path>"
puts "method_name: 'min', 'first_positive_index' или 'first_positive'"
exit
end
begin
array = File.read(file_path).split.map(&:to_i)
rescue Errno::ENOENT
puts "Файл не найден: #{file_path}"
exit
end
case method_name
when 'min'
result = find_min_element(array)
puts "Минимальный элемент: #{result}"
when 'first_positive_index'
result = find_first_positive_index(array)
puts "Индекс первого положительного элемента: #{result.nil? ? 'Нет положительного элемента' : result}"
when 'first_positive'
result = find_first_positive(array)
puts "Первый положительный элемент: #{result.nil? ? 'Нет положительного элемента' : result}"
else
puts "Неизвестный метод: #{method_name}"
puts "Доступные методы: 'min', 'first_positive_index', 'first_positive'"
end
end
main if __FILE__ == $0

@ -1 +0,0 @@
-10 -5 0 3 5 -2

@ -1,4 +0,0 @@
# Lab 2
> "И тут я обнаружил что случайно сделал 3-5 задачи в 1-2"

@ -1,59 +0,0 @@
require_relative 'student'
require_relative 'student_short'
begin
student_string = "Норакет Норакет Норакет | ID: 2 | Phone: +1234567890 | Telegram: @noracat | Email: nora@example.com | Git: https://github.com/nora"
student_from_string = Student.from_string(student_string)
puts "Создан объект из строки:\n#{student_from_string}"
student1 = Student.new(
surname: 'Алексеевич',
name: 'Артем-Дариус',
patronymic: 'Вебер',
id: 1,
git: 'https://github.com/space-creator'
)
student1.set_contacts(
phone: '+79891242223',
telegram: '@alstroemeria22',
email: 'no-replay@djft.ru'
)
puts student1.get_info
puts "Surname and Initials: #{student1.surname_and_initials}"
puts "Git Info: #{student1.git_info}"
puts "Contact Info: #{student1.contact_info}"
student2 = Student.new(
surname: 'Норакет',
name: 'Норакет',
patronymic: 'Фамилия'
)
student2.set_contacts(
phone: '+70000000000'
)
puts student1
puts '-' * 40
puts student2
student_short_from_student = StudentShort.new(student1)
puts "StudentShort from Student object:"
puts "ID: #{student_short_from_student.id}"
puts "Surname and Initials: #{student_short_from_student.surname_initials}"
puts "Git: #{student_short_from_student.git}"
puts "Contact: #{student_short_from_student.contact}"
student_short_from_string = StudentShort.from_string(5, 'Skye A.A., Git: https://github.com/skye, Contact: Phone: +4923467890')
puts "StudentShort from string:"
puts "ID: #{student_short_from_string.id}"
puts "Surname and Initials: #{student_short_from_string.surname_initials}"
puts "Git: #{student_short_from_string.git}"
puts "Contact: #{student_short_from_string.contact}"
rescue ArgumentError => e
puts "Ошибка: #{e.message}"
end

@ -1,65 +0,0 @@
class Person
attr_accessor :id, :git
def initialize(args = {})
@id = args[:id] || nil
@git = args[:git]
validate
end
def set_contacts(phone: nil, telegram: nil, email: nil)
@phone = phone
raise ArgumentError, "Invalid phone number format: #{@phone}" if @phone && !self.class.valid_phone_number?(@phone)
@telegram = telegram
raise ArgumentError, "Invalid telegram format: #{@telegram}" if @telegram && !self.class.valid_telegram?(@telegram)
@email = email
raise ArgumentError, "Invalid email format: #{@email}" if @email && !self.class.valid_email?(@email)
end
def self.valid_phone_number?(phone)
phone.match?(/\A\+?[0-9]{10,15}\z/)
end
def self.valid_name?(name)
name.match?(/\A[А-Яа-яЁёA-Za-z\-]+\z/)
end
def self.valid_telegram?(telegram)
telegram.nil? || telegram.match?(/\A@[A-Za-z0-9_]{5,32}\z/)
end
def self.valid_email?(email)
email.nil? || email.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/)
end
def self.valid_git?(git)
git.nil? || git.match?(/\Ahttps:\/\/github\.com\/[A-Za-z0-9_\-]+\z/)
end
def git_present?
!@git.nil? && !@git.empty?
end
def contact_present?
!(@phone.nil? || @phone.empty?) || !(@telegram.nil? || @telegram.empty?) || !(@email.nil? || @email.empty?)
end
def validate
raise ArgumentError, "Git link is required" unless git_present?
raise ArgumentError, "At least one contact (phone, telegram, or email) is required" unless contact_present?
end
def contact_info
return "Phone: #{@phone}" if @phone
return "Telegram: #{@telegram}" if @telegram
return "Email: #{@email}" if @email
'No contact available'
end
private
attr_reader :phone, :telegram, :email
attr_writer :phone, :telegram, :email
end

@ -1,92 +0,0 @@
require_relative 'person'
class Student < Person
attr_accessor :surname, :name, :patronymic
def initialize(args = {})
super(args)
@surname = args.fetch(:surname)
raise ArgumentError, "Invalid surname format: #{@surname}" unless self.class.valid_name?(@surname)
@name = args.fetch(:name)
raise ArgumentError, "Invalid name format: #{@name}" unless self.class.valid_name?(@name)
@patronymic = args.fetch(:patronymic)
raise ArgumentError, "Invalid patronymic format: #{@patronymic}" unless self.class.valid_name?(@patronymic)
set_contacts(
phone: args[:phone],
telegram: args[:telegram],
email: args[:email]
)
end
def self.from_string(student_string)
parts = student_string.split('|').map(&:strip)
surname, name, patronymic = parts[0].split(' ')
id = parts[1].split(': ').last.to_i
phone = parts[2].split(': ').last
telegram = parts[3].split(': ').last
email = parts[4].split(': ').last
git = parts[5].split(': ').last
new(
surname: surname,
name: name,
patronymic: patronymic,
id: id,
phone: phone,
telegram: telegram,
email: email,
git: git
)
end
def self.read_from_txt(file_path)
raise IOError, "File path is invalid or file does not exist: #{file_path}" unless File.exist?(file_path)
students = []
File.foreach(file_path) do |line|
line.strip!
next if line.empty?
begin
student = from_string(line)
students << student
rescue ArgumentError => e
puts "Error processing line: '#{line}'. Reason: #{e.message}"
end
end
students
end
def self.write_to_txt(file_path, students)
raise ArgumentError, "Expected an array of Student objects" unless students.is_a?(Array) && students.all? { |s| s.is_a?(Student) }
File.open(file_path, 'w') do |file|
students.each do |student|
file.puts student.to_s
end
end
puts "Data successfully written to #{file_path}"
rescue IOError => e
puts "An error occurred while writing to the file: #{e.message}"
end
def surname_and_initials
"#{@surname} #{name[0]}.#{patronymic[0]}."
end
def to_s
"#{@surname} #{@name} #{@patronymic} | ID: #{@id || 'N/A'} | " \
"Phone: #{@phone || 'N/A'} | Telegram: #{@telegram || 'N/A'} | " \
"Email: #{@email || 'N/A'} | Git: #{@git || 'N/A'}"
end
def get_info
"#{surname_and_initials}, Git: #{git_info}, Contact: #{contact_info}"
end
end

@ -1,31 +0,0 @@
require_relative 'person'
class StudentShort < Person
attr_reader :surname_initials, :contact
def initialize(student)
super(id: student.id, git: student.git_info)
@surname_initials = student.surname_and_initials
@contact = student.contact_info
end
def self.from_string(id, info_string)
parts = info_string.split(', ').map(&:strip)
surname_initials = parts[0]
git = parts[1].split(': ').last
contact = parts[2].split(': ').last
new_instance = allocate
new_instance.send(:initialize_from_data, id, surname_initials, git, contact)
new_instance
end
private
def initialize_from_data(id, surname_initials, git, contact)
@id = id
@surname_initials = surname_initials
@git = git
@contact = contact
end
end

@ -0,0 +1,2 @@
source "https://rubygems.org"
gem "minitest", "~> 5.15"

@ -0,0 +1,113 @@
def indices_sorted_by_descending_values(array)
array.each_with_index.to_a
.sort_by { |(element, index)| -element }
.map { |(element, index)| index }
end
def elements_between_first_and_second_max(array)
max_value = array.max
max_indices = array.each_with_index.select { |element, index| element == max_value }.map { |_, index| index }
if max_indices.size >= 2
first_max_index = max_indices[0]
second_max_index = max_indices[1]
else
second_max_value = array.select { |element| element != max_value }.max
return [] if second_max_value.nil?
first_max_index = array.index(max_value)
second_max_index = array.index(second_max_value)
end
first_max_index, second_max_index = [first_max_index, second_max_index].sort
array[(first_max_index + 1)...second_max_index]
end
def elements_between_first_and_last_max(array)
max_value = array.max
first_max_index = array.index(max_value)
last_max_index = array.rindex(max_value)
return [] if first_max_index == last_max_index
first_max_index, last_max_index = [first_max_index, last_max_index].sort
array[(first_max_index + 1)...last_max_index]
end
def minimal_even_element(array)
even_elements = array.select(&:even?)
even_elements.min
end
def prime_divisors(number)
require 'prime'
(2..number).select { |x| number % x == 0 && Prime.prime?(x) }
end
# IO
def get_array_input(input_method)
if input_method == 1
puts "Введите элементы массива через пробел:"
gets.chomp.split.map(&:to_i)
elsif input_method == 2
puts "Введите имя файла:"
file_name = gets.chomp
File.read(file_name).split.map(&:to_i)
else
raise "Неверный метод ввода."
end
end
def get_number_input(input_method)
if input_method == 1
puts "Введите число:"
gets.chomp.to_i
elsif input_method == 2
puts "Введите имя файла:"
file_name = gets.chomp
File.read(file_name).to_i
else
raise "Неверный метод ввода."
end
end
puts "Выберите задачу для выполнения:"
puts "1. Вывести индексы массива в порядке убывания элементов."
puts "2. Найти элементы между первым и вторым максимальным."
puts "3. Найти элементы между первым и последним максимальным."
puts "4. Найти минимальный четный элемент."
puts "5. Найти все простые делители числа."
task_number = gets.chomp.to_i
puts "Выберите метод ввода данных (1: С клавиатуры, 2: Из файла):"
input_method = gets.chomp.to_i
case task_number
when 1
array = get_array_input(input_method)
puts "Индексы в порядке убывания элементов:"
puts indices_sorted_by_descending_values(array).join(", ")
when 2
array = get_array_input(input_method)
puts "Элементы между первым и вторым максимальным:"
puts elements_between_first_and_second_max(array).join(", ")
when 3
array = get_array_input(input_method)
puts "Элементы между первым и последним максимальным:"
puts elements_between_first_and_last_max(array).join(", ")
when 4
array = get_array_input(input_method)
puts "Минимальный четный элемент:"
puts minimal_even_element(array)
when 5
number = get_number_input(input_method)
puts "Простые делители числа:"
puts prime_divisors(number).join(", ")
else
puts "Неверный номер задачи."
end

@ -0,0 +1,27 @@
# Run
### Run example
```bash
ruby ./main.rb
```
### Run test
```bash
ruby test/test_array_processor.rb
```
# Methods:
chunk - дробит массив на сущности по результату выполнения кода, even - четные число
include - содержит ли массив элемент
member - аналогично include
reduce - накапливает значения в аккумулияторе складывая все значения
filter - select элементов для который блок вернул true. odd - нечетное число

@ -0,0 +1,67 @@
class ArrayProcessor
def initialize(array)
@array = array.dup.freeze
end
# Возвращает элементы массива
def elements
@array
end
# группировка элементов
def chunk
raise "No block given" unless block_given?
result = []
current_group = []
@array.each do |element|
if current_group.empty? || yield(element) == yield(current_group.last)
current_group << element
else
result << current_group
current_group = [element]
end
end
result << current_group unless current_group.empty?
result
end
# проверка наличия элемента
def include?(value)
@array.each do |element|
return true if element == value
end
false
end
# свёртка массива
def reduce(initial = nil)
raise "No block given" unless block_given?
accumulator = initial
@array.each do |element|
if accumulator.nil?
accumulator = element
else
accumulator = yield(accumulator, element)
end
end
accumulator
end
# проверка членства
def member?(value)
include?(value)
end
# фильтрация массива
def filter
raise "No block given" unless block_given?
result = []
@array.each do |element|
result << element if yield(element)
end
result
end
end

@ -0,0 +1,23 @@
require_relative 'lib/array_processor'
processor = ArrayProcessor.new([1, 2, 3, 4, 5, 6, 7, 8, 9])
# chunk
puts "Chunk example:"
p processor.chunk { |x| x.even? }
# include?
puts "Include example (5): #{processor.include?(5)}"
puts "Include example (10): #{processor.include?(10)}"
# reduce
puts "Reduce example (sum): #{processor.reduce(0) { |acc, x| acc + x }}"
# member?
puts "Member example (5): #{processor.member?(5)}"
puts "Member example (10): #{processor.member?(10)}"
# filter
puts "Filter example (odd numbers):"
p processor.filter { |x| x.odd? }

@ -0,0 +1,34 @@
require 'minitest/autorun'
require_relative '../lib/array_processor'
class ArrayProcessorTest < Minitest::Test
def setup
@processor = ArrayProcessor.new([1, 2, 3, 4, 5, 6, 7, 8, 9])
end
def test_chunk
result = @processor.chunk { |x| x.even? }
assert_equal [[1], [2], [3], [4], [5], [6], [7], [8], [9]], result
end
def test_include
assert_equal true, @processor.include?(5)
assert_equal false, @processor.include?(10)
end
def test_reduce
assert_equal 45, @processor.reduce(0) { |acc, x| acc + x }
assert_equal 120, @processor.reduce(1) { |acc, x| acc * x }
end
def test_member
assert_equal true, @processor.member?(5)
assert_equal false, @processor.member?(10)
end
def test_filter
result = @processor.filter { |x| x.odd? }
assert_equal [1, 3, 5, 7, 9], result
end
end

@ -0,0 +1,118 @@
require 'nokogiri'
class HtmlTree
include Enumerable
def initialize(html)
puts "Input HTML:\n#{html.inspect}"
@root = parse_html(html)
raise "Parsed HTML tree is empty" if @root.nil?
end
def each(order = :breadth_first, &block)
case order
when :breadth_first
breadth_first_traversal(&block)
when :depth_first
depth_first_traversal(&block)
else
raise ArgumentError, "Unknown order: #{order}"
end
end
def select(order = :breadth_first, &block)
results = []
each(order) do |node|
results << node if block.call(node)
end
results
end
def reduce(accumulator = nil, order = :breadth_first, &block)
each(order) do |node|
accumulator = block.call(accumulator, node)
end
accumulator
end
private
def parse_html(html)
doc = Nokogiri::HTML::DocumentFragment.parse(html)
root_node = doc.at_css('body') || doc.children.find(&:element?) || doc.root
return nil if root_node.nil? || root_node.children.empty?
build_tree(root_node)
end
def build_tree(node)
if node.element?
children = node.children.map { |child| build_tree(child) }.compact
HtmlTag.new(node.name, node.attributes.transform_values(&:value), children)
elsif node.text? && !node.content.strip.empty?
HtmlTag.new("text", { "content" => node.content.strip }, [])
end
end
def breadth_first_traversal
queue = [@root].compact
until queue.empty?
current = queue.shift
next if current.nil?
yield current
queue.concat(current.children.compact) if current.has_children?
end
end
def depth_first_traversal(node = @root, &block)
return if node.nil?
yield node
node.children.compact.each { |child| depth_first_traversal(child, &block) } if node.has_children?
end
end
class HtmlTag
attr_reader :name, :attributes, :children
def initialize(name, attributes, children = [])
@name = name
@attributes = attributes
@children = children
end
def has_children?
!@children.empty?
end
def to_s
"#{@name} #{@attributes}"
end
end
html = <<-HTML
<div id="root">
<p class="text">Hello, world!</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
HTML
tree = HtmlTree.new(html)
puts "Traversal in breadth-first order:"
tree.each(:breadth_first) { |tag| puts tag }
puts "\nTraversal in depth-first order:"
tree.each(:depth_first) { |tag| puts tag }
puts "Select tags with class 'text':"
selected_tags = tree.select { |tag| tag.attributes["class"] == "text" }
puts selected_tags
puts "\nReduce example (concatenate all tag names):"
reduced_value = tree.reduce("") { |acc, tag| acc + " " + tag.name }
puts reduced_value.strip

@ -0,0 +1,30 @@
numbers = [5, 3, 8, 1, 2]
# сортировка чисел
sorted_numbers = numbers.sort
puts "Sorted numbers using sort: #{sorted_numbers}"
# сортировка по алфавиту
words = ["apple", "orange", "banana", "grape"]
sorted_words = words.sort
puts "Sorted words using sort: #{sorted_words}"
people = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
]
# сортировка по возрасту
sorted_people_by_age = people.sort { |a, b| a[:age] <=> b[:age] }
puts "Sorted people by age using sort: #{sorted_people_by_age}"
# сортировка по возрасту
sorted_people_by_age2 = people.sort_by { |person| person[:age] }
puts "Sorted people by age using sort_by: #{sorted_people_by_age2}"
# сортировка по длине строки
words = ["cat", "elephant", "dog", "hippopotamus"]
sorted_by_length = words.sort_by { |word| word.length }
puts "Sorted words by length using sort_by: #{sorted_by_length}"
Loading…
Cancel
Save