Ruby &引用;棋盘上的麦粒;红宝石色

Ruby &引用;棋盘上的麦粒;红宝石色,ruby,Ruby,棋盘上有64个正方形。每个正方形都有它的两倍 前一个。编写一个显示以下内容的程序: -每个正方形上有多少个颗粒,以及 -谷物总数 我的代码适用于第一部分,但我在声明总数时遇到问题。 我缺少的一些基本类/方法声明。 谢谢你的帮助 class Grains def square(n) array_of_grains = [] (0..63).each {|x| array_of_grains << 2**x} n = n-1 array_of_gr

棋盘上有64个正方形。每个正方形都有它的两倍 前一个。编写一个显示以下内容的程序: -每个正方形上有多少个颗粒,以及 -谷物总数

我的代码适用于第一部分,但我在声明总数时遇到问题。 我缺少的一些基本类/方法声明。 谢谢你的帮助

class Grains

  def square(n)
    array_of_grains = []
    (0..63).each {|x| array_of_grains << 2**x}
     n = n-1
    array_of_grains[n]
  end

  def total
     array_of_grains.each {|x| sum += x }
  end

end
类粒度
def方形(n)
数组_的_颗粒=[]

(0..63).每一个{x |数组_ _晶粒这里都有一堆问题

首先,
array\u of_grains
square
的局部变量。它不存在于方法之外。如果希望它是
Grain
实例上的实例变量,它必须是
@array\u of_grains

其次,您的
total
方法会导致错误,因为没有本地
array\u of_grains
变量供它调用
每个
。即使存在,
sum
也将是未定义的。您需要声明
sum
并将其初始值设置为
0
,或者只需使用
注入(&:+)
,这是其中一个

第三,每次调用方法
square
时,您都在构建整个
数组(由粒度组成)
数组。您可以使用
|124;=
只计算该值一次

您的方法应该如下所示:

def square(n)
  @array_of_grains ||= (0..63).map {|x| 2 ** x }
  @array_of_grains[n - 1]
end

def total
  @array_of_grains.inject(&:+)
end

通过在方法上方添加一个
attr\u访问器:array\u of_grains
,您可以使代码几乎正常工作,但这仍然不能解决未定义的
sum
的问题。

如果您希望
array\u of_grains
作为实例变量提供,请使用
@array\u of_of_grains

您还可以使用Ruby的访问器:

attr_accessor array_of_grains # getter and setter
attr_reader array_of_grains # getter
attr_writer array_of_grains # setter
在这种情况下,您可以:

class Grains

  attr_accessor :array_of_grains

  def set_grains(array)
    self.array_of_grains = array
  end

  def total
    return self.array_of_grains.count
  end

end

这是写它的一种方式:

square = 63.times.with_object([1]) { |i,a| a << 2 * a.last }
  #=> [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192,
  #    16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152,
  #...
  #    2305843009213693952, 4611686018427387904, 9223372036854775808]
square=63.times.with_object([1]){i,a | a[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,
#    16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152,
#...
#    2305843009213693952, 4611686018427387904, 9223372036854775808]
为了确定总数(我最初在问题中遗漏了):

total,square=63.times.reduce([0,[1]])do |(t,a)_|
v=2*a
[t+v,a 18446744073709551614
方形#=>(如上所述)

这里有一个元答案,它使用您的类将这里所有的好想法(全部投票!)组合成一个完整的解决方案

class Grains

  attr_accessor :array_of_grains

  def initialize(n = 1)
    @array_of_grains = 63.times.with_object([n]) { |i,a| a << 2 * a.last }
  end

  def square(n)
    array_of_grains[n - 1]
  end

  def total
    array_of_grains.reduce(:+)
  end
end

这仍然需要时间,但这是你想要做的数学运算。

作为旁白,使用map:
array\u of_grains=(0..63)。map{i}i | 2**i}
而不是
array\u of_grains.each{x | sum+=x}
使用
array\u of_grains.inject(:+)
。它是说square 1有多少个颗粒?还是你要提供这些信息?你从一个开始。这里你有更多关于这个奇怪问题的信息:)这太过分了,比
square=(1..63)更清晰的解要长得多。map{i | i | 2**i};total=squares inject.inject(&:+)
毫无收获,对可读性造成了巨大的冲击。如果我在我编写的任何代码库中遇到这段代码,我会用更干净的代码替换它。你也会解雇我吗?(我把它放在那里是为了教育价值。)不,我会指导你为什么这是一个奇怪而丑陋的解决方案。我认为count方法只用于返回我们拥有的元素数量之和。我们需要计算值的反求和。
class Grains

  attr_accessor :array_of_grains

  def initialize(n = 1)
    @array_of_grains = 63.times.with_object([n]) { |i,a| a << 2 * a.last }
  end

  def square(n)
    array_of_grains[n - 1]
  end

  def total
    array_of_grains.reduce(:+)
  end
end
board = Grains.new
board.square(3) #=> 4
board.total #=> 18446744073709551615
@square_of_sums = (n * (n + 1) / 2)**2
@number_of_squares = n * (n + 1) * (2 * n + 1) / 6