emson / elixirgolf

Elixir Golf web site
MIT License
3 stars 1 forks source link

Elixir Rock, Paper, Scissors #4

Open emson opened 8 years ago

emson commented 8 years ago

Recreate the classic "Rock, Paper, Scissors" game in Elixir. See the website for more details : http://elixirgolf.com/articles/elixir-rock-paper-scissors/

henrik commented 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:

Some things to note:

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.

hassox commented 8 years ago

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:

@hassox on Twitter

henrik commented 8 years ago

@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.

mmrobins commented 8 years ago

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

markolson commented 8 years ago

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.

f-lombardo commented 8 years ago

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

emson commented 8 years ago

@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.