Оператор Ruby с соответствием регулярному выражению - PullRequest
3 голосов
/ 20 марта 2012

Я работаю над своей второй программой ruby ​​и буквально застрял на последней вещи, стоящей между мной и законченной программой.Моя задача - написать метод «Камень, бумага, ножницы», который возвращает победившего игрока.Для этого требуется игровой аргумент в виде [["Dave", "S"], ["Dan", "R"]], где "S" и "R" - это "Ножницы" и "Скала".соответственно.Затем он определяет победителя и возвращает массив, содержащий стратегию выигрыша.Также выдает ошибки, если игра неправильной длины или стратегии == или не находятся в диапазоне.

class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end


def rps_game_winner(game)

raise WrongNumberOfPlayersError unless game.length == 2

  #Hash of whose Keys are the strategies and values are the players
  playr = {(game[0].slice(1).downcase) => game[0],
    (game[1].slice(1).downcase) => game[1]} #This fits on the above line in IRB

  #Collect Strategies in array for comparison
  stgys = playr.keys

  #raise NoSuchStrategyError unless players give strategies in range, no duplicates
  raise NoSuchStrategyError unless (stgys.select { |s| s.match /[prs]/ }.size == 2) 

  #determine Winner
  case stgys.to_s
   when /p/ && /r/
     playr["p"]
   when /p/ && /s/
     playr["s"]
   when /s/ && /r/
     playr["r"]
  end
end

Это работает, как я ожидаю, проверяя стратегии на соответствие регулярным выражениям и возвращая победителя.За исключением последнего случая, когда при встрече всегда возвращается ноль.Если я вызываю player ["r"] под любым другим, когда это удается, и он возвращает нужного игрока в "/ p / && / r /".Если я изменю порядок, он все равно не будет работать, поэтому я знаю, что это не имеет отношения к его позиции.Регулярное выражение / r / вычисляет, когда это должно произойти, если я сделаю отдельный вызов сопоставления вне оператора case.Поэтому я считаю, что я сузил это до того, что связано с тем, как / s / и / r / связаны, но в остальном я в тупике.Также приветствуется любая помощь с DRYness, спасибо за помощь!

Ответы [ 4 ]

0 голосов
/ 14 октября 2012

С помощью инструкций в задаче я решил проблему другим способом.

def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  raise NoSuchStrategyError unless game[0].length == 2 and game[1].length == 2
  raise NoSuchStrategyError unless game[0][1] =~ /^[RPS]$/ and game[1][1] =~ /^[RPS]$/
  return game[0] unless (game[0][1] == "P" and game[1][1] == "S") or
                        (game[0][1] == "S" and game[1][1] == "R") or
                        (game[0][1] == "R" and game[1][1] == "P")
  return game[1]
end

def rps_tournament_winner(tournament)
  return rps_game_winner(tournament) unless tournament[0][1] !~ /^[RPS]$/
  return rps_tournament_winner([rps_tournament_winner(tournament[0]), rps_tournament_winner(tournament[1])])
end

Я протестировал все приведенные сценарии, и у меня это сработало.

0 голосов
/ 21 марта 2012

На самом деле вам не нужно case вообще. Моя версия решения для этой задачи:

def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  raise NoSuchStrategyError if game.any? {|n| !(n[1] =~ /^[spr]$/i)}
  loose_hash = {'s' => 'r', 'p' => 's', 'r' => 'p'}
  strategy1 = game[0][1].downcase
  strategy2 = game[1][1].downcase
  loose_hash[strategy1] == strategy2 ? game[1] : game[0]
end
0 голосов
/ 21 марта 2012

Ваша проблема в том, что /p/ && /r/ оценивается до того, как оно фактически используется в качестве метки.Поскольку ни один из них не является ложным или нулевым, /p/ && /r/ равен /r/, и аналогично для других ваших меток кейсов.

Если вы не перепишите это, чтобы иметь по одному кейсу для каждого случая, кажется, чтомне, что case просто не очень подходит для того, что вы делаете

0 голосов
/ 21 марта 2012

Проблема в вашем /X/ && /X/ формате.Ruby не будет интерпретировать это как требование соответствия обоих регулярных выражений.Я не уверен, что именно, но я верю, что это будет относиться к нему так же, как к when /p/, /r/, что будет истинно, если или регулярное выражение совпадает.Когда вы проверяете game = [["Dave","S"], ["Dan","R"]], "r" совпадает с первым оператором case, и вы пытаетесь сослаться на playr["p"].

Попробуйте вместо этого:

case stgys.to_S
  when "pr", "rp"
    playr["p"]
  when "ps", "sp"
    playr["s"]
  when "sr", "rs"
    playr["r"]
end
...