# Lonely Multiplication

Based on this question from Code Review.

Given precisely three positive integers, return the product of all of the distinct inputs. If none of the inputs are distinct, return 1. That is, implement the function:

$$\ f(a,b,c) = \cases{1 & a = b = c \\ a & b = c \\ b & a = c \\ c & a = b \\ a b c & otherwise } \$$

Shortest code in each language wins.

### Test cases

a, b, c -> f(a,b,c)
7, 7, 7 -> 1
3, 3, 5 -> 5
2, 6, 6 -> 2
3, 4, 3 -> 4
1, 2, 3 -> 6
12, 9, 16 -> 1728


# 05AB1E, 3 bytes

¢ÏP


Try it online!

¢       # count occurences of each number
Ï      # keep only those where the count is 1
P     # product (1 if the list is empty)

• I had this exact solution prepared when I saw it in the Sandbox last week. Of course it had to go live yesterday evening, haha. ;) Obvious +1 from me. Feb 11, 2020 at 7:26

# C (gcc), 46 $$\\cdots\$$ 43 42 bytes

Saved 2 bytes thanks to 79037662!!!

f(a,b,c){a=a^b?a^c?b^c?a*b*c:a:b:b^c?c:1;}


Try it online!

• I believe you can use a^c (bitwise xor) to check for equality which is shorter than c==a. Note that you'd have to flip the other parts of the ternary. Feb 10, 2020 at 19:04
• @79037662 Yes, I have thought of that but my head's still spinning from getting this to work! T_T Feb 10, 2020 at 19:20
• Here's a version for 45 bytes, I think it can be reduced further but I'm not sure. tio.run/##S9ZNT07@/… Feb 10, 2020 at 19:37
• @79037662 Well done - we got there! :-) Feb 10, 2020 at 19:52
• @AdamChalcraft gcc uses the same register for the first function parameter and the return value if they're both int. So yes, it's a golf hack to simply assign the return value to the first parameter. Feb 11, 2020 at 9:51

# JavaScript (ES6), 38 bytes

(a,b,c)=>a-b?b-c?c-a?a*b*c:b:a:b-c?c:1


Try it online!

# JavaScript (ES6), 53 bytes

Takes input as [a,b,c].

A=>[[a,b,c]=A,1,a-b?a-c?a:b:c,a*b*c][new Set(A).size]


Try it online!

### Commented

A =>                // A[] = input
[                 // lookup table:
[a, b, c] = A,  //   set size = 0 --> impossible, so use this slot
//   to split A[] into 3 distinct variables
1,              //   set size = 1 --> return 1
a - b ?         //   set size = 2 --> if a is not equal to b:
a - c ?       //     if a is not equal to c:
a           //       return a
:             //     else:
b           //       return b
:               //   else:
c,            //     return c
a * b * c       //   set size = 3 --> return a * b * c
]                 //
[new Set(A).size] // index into lookup table = size of the set

• Thanks for including the second solution. It's way cooler than the fully golfed version. Feb 10, 2020 at 19:32
• For the case where two are the same, a^b^c gives the unique one. That saves 8 bytes in the second version. Feb 11, 2020 at 5:48

# J, 10 bytes

*/@-.}./.~


Try it online!

     }./.~  group by value and remove one from each group
-.       set subtract from input
*/          product

• This is quite nice Feb 11, 2020 at 0:54

# APL (Dyalog), 10 bytes

Thanks to Adám and Bubbler in chat for helping golf this

×/∪*1=⊢∘≢⌸


Try it online!

### Explanation:

×/             ⍝ Reduce by multiplication
∪            ⍝ The unique values of the input
*           ⍝ To the power of
1=         ⍝ Whether one is equal to
≢      ⍝ The length of
⊢∘ ⌸     ⍝ The indexes of each unique element

• These days (18.0+), ×/∪*=Ö≢⌸ works.
Jun 6, 2021 at 4:05

# Python, 48 bytes

lambda l:eval("(%sin[%s,%s]or %s)*"*3%(l*4)+"1")


Try it online!

