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

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

@ -1,27 +0,0 @@
require_relative 'student'
begin
student1 = Student.new(
surname: 'Алексеевич',
name: 'Артем-Дариус',
patronymic: 'Вебер',
id: 1,
phone: '+79891242223',
telegram: '@alstroemeria22',
email: 'no-replay@djft.ru',
git: 'https://git.djft.ru'
)
student2 = Student.new(
surname: 'nil',
name: 'Норакет',
patronymic: 'nil'
)
puts student1
puts '-' * 40
puts student2
rescue ArgumentError => e
puts "Err.: #{e.message}"
end

@ -1,33 +0,0 @@
class Student
attr_accessor :id, :surname, :name, :patronymic, :phone, :telegram, :email, :git
def self.valid_phone_number?(phone)
phone.match?(/\A\+?[0-9]{10,15}\z/)
end
def initialize(args = {})
@surname = args.fetch(:surname)
@name = args.fetch(:name)
@patronymic = args.fetch(:patronymic)
@id = args[:id] || nil
@phone = args[:phone]
if @phone && !Student.valid_phone_number?(@phone)
raise ArgumentError, "Invalid phone number format: #{@phone}"
end
@telegram = args[:telegram] || nil
@email = args[:email] || nil
@git = args[:git] || nil
end
def to_s
"Student: #{@surname} #{@name} #{@patronymic}\n" \
"ID: #{@id || 'N/A'}\n" \
"Phone: #{@phone || 'N/A'}\n" \
"Telegram: #{@telegram || 'N/A'}\n" \
"Email: #{@email || 'N/A'}\n" \
"Git: #{@git || 'N/A'}"
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