43
\$\begingroup\$

Given a nonempty finite list of integers, output a truthy value if there are exactly two equal entries and all other entries are distinct, and a falsey value otherwise.

Examples

truthy:
[1,1]
[1,2,1]
[1,6,3,4,4,7,9]
 
falsey:
[0]
[1,1,1]
[1,1,1,2]
[1,1,2,2]
[2,1,2,1,2]
[1,2,3,4,5]
\$\endgroup\$
11
  • \$\begingroup\$ I suppose we can't assume that the integers will always be less than 10? \$\endgroup\$ Commented Oct 11, 2017 at 20:17
  • 1
    \$\begingroup\$ Yes except if your language does not support any larger integers. \$\endgroup\$
    – flawr
    Commented Oct 11, 2017 at 20:22
  • 1
    \$\begingroup\$ Can you elaborate what you mean by consistent? \$\endgroup\$
    – flawr
    Commented Oct 11, 2017 at 20:40
  • 34
    \$\begingroup\$ Saw this on the top of HNQ & thought we’d reached the final interpersonal.se question \$\endgroup\$
    – gntskn
    Commented Oct 11, 2017 at 23:15
  • 4
    \$\begingroup\$ @Walfrat Post it as your own challenge. Also such feedback is usually appreciated in the sandbox. \$\endgroup\$
    – flawr
    Commented Oct 12, 2017 at 14:37

56 Answers 56

23
\$\begingroup\$

Python 3, 30 28 bytes

lambda m:len({*m})+1==len(m)

Try it online!

{*m} casts the list to a set object, an unordered list of items without duplicates. Doing this will always decrease the length of the list by the number of duplicates in it. By computing how much the length has changed, we can easily tell if the list had a single duplicate and return the result of the test.

-2 bytes thanks to ovs.

\$\endgroup\$
3
  • \$\begingroup\$ Exactly the solution I had, but forgot about the {*m} shortcut instead of set, well golfed! \$\endgroup\$
    – FlipTack
    Commented Oct 11, 2017 at 20:29
  • \$\begingroup\$ 27 bytes for the negation. (Falsey when it should be Truthy, etc) \$\endgroup\$
    – mbomb007
    Commented Oct 11, 2017 at 21:02
  • 3
    \$\begingroup\$ Here's another weird way to do it (also negation): lambda m:~-len(m[len({*m}):]) \$\endgroup\$
    – mbomb007
    Commented Oct 11, 2017 at 21:06
11
\$\begingroup\$

Husk, 4 bytes

εṠ-u

Try it online!

Explanation

εṠ-u  Implicit input.
   u  Unique elements.
 Ṡ-   Delete them from input, counting multiplicities.
ε     Is the result a singleton list?
\$\endgroup\$
8
\$\begingroup\$

Haskell, 34 bytes

f x=[1|a<-x,b<-x,a==b]==1:1:(1<$x)

Try it online! Based on H.PWiz' answer.

\$\endgroup\$
7
\$\begingroup\$

Jelly, 8 5 bytes

QL‘=L

Try it online!

Explanation

QL‘=L  - Main link, argument L (a list)   e.g [1,6,3,4,4,7,9]
Q      - Deduplicated elements                [1,6,3,4,7,9]
 L     - Length                               6
  ‘    - Increment                            7
    L  - Length of the input                  7 ([1,6,3,4,4,7,9])
   =   - Are they equal?                      1

If the output values can be any consistent values, then QL_L works, which outputs -1 for truthy and any other non-positive number for falsey (thanks @JonathanAllan)

\$\endgroup\$
2
  • \$\begingroup\$ QL_L would output -1 for truthy and some number less than -1 or 0 for falsey (e.g. [1,6,3,4,4,7,9,9,9] would return -3, while [1,6,3,4,7,9] would return 0). \$\endgroup\$ Commented Oct 11, 2017 at 21:01
  • \$\begingroup\$ @JonathanAllan Oh yeah. I guess the examples I tested it on all happened to return -2. \$\endgroup\$ Commented Oct 11, 2017 at 21:06
7
\$\begingroup\$

MATL, 7, 6 bytes

&=sp4=

Try it online!

One byte saved thanks to @Guiseppe!

