# Matchmaker, Matchmaker, make me a match

(we won't be finding a Find or catching a tryCatch, though)

This is part two of a multi-part series of implementing some interesting R functions. Part one can be found here.

You are to implement R's match function in as few bytes as possible.

## Input:

• x, a possibly empty list/array of integers
• table, a possibly empty list/array of integers
• nomatch, a single integer value
• incomparables, a possibly empty list/array of integers

## Output:

• a single array/list of integers O of equal length to x, where each value O[i] represents either:
• The index j of the first value in table where table[j]==x[i]
• nomatch, indicating that no value in table is equal to x[i] OR that x[i] is in the list of incomparables.

# Test Cases

All in the form x, table, nomatch, incomparables -> output
outputs

[], [1,2,3], 0,  -> []

[1, 2, 3], [], 0,  -> [0, 0, 0]

[9, 4, 3, 6, 3], [9, 8, 7, 6, 5, 4, 3, 2, 1], -1,  -> [1, -1, 7, 4, 7]

[8, 6, 7, 5, 3, 0, 9], [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6], 1000,  -> [12, 8, 14, 5, 1, 1000, 6]


More test cases can be generated as needed.

• R has 1-based indices, but a consistent alternative-based indices are acceptable. So you can use indices that start at 3 or 17 or whatever, but this must be consistent, and you must indicate this in your answer.
• If you chosen language has a builtin that does this, please also implement your own solution.
• Explanations are appreciated.

This is , so shortest solution in bytes wins!

• Must it support negative numbers? I'll assume it doesn't need to, since only the example assumes it and I'm pretty sure there's a standard rule for it. Jul 11 '19 at 11:01
• @wizzwizz4 no, because 4 is in incomparables, so it can't be matched. If your language can't support negative numbers, then it's fine to require non-negative numbers, but state that assumption in your submission. Jul 11 '19 at 16:03
• Addition to header comment: we also won't be making make. Jul 12 '19 at 21:16
• @val it's actually a pretty bad reference to Fiddler on the Roof; all of these challenges have titled themed after various showtunes because this one fit so perfectly that I thought it would make a good theme. Jul 13 '19 at 15:09

# Jelly,  10  8 bytes

-2 thanks to Erik the Outgolfer

,⁷y⁵iⱮ⁶o


A full program accepting four command line arguments, incomparables nomatch table x which prints a Jelly representation* of the list of R's match function results.

Try it online!

### How?

e.g. with incomparables nomatch table x = [1,4], 2, [2,4], [4,3,2,1,0]:

,⁷y⁵iⱮ⁶o - Main Link: list, incomparables; list, nomatch
⁷       - newline character                                '\n'
,        - pair (incompararables) with (right)              [[1,4],'\n']
⁵     - 5th argument (3rd input = table)                 [2,4]
y      - translate (right) with lookup (left)             [2,'\n']
⁶  - 6th argument (4th input = x)                     [4,3,2,1,0]
Ɱ   - map with:
i    -   first index of (right) in (left)               [0,0,1,0,0]
o - logical OR                                       [2,2,1,2,2]


* An empty list is represented as nothing, a list of lenth one is represented as just the item, while other lists are enclosed in [] and delimited by ,

# R, 83 bytes

function(x,t,n,i)sapply(x,function(a)c(which(a==t/!rowSums(outer(t,i,==))),n))


Try it online!

Avoids match, %in% and setdiff.

• 66 bytes
Jul 12 '19 at 13:24

# R, 55 bytes

In this case, the code doesn't use match with its full functionality, it is just used as an index function. First R answer, so probably incredibly inefficient byte-wise!

Note (thanks to Giuseppe for the info): %in% and setdiff are also both internally implemented using match, so completely getting rid of this surprisingly useful function will result in a mess. Therefore, there is a 150-rep bounty with no deadline for this! (note that setdiff is allowed, though)

function(x,t,n,i)ifelse(x%in%setdiff(t,i),match(x,t),n)


Try it online!

or...

# R, 5 bytes

match


Try it online!

• I'm not sure I could do better although I was eschewing the use of %in% and match; if you want to find a good golfy answer without either of those functions (likely to be horrible), I'll bounty this. Jul 10 '19 at 19:28
• Ah lol, I just commented in golfR about that... Jul 10 '19 at 19:30
• Upvoted solely for the snarky match submission Jul 11 '19 at 18:48
• You can shorten ifelse using this tip: codegolf.stackexchange.com/a/97826/59530
Jul 12 '19 at 13:07
• also, your longer submission actually uses match :S
Jul 12 '19 at 13:07

# Jelly, 9 8 bytes

ṣK¥ƒiⱮo⁶


Try it online!

A full program that takes three arguments: [[table], incomparables], x, nomatch in that order.

# C# (Visual C# Interactive Compiler), 60 bytes

(a,b,c,d)=>a.Select(x=>d.Contains(x)|(x=b.IndexOf(x))<0?c:x)


Try it online!

# Ruby, 44 bytes

Zero-indexed.

->x,t,n,i{x.map{|e|i-[e]==i&&t.index(e)||n}}


Try it online!

# R, 79 bytes

function(x,t,n,i)sapply(x,function(y)if(any(z<-y==t)&all(y-i),which(z),n))


Try it online!

# R, 66 bytes

function(x,t,n,i)sapply(x,function(y)c(which(y==t&all(y-i)),n))


Combining my solution with parts of Nick's solution.

Try it online!

# Japt, 14 bytes

Ë!XøD ©ÒVbD ªW


Try it

# Python 3, 60 bytes

lambda x,t,n,i:[v in{*t}-{*i}and-~t.index(v)or n for v in x]


Try it online!

• What features of this are specific to 3.8? Looks to me like this could work for any subversion of Python 3.
– Theo
Jul 10 '19 at 18:45
• Well, it is not specific to 3.8. I just copy-pasted the auto-generated template on TIO so I didn't notice I used 3.8. Thanks for the heads-up, will adjust. Jul 10 '19 at 18:46
• R has 1-based indices, but a consistent alternative-based indices are acceptable. So you can take out the -~ and just use 0-indexing for -1 bytes. Jul 10 '19 at 18:46
• @ValueInk That fails for the 3rd test case (and in general when a matching element is at the beginning of a list), since 0 is falsy in Python. Jul 10 '19 at 18:48
• Ah, fair show. Incidentally, t.index(v)if v in{*t}-{*i}else n has the exact same bytecount as your current v in{*t}-{*i}and-~t.index(v)or n solution, haha Jul 10 '19 at 18:57

# PowerShell, 63 bytes

param($x,$t,$n,$o)$x|%{($n,$t.indexof($_))[$_-in$t*!($_-in$o)]}


Try it online!

0-indexed

# JavaScript (ES6), 53 bytes

(x,t,n,i)=>x.map(v=>!~i.indexOf(v)*-~t.indexOf(v)||n)


Try it online!

# Perl 6, 45 bytes

->\b,\c,\d{*>>.&{$_∉d&&~b.first($_,:k)||c}}


Try it online!

Anonymous code block that takes input curried, like f(table, nomatch, incomparables)(x) and returns the matches 0 indexed.

### Explanation:

->\b,\c,\d{                               }    # Anonymous code block taking 3 inputs
*           # Return an anonymous Whatever lambda
>>.&{                        }  # Mapping input to
$_∉d # If the element is not an uncomparable && b.first($_,:k)      # Return the first index in the table
~                    # Stringified so Nils are false
||c   # Else the nomatch element
~~

• +1 I worked on this briefly but was doing $_∉d&&b.antipairs.Map{$_}||c which would have worked well but for the falsey value of 0. The first($_:k) is a great solution that avoids the long antipairs.Map coercion. Jul 16 '19 at 11:23 # Charcoal, 14 bytes ＩＥθ∨∧¬№ει⊕⌕ηιζ  Try it online! Link is to verbose version of code. 1-indexed. Explanation:  θ First input (x) Ｅ Map over elements ε Fourth input (incomparables) № Count occurrences of ι Current element ¬ Is zero ∧ Logical And η Second input (table) ⌕ Find 0-based index of ι Current element ⊕ Convert to 1-indexed ∨ Logical Or ζ Third input (nomatch) Ｉ Cast to string Implicitly print on separate lines  # C (gcc), 125 bytes 1-indexed. Given that I can't use a sentinel value in the passed arrays, I need to give the array bounds for each array. f(x,c,t,d,n,i,e,j,f)int*x,*t,*i;{for(;f=0,c-->0;x[c]=--f?n:j){for(j=e;!f&j;x[c]-i[--j]||--f);for(;!f&j<d;x[c]-t[j++]||++f);}}  Try it online! # Attache, 39 bytes ${{[_,y][nil=_or x@_in z]}=>x&Index@_4}


Try it online!

Pretty simple verification. Note that the argument order differs from that of match; specifically, x is the last argument rather than the first, and corresponds to _4 in the above snippet.

## Explanation

${{[_,y][nil=_or x@_in z]}=>x&Index@_4}${                                    }   named lambda, taking parameters x, y, z, and _4
x&Index@_4    short for Index[x, _4];
calculates where each element in _4 occurs in x
returns nil for no match
{                      }=>              over each index:
[_,y][               ]                     choose y (nomatch) if
nil=_                                    the index is nil
or x@_in z                          or the element is in incomparables
_                                         otherwise, choose the index


(t#n)i=map$maybe n id.($zip i[n,n..]++zip t[1..]).lookup


Argument order is: table, nomatch, incomparables, x.

Try it online!

# 05AB1E, 7 bytes

õ:Ik®I:


0-indexed. Inputs are in the order: incomparables, table, x, nomatch.

Try it online.

Explanation:

õ:       # Replace all values of the (implicit) first incomparables-list in
# the (implicit) second table-list with an empty string
#  i.e. incomparables= and table=[9,8,7,6,5,4,3,2,1] → [9,8,7,6,5,"",3,2,1]
Ik     # Get the index of each value in the third x-list in this list (-1 if not found)
#  i.e. x=[9,4,3,6,3] → [0,-1,6,3,6]
®I:  # Replace all -1 with the fourth input-integer
#  i.e. nomatch=-99 → [0,-99,6,3,6]
# (and output the mapped list implicitly as result)