2014-09-22 3 views
2

비슷한 객체 배열을 갖고 있으며 a 속성의 값은 b 또는 c입니다. 배열은 배열의 각 항목 쌍이 하나의 행을 나타내는 행 모음으로 간주 될 수 있습니다.루비 배열 반복 및 돌연변이

array = [c, b, b, c, c, c, b] 
# array[0], array[1] is one row (c, b) 
# array[2], array[3] is another (b, c) 
# ... 

이 단지 (b, b)의 더 열 수 없습니다 수 있으며, 그런 경우는 다음 b 값 중 하나 인 경우에 대한 교환해야합니다 난 그냥 단순화하기 위해, 예를 속성 a의 값을 나열했습니다 배열에서 가장 가까운 c 값입니다. c 값이 더 이상 없으면 b 값이 배열 끝에 남아있는 한 배열이 유효합니다.

배열의 최종 행은 단지 하나의 값으로 구성 될 수 있습니다. 이자형. (b,).

예 :

array = [b, c, b, b, c, b, b, b, c, b, b, c, c] 
# becomes 
array = [b, c, b, c, b, b, b, b, c, b, b, c, c] 
array = [b, c, b, c, b, c, b, b, b, b, b, c, c] 
array = [b, c, b, c, b, c, b, c, b, b, b, b, c] 
array = [b, c, b, c, b, c, b, c, b, c, b, b, b] 
# rows: (b, c), (b, c), (b, c), (b, c), (b, c), (b, b,), (b,)  

이것은 내가 (매우 필수적 및 자세한 때문에) 내가 정말 좋아한다하는 해낸 솔루션입니다

while true do 
    cand = nil 
    array.each_slice(2) do |item, nxt| 
    return if nxt.nil? 
    # pseudo-code: assume b? returns true for a == b   
    next unless item.b? && nxt.b? 
    cand = nxt 
    break 
    end 
    swap_cand = array.slice(array.index(cand), array.length).reject{ |item| item.popular? }.first 
    return if swap_cand.nil? 
    old_index, new_index = array.index(cand), array.index(swap_cand) 
    array[old_index], array[new_index] = array[new_index], array[old_index] 
end 

내가으로 계속 실행 문제 배열을 반복하면서 배열을 변형 할 수 없기 때문에 두 개의 루프가 필요했습니다.

편집 @ 7stud의 제안에 따라 break 문을 정리했습니다.

+0

'수익률은 = 사실 일 경우 nxt.nil? '응? LocalJumpError가 무엇인지 아십니까? 게시 한 코드가 실제로 def 내부에 있다면, 설정은 = true가 무엇입니까? 데프에서 돌아 왔을 때 더 이상 루프가 없습니다. 더 이상 루프가 없습니다. – 7stud

+0

이렇게하면 간단히'done' 변수를 설정하고 이후에'each_slice' 루프를 종료한다고 가정했습니다. 이것은 실제로 함수 정의 내부에 있으며'until' 루프에 의해 지정된대로이 외부 루프는'done'이'true' 일 때 종료됩니다. – nicohvi

+0

** 계속 진행하고있는 문제는 배열을 반복하면서 ** 배열을 변경할 수 없다는 것입니다. 'results = []; 임시 = []; arr.each do | obj | 결과 << obj # 또는 temp << obj. 필요한만큼 배열을 사용하고 각 루프에서 앞뒤로 물건을왔다 갔다합니다. – 7stud

답변

0

열거 할 수있는 # 청크가이 문제에 적합합니다.

코드

def valid?(arr, b) 
    arr.chunk { |e| e } 
    .map(&:last)[0..-2] 
    .select { |e| e.first == b } 
    .max_by(&:size) 
    .size <= 2 
end 

b = 0 
c = 1 
valid?([c, b, b, c, b, b, b], b) #=> true 
valid?([c, b, b, b, c, c, b], b) #=> false 

설명

b = 0 
c = 1 
arr = [c, b, b, c, b, b, b] 
    #=> [1, 0, 0, 1, 0, 0, 0] 
enum = arr.chunk { |e| e } 
    #=> #<Enumerator: #<Enumerator::Generator:0x0000010205aa70>:each> 
enum.to_a # Let's examine the elements of `enum` 
    #=> [[1, [1]], [0, [0, 0]], [1, [1]], [0, [0, 0, 0]]] 
a = enum.map(&:last) 
    #=> [[1], [0, 0], [1], [0, 0, 0]] 
d = a[0..-2] # disregard last value, which may or may not be an array of `b`'s 
    #=> [[1], [0, 0], [1]] 
e = d.select { |e| e.first == b } 
    #=> [[0, 0]] 
f = e.max_by(&:size) 
    #=> [0, 0] 
g = f.size 
    #=> 2 
g <= 2 
    #=> true 
+0

공유 해 주셔서 감사합니다.이 방법으로 값을 바꾸고 배열을 변환하는 방법을 설명해 주시겠습니까? – nicohvi

+0

나는이 질문을 단지 스와핑을 언급하지 않고 배열이 "유효"한지를 결정하는 것으로 해석했다. 그 맞습니까? 덧붙여 말하면, 당신이 코멘트를 남겼을 때 설명을 준비하고있었습니다. –

+0

불명확하면 죄송합니다! 이것은 질문에서 온 것입니다. (그것은 가끔은 숨겨 졌던 것 같습니다)'연속해서 세 개의 b 값이 발생하면 배열이 그 배열을 준수하도록 b 값 중 하나를 가장 가까운 c 값으로 바꿔야합니다 만약 존재한다면 규칙이 적용됩니다. " – nicohvi