2012-03-02 4 views
1
def rps_tournament_winner(tournament) 
    for i in 0..1 do 
    if tournament[i][1].is_a? Array then 
     rps_tournament_winner(tournament[i]) 
    else 
     tournament=rps_game_winner(tournament) 
     return 
    end 
    end 
    return tournament 
end 

Это является частью реализации рока-бумага-ножницы в РубинеМанипулирование массивы с рекурсивной функцией

rps_game_winner 

принимает массив двух массивов в формате

[ ["Allen", "S"], ["Omer", "P"] ] 

, где первый элемент имя игрока, вторым элементом является их решение и возвращает победителя.

rps_tournament_winner 

принимает ввод вложенных массивов с произвольной глубиной, как

[ 
    [ 
    [ ["Armando", "P"], ["Dave", "S"] ], 
    [ ["Richard", "R"], ["Michael", "S"] ], 
    ], 
    [ 
    [ ["Allen", "S"], ["Omer", "P"] ], 
    [ ["David E.", "R"], ["Richard X.", "P"] ] 
    ] 
] 

То, что я пытаюсь сделать, это изменение оригинального вклада как функция делает прогресс, но вход выходит, как он вошел. Включение глобальных переменных - это решение, но это работа, которая должна быть оценена с помощью автогрейдера, и я подозреваю, что она просто подталкивает некоторый ввод непосредственно к функции и сравнивает вывод, поэтому его не вариант.

+0

@NiklasB. Конечно, поскольку это Ruby, невозможно * не * использовать объекты ';)'. (Я предполагаю, что вы имеете в виду классы, я просто педантичен.) –

+0

@Andrew: О, конечно, я имел в виду объекты с типами, разумными для этой цели;) –

ответ

3

Несколько проблем с оригинальным кодом:

  • Вы смешиваете итерации с помощью рекурсии
  • Вы отбрасывать результат рекурсии (rps_tournament_winner(tournament[i]))
  • Вы не ничего полезного (return просто возвращает вернуться nil, но это не имеет значения, потому что вы все равно не используете результат)

Исправлена ​​версия с использованием оригинала l OGIC будет:

def rps_tournament_winner(tournament) 
    result = [] 
    for i in 0..1 do 
    if tournament[i][0][0].is_a? Array then 
     result << rps_tournament_winner(tournament[i]) 
    else 
     result << rps_game_winner(tournament[i]) 
    end 
    end 
    return result  
end 

Но на самом деле это эквивалентно простой

def rps_tournament_winner(tournament) 
    if tournament[0][0].is_a? String 
    rps_game_winner(tournament) 
    else 
    tournament.map { |t| rps_tournament_winner(t) } 
    end 
end 

И это было бы намного лучше, используя объекты:

class Game < Struct.new(:player1, :choice1, :player2, :choice2) 
    def winner 
    'PRSP'.include?(choice1 + choice2) ? player1 : player2 
    end 
end 

def rps_tournament_winner(tourn) 
    return tourn.winner if tourn.is_a? Game 
    tourn.map { |t| rps_tournament_winner(t) } 
end 
+0

IMHO повторное использование того же имени переменной в блоке, что и снаружи, не является лучший способ научить нового пользователя :) – Phrogz

+0

@Phrogz: Да, я думаю, проблема в том, что я использовал однобуквенное имя аргумента: P fixed. –

+0

Я думаю, что фактическое утверждение if/else будет лучше, чем условное раннее возвращение одной строки (тем более, что метод настолько короткий). Да, это будет еще две строки, но я думаю, что это лучше. –

1

Следующая функция также может быть решением для управления массивами с рекурсивной функцией:

def rps_tournament_winner(tournament) 
    while not tournament[0].is_a? String do 
     i = i == 0 ? 1 : 0 
     if tournament[i][0].is_a? String 
      return rps_game_winner(tournament) 
     else 
      tournament[i] = rps_tournament_winner(tournament[i]) 
     end 
    end 
    return tournament 
end 
3

Ваше рекурсивное решение должно продолжать выбирать победителей, если не будет выбран окончательный победитель. Niklas's second solution останавливается, когда решаются победители первого уровня. Его следует уточнить следующим образом:

def rps_tournament_winner(tournament) 
    if(tournament[0][0].is_a? String) 
     rps_game_winner(tournament) 
    else 
     rps_tournament_winner(
      [rps_tournament_winner(tournament[0]), 
      rps_tournament_winner(tournament[1])] 
     ) 
    end 
end 
+0

Это гораздо лучшее решение – PerseP