Even or odd: three player

15

0

It's a three players game, play with one hand.

At same time, each player show his hand with 0 to 5 fingers extended.

If all player show same kind of (even or odd) number, there is no winner. But else, the player showing different kind the two other win.

 P l a y e r s
A      B      C       Winner

Even   Even   Even    No winner
Odd    Odd    Odd     No winner
Even   Odd    Odd     Player A
Odd    Even   Even    Player A
Even   Odd    Even    Player B
Odd    Even   Odd     Player B
Odd    Odd    Even    Player C
Even   Even   Odd     Player C

The requested tool could use arguments (3 arguments as numeric between 0 and 5) or STDIN (3 values by line, separated by spaces).

There is no need to check input: Irregular input could produce unexpected output.

Arguments or values on line is given from left to right, from player A to player C.

Output must only contain A, B or C (capitalized) or the string no one (in lower case, with a regular space).

Tool may work only once or as a filter on all input lines.

Shortest code win.

F. Hauri

Posted 2013-11-30T21:43:16.453

Reputation: 2 654

6Might be more interesting as a [king-of-the-hill]. Play the game. – dmckee --- ex-moderator kitten – 2013-12-01T01:49:23.010

I wonder how the fact we have 5 fingers (so there are 3 odd and 2 even numbers of fingers possible) affects the winning strategy... – Olivier Dulac – 2013-12-02T11:16:10.177

@OlivierDulac, 0 is also an even number. – Peter Taylor – 2013-12-02T12:25:07.420

In this game rule yes, this let same chances for even than for odd numbers (0 2 4 vs 1 3 5) – F. Hauri – 2013-12-02T12:38:10.380

