2016-05-31 2 views
-2

Я пишу метод печати лестницы, было бы какКаков наилучший способ печати лестницы с помощью Ruby?

 # 
    ## 
    ### 
    #### 
##### 
###### 

Это лестница из 6 рядов. Так что я придумал этот код:

def print_staircase(num_rows) 
    for i in (1..num_rows) 
    puts ' ' * (num_rows-i) + '#' * i 
    end 
end 

print_staircase(6) 
=> 
    # 
    ## 
    ### 
    #### 
##### 
###### 

Так это работает, но я думаю, что это своего рода неэффективно, лучше решение?

Потому что, если num_rows большой, поэтому мы будем строить результат как ' ' * (n-i) + '#' * i каждый раз, я думаю, что это не очень хорошая идея!

+1

Почему вы думаете, что это хак? –

+0

@JanDvorak Извините, я имею в виду неэффективность, проверьте мое обновление! –

+0

Я не думаю, что это неэффективно. Кроме того, в этом случае вам не нужна производительность. –

ответ

3

Вы можете создать начальную строку один раз и установить # на каждой итерации:

def print_staircase(num_rows) 
    str = ' ' * num_rows 
    1.upto(num_rows) do |i| 
    str[-i] = '#' 
    puts str 
    end 
end 

Это повторно использует str вместо создания новой строки экземпляру каждый раз.

Но, как правило, вы увидите что-то вроде этого:

def print_staircase(num_rows) 
    1.upto(num_rows) { |i| puts ('#' * i).rjust(num_rows) } 
end 
1

Сначала необходимо определить переменную, равную пустой строке. Затем с циклом всегда добавляйте '#' к нему и покажите его. Это сохранит текущее значение после каждой итерации, и вам нужно будет добавить в строку только «#», вместо того чтобы пересчитывать ее с нуля на каждой итерации.

1

Существует много способов сделать это, ваш - одно решение, и мне кажется, что это хорошо. Если реализованы два дополнительных решения и контрольный показатель. Ваше решение было самым быстрым из этих трех (заявление об отказе от microbenchmark применяется, особенно потому, что я делаю IO с puts/print).

def staircase_0(size) 
    string = ' ' * (size - 1) + '#' * size 
    size.times do |offset| 
    puts string[offset...(offset + size)] 
    end 
end 

def staircase_1(size) 
    prefix = ' ' * (size - 1) 
    postfix = '#' 
    size.times do 
    print prefix 
    puts postfix 
    prefix = prefix[1..-1] 
    postfix += '#' 
    end 
end 


def staircase_2(num_rows) 
    for i in (1..num_rows) 
    puts ' ' * (num_rows-i) + '#' * i 
    end 
end 


require 'benchmark/ips' 

Benchmark.ips do |x| 
    x.report('_0') do 
    staircase_0(6) 
    end 
    x.report('_1') do 
    staircase_1(6) 
    end 
    x.report('_2') do 
    staircase_2(6) 
    end 
    x.compare! 
end 

И результаты:

Comparison: 
        _2: 35649.0 i/s 
        _0: 29716.3 i/s - 1.20x slower 
        _1: 25848.2 i/s - 1.38x slower 

Помните, что в связи с IO результаты могут сильно отличаться. IO медленный (поэтому он имеет больше веса, чем ваш алгоритм и конкатенация строк). Он также не предсказуем и может отличаться от прогона до бега. Поэтому более эффективным (с точки зрения выполнения) решение может быть выходом только одна строка:

def staircase_3(size) 
    string = '' 
    size.times do |index| 
    string += ' ' * (size - index - 1) + '#' * (index + 1) + "\n" 
    end 
    puts string 
end 

И действительно, когда я запускать тесты это быстрее:

Comparison: 
        _3: 52923.7 i/s 
        _0: 36377.7 i/s - 1.45x slower 
        _2: 33508.7 i/s - 1.58x slower 
        _1: 25991.6 i/s - 2.04x slower 

отметить также, что в этом пробеге ваша версия алгоритма (staircase_2) медленнее, чем staircase_0 ... что связано с IO. Но во всех моих прогонах staircase_3 был самым быстрым.

+0

Хороший улов, мужик, спасибо! –

+0

@HieuPham Я обновил свой ответ, чтобы добавить другое решение. –

+0

Спасибо, я также проверю ваше решение, отличный вклад, я очень ценю это :) –

Смежные вопросы