g | x | w | all
Bytes Lang Time Link
052Python 2241111T014628ZLucenapo
041JavaScript ES6241107T102914ZArnauld
063Perl 5 MListUtil=sum pF241107T183600ZXcali
024Charcoal241107T165503ZNeil
01205AB1E241107T110048ZKevin Cr
100Retina 0.8.2241107T101047ZNeil
022Uiua241107T093208Zmousetai

Python 2, 52 bytes

lambda i:i[88614024>>int(`sorted(i)`[2::5])%74%28&3]

Try it online!

This is Arnauld's answer which I translated into Python.

JavaScript (ES6), 41 bytes

Expects an array of 3 integers and returns an integer.

Mapping: 0, 1, 2, 3, 4 → Fire, Soil, Metal, Water, Wood.

a=>a[88614024>>a.sort().join``%37%14*2&3]

Try it online!

Method

Once the input array is sorted in ascending order, there are only 35 possible cases that can be identified with the concatenation of the values:

000, 001, ..., 333, 334, 344, 444

It turns out that it's quite efficient to use a modulo chain on this identifier, combined with a bitmask encoding the position of the answer in the sorted array.

It's worth noting that we may have several possibilities for the position (e.g. for 000 all positions are correct). This potentially allows us to optimize the collisions in the lookup data. But in practice, taking the first matching position is apparently just as good.


JavaScript (ES6), 39 bytes

We can exploit the loose I/O format to save a few bytes. But I don't really like doing so.

Mapping: 0, 2, 4, 6, 8 → Fire, Soil, Metal, Water, Wood.

a=>a[88614024>>a.sort().join``%74%28&3]

Try it online!

Perl 5 -MList::Util=sum -pF, 63 bytes

s;.;$a[5+sum map{($b=($_-$&)%5)==1||-($b==2)}@F]=$&;ge;$_=pop@a

Try it online!

Input as three digits with no spaces:

4   Fire
3   Soil
2   Metal
1   Water
0   Wood

Output uses the same encoding.

Charcoal, 24 bytes

Fθ⊞υ↨E²№θI﹪⁺κ⊕ι⁵±¹§θ⌕υ⌊υ

Try it online! Link is to verbose version of code. Takes input as a string of digits 1-5 representing Wood, Water, Metal, Soil, Fire. Explanation:

Fθ

Loop over each digit.

⊞υ↨E²№θI﹪⁺κ⊕ι⁵±¹

Count the number of times the incremented and double incremented digit appears (modulo 5) in the input string, and take the difference (but the wrong way around, so that the points are negated).

§θ⌕υ⌊υ

Output the digit with the minimum negated points.

05AB1E, 16 14 12 bytes

Σ-5%2LδQÆO}θ

Mapping: Wood=1; Water=2; Metal=3; Soil=4; Fire=5.

Try it online or verify all possible combinations.

Explanation:

Σ          # Sort the (implicit) input-triplet by:
 -         #  Subtract the current value from each value in the (implicit) input
  5%       #  Modulo-5 each (-4,-3,-2,-1,0,1,2,3,4 becomes 1,2,3,4,0,1,2,3,4)
    2L     #  Push pair [1,2]
      δ    #  Apply double-vectorized:
       Q   #   Equals check
           #  (==1 are +1 point cases; ==2 are -1 point cases)
        Æ  #  Reduce each inner-most pair of checks by subtracting
         O #  Sum this triplet together
}θ         # After the sort-by: pop and keep the last/maximum item
           # (which is output implicitly as result)

Retina 0.8.2, 100 bytes

O`.
$
¶$`
T`d`0670`.+$
.
$*_¶
O$^`(_+)(?=¶+\1(_)\b)?((?!(¶+_+)*¶+\1__\b))?
$#2$*1$#3$*
1G`^_{1,5}$
_

Try it online! Takes input as a string of digits 1-5 representing Wood, Water, Metal, Soil, Fire but link is to test suite that converts from and to words for convenience. Explanation:

O`.

Sort the digits.

$
¶$`

Make a copy of the digits.

T`d`0670`.+$

Change 1 and 2 to 6 and 7 and the other copies to 0.

.
$*_¶

Convert to unary.

O$^`(_+)(?=¶+\1(_)\b)?((?!(¶+_+)*¶+\1__\b))?
$#2$*1$#3$*

Sort descending by points plus one ($#3 is 1 if there is no negative action).

1G`^_{1,5}$

Take the first, but take care not to take 6 or 7 by mistake, as they are only used for scoring purposes.

_

Convert to decimal.

Uiua, 22 chars

=⟜/↥×⊃(+1-⊃(↻2|↻1))±/+

Pad Link

Represents the elements as follows:

Fire  ← 0_0_0_0_1
Soil  ← 0_0_0_1_0
Metal ← 0_0_1_0_0
Water ← 0_1_0_0_0
Wood  ← 1_0_0_0_0

Basic explanation:

total = sum(input)
mask = sign(s) # filter non-zero elements
scores = rotate(total, 1) - rotate(total, 2) + 1
masked_scores = scores * mask
max_value = max(masked_scores)
output = max_value == masked_scores