Explanation:

&=  % Table of pair-wise equality comparisons
    %
    % [1 0 0 0 0 0 0
    %  0 1 0 0 0 0 0
    %  0 0 1 0 0 0 0
    %  0 0 0 1 1 0 0
    %  0 0 0 1 1 0 0
    %  0 0 0 0 0 1 0
    %  0 0 0 0 0 0 1]
    %
s   % Sum each Column. Stack:
    %
    % [1 1 1 2 2 1 1]
    %
p   % Product of the array. Stack:
    %
    % [4]
    %
4=  % Compare the stack to '4'
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Since s is sum and sum sums along the first non-singleton dimension (columns), and the matrix is symmetric, couldn't this just be s instead of Xs? \$\endgroup\$
    – Giuseppe
    Commented Oct 11, 2017 at 21:11
  • 1
    \$\begingroup\$ @Giuseppe Ah, TIL. Thankyou! \$\endgroup\$
    – DJMcMayhem
    Commented Oct 11, 2017 at 21:13
5
\$\begingroup\$

JavaScript (ES6), 30 bytes

a=>new Set(a).size==a.length-1

Try it online

\$\endgroup\$
4
\$\begingroup\$

Pushy, 8 bytes

Simple implementation of checking whether len(set(list)) == len(list)-1:

LtvuL^=#

Explanation:

       \ Implicit: Put all input on stack
Ltv    \ Get the stack length - 1, save in auxiliary stack
u      \ Remove non-unique elements
L      \ Get the new length
^=     \ Compare with the previously saved length
#      \ Print result

This works as the length will only decrease by 1 if there was only exactly 1 non-distinct integer in the initial list.

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Wow, haven't seen a Pushy answer in ages! +1 \$\endgroup\$ Commented Oct 11, 2017 at 21:09
  • 1
    \$\begingroup\$ @cairdcoinheringaahing Pushy will never die. It will only come back stronger. \$\endgroup\$
    – FlipTack
    Commented Oct 11, 2017 at 21:16
4
\$\begingroup\$

Octave, 25 bytes

This is not using a group or unique approach as many of the other answers, but rather the "cartesian product" of all possible comparisions.

