Ruby и красивый код #3

ноября 20, 2010  |  Published in Ruby  |  6 Comments

ruby
Предыдущие статьи из рубрики:
Ruby и красивый код #1
Ruby и красивый код #2

Исходя из активности комментирования последнего поста Ruby и крассивый код #2 делаю вывод о том, что рубрика действительно интересна и стоет ее развивать. По сему представляю еще 2 задачи:

Задача #1
Дан массив целых чисел. Вывести напечатать номер последнего его элемента, который удовлетворяет двойному неравенству A[0] < A[i] < A[-1]. Если такого элемента не найдено, то напечатать «[ ]«.

Решение #1

nums = [3,5,6,8,10,4,4,46,4,5]

first, last = nums.slice(0), nums.slice(-1)
s_elem = "[ ]"

nums.each do |elem|
  if first < elem && elem < last
    s_elem = elem
  end
end

s_elem_index = nums.rindex s_elem 
puts s_elem
puts s_elem_index

Решение после рефакторинга:

nums = [3,5,6,8,10,4,4,46,4,5]

first, last = nums.slice(0), nums.slice(-1)

s_elem = nums.find_all {|n|  n > first && n < last}.inject("[ ]") {|r, n|  r = n}
s_elem_index = nums.rindex s_elem
puts "#{s_elem_index} => #{s_elem}"

(Спасибо за правки коментатору dre3k)
Задача #2
Дан целочисленный массив и интервал a..b. Найти минимальный из элементов массива в этом интервале.

arr = [1,2,5,8,9,4,8,9,15,3,7,5,22]
range = (7..15)

range = range.to_a
new_array = arr & range
min = new_array[0]

i = 0
while i < new_array.size   min = new_array[i] if min > new_array[i]
  i+=1
end

puts min

Решение задачи после рефакторинга:

arr = [1,2,5,8,9,4,8,9,15,3,7,5,22]
range = (7..15)

new_array = arr & range.to_a
num = new_array.min
puts num

А вот задачка для желающих поупражняться:

Необходимо создать транслятор арабских цыфр (1, 2, 3, 4, 5,...) в Римские (I, II, III, IV, V,...) и обратно. Вот небольшая шпаргалка:
ROMAN_MAP = {
1 => "I",
4 => "IV",
5 => "V",
9 => "IX",
10 => "X",
40 => "XL",
50 => "L",
90 => "XC",
100 => "C",
400 => "CD",
500 => "D",
900 => "CM",
1000 => "M" }

Вид должен быть примерно такой: to_roman (Fixnum) => String, to_arabic (String) => Fixnum. Диапазон чисел от 1 до 1000.

Задача взята из книги "Best of Ruby Quiz" Джеймса Эдварда Грея II.

P.S. Решения пишите в комментариях. Вы также можете представить свое решение 1й и 2й задач из сего поста.

Tags: , ,

Responses

  1. dre3k says:

    ноября 20, 2010 at 02:31 (#)

    Замечание к коду решения задачи #1
    1)По условиям задачи выводится должен порядковый номер(индекс), а не значение элемента.
    2)

     first, last = nums.slice(0), nums.slice(-1) 

    тоже самое что и

     first, last = nums.first, nums.last 

    Метод find_all и его синоним select возврашают массив. Метод last возвращает последний эллемент массива. Метод rindex возвращает индекс последнего местонахождения эллемента в массиве. Про tap читаем здесь

    Вот мой вариант решения задачи:

    nums = [3,5,6,8,10,4,4,46,4,5]
    
    p nums.select{|n| (nums.first < n) && (n < nums.last)}.last.
      tap{|n| print "index=#{nums.rindex(n).inspect} value="} || []
    

    на выходе

     index=8 value=4 

    при

     nums = [13,5,6,8,10,4,4,46,4,5] 

    на выходе

     index=nil value=[] 

    Мой всем совет — прежде чем братся за решение задачек с помощью ruby, если вы уже вроде как знаете сам язык, прочитайте Ruby API, от и до, хотябы один раз. Там много интересных классов и методов, которые делают код крассивее и эффективнее, а жизнь прекраснее 8-). Даже, если всё не запомните, то по крайней мере будете знать где посмотреть, например с помощью ri (Ruby API reference front end)
    Ещё вот здесь ответил человеку что читать, и ссылки прикрепил.

  2. dre3k says:

    ноября 20, 2010 at 12:57 (#)

    Решение задачи #2

    arr = [1,2,5,8,9,4,8,9,15,3,7,5,22]
    range = (7..15)
    
    p arr.select{|e| range === e}.min
    

    Насчёт последней задачи, то как сказано она взята из
    Best of Ruby Quiz
    Volume One
    By James Edward Gray II
    Publisher: The Pragmatic Bookshelf
    Pub Date: March, 2006

    В этой книжке также имееются варианты решения задач, один-два варианта на задачу.

    В своё время, когда учил ruby, прочитал её первый раз, и проработал все примеры, некоторые даже с отладчиком(в netbeans) пришлось разбирать. Второй раз, решил каждую задачу самостоятельно с использованием ruby 1.9.1 и новых методов появившихся с момента публикации книги. Три месяца назад вышел ruby 1.9.2-p0. Вот список новых методов и других нововведений. Будет время, модифицирую решения задачек под реалии наших дней 8-)

    Вот здесь полный список задачек.

  3. admin says:

    ноября 20, 2010 at 13:33 (#)

    dre3k, решение:

    arr = [1,2,5,8,9,4,8,9,15,3,7,5,22]
    range = (7..15)
    
    p arr.select{|e| range === e}.min
    

    просто превосходно!

  4. dre3k says:

    ноября 20, 2010 at 13:54 (#)

    Решение автора, для задачи #2, оказалось чуть-чуть быстрее моего:

    require 'benchmark'
    include Benchmark
    
    arr = [1,2,5,8,9,4,8,9,15,3,7,5,22]
    range = (7..15)
    
    bm(6) do |x|
      x.report("dre3k") do
        200_000.times{arr.select{|e| range === e}.min}
      end
      x.report("admin") do
        200_000.times{(arr & range.to_a).min}
      end
    end
    

    на выходе:

                user     system      total        real
    dre3k   3.860000   0.020000   3.880000 (  3.908857)
    admin   3.210000   0.040000   3.250000 (  3.255516)
    
  5. admin says:

    ноября 20, 2010 at 14:01 (#)

    на самом деле я не автор, задачи взяты из Списка Задач по высокоуровневому программированию (ФГОУ ДПО МЭТТ ГАИ). К следующему одному из следующих постов подготовлю более сложные и интересные задачи.

  6. octoman says:

    марта 13, 2013 at 19:57 (#)

    arr = Array.new(15) { |x| x * 3 }
    
    
    puts "Create Massive"
    puts "#{arr.sort!}"
    
    puts "Чётные числа"
    arr.map do |x| 
            if x.even? != false
                    puts "#{x.to_s} Чётное число"
            else x.even? != true 
                    puts "#{x.to_s} Не чётное"
            end
    end
    

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.