Takes in a tuple. The idea is similar to an answer in the Code Review question, which can be golfed to:

51 bytes

lambda a,b,c:a**(b!=a!=c)*b**(c!=b!=a)*c**(a!=c!=b)


Try it online!

Each element is included in the product if it's different from the other two, with the power setting to a harmless x**0 == 1 otherwise. We want to avoid writing the three similar terms being multiplied. Python unfortunately doesn't have a built-in list product without imports. So, we turn to eval shenanigans.

We use a longer expression that use logical short-circuiting:

60 bytes

lambda a,b,c:(a in[b,c]or a)*(b in[c,a]or b)*(c in[a,b]or c)


Try it online!

In this expression, the variable names cycle through a,b,c in that order four times. So, by tripling the format string "(%sin[%s,%s]or %s)*" and plugging in the input tuple repeated four times, we get the desired expression. We just need to append a "1" to deal with the trailing multiplication.

• Very nice! I only found the 51 :) Feb 11, 2020 at 5:30
• @FryAmTheEggman so this was it! I had the expression with the powers but I wasn't being able to write it in a short format!
– RGS
Feb 11, 2020 at 8:49

# R, 40 37 bytes

-3 bytes by taking input with scan().

prod(unique(x<-scan())^2,1/x)^!!sd(x)


Try it online!

sd(x) computes the standard deviation (which is 0 iff all entries are equal), so !!sd(x) is TRUE if some entries are different, and FALSE if all are equal.

• if all entries are different, then unique(x)==x, so we are down to prod(x)^1
• if 2 entries are equal, then the corresponding value gets cancelled out between unique(x)^2 and 1/x, so we are left with the sole "lonely" value
• if all 3 entries are equal, then we have (...)^0 which is 1.

This is shorter than anything I could come up with based on table, tabulate, duplicated or rle(sort()).

• I had the obvious 47 bytes with duplicated; I did not even come close to this approach! Feb 10, 2020 at 23:35
• I think I've pipped you to 39 with rle(sort()), don't have the chance to fully bugtest it right now though. Apparently prod(numeric(0)) == 1 so it might be solid: Try it online! Feb 11, 2020 at 14:31
• @CriminallyVulgar The main reason for the difference is that you are using scan() to take input (which is surely fine). With scan(), my solution goes down to 37 bytes: Try it online! Feb 11, 2020 at 14:55
• @RobinRyder I was massively overcomplicating my indexing at the ends, so here's 36: Try it online! Feb 11, 2020 at 15:38
• @CriminallyVulgar Well done! Worth posting separately IMO. Feb 11, 2020 at 16:28

# Jelly,  7  6 bytes

ḟœ-Q$P  Try it online! ### How? ḟœ-Q$P - list, L
$- last two links as a monad: Q - de-duplicate (L) œ- - (L) multi-set difference (that) ḟ - (L) filter discard if in (that) P - product  7s: ĠṖÐḟị⁸P ḟṖƙF$P

• @FryAmTheEggman was it that? Feb 10, 2020 at 21:11
• Basically, just reordered: œ-QɓḟP Feb 10, 2020 at 21:21

f l=product[x|x<-l,filter(==x)l==[x]]


Try it online!

Pretty straightforward -- filter for elements that appear only once and take the product.

# Excel (Version 1911), 80 Bytes, 42 Bytes

