пытаясь найти самую низкую среднюю высоту в этом файле чисел .dat - PullRequest
0 голосов
/ 10 ноября 2011

Я пытаюсь разместить бассейн на этом участке местности. Ландшафт - это первый индекс (в данном случае 10x10), а последний индекс - это размер пула (2x2). Я разобрался, как читать на местности и получить среднее значение и стандартное отклонение, но теперь мне нужно найти самую низкую среднюю высоту. Я знаю, что мне нужно использовать цикл while, но я не знаю, как это сделать, может кто-нибудь мне помочь?

10
1 1 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 12 12 12
1 2 3 4 5 6 7 12 12 12
1 2 3 4 5 6 7 12 12 12
21

Ответы [ 2 ]

2 голосов
/ 11 ноября 2011

Вот два ответа, показывающие разные стили.Первый более быстрый (важен только для ОГРОМНЫХ размеров местности), но менее "Ruby-esque";вторая более функциональна, но создает дополнительные промежуточные данные.Для вашего лучшего образования, я призываю вас убедиться, что вы понимаете это полностью и выбираете, как поступить так, как вам лучше.

Кроме того, я предположил, что 21 у вас естьв вашем вопросе есть ошибка, и вы хотели иметь 2 там.

Во-первых, оба решения начинаются с одного и того же кода, который создает массив массивов для ландшафта:

# Load the text file as an array of strings
lines = IO.readlines('pool.txt')

# Turn it into an array of arrays of numbers
terrain = lines.map{ |s| s.scan(/\d+/).map(&:to_i) }

# Throw out the silly grid size; we'll infer it from real data instead!
terrain.shift 

# Take the last line (pool size) out of the terrain
pool_size = terrain.pop.first

Первое решение проходит по рельефу и вычисляет среднее значение для каждой подсетки, отслеживая наименьшее число:

# For fun, we'll allow terrain that doesn't have to be square
rows = terrain.length
cols = terrain.first.length

best_size = Float::INFINITY
0.upto(rows-pool_size-1) do |y|
  0.upto(cols-pool_size-1) do |x|
    # x,y is the upper left corner of a valid pool_size × pool_size grid
    average = 0.0
    0.upto(pool_size-1) do |m|
      0.upto(pool_size-1) do |n|
        # Add up each point in the sub-grid
        average += terrain[y+n][x+m]
      end
    end

    # The number of points we added is the square of the size
    average /= (pool_size*pool_size)

    # Mark this as the best seen so far
    best_size = average if average < best_size
  end
end

p best_size
#=> 1.25

Второе решение находит все подсетки, а затем использует Enumerable#min_by метод, чтобы найти лучшее.Мы также создаем метод для вычисления среднего по массиву чисел, просто для забавы и более самоописываемый код:

# See http://ruby-doc.org/stdlib-1.9.3/libdoc/matrix/rdoc/Matrix.html
require 'matrix' 

class Matrix
  # Average all values in the array (as a float)
  def average
    parts = to_a.flatten
    parts.inject(:+) / parts.length.to_f
  end
end

# Hey look, a nice 2D grid of elevations!
terrain = Matrix[ *terrain ]

# Create an array of matrices, each one representing a possible pool
rows = 0...(terrain.row_size    - size)
cols = 0...(terrain.column_size - size)
pools = rows.flat_map{|x| cols.map{ |y| terrain.minor(x,size,y,size) } }

# Find the lowest pool by calling the above 'average' method on each
lowest = pools.min_by(&:average)

p lowest, lowest.average
#=> Matrix[[1, 1], [1, 2]]
#=> 1.25

На моем компьютере простой метод массива массивов занимает ~ 0,6 снайти самый низкий пул 3х3 в случайной местности 400 × 400, в то время как матричный метод занимает ~ 1,3 с.Таким образом, стиль матрицы более чем вдвое медленнее, но все же достаточно быстр для вашего задания.:)

0 голосов
/ 10 ноября 2011

Это Руби. Вы, вероятно, хотите использовать итераторы, а не while loop.

Но сделай свою домашнюю работу. Вы узнаете больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...