2012-07-05 38 views
6
class CartesianProduct 
include Enumerable 
# your code here 
end 
#Examples of use 
c = CartesianProduct.new([:a,:b], [4,5]) 
c.each { |elt| puts elt.inspect } 
# [:a, 4] 
# [:a, 5] 
# [:b, 4] 
# [:b, 5] 
c = CartesianProduct.new([:a,:b], []) 
c.each { |elt| puts elt.inspect } 
# (nothing printed since Cartesian product 
# of anything with an empty collection is empty) 

Tôi mới dùng ruby. Và tôi hiểu cách xác định một phương pháp thể hiện của Cartesian Product, nhưng tôi không có đầu mối cho điều này. Làm thế nào tôi nên xây dựng đối tượng lớp để đáp ứng yêu cầu.Sản phẩm Cartesian Ruby

+0

Bạn có thể làm rõ những gì bạn đang yêu cầu không? Làm thế nào bạn nên xây dựng những gì? Bạn đang cố tạo một lớp có tên 'CartesianProduct' sẽ làm gì được hiển thị? – denniss

+0

Có, nó đòi hỏi một phương pháp lớp học. Tôi biết cách xây dựng một phương thức thể hiện để trả về một giá trị, nhưng tôi không biết cách xây dựng phương thức lớp để sửa đổi giá trị của một đối tượng lớp. – ZhijieWang

+0

Đây có phải là bài tập về nhà không? Nếu có, điều đó là ổn, mọi người sẽ cố gắng đưa bạn đi đúng hướng. – steenslag

Trả lời

6

tôi sẽ không sử dụng một lớp cho rằng, nhưng vẫn giữ cấu trúc của câu hỏi, tôi muốn viết:

class CartesianProduct 
    include Enumerable 

    def initialize(xs, ys) 
    @xs = xs 
    @ys = ys 
    end 

    def each 
    return to_enum unless block_given? 
    @xs.each do |x| 
     @ys.each { |y| yield [x, y] } 
    end 
    end 
end 

Thay vào đó, tôi muốn chỉ đơn giản là viết xs.product(ys) hoặc xây dựng của riêng tôi Array#lazy_product nếu lười biếng là quan trọng (xem điều này ticket).

+0

Không cần phải sử dụng lười biếng, mặc dù, là có? Thẳng ra 'each' và' yield' sẽ đơn giản và nhanh hơn –

+0

ok, bạn đã đúng, mặc dù thành thật mà nói tôi thích phiên bản lười hơn, đó là phương pháp tiếp cận chức năng hơn (và trả về một điều tra nếu được sử dụng không có khối, như một tiêu chuẩn 'each'). – tokland

+0

Thật vậy, bạn có lẽ nên bắt đầu với 'return to_enum điển hình trừ khi block_given?' –

22

Tôi khuyên bạn nên sử dụng Array#product.

[:a, :b].product [4,5] 

Điều này sẽ mang lại kết quả bạn muốn.

irb(main):001:0> [:a, :b].product [4,5] 
=> [[:a, 4], [:a, 5], [:b, 4], [:b, 5]] 
irb(main):002:0> 

Nếu bạn muốn tạo bộ tạo hoán vị, tôi đã viết một cái gì đó như thế này trước đây. Nhưng tôi cảnh báo bạn, nếu bạn có nhiều hoán vị để tính toán thì có thể mất một lúc. Bạn sẽ có thể lấy những gì bạn cần từ 40 - 45 dòng đầu tiên của this file (tệp này vẫn là một thử nghiệm).

Bí quyết là xây dựng các điều tra viên sử dụng Ruby 1.9.2 để làm việc theo cách của bạn thông qua một mảng các mảng. Vì vậy, bạn đầu tiên xây dựng một điều tra viên sẽ không ngừng chu kỳ thông qua một mảng, và trong bảng liệt kê mảng của bạn, bạn theo dõi tập đầu ra đầu tiên và kết thúc vòng lặp khi được nhấn lần thứ hai. Đây là cách duy nhất tôi có thể tìm ra cách chấm dứt vòng lặp như vậy.

def infinite_iterator(array) 
    Enumerator.new do |result| 
    loop do 
     array.cycle { |item| result << item } 
    end 
    end 
end 

def cartesian_iterator(data) 
    Enumerator.new do |result| 
    first = data.map { |p| p.next } 
    result << first 

    i = 1 
    parts = first.dup 
    loop do 
     parts[2-i] = data[2-i].next 
     break if parts == first 

     result << parts.join 
     i = ((i + 1) % parts.size) 
    end 
    end 
end 

array = [ infinite_iterator([:a,:b]), infinite_iterator([4,5]) ] 
generator = cartesian_iterator(array) 

generator.each { |a| p a } 
+0

còn hai mảng trống thì sao? Kết quả sẽ như thế nào? – ZhijieWang

+1

@ user1505108 bạn đã thử IRB trước đây chưa? Kết quả là '[]'. –

6

Bạn cần phải xác định một phương pháp each trong lớp học của bạn mà các cuộc gọi yield cho mỗi sự kết hợp của sản phẩm.

Bạn có thể sử dụng Array#product, nhưng nó trả về một mảng, vì vậy nó không phải là lười biếng.

Có một proposal for Array.product trong Ruby 2.0 sẽ thực hiện điều đó.

+0

Cảm ơn bạn, giải quyết vấn đề – ZhijieWang

+0

@ user1505108 Sau đó, bạn nên đánh dấu câu trả lời này (dấu v). – steenslag

Các vấn đề liên quan