=PRODUCT(FILTER(A1#,COUNTIF(A1#,A1#)=1,1))


Input entered as a static column array (e.g. ={1;2;3}) in cell A1

• Saved 38 bytes due to inspiration from Grimmy's 05AB1E solution.
• How about =PRODUCT(IFERROR(UNIQUE(A1#,,1),1))? Jun 5, 2021 at 20:55

# R, 36 bytes

prod((a=rle(sort(scan())))$v[a$l<2])


Try it online!

rle() shows its worth again. Feels like some parentheses could be golfed out somehow.

The fact that prod() of an empty numeric evaluates to 1 is the only reason this is efficient.

# PHP, 7271 bytes

sort($argv);[,$a,$b,$c]=$argv;echo$a-$b?$b-$c?$a*$b*$c:$a:($b-$c?$c:1);


Try it online!

Might be shorter without the sort but nested ternary operator precedence blows my mind.

-1 byte thanks to @640KB

# PHP, 66 bytes

fn($a,$b,$c)=>$a-$c?$a-$b?$b-$c?$a*$b*$c:$a:$b==$c?:$c:$b==$c?:$b;  Try it online! Kudos to @640KB for taming the ternary operator beast! • Think you can -1 byte removing the $n= tio.run/##LcixCoAgEAbgl/kHDR2CXLTwQaLh7ojcFIte/… Feb 13, 2020 at 16:44
• And here's a ternary version without the sort()! tio.run/##Vc9Ba4MwFAfw8/Ip/… Feb 13, 2020 at 17:11
• I think the $b==$c can be reduced down to $b-$c by inverting the ternary truth/false parts. Not sure if my brain can handle it. Feb 13, 2020 at 17:17
• What happens with subtraction is that it changes the order of operations of the chained ternaries and you'd have to put parenthesis around it, so it actually adds one byte. Feb 13, 2020 at 17:19
• though it only works when you want to end with a 1. The subtraction is better for the upper leaves. Feb 13, 2020 at 17:23

# GolfScript, 31 bytes

...{{*}*}:m;m\.|m/-m\.|,1=\1\if


This was... a lot more difficult than I thought it would be. Can be optimized. So much so, that I don't really want to give this much of an explanation.

Here's the process:

Take your input array and make 3 more copies of it. Make a function m, which multiplies the elements in an array together. Do that to the first array, then eliminate dupes from a second (keeping one of each). Perform m on it, then divide it from the first number. You should have the duplicate number (if there's only one pair dupe). Remove it rom your array, then return the last number. If the "suspected dupe" is 1, then just multiply again and output. If, when you remove all of the "suspected dupe"s, you're left with an array of size 1, just output 1 instead.

This was incredibly and probably needlessly complicated, but I couldn't find any good GolfScript shortcuts besides the multiplication bit. PITA.

Try it online, I guess

,1+($args|group|? C* -eq 1|% N*)-join'*'|iex  Try it online! where |? C* -eq 1 means |? Count -eq 1 and |% N* means |% Name. # PowerShell, 45 bytes $p=1;$args|group|? C* -eq 1|%{$p*=$_.Name};$p


Try it online!

• Ah, that's really clever. I was playing around with something similar, but couldn't get it functional. Feb 10, 2020 at 20:28

# Python 3, 6362 61bytes

lambda l:prod(x for x in l if l.count(x)<2)
from math import*


You can try it online!

Thanks @FryAmTheEggman for saving me 1 byte.

• You can use <2 instead of ==1. I also recommend looking through the code review responses - some of them can make for good golfing! :) Feb 10, 2020 at 18:44
• @FryAmTheEggman thanks! Also, you think so? A first glance didn't show me anything very promising. Most answers used a LOT of if/else or imports...
– RGS
Feb 10, 2020 at 18:58
• I actually know there is something shorter :) Yours is different and works for any number of arguments, but you can save bytes by using that there are only 3 inputs! (Since it'll be totally different, if you find one I recommend posting another answer) Feb 10, 2020 at 19:01
• @FryAmTheEggman shaved 1 more byte but still not what you were talking about
– RGS
Feb 10, 2020 at 23:32

# Wolfram Language (Mathematica), 31 bytes

#&@@Times@@Tally@#~Cases~{_,1}&


Try it online!

• #&@@ and {a_,1}->a use the same number of characters to take first but the rule has lower precedence than the infix operator.
– Hood
Feb 11, 2020 at 3:58

# PHP, 92 79 bytes

fn($a)=>array_product(array_keys(array_intersect(array_count_values($a),)));


Try it online!

This isn't going to win for brevity, but just thought I'd try it entirely using chained PHP array functions.

Now using @Guillermo Phillips's suggestion for PHP 7.4 arrow function syntax to save 13 bytes.

# PHP, 66 bytes

fn($a,$b,$c)=>$a-$c?$a-$b?$b-$c?$a*$b*$c:$a:$b==$c?:$c:$b==$c?:$b;  Try it online! And another crazy ternary version inspired by @Guillermo Phillips's answer! • It's a shame because the functions are powerful but verbose. Also, of course you can always use arrow functions: fn($a)=>..., but that's probably beside the point. Feb 13, 2020 at 16:17
• @GuillermoPhillips Yeah, they certainly weren't named for golfing. array_count_values()? Come on guys! I've avoided the PHP 7.4+ short syntax, though I can't think of a good reason why... perhaps it's time. It's a good suggestion because it actually will save a non-trivial number of bytes. Feb 13, 2020 at 16:31

# Burlesque, 24 bytes

psJ{{1j}qfcqpd}M-jNBL[!!


Try it online!

ps     # Parse to list
J      # Duplicate
{
{1j}  # Push 1 & swap
qfc   # Find least common element
qpd   # Product
}M-    # Create array applying each function to make each element
# {{Original list}, 1, least common, product}
jNB    # Remove duplicates from original list
L[     # Find length
!!     # Select that element from the array
# (zero indexed, hence the push swap to fill zero)


# Burlesque, 31 bytes

psJU_qpd{f:{-]1==}fe[~}IEisq1if


Try it online!

Can probably be golfed further.

ps      # Parse to array
JU_     # (Non-destructive) is each element unique?
qpd     # boxed product
{
f:     # Frequency (returns {{count val} ...})
{
-]1== # Count == 1
}
fe     # Find element where
[~     # Take the tail
}
IE      # If unique then product, else find single
q1      # boxed 1
if      # If error, push 1


# Mathematica, 40 bytes

f[l_]:=Times@@(If[Count[l,#]<2,#,1]&/@l)


You can try it online!

# Python 2, 52 bytes

l=input();r=1
for x in l:r*=1%l.count(x)or x
print r


Try it online!

# Bash + GNU utilities, 26

sort|uniq -u|dc -e1?*?*?*p


The 3 input integers are each given on their own line.

In the case of non-distinct inputs, dc warnings are printed to stderr. These may be ignored.

uniq -u does most of the heavy lifting here. With the -u option, only non-duplicated lines are returned. uniq requires its input to be sorted.

The dc expression pushes 1 to the stack, then reads up to 3 integers, multiplying each in turn, then printing the output. If uniq pipes less than 3 integers to dc, then the surplus ? will not add to the stack and the following * will spit out a warning because * needs to pop 2 operands from the stack. But these are just warnings, dc continues execution until it prints the final product.

Try it online!

# C#, 60 bytes

int f(int a,int b,int c)=>a==b?a==c?1:c:a==c?b:b==c?a:a*b*c;

• Hi and welcome to code golf! I edited your submission to include the score, since we require that for all posts. I think you can save some bytes by removing some spaces. Good luck and I hope you enjoy your time here :) Feb 11, 2020 at 19:31

# Perl 6, 27 bytes

{[*] .Bag.grep(0=>1)>>.key}


Try it online!

(Using a Pair as matcher compares only values and ignores the key.)

# TI BASIC, 45 Bytes

Prompt A,B,C
ABC
If A=B
C
If A=C
B
If B=C
A
If A=B and A=C
1
Ans

• I'm not sure that A=sqrt(BC) is what you want...Suppose A=12, B=9, and C=16. Then A=sqrt(BC), but A!=B and A!=C. Feb 12, 2020 at 18:59
• Yeah that might not be as clean as hoped. I think you can also do prod(A={B,C but that comes out to the same bytes as A=B and A=C Feb 12, 2020 at 19:08

# Brachylog, 6 bytes

≡ᵍ~gˢ×


Try it online!

 ᵍ        Group elements by
≡         value.
ˢ     For each group,
~g      if it is a singleton list, extract its only element,
×    Take the product.

• I'm curious about the "select" (meta?)predicate and your explanation. I am having trouble following as the explanation (and my brief glance at the documentation) makes it seem a bit like just a mapping. When/why does it discard results and what does ~g do for non-singleton lists? Jan 31, 2021 at 17:46
• @FryAmTheEggman The difference between xᵐ and xˢ (where x is any predicate) is that, if x fails on any element, xᵐ fails in its entirety, but xˢ discards any and all elements which fail instead. Failing is also what ~g does given a non-singleton list (g wraps its input into a singleton list, ~ inverts it). The utility of failure is backtracking to the most recent choice-point, and ˢ has one internally for that. Jan 31, 2021 at 23:28

# MMIX, 48 bytes (12 instrs)

foo CMP $255,$0,$1 CMP$3,$1,$2
BZ  $255,0F // if(a == b) goto ab BZ$3,1F       // if(b == c) goto bc
CMP $255,$0,$2 BZ$255,2F     // if(a == c) goto ac
MUL $0,$0,$1 // a *= b MUL$0,$0,$2    // a *= c
1H  POP 1,0         // bc: return a
0H  CSZ $2,$3,1     // ab: if(b == c) c = 1
POP 3,0         // return c
2H  POP 2,0         // ac: return b


# PowerShell, 97 bytes

param($n)$a,$b,$c=$n|group;(($n-join'*'|iex),(($a,$b|?{$_.count-eq1}).name,1)[$a.count-eq3])[!$c]  Try it online! Not terribly impressive, but given that PowerShell doesn't have a ternary operator like JavaScript, nor the same for structure as Python, I don't think this is too bad. We take input $n as an array, then feed that into Group-Object, which stores the (potentially) three values into $a,$b, $c. Then we use array-indexing as a pseudo-ternary. We work "backwards" on the function definition given in the challenge, starting from the bottom. If we have a $c, then we have three unique values, so we -join $n with * and iex it (similar to eval). Otherwise, we have at least a duplicate, so we re-index whether $a's .count is -equal to 3. If it is, then all three values are the same, and we output 1. Otherwise, we pull out the lonely value (i.e., its .count is -equal to 1) and output its .name. In any case, the result is left on the pipeline and output is implicit.

# Perl 5-MList::Util=product -apl, 45 44 bytes

@FryAmTheEggman saves a byte

$_=product(grep{$t=$_;2>grep$t==$_,@F}@F)||1  Try it online! # Charcoal, 11 bytes ＩΠＥθ⎇⊖№θι¹ι  Try it online! Link is to verbose version of code. Explanation:  θ Input array Ｅ Map over elements № Count of ι Current element θ In input array ⊖ Decremented ⎇ Ternary ι If count was 1 then original element ¹ Otherwise literal 1 Π Take the product Ｉ Cast to string for implicit print  I found other ways of formulating the condition, but they were all the same length. Alternate approach, also 11 bytes: ＩΠ∨Φθ⁼¹№θι¹  Try it online! Link is to verbose version of code. Explanation:  θ Input array Φ Filter where № Count of ι Current element θ In input array ⁼ Equals ¹ Literal 1 ∨ Or if list is now empty ¹ Then literal 1 Π Take the product Ｉ Cast to string for implicit print  # Retina, 51 bytes N\d+ \b(\d+)(,\1)+\b ~["^.*¶$.("|""]'_L$\d+$&$*  Try it online! Link includes test cases. Explanation: N\d+  Sort the input list. \b(\d+)(,\1)+\b  Delete all duplicated numbers. L\d+  List all the remaining numbers, discarding any commas. $
$&$*


Suffix each number with a *.

|""


Don't separate the numbers.

["^.*¶$.("  Prefix the result with ^.* on its own line and $.( on the same line as the numbers.

]'_


Suffix the result with a _.

~


Evaluate the result on the previous contents of the buffer. This results in one of three evaluations:

1. If all three numbers were identical, it evaluates this:

^.*
$.(_  2. If two numbers were identical, it evaluates this: ^.*$.(5*_

3. If the numbers were distinct, it evaluates this:

^.*
\$.(1*2*3*_


This takes the string _, and repeats it by the remaining numbers in turn, and then takes the length of the result, which is exactly the same as the product of the numbers, or 1 if there were none left.