Open emson opened 8 years ago
(I'll keep editing this one post for my solutions.)
200 characters with some error checking:
import Enum;case IO.gets''do<<a,b,c,10>>->x=for _<-1..3,do: random'rps';s=sum map zip([a,b,c],x),fn{v,v}->0;{?p,?r}->1;{?r,?s}->1;{?s,?p}->1;_->-1end;IO.puts [x,s<0&&"Lose"||s>0&&"Win"||"Draw"];_->end
(Was inspired to give map
a shot after seeing @hassox's solution – thank you! Also borrowed -1end
– hadn't realized you could skip the ;
in that one.)
This is basically what it does:
_ ->
) if it's not three chars followed by a newline. Otherwise, it sticks those chars into three vars a, b, c
and…x
s
by comparing each pair of your chars and the computer's. Each equal pair (draw) is 0, wins are 1, losses are -1. These three numbers are summed together.Some things to note:
10
is ASCII for a newline.Enum.random
, Enum.sum
, Enum.map
and Enum.zip
are all used without the module name (thanks to the import).The specification isn't completely clear, so I chose to do some minimal error handling:
186 chars without error checking:
import Enum;<<a,b,c,10>>=IO.gets'';x=for _<-1..3,do: random'rps';s=sum map zip([a,b,c],x),fn{v,v}->0;{?p,?r}->1;{?r,?s}->1;{?s,?p}->1;_->-1end;IO.puts [x,s<0&&"Lose"||s>0&&"Win"||"Draw"]
Older version, 196 chars, for
+ anonymous function instead of map
:
import Enum;<<a,b,c,10>>=IO.gets'';x=for _<-1..3,do: random'rps';s=sum for{p,c}<-zip([a,b,c],x),do: fn[v,v]->0;'pr'->1;'rs'->1;'sp'->1;_->-1;end.([p,c]);IO.puts [x,s<0&&"Lose"||s>0&&"Win"||"Draw"]
If we don't care about independent probabilities, we can shorten the randomness a little (my first solution did this until I realized my mistake):
…;x=take_random'rrrpppsss',3;…
Just for fun, this is one way (probably not the shortest one) to add stricter input checking to my solutions above, like @mmrobins brought up:
…<<a,b,c,10>>when a in'rps'and b in 'rps'and c in'rps'->…
You can't use a variable for the 'rps'
here, sadly.
Using Erlang strings instead of tuples for the zipping – ended up longer:
…;s=sum map :lists.zipwith(&[&1,&2],[a,b,c],x),fn[v,v]->0;'pr'->1;'rs'->1;'sp'->1;_->-1end;…
@henrik on Twitter.
This is my first one of these. Never been a code golfer before. I measured it at 203 characters:
import Enum;import String;case(zip(codepoints(strip(IO.gets"")),take_random(~w(r p s),3))|>map(fn{a,a}->0;{"r","s"}->1;{"p","r"}->1;{"s","p"}->1;_->-1end)|>sum)do 0->"Draw";a when a>0->"Win";_->"Lose"end
This has no error checking. Here's what it does:
["r", "p", "s"]
["r", "p", "s"]
(computer move) to produce a list of tuples [{"r", "p"}, {"p", "r"}, {"s", "s"}]
. The first element is the user move, second is the computer move.{a, a}
and set those to 0, identify wins r/s, s/p, p/r and set those to 1, all others are -1. @hassox on Twitter
@hassox That's a neat solution! This one wasn't easy :) Some thoughts:
I think take_random
won't repeat values, so you could never get "rrr" for example.
If I understood the description correctly, you want to also show the computer's choices in the output.
I'm nowhere close for character count (341), but here's my solution anyway:
import String;import Enum;l= ~w{r p s};m=IO.gets "";n=m|>strip|>split("",trim: true);if any?(n,fn(x)->!member?(l,x)end)do;else;f = fn()->random l end;o = [f.(), f.(), f.()];IO.puts o;g=fn(x)->case x do;{x,x}->0;{"r","s"}->1;{"p","r"}->1;{"s","p"}->1;_->-1;end;end;case zip(n,o)|>map(g)|>sum do;0->"Draw";x when x > 0->"Win";_->"Lose";end;end;
https://gist.github.com/mmrobins/df54ebe7cf28f58c2a00 easier to read version
One thing I noticed from the other solutions up to this point is they don't seem to exit if you give bad input, like "abc"
Twitter: @mmrobins
This 355'er has a bunch of inefficiencies I probably can't get rid of easily given how I trial-and-error'd my way through writing it, but it does have some checks to make sure that the input is only 'r', 'p', or 's'.
import Enum;t='rps';c=fn(s)->into(s,HashSet.new)end;s=(IO.gets"")|>String.strip|>String.to_char_list;case count(Set.difference(c.(s),c.(t)))do 0 when length(s)==3->e=for x<-s,do: {x,random(t)};IO.puts map(e,&(elem(&1,1)));x=sum(map(e,fn(x)->case x do {x,x}->0;{?r,?s}->1;{?p,?r}->1;{?s,?p}->1;_->-1end end));IO.puts(x<0&&"Lose"||x>0&&"Win"||"Draw");_->end
https://gist.github.com/markolson/420d59d8a6f665254a5e for the gist, @mark_olson for twitter.
I don't know if it could be acceptable :-) , but this is 193 chars:
case IO.gets''do<<a,b,c,10>>->{f, n}=Enum.random([{fn ?r->?p;?p->?s;?s->?r;_->:ko;end,"Lose"},{fn ?p->?r;?s->?p;?r->?s;_->:ko;end,"Win"},{&(&1),"Draw"}]);IO.puts <<f.(a),f.(b),f.(c)>><>n;_->end
Twitter: @f_lombardo
@f-lombardo great solution thanks. Yes it is acceptable - also I made a typo: Loose -> Lose
therefore could you update your solution which is now 193
chars! Well done.
Recreate the classic "Rock, Paper, Scissors" game in Elixir. See the website for more details : http://elixirgolf.com/articles/elixir-rock-paper-scissors/