@(x)nnz(triu(x==x',1))==1

Explanation

             x==x'        %create a matrix where the entry at (i,j) compares whether x(i) == x(ju)
        triu(x==x',1)     %only consider the strict upper triangular matrix
    nnz(triu(x==x',1))    %count the number of nonzero entries
@(x)nnz(triu(x==x',1))==1 %check whether this number is actually 1

Try it online!

And because no program would be complete without a convolution (thanks @LuisMendo for fixing a mistake):

Octave, 40 bytes

@(x)nnz(~conv(sort(x),-1:2:1,'same'))==1

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You inspired me to come up with this approach :) \$\endgroup\$ Commented Oct 12, 2017 at 7:06
  • 2
    \$\begingroup\$ @StewieGriffin I think the MATL answer used your exact approach:) \$\endgroup\$
    – flawr
    Commented Oct 12, 2017 at 14:27
4
\$\begingroup\$

J, 7 6 bytes

=&#0,=

= check every element for equality with every unique element, creates a matrix with m rows for m unique elements.
0, add an empty row on top.
=&# does the number of rows equal the length of input?

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ I think you can replace .~ with = \$\endgroup\$
    – H.PWiz
    Commented Oct 11, 2017 at 23:13
  • \$\begingroup\$ @H.PWiz Nice, edited. \$\endgroup\$
    – FrownyFrog
    Commented Oct 11, 2017 at 23:46
4
\$\begingroup\$

Retina, 15 12 11 bytes

Thanks to Neil for saving 1 byte.

D`
Mm2`^$
1

Try it online!

Input is linefeed-separated. (The test suite uses comma-separation for convenience.)

Explanation

D`

Deduplicate the lines in the input, which removes any integer that has appeared before (but leaves the surrounding linefeed(s)).

Mm2`^$

Count the number of empty lines, which is equal to the number of duplicates we removed, but only consider the first two matches. So the output will only be 0 (no duplicates), 1 (one duplicate), 2 (two or more duplicates).

1

Make sure that exactly one duplicate was removed.

\$\endgroup\$
5
  • \$\begingroup\$ Save a byte by limiting the newline match to 2, so that the input to the third line is always 0, 1, or 2, simplifying the test. (Annoyingly you can't use A`. to count newlines, because it drops the last one.) \$\endgroup\$
    – Neil
    Commented Oct 12, 2017 at 9:00
  • \$\begingroup\$ @Neil Thanks, the limit is a neat idea. I also tried using A`., but the problem is rather that you can't distinguish a single empty line from having no lines at all. Maybe I should consider terminating A and G output with a linefeed if there are any lines. Although that should probably be an option since I can imagine that linefeed being annoying in other scenarios. \$\endgroup\$ Commented Oct 12, 2017 at 10:38
  • \$\begingroup\$ Matching a single empty line is easy - that's just ^$¶. \$\endgroup\$
    – Neil
    Commented Oct 12, 2017 at 11:58
  • \$\begingroup\$ @Neil No, I mean that the output of A is identical regardless of whether it retains a single empty line or discards all lines. \$\endgroup\$ Commented Oct 12, 2017 at 11:59
  • \$\begingroup\$ Sorry, that's what I meant by "drops the last one" - it returns one fewer empty line, but then you can't distinguish between 0 and 1. \$\endgroup\$
    – Neil
    Commented Oct 12, 2017 at 12:02
4
\$\begingroup\$

R, 32 31 bytes

-1 byte thanks to @JarkoDubbeldam

cat(sum(duplicated(scan()))==1)

Try it online!

Reads from stdin, writes to stdout.

duplicated iterates through the list, replacing the values of l with TRUE if that value occurs earlier in the list, and FALSE otherwise. If there's a unique pair of soulmates, there should be exactly one TRUE value, so the sum should be 1.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ 31 bytes \$\endgroup\$
    – JAD
    Commented Oct 12, 2017 at 19:46
  • 1
    \$\begingroup\$ @JarkoDubbeldam ah, of course. Good to see you again! It's been a while. \$\endgroup\$
    – Giuseppe
    Commented Oct 12, 2017 at 19:48
  • \$\begingroup\$ Been busy with some other stuff, not sure I'm completely back yet. \$\endgroup\$
    – JAD
    Commented Oct 12, 2017 at 20:04
  • \$\begingroup\$ @Giuseppe, I just read this question and immediately thought of your Original Approach.... Very nice! I would have never thought of the scan() approach. \$\endgroup\$ Commented Oct 12, 2017 at 23:15
4
\$\begingroup\$

K (ngn/k), 10 bytes

1=-/#'1?:\

Try it online!

A tacit version of {1=(#x)-#?x}.

  • 1?:\ run a distinct-do-scan for one iteration, returning a two-item list containing the original input and the distinct items of the input
  • #' take the count/length of each item in that list
  • 1=-/ is the difference between the counts one?
\$\endgroup\$
4
\$\begingroup\$

K (ngn/k), 8 bytes

2=*/#'=:

Try it online!

Checks if the product of the counts of unique elements is 2. This works because the only way to get the product of 2 is (1, 1, 1, ..., 1, 2) in some order.

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 4 bytes

{¥_O

Try it online!

Outputs 1 as truthy, any other non-negative integer as falsy. In 05AB1E, 1 is the only truthy number (thanks @Emigna for the insight!).

Explanation

{       Implicit input. Sort
 ¥      Consecutive differences
  _     Boolean negate
   O    Sum. Implicit display
\$\endgroup\$
3
\$\begingroup\$

Ruby, 32 bytes

->(s){s.uniq.length==s.length-1}
\$\endgroup\$
3
  • \$\begingroup\$ Welcome to PPCG! Because this is code golf, you need to include the byte count of your program. I've taken the liberty of doing it for you this time. \$\endgroup\$
    – Pavel
    Commented Oct 12, 2017 at 1:16
  • \$\begingroup\$ How about Array#size? \$\endgroup\$
    – Travis
    Commented Oct 12, 2017 at 21:31
  • \$\begingroup\$ You can get down to 26 bytes by using ->s{s.uniq.size==s.size-1} \$\endgroup\$ Commented May 25, 2018 at 2:35
3
\$\begingroup\$

Pyth, 6 bytes

qtlQl{

Verify all the test cases.

  • l{ - Gets the number of unique elements.

  • tlQ - Gets the length of the input list, decremented.

  • q - Checks equality.

7 bytes

q1l.-Q{

Verify all the test cases

\$\endgroup\$
3
\$\begingroup\$

C# (.NET Core), 35 + 18 bytes

+18 for using System.Linq.

n=>n.Distinct().Count()==n.Length-1

Try it online!

67 byte alternative without Linq:

n=>new System.Collections.Generic.HashSet<int>(n).Count==n.Length-1

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Excel, 42 bytes

Danish language version

=TÆLV(A:A)=SUM(--(FREKVENS(A:A,A:A)>0))+1

Assumes each integer from the list in separate cell in column A.
If we were allowed for inconsistent falsey values, we could save 3 bytes:

=TÆLV(A:A)+SUM(-(FREKVENS(A:A,A:A)>0))

English language version (44 bytes)

=COUNTA(A:A)=SUM(--(FREQUENCY(A:A,A:A)>0))+1
\$\endgroup\$
3
\$\begingroup\$

PowerShell, 40 37 bytes

($args|sort -u).count-eq$args.count-1

Try it online!

The Sort-Object command (alias sort) with the -unique flag pulls out only the unique components of the input. For example, for input @(1,3,3,2), this will result in @(1,2,3).

Thus, we just need to make sure that the .count of this object (i.e., how many elements it has) is -equal to the .count of our input array -1 (i.e., we have exactly one duplicate entry).

Saved 3 bytes thanks to Sinusoid.
Fixed bug thanks to TessellatingHeckler.

\$\endgroup\$
4
  • \$\begingroup\$ Can you use the get-unique alias 'gu' instead of group to reach the same result? \$\endgroup\$
    – Sinusoid
    Commented Oct 12, 2017 at 20:54
  • \$\begingroup\$ @Sinusoid Yes, we can. Thanks! \$\endgroup\$ Commented Oct 13, 2017 at 12:19
  • \$\begingroup\$ This doesn't work on the second test case 1,2,1 - get-unique only works on pre-sorted input. How about ($args|sort -u).count-eq$args.count-1 which is also 37 but does work for all the test cases, if you call it like f 1 2 1 instead of f 1,2,1 ? \$\endgroup\$ Commented Oct 15, 2017 at 23:48
  • \$\begingroup\$ @TessellatingHeckler Ah, good catch. All of the testing I did was with pre-sorted input. Thanks! \$\endgroup\$ Commented Oct 16, 2017 at 12:55
2
\$\begingroup\$

Jelly, 10 bytes

ċ@€`QṢ⁼1,2

Try it online!

a longer but different approach

\$\endgroup\$
2
\$\begingroup\$

Haskell, 37 bytes

f x=sum[1|0<-(-)<$>x<*>x]==2+length x

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Perl 5, 36 + 1 (-a) = 37 bytes

map$k{$_}++,@F;@a=keys%k;say@a+1==@F

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ may be golfed @k{@F}++;say@F==1+keys%k \$\endgroup\$ Commented Oct 12, 2017 at 12:47
2
\$\begingroup\$

05AB1E, 5 bytes

gIÙg-

Try it online!

g     # Get number of elements in input
 IÙg  # Get number of unique elements in input
    - # Subtract

In 05AB1E 1 is the only truthy value, so for a truthy result there must be exactly 1 duplicate element removed by the uniquify.

\$\endgroup\$
2
\$\begingroup\$

Haskell, 37 bytes

f x=sum[1|a<-x,b<-x,a==b]==2+length x

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Octave / MATLAB (with Statistics package / toolbox), 21 bytes

@(x)nnz(~pdist(x))==1

Anonymous function. Input is a column vector. Output is true (displayed as 1) or false (displayed as0).

Try it online!

Explanation

pdist(x) computes a vector of Euclidean distances between all pairs of rows from x. It considers each pair only once (order of the two rows doesn't matter), and doesn't consider pairs formed by the same row twice.

In our case x is a column vector, so Euclidean distance between two rows is just absolute difference between the two numbers.

~ is logical (Boolean) negation, nnz is number of nonzeros, and ==1 compares to 1. So the result is true if and only if there is only one pair that gives zero distance.

\$\endgroup\$
2
\$\begingroup\$

Jq 1.5, 53 25 bytes

length-(unique|length)==1

Inspired by Riley's answer and much shorter then my original solution.

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Julia, 39 26 bytes

!a=sum(a.==a')==endof(a)+2

Explanation

The code generates a 2-dimensional table of booleans, which is then collected using the sum function, counting the number of same-element pairs in the cartesian square of A. Then this is compared to the length of the string plus two, and the quantities are equal only when there is exactly one repeat character.

This code redefines the NOT operator.

\$\endgroup\$
1
  • \$\begingroup\$ !a=sum(a.==a')==endof(a)+2 saves a few bytes. Try it online! \$\endgroup\$
    – Dennis
    Commented Oct 11, 2017 at 23:55
2
\$\begingroup\$

Octave, 23 26 bytes

@(x)prod(sum(x==x'))==4

Try it online!

The x==x' part was inspired by flawr's answer. This is longer than Luis' answer, but it doesn't use any toolboxes.

Explanation:

This is an anonymous function that takes a vector x as input, and compares it to itself transposed. This will give a matrix where all diagonal elements are 1, and any off diagonal elements signals that there are duplicates elements.

The sum along any given column shows how many duplicates there are of that number. We want two of the numbers to have a duplicate, so we two values equal to two, and the rest unequal to two.

If we take the product of this matrix, we'll get 4 if there are only two equal elements (2*2*1*1*1*1*...), and something other than 4 if there are no duplicates, or more than two.

\$\endgroup\$
2
\$\begingroup\$

PHP, 46 bytes

<?=count(array_unique($argv))==count($argv)-1;

Counts the number of entries in $argv and compares it to the number of unique entries. If the former is higher than the latter by 1 then truthy, else falsey.

Try it on eval.in!

\$\endgroup\$
2
  • \$\begingroup\$ Do you have to use the variable name $argv can you not just use $a instead? \$\endgroup\$
    – dading84
    Commented Oct 12, 2017 at 10:44
  • 3
    \$\begingroup\$ @dading84 $argv is the list of command line parameters. So: no, he cannot just use $a. \$\endgroup\$
    – Titus
    Commented Oct 12, 2017 at 11:36
2
\$\begingroup\$

05AB1E, 6 5 bytes

{¥>ΘO

Try it online!

{¥>ΘO   # example input:               [1, 6, 3, 4, 4, 7, 9]
{       # sort                      -> [1, 3, 4, 4, 6, 7, 9]
 ¥      # get deltas                -> [  2, 1, 0, 2, 1, 2 ]
  >     # increment                 -> [  3, 2, 1, 3, 2, 3 ]
   Θ    # truthify (only 1 gives 1) -> [  0, 0, 1, 0, 0, 0 ]
    O   # sum                       -> 1

1 being the only truthy value in 05AB1E, we can stop here. (Thanks @Emigna for pointing that out.)

To get only two distinct values, we can optionally add:

     Θ  # equals 1?                 -> 1
\$\endgroup\$
7
  • 1
    \$\begingroup\$ If it is okay to return any falsey value for the falsey cases, you can skip the Θ, as 1 is the only truthy value in 05AB1E. \$\endgroup\$
    – Emigna
    Commented Oct 11, 2017 at 21:06
  • \$\begingroup\$ @Emigna Thanks! I was not sure whether it was approved by the OP, but I guess it is. \$\endgroup\$
    – Arnauld
    Commented Oct 11, 2017 at 21:52
  • \$\begingroup\$ I'm afraid you need to revert to the previous solution as ¢ will not work. It would count [19,4,4,9] as false and [19,9] as true since it finds the 0 in 10. \$\endgroup\$
    – Emigna
    Commented Oct 12, 2017 at 6:10
  • \$\begingroup\$ @Emigna Thanks for spotting that. I think that's fixed. \$\endgroup\$
    – Arnauld
    Commented Oct 12, 2017 at 11:42
  • \$\begingroup\$ {¥_O should be okay as well. \$\endgroup\$
    – Emigna
    Commented Oct 12, 2017 at 11:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.