9

I'm in an introductory software development class, and my homework is to create a rock paper scissors program that takes two arguments (rock, paper), etc, and returns the arg that wins.

Now I would make quick work of this problem if I could use conditionals, but the assignment says everything we need to know is in the first three chapters of the ruby textbook, and these chapters DO NOT include conditionals! Would it be possible to create this program without them? Or is he just expecting us to be resourceful and use the conditionals? It's a very easy assignment with conditionals though...I'm thinking that I might be missing something here.

EDIT: I'm thinking of that chmod numerical system and think a solution may be possible through that additive system...

boulder_ruby
  • 38,457
  • 9
  • 79
  • 100
  • 4
    There's a justifiable movement called the [Anti-IF campaign](http://www.antiifcampaign.com/), which uses the objects to provide the condition itself. There's some more information in [this SO answer.](http://stackoverflow.com/a/7264192/1079354) – Makoto Jun 06 '12 at 23:09
  • 1
    Any idea what falls into the _conditionals_ camp for you professor? Will `any?` or `all?` or `includes?` or similar methods count here? How about the `?:` ternary operator? – sarnold Jun 06 '12 at 23:09
  • We have literally not used a single conditional operator. I'm familiar with Java and Javascript so I know all that stuff, but I want to do the assignment in the straightjacket, if you will. Houdini. – boulder_ruby Jun 06 '12 at 23:10
  • What did you learn in the first 3 chapters? – at. Jun 06 '12 at 23:11
  • arrays, hashes, SYMBOLS, classes, objects, variables, lots of command line and emacs stuff, attributes, parameters (obviously), the == test, instance variables, basically everything up to conditionals – boulder_ruby Jun 06 '12 at 23:16
  • @boulder_ruby It frustrates me that professors have students write bad code like this from the beginning. – Andrew Larsson Nov 01 '13 at 00:00
  • I didn't expect that when posting an answer to a three-year old question, and certainly not before the ink was dry. – Cary Swoveland Aug 21 '15 at 02:44
  • Are you good at that game, boulder, paper, scissors? – Cary Swoveland Aug 21 '15 at 02:49

8 Answers8

11

Here's one only using hashes:

RULES = {
  :rock     => {:rock => :draw, :paper => :paper, :scissors => :rock},
  :paper    => {:rock => :paper, :paper => :draw, :scissors => :scissors},
  :scissors => {:rock => :rock, :paper => :scissors, :scissors => :draw}
}

def play(p1, p2)
  RULES[p1][p2]
end

puts play(:rock, :paper)        # :paper
puts play(:scissors, :rock)     # :rock
puts play(:scissors, :scissors) # :draw
dereckrx
  • 446
  • 4
  • 5
8
def winner(p1, p2)
  wins = {rock: :scissors, scissors: :paper, paper: :rock}
  {true => p1, false => p2}[wins[p1] == p2]
end

winner(:rock, :rock) # => :rock d'oh! – tokland

Per @sarnold, leaving this as an exercise for the student :).

Mori
  • 27,279
  • 10
  • 68
  • 73
3

I very much doubt you've seen array/set intersections, so just for fun:

def who_wins(p1, p2)
  win_moves = {"rock" => "paper", "paper" => "scissors", "scissors" => "rock"}
  ([p1, p2] & win_moves.values_at(p1, p2)).first
end

who_wins("rock", "paper") # "paper"
who_wins("scissors", "rock") # "rock"
who_wins("scissors", "scissors") # nil
tokland
  • 66,169
  • 13
  • 144
  • 170
2

A simple hash to the rescue:

def tell_me(a1, a2)
  input = [a1 , a2].sort.join('_').to_sym
  rules = { :paper_rock => "paper", :rock_scissor => "rock", :paper_scissor => "scissor"}
  rules[input]
end
Anil
  • 3,899
  • 1
  • 20
  • 28
  • 1
    When answering homework questions, consider giving _sketches_ of answers rather than fully functioning code... – sarnold Jun 06 '12 at 23:14
  • @sarnold Any good teacher will fail him if his answer is this succinct. He better write it in his own words. – Anil Jun 06 '12 at 23:16
  • don't worry about it guys, I didn't have the guts to tell you but I re-read through chapter 3 and found out that it DOES have conditionals in it. – boulder_ruby Jun 06 '12 at 23:37
  • +1. @Anil, some comments: 1) Explicit returns are extremely unidiomatic. 2) maybe use "_" to join the strings? it would look better. 3) you can use an array-pair as keys, but the symbol is also ok 4) nice solution! – tokland Jun 06 '12 at 23:40
  • @tokland I had it in one line, but changed it for readability. Thanks for the compliment. Changed per suggestion. – Anil Jun 06 '12 at 23:44
1

I just think the simplest solution has to be something like:

@results = {
  'rock/paper' => 'paper',
  'rock/scissors' => 'rock',
  'paper/scissors' => 'scissors',
  'paper/rock' => 'paper',
  'scissors/paper' => 'scissors',
  'scissors/rock' => 'rock'
}

def winner p1, p2
  @results["#{p1}/#{p2}"]
end
pguardiario
  • 53,827
  • 19
  • 119
  • 159
1
WINNAHS = [[:rock, :scissors], [:scissors, :paper], [:paper, :rock]]

def winner(p1, p2)
  (WINNAHS.include?([p1,p2]) && p1) || (WINNAHS.include?([p2,p1]) && p2) || :tie
end

winner(:rock, :paper)        #=> :paper 
winner(:scissors, :paper)    #=> :scissors 
winner(:scissors, :scissors) #=> :tie 
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
  • this answer is a little bit more obfuscated than the other hash answer so I'm switching the correct answer to the @dereckrx's answer again. This is very cool though, kind of like a ternary operator in its brevity. Will be studying this one for some time – boulder_ruby Aug 24 '15 at 03:37
0

I don't know much about ruby, but I solved a problem like this long ago by using values for each one (eg, R = 1, P = 2, S=3).

Actually, I just googled after thinking about that and someone solved the problem in python using an array.

Ammar
  • 1,068
  • 2
  • 13
  • 20
0

pguardiario's solution above can be modified per the below to show both (1) which player won (as opposed to the choice of object that won) and (2) the result when there is a draw:

def rps(p1, p2)
   @results = {
   'rock/paper' => "Player 2 won!",
   'rock/scissors' => "Player 1 won!",
   'paper/scissors' => "Player 2 won!",
   'paper/rock' => "Player 1 won!",
   'scissors/paper' => "Player 1 won!",
   'scissors/rock' => "Player 2 won!",
   'rock/rock' => "Draw!",
   'scissors/scissors' => "Draw!",
   'paper/paper' => "Draw!"
   }

   @results["#{p1}/#{p2}"]
end

rps("rock", "rock")     => "Draw!"
rps("rock", "scissors") => "Player 1 won!"
rps("rock", "paper")    => "Player 2 won!"

...etc

awye765
  • 1
  • 1