# Find how many ordered pairs of integers share only one digit

Your task is to make the smallest function/program that can, when gives an number N, return/print:

the number of possible choices a, b such that $$\1 \leq a < b < N\$$ and a and b have exactly one common digit in base 10 (there exists a digit, and only one digit, which appears both in a and b, for example 12 and 23, where 2 appears both in 23 and in 12)

note - 1 and 11 count as having exactly one common digit, as 1 is a digit which appears in both of them, and it's the only one that appears in both of them.

You function/program should work for all n from 1 to 1000.

# Test Cases

20 -> 63
40 -> 267
60 -> 575
80 -> 987
100 -> 1503
1000 -> 235431


# Rules

This is a code golf so the lowest score in bytes wins. Good luck!

# J, 39 bytes

1#.[:,1=[:(</*([#@~.@-.-.)&":"0/)~1}.i.


Try it online!

Interestingly, almost exactly the same as Adam's APL answer, though I arrived at it independently. A bit more verbose in J, though... ಥ_ಥ

# APL (Dyalog Extended or 18.0), 24 22 bytesSBCS

Full program.

≢⍸∘.(<∧1=∘≢∘∪∩⍥⍕)⍨1↓⍳⎕


Try it online!

⎕ prompt for N from the console

⍳ first N integers

1↓ drop the first one (0)

⍨ apply the following function using those integers as both left and right argument:

∘.() apply the following function between all combinations of left and right elements:

⍥⍕ stringify (make into character list) both arguments, then:

∩ find the intersection between the character lists

∪ find the Unique elements of that

∘ then:

≢ count that

∘ then:

1= check if that is equal to 1

∧ and

< the left argument is less than the right argument

⍸ find the ɩndices of the trues

≢ count them

• the code doesn't work in tio, it errors. – Command Master Mar 23 at 16:00
• @CommandMaster I hadn't filled in the test cases. Should be all good now. – Adám Mar 23 at 16:09

# 05AB1E, 1514 12 bytes

L¨2.ÆʒÃÙg}g


-2 bytes thanks to @Shaggy.

Explanation:

L           # Push a list in the range [1, (implicit) input]
¨          # Remove the last value to make the range [1, input)
2.Æ       # Get all non-duplicated combinations of size 2 of this list
ʒ      # Filter this list of pairs by:
#  Push them separated to the stack
Ã    #  Only keep the digits of the first number which are also in the second
Ù   #  Uniquify those remaining digits
g  #  Get the length of the remaining digits (only 1 is truthy in 05AB1E)
}g     # After the filter: get the amount of remaining items by taking the length
# (which is output implicitly as result)

• cool! I've found an answer in 05AB1E of 24 bytes – Command Master Mar 23 at 16:02
• Does this approach offer any advantage? I know it's pretty bad right now... – Expired Data Mar 23 at 20:09
• Does 05AB1E not have a way to get combinations of a specified length? – Shaggy Mar 23 at 20:35
• @Shaggy .Æ should do that – Expired Data Mar 23 at 20:58
• @ExpiredData Well, you can remove the s, but apart from that it's still a byte longer I'm afraid. – Kevin Cruijssen Mar 23 at 21:14

# Jelly, 12 bytes

ṖDŒcf/QLƊ€ċ1


A monadic Link accepting a non-negative integer which yields a non-negative integer.

Try it online!

### How?

ṖDŒcf/QLƊ€ċ1 - Link: integer, N   e.g. 1000
Ṗ            - pop (implicit range)    [1,2,3,...,999]
D           - to decimal (vectorises) [,,,...,[9,9,9]]
Œc         - unordered pairs         [[,],[,],...,[,[1,9]],[,],...,[[9,9,8],[9,9,9]]]
€   - for each:                   e.g. [[2,5,2],[2,7,0]]
/       -     reduce by:
f        -       filter keep                [2,2]
Q      -     de-duplicate                 
L     -     length                       1
1 - literal one
ċ  - count occurrences       235431


# Python 2, 77 bytes

lambda n:sum(len(set(a)&set(b))==1for a in range(1,n)for b in range(1,a))


Try it online! Thanks to @SurculoseSputum for translating my Python 3 program into Python 2, helping me golf the v3 and creating a shorter one in Python 2.