@PeterTaylor: thanks, I misread the question (and I didn't think it would count). – Olivier Dulac – 2013-12-02T13:04:27.047

Answers

12

APL (34 30)

(1⍳⍨+/∘.=⍨2|⎕)⊃'ABC',⊂'no one'

Explanation:

  • 2|⎕: read a line of input, take the mod-2 of each number (giving a list, i.e. 1 0 1)
  • ∘.=⍨: compare each element in the vector to each element in the vector, giving a matrix
  • +/: sum the rows of the matrix, giving for each element how many elements it was equal to. If there were two the same and one different, we now have a vector like 2 1 2 where the 1 denotes who was different. If they were all the same, we get 3 3 3.
  • 1⍳⍨: find the position of the 1. If there is no 1, this returns one more than the length of the vector, in this case 4.
  • ⊃'ABC',⊂'no one': display the string at the given index.

marinus

Posted 2013-11-30T21:43:16.453

Reputation: 30 224

Nice, good use of array-oriented programming to compute the index. – FireFly – 2013-11-30T23:54:29.503

8

Mathematica, 45 43 42 41 chars

f="no one"[A,B,C]〚Mod[Tr@#-#,2].{2,1,0}〛&

Example:

f[{0 ,0, 0}]

no one

f[{1, 3, 5}]

no one

f[{2, 3, 5}]

A

f[{2, 3, 4}]

B


Another solution with 43 42 chars:

f=Mod[Tr@#-#-1,2].{A,B,C}/._+__->"no one"&

alephalpha

Posted 2013-11-30T21:43:16.453

Reputation: 23 988

5

Powershell, 65

param($a,$b,$c)"@ABCCBA@"[$a%2+$b%2*2+$c%2*4]-replace"@","no one"

Danko Durbić

Posted 2013-11-30T21:43:16.453

Reputation: 10 241

Thanks. This gave me an idea on shortening my Rock, Paper, Scissors script!

– Iszi – 2013-12-03T00:49:36.417

4

Befunge-98, 61 50 45 characters

&&&:11p+2%2*\11g+2%+:"@"+#@\#,_0"eno on">:#,_

Uses Fors' clever expression to shave off yet a few more characters. Now single-line (i.e. Unefunge-compatible)! Reads until a game is won; add @ at the end for a one-shot program.

Treats input mod 2 as a binary number, as with my JS answer, then relies on lookup for A-C and falls back to 'no one' if out-of-bounds (by testing if the character is ≥'A', which allows me to use nearby code as data :D).

Variation that reads a line of input, produces output, reads a new line of input, etc until a game is decided (i.e. not 'no one'):

&2%4*&2%2*&2%++1g:" "#@-#,_0"eno on">:#,_
 CBAABC

FireFly

Posted 2013-11-30T21:43:16.453

Reputation: 7 107

I ported this to fish for my answer. I noted you. +1 btw – Cruncher – 2013-12-02T16:59:14.817

4

APL, 30

(1+2=/2|⎕)⊃'BA'('C',⊂'no one')

If I am allowed to change system variables by configuration, 2 chars can be shaved off. (Specifically, changing index origin ⎕IO to 0)

The crucial bit

If we represent all odds the same way and all evens the same way, then a pair-wise equality operation can distinguish all 4 cases: 0 0 for B wins, 0 1 for A wins, etc.

Explanation

2|⎕ Takes input and mod 2
2=/ Pair-wise equality
1+ Add 1 for indexing (APL arrays are 1-based by default)

'BA'('C',⊂'no one') Nested array
Picks out the correct element from the nested array

TwiNight

Posted 2013-11-30T21:43:16.453

Reputation: 4 187

3

Ruby, 61 chars

w=0
$*.map{|p|w+=w+p.to_i%2}
$><<%w(no\ one C B A)[w>3?w^7:w]

Darren Stone

Posted 2013-11-30T21:43:16.453

Reputation: 5 072

['no one',?C,?B,?A] == %w(no\ one C B A) (2 chars saved). – daniero – 2014-01-04T00:54:42.173

Nice. Applied that. Thx! – Darren Stone – 2014-01-04T07:56:52.973

3

C: 88 characters

Unfortunately C, as always, requires quite a lot of unnecessary junk. But still, in which other language can one write =**++b+**(++ and it actually means something? Quite simply sublime.

main(int a,char**b){(a=**++b+**(++b+1)&1|2*(**b+**++b&1))?putchar(a+64):puts("no one");}

Simply pass three numbers as arguments, and voilà!

Fors

Posted 2013-11-30T21:43:16.453

Reputation: 3 020

Is the precise order of those preincrements specified? I thought it wasn't... although, you could replace them with *b[1] etc for no size difference (though some loss in elegance.. :( ) – FireFly – 2013-12-01T18:18:55.430

In Ruby: s = "=**++b+**(++" :P in all seriousness, wow, how does that... how does that even work? :O – Doorknob – 2013-12-01T18:23:56.467

@Doorknob it's very clever, but if you substitute the dereferencing and preincrements with indexing b instead, and pretty-print the condition some, you should be able to figure it out. :D (pen and paper also helps, for the resulting truth table) – FireFly – 2013-12-01T19:01:42.283

3

GolfScript (31 chars)

~]{1&}%.$1=!?)'no one
A
B
C'n/=

Very simple logic: reduce the input modulo 2, then sort a copy. The middle item of the sorted array is in the majority, so look for an index which is different (and hence in the minority).

Peter Taylor

Posted 2013-11-30T21:43:16.453

Reputation: 41 901

3

Ruby (function body), 42 chars

Assuming 3 numerical arguments a, b, and c:

['zCBAABCz'[a%2*4|b%2*2|c%2],'no one'].min

Ruby (command line tool), 61 chars

Version 1 comes in at 62 chars:

$><<["zCBAABCz"[$*.reduce(0){|i,n|i*2|n.to_i%2}],'no one'].min

But, by piggybacking off of Darren Stone's answer, Version 2 gets down to 61 chars:

i=0;$*.map{|n|i+=i+n.to_i%2};$><<['zCBAABCz'[i],'no one'].min

Jonathan Hefner

Posted 2013-11-30T21:43:16.453

Reputation: 61

2

JavaScript (node), 87 characters

p=process.argv;console.log("ABC"[3-Math.min(x=p[2]%2*4+p[3]%2*2+p[4]%2,7-x)]||"no one")

To get the ball rolling... expects input as three extra arguments. Makes use of the following pattern for input/output (/ represents "no-one"):

  A B C  res  #
 ───────────────
  0 0 0   /   0
  0 0 1   C   1
  0 1 0   B   2
  0 1 1   A   3
  1 0 0   A   4
  1 0 1   B   5
  1 1 0   C   6
  1 1 1   /   7

FireFly

Posted 2013-11-30T21:43:16.453

Reputation: 7 107

2

Perl, 84 characters.

$x=oct"0b".join"",map{$_%2}<>=~/(\d)/g;print"",('no one','C','B','A')[$x>=4?7-$x:$x]
  • <>=~/(\d)/g parses the input line into distinct digits
  • map{$_%2 takes this list and computes value mod 2 (even or odd)
  • oct"0b".join"", takes this list of mod values, joins them into a string, appends an octal specifier, and converts the string to a number.

Basically what I did was to create a truth table, and then carefully reordered it so I had an inversion operation around $x == 4. So if $x >=4, we did the inversion [$x>=4?7-$x:$x] which we used to index into the array ('no one','C','B','A')

Its not the shortest possible code, but its actually not line noise ... which is remarkable in and of itself.

Perl: 74 characters + 3 flags = 77, run with perl -anE '(code)'

s/(\d)\s*/$1%2/eg;$x=oct"0b".$_;say"",("no one","C","B","A")[$x>3?7-$x:$x]

This is an improvement, by leveraging autosplit (the -a), say (the -E), and finally figuring out what was wrong with the comparison.

Joe

Posted 2013-11-30T21:43:16.453

Reputation: 61

Why >=4 instead of simply >3? +1 for the tips '0b'. I didn't know before – F. Hauri – 2013-12-01T07:46:00.840

I tried both in the debugger ( >3 and >=4), and I am not sure why, but the >=4 worked, but >3 did not. I can't explain it (possibly borked debugger?) to my own satisfaction either – Joe – 2013-12-01T14:23:35.457

you seem to have had an extra char in both counts, which I fixed. Also, flags count as characters. – Doorknob – 2013-12-01T23:27:12.523

2

GolfScript, 36 35 33 characters

~]0\{1&\.++}/'no one
C
B
A'n/.$+=

Takes input as described from STDIN. You can also test the code online.

Howard

Posted 2013-11-30T21:43:16.453

Reputation: 23 109

2

Common Lisp, 114 106 70 chars

From the three values create a pair representing difference in parity between adjacent elements. Treat that as a binary number to index into result list.

(defun f(a b c)(elt'(no_one c a b)(+(mod(- b c)2)(*(mod(- a b)2)2)))))

Older algorithm:

(defun f(h)(let*((o(mapcar #'oddp h))(p(position 1(mapcar(lambda(x)(count x o))o))))(if p(elt'(a b c)p)"no one")))

Paul Richter

Posted 2013-11-30T21:43:16.453

Reputation: 770

2

Python 2, 54

f=lambda a,b,c:[['no one','C'],'BA'][(a^b)&1][(a^c)&1]

TheCrypt

Posted 2013-11-30T21:43:16.453

Reputation: 141

1

Mathematica 100 94 89

f=If[(t=Tally[b=Boole@OddQ@#][[-1,2]])==1,{"A","B","C"}[[Position[b,t][[-1,1]]]],"no one"]&

Testing

f[{5, 3, 1}]
f[{2, 0, 4}]
f[{0, 1, 2}]
f[{0, 1, 3}]
f[{1, 3, 0}]

"no one"
"no one"
"B"
"A"
"C"

DavidC

Posted 2013-11-30T21:43:16.453

Reputation: 24 524

1

Haskell, 97

main=interact$(["no one","A","B","C"]!!).(\x->min x$7-x).foldr(\y x->x*2+mod y 2)0.map read.words

Robin Green

Posted 2013-11-30T21:43:16.453

Reputation: 111

1

R 67

z="no one";c("A","B","C",z,z)[match(2-sum(x<-scan()%%2),c(x,2,-1))]

flodel

Posted 2013-11-30T21:43:16.453

Reputation: 2 345

Interesting! How could I test this? What do I have to run (maybe a shebang?) – F. Hauri – 2013-12-02T01:53:21.540

You'll need to start an interactive R session (e.g. /usr/bin/R) then enter the code above. scan() is what will prompt you for the input: an example would be to type 1[space]3[space]5[space][enter][enter] and you will see the corresponding output (here, no one) printed to the screen. You can download R here: http://cran.r-project.org/mirrors.html

– flodel – 2013-12-02T03:42:24.740

1

C, 85 chars

main(int j,char**p){puts("C\0A\0B\0no one"+((**++p&1)*2+(**++p&1)^(**++p&1?0:3))*2);}

Not as short as my Ruby answer but I'm happy with it, considering the main cruft.

Darren Stone

Posted 2013-11-30T21:43:16.453

Reputation: 5 072

1

Fish - 41

:&+2%2*$&+2%+:"@"+!;$!o :?#"eno on"!;ooo<

Stole FireFly's befunge answer and ported it to fish because using registers in fish allows us to shave off some characters. Lost a few characters on not having the horizontal if operator though.

This takes parameters in through arguments.

python fish.py evenodd.fish -v 2 2 2  
no one
python fish.py evenodd.fish -v 2 3 2  
B
python fish.py evenodd.fish -v 2 3 3  
A
python fish.py evenodd.fish -v 3 3 4  
C

Cruncher

Posted 2013-11-30T21:43:16.453

Reputation: 2 135

Ooooooooooo nice! – F. Hauri – 2013-12-02T16:45:15.677

Hm, fish huh. Do you have trampoline? if so, maybe you could use (the equivalent of) #@...< at the end to save a char. Oh, and your current code looks like 42 chars to me, so decrement that char-count of yours. :) – FireFly – 2013-12-02T18:18:32.457

@FireFly thanks! That did save a char, and you're right, I was over counted by one. My text editor said "col 43" at the end. But of course, cursor on an empty line says "col 1". – Cruncher – 2013-12-02T18:21:53.993

1

Smalltalk, 128 characters

[:c|o:=c collect:[:e|e odd].k:=o collect:[:e|o occurrencesOf:e].u:=k indexOf:1.^(u>0)ifTrue:[#($a $b $c)at:u]ifFalse:['no one']]

send value: with a collection

Paul Richter

Posted 2013-11-30T21:43:16.453

Reputation: 770

1

JavaScript (ES6) / CoffeeScript, 50 bytes

Uses the truth table as per Firefly's answer but takes a more direct approach in character access:

f=(a,b,c)=>'CBAABC'[(a%2*4+b%2*2+c%2)-1]||'no one' // JavaScript
f=(a,b,c)->'CBAABC'[(a%2*4+b%2*2+c%2)-1]||'no one'  # CoffeeScript

Demo

// Translated into ES5 for browser compatibility
f=function(a,b,c){return'CBAABC'[(a%2*4+b%2*2+c%2)-1]||'no one'}

//f=(a,b,c)=>'CBAABC'[(a%2*4+b%2*2+c%2)-1]||'no one'

for(i=6;i--;)
  for(j=6;j--;)
    for(k=6;k--;)
      O.innerHTML += i + ', ' + j + ', ' + k + ' => ' + f(i,j,k) + "\n"
<pre id=O></pre>

rink.attendant.6

Posted 2013-11-30T21:43:16.453

Reputation: 2 776

0

Game Maker Language, 116

My new answer relies heavily on FireFly's formula:

a[1]="no one"a[2]='A'a[3]='B'a[4]='C'return a[(3-min(b=argument0 mod 2*4+argument1 mod 2*2+argument2 mod 2,7-b)||1)]

The old code compiled with uninitialized variables as 0, 183 characters:

a=argument0 mod 2b=argument1 mod 2c=argument2 mod 2if((a&&b&&c)||(!a&&!b&&!c))return "no one" else{if((a&&b)||(!a&&!b))return "C" else{if((a&&c)||(!a&&!c))return "B" else return "A"}}

Edit #1 - Whole different code

Timtech

Posted 2013-11-30T21:43:16.453

Reputation: 12 038

Interesting!? I didn't know this language before! But as this language does permit the use of array, this code seem not to be the smallest possible for this job. – F. Hauri – 2013-11-30T22:19:25.417

@F.Hauri Yes, I'm trying to use arrays to get it shorter. – Timtech – 2013-11-30T22:22:36.157

0

Python 3, 115

l=[int(x)%2for x in input().split()];0if[print("ABC"[i])for i,x in enumerate(l)if l.count(x)%2]else print("no one")

Ramchandra Apte

Posted 2013-11-30T21:43:16.453

Reputation: 189

0

Two different method in two different languages + variations -> 6 answers

There are essentially 2 way for this operation:

  • array based: Built a binary number of 3 digit, than take answer from an array
  • count based: Count even and odd, and look if there is a count == 1

Perl 71 (array based + variation)

s/(.)\s*/$1&1/eg;$==oct"0b".$_;$==$=>3?7-$=:$=;say$=?chr 68-$=:"no one"

One of my shortest perl:

  • s/(.)\s*/$1&1/eg; transform a string like 1 2 3 into 101
  • $==oct"0b".$_; transform binary to oct (same as dec, under 8)
  • $==$=>3?7-$=:$=; if > 3 oper 7-. (From there no one == 0)
  • say$=?chr 68-$=:"no one" if not 0, print char from value, else print no one.

Perl 71 (array based)

s/(.)\s*/$1&1/eg;$==oct"0b".$_;say@{["no one",qw{A B C}]}[$=>3?7-$=:$=]

slightly different in the print step: The output is based on an 'array'.

Perl 81 (count based)

$c=A;map{$a[$_%2]=$c++;$b[$_%2]++}split;say$b[0]==1?$a[0]:$b[0]==2?$a[1]:"no one"

Different meaning:

  • $c=A Initialise a counter c with A.
  • map{$a[$_%2]=$c++;$b[$_%2]++}split Counter b count even and odd, a only store which one
  • say$b[0]==1?$a[0]: if even counter == 1 ? also print even player.
  • $b[0]==2?$a[1]: if even counter == 2 ? also print odd player.
  • :"no one" else print no one.

Bash 85 (array based)

c=$((($1%2)<<2|($2&1)*2+($3%2)));((c>3))&&c=$((7-c));o=("no one" C B A);echo ${o[c]}

This is based on my second perl version:

  • c=$((($1%2)<<2|($2&1)*2+($3%2))) make the index pos.
    • $1%2 transform first arg in binary by using mod
    • $2&1 transform second arg in binary by using and
    • <<2 shift-to-the-left is same than *4
    • *2 multiply by 2 is same than <<1.
  • ((c>3))&&c=$((7-c)) if c >= 4 then c = 7-c.
  • o=() declare an array
  • echo ${o[c]} based on array

Bash 133 (count based)

a[$1&1]=A;a[$2&1]=B;a[$3&1]=C;((b[$1&1]++));((b[$2&1]++));((b[$3&1]++))
case $b in 1)echo ${a[0]};;2)echo ${a[1]};;*)echo no one;esac
  • a[$1&1]=A;a[$2&1]=B;a[$3&1]=C store player into variable a[even] and a[odd]
  • ((b[$1&1]++));((b[$2&1]++));((b[$3&1]++)) count even/odd into b.
  • case $b in 1) echo ${a[0]} in case even counter==1 print even player
  • 2)echo ${a[1]};; case even counter==2 print odd player
  • *)echo no one;esac else print no one.

Bash 133 (count based)

a[$1&1]=A;a[$2&1]=B;a[$3&1]=C;((b[$1&1]++));((b[$2&1]++));((b[$3&1]++))
((b==1))&&echo ${a[0]}||(((b==2))&&echo ${a[1]}||echo no one)

Same version, using bash's condition and command group instead of case ... esac

F. Hauri

Posted 2013-11-30T21:43:16.453

Reputation: 2 654

0

Python 3, 114

r=[0,3,2,1,1,2,3,0][int("".join(map(str,(int(x)%2for x in input().split()))),2)];print("ABC"[r-1]if r else"no one")

Ramchandra Apte

Posted 2013-11-30T21:43:16.453

Reputation: 189

0

Python 3, 80 chars

r=int(input().replace(' ',''),2)
print(['no one','C','B','A'][7-r if r>3 else r])

Note: input must be '1' [odd] or '0' [even]. For example:

> 1 1 0
C
> 1 1 1
no one

Dhara

Posted 2013-11-30T21:43:16.453

Reputation: 749

The challenge requires the input to be "separated by spaces". Perhaps there is a way to effectively golf a split and join so you can still use your (very smart) int(...input...) idea. ? – Darren Stone – 2013-12-02T19:52:57.263

You could remove the '0b'+ I think, at least it looks redundant to me, and just int(input(),2) seems to work in a REPL. – FireFly – 2013-12-03T06:58:41.753

@DarrenStone I used a string replace instead, see edit – Dhara – 2013-12-03T08:31:35.633

@FireFly Thanks, you're right, I edited my answer. I first tested the code with Python 2, where the '0b' was needed. – Dhara – 2013-12-03T08:32:09.280

The challenge also requires the input to accept numbers from 0 to 5. – Peter Taylor – 2013-12-03T10:17:07.973

0

Clojure, 116

(fn[& h](let[a(map #(bit-and % 1)h)](["no one"\A\B\C](+(.indexOf(map(fn[x](reduce +(map #(if(= x %)1 0)a)))a)1)1))))

omiel

Posted 2013-11-30T21:43:16.453

Reputation: 101

0

vba, 116

Function z(q,r,s)
a="A":b="B":c="C":d="no one"
z=Array(d,c,b,a,a,b,c,d)((q And 1)*4+(r And 1)*2+(s And 1))
End Function

call with ?z(1,2,3) or assign to a variable with q=z(1,2,3), or even use as a UDF within excel, and use =z(1,2,3) in your excel formula

SeanC

Posted 2013-11-30T21:43:16.453

Reputation: 1 117

0

Java, 226 chars

void func(int a, int b, int c){
    a = a%2;
    b = b%2;
    c = c%2;
    String out = "B";
    if((a+b+c)==0 || (a+b+c)==3)
        out = "no one";
    else if(a==b)
        out = "C";
    else if(b==c)
        out = "A";
    System.out.println(out);
}

Anurag

Posted 2013-11-30T21:43:16.453

Reputation: 121

0

C 101 96

C, probably the most trivial example (some ternary operations):

main(int v,char** c){(v=c[1]==c[2]?c[1]==c[3]?0:3:c[1]==c[3]?2:1)?puts("no one"):putchar(v+64);}

tasegula

Posted 2013-11-30T21:43:16.453

Reputation: 141