## Python 3.8 (pre-release), 99 79 bytes

lambda n:sum(len({*str(a)}&{*str(b)})==1for a in range(1,n)for b in range(1,a))


Try it online!

• 77 bytes – Surculose Sputum Mar 23 at 15:22
• Ugh, I should learn some Python 2..... Thanks @SurculoseSputum! – RGS Mar 23 at 15:23
• Won't len(set(a)&set(b))==1 be true for, say, 22 and 202? – Noodle9 Mar 23 at 15:34
• @Noodle9 yes it will, and that is what the OP means by "sharing a digit", 22 and 202 share the digit 2. – RGS Mar 23 at 15:37
• Ah, ok got it now. – Noodle9 Mar 23 at 15:38

# JavaScript (ES6), 83 bytes

f=(a,b=--a)=>a?--b?!~-new Set((a+[,b]).match(/(.)(?=.*,.*\1)/g)).size+f(a,b):f(a):0


Try it online!

### How?

To test how many distinct digits the integers $$\a\$$ and $$\b\$$ have in common, we concatenate them with a comma in between and apply the following regular expression:

/(.)(?=.*,.*\1)/g

(.)              // a digit in the first integer
(?=           // followed by:
.*         //   some optional digits
,        //   a comma (the separator between the 2 integers)
.*      //   some optional digits
\1    //   the same digit in the 2nd integer


We then turn all matches into a set and test whether its size is exactly $$\1\$$. For golfing reasons, we actually decrement the size and test whether the result is $$\0\$$:

!~-new Set(...).size


When nothing is matched, match() returns null rather than an empty array, which is usually painful to deal with if we want to apply some array method or property to the result. But we don't have to worry about that here because new Set(null) simply generates an empty set, which is what we want.

# Non-recursive, 93 bytes

n=>{for(t=0;--n;)for(b=n;--b;)t+=new Set((n+[,b]).match(/(.)(?=.*,.*\1)/g)).size==1;return t}


Try it online!

# Japt-x, 16 15 bytes

oì à2 Ërf â Ê¶1


Try it

# Wolfram Language (Mathematica), 83 bytes

(t=0;Do[If[Tr[1^Intersection@@IntegerDigits@{i,j}]==1,t++],{i,#-1},{j,i+1,#-1}];t)&


Try it online!

# Java 8, 166 156 bytes

n->{int r=0,a=n,b,i;for(;a-->2;)for(b=a;b-->1;){var s="";for(var t:(a+s).split(s))if((b+"").contains(t)&!s.contains(t))s+=t;r+=s.length()==1?1:0;}return r;}


Try it online.

Explanation:

n->{                    // Method with integer as both parameter and return-type
int r=0,              //  Result-counter, starting at 0
a=n,b,i;          //  Integers a,b,i
for(;a-->2;)          //  Loop a in the range (n, 2]:
for(b=a;b-->1;){    //   Inner loop b in the range (a, 1]:
var s="";         //    Create an empty String
for(var t:(a+s).split(s))
//    Loop over the digits of a:
if((b+"").contains(t)
//     If b contains this digit
&!s.contains(t))
//     and the String doesn't contain this digit yet:
s+=t;         //      Append this digit to the String
r+=               //    Increase the counter by:
s.length()==1? //     If the length of the String is 1:
1             //      Increment the counter by 1
:              //     Else:
0;}           //      Leave the counter the same by increasing with 0
return r;}            //  After the loops, return the counter-integer as result


# Charcoal, 25 bytes

ＩΣＥＮＬΦι∧λ⁼¹ＬΦχ∧№ＩιＩν№ＩλＩν


Try it online! Link is to verbose version of code. Explanation:

   Ｎ                       Input n as a number
Ｅ                        Loop 0<=b<n
ι                    b
Φ                     Loop 0<=a<n
λ                  a
∧                   Is non-zero and
ＬΦχ             Count of digits where
№ＩιＩν       Digit present in b
∧            And
№ＩλＩν  Digit present in a
⁼¹                Equals 1
Ｌ                      Number of matching values
Σ                         Sum of numbers
Ｉ                          Cast to string for implicit print