18
\$\begingroup\$

Given a finite sequence, each of its elements has a first occurrence. Your task is to output the symbol whose first occurrence is last in the sequence. If the elements represent posts and reposts of memes over time, we want to see the newest meme!

Example

Input: A-BANAL-BANANA-LAB

  • A first occurs at position 0 (it occurs at positions 0,3,5,9,11,13,16)
  • - first occurs at position 1
  • B first occurs at position 2
  • N first occurs at position 4
  • L first occurs at position 6

max(0,1,2,4,6) = 6, so

Output: L

Input/output format

You can assume that the input sequence is nonempty, and is either a string of printable non-whitespace ASCII characters or a list of nonnegative integers in any reasonable form (your choice). You will output one element of the input sequence.

And of course

This is , so the shortest solution in each language wins.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I downvoted because the trivial solution to this is almost the same task as removing duplicates from a list, which is already a task on this site. (Not to say that's the only way, but it's the trivial and usually shortest way.) \$\endgroup\$ Commented Jul 28 at 21:05

39 Answers 39

14
\$\begingroup\$

JavaScript (ES6), 24 bytes

Note that it works because Set is guaranteed to maintain the insertion order of its elements.

s=>[...new Set(s)].pop()

Try it online!

Commented

s =>         // s = input string
[...         // turn into an array ...
  new Set(s) //   ... the set generated from s
             //       e.g. "BANANA" -> Set {'B','A','N'}
]            //
.pop()       // return the last element
\$\endgroup\$
14
\$\begingroup\$

Python, 26 bytes

lambda s:max(s,key=s.find)

Try it online!

Takes a string as input. s.find(c) outputs the first index in s where the character c appears, so using s.find as a key for max returns the character whose first occurrence in s comes latest.

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

APL (Dyalog Vision), 2 bytes

⊇∪

last unique

\$\endgroup\$
6
\$\begingroup\$

Google Sheets, 36 bytes

=chooserows(unique(tocol(A:A,1)),-1)

64 bytes:

=+let(β,A:A,γ,sort(row(β)),sort(β,1=countifs(β,β,γ,"<="&γ),,γ,))

...or:

=chooserows(filter(A:A,1=map(A:A,lambda(β,countif(A1:β,β)))),-1)

Put the array in column A1:A and the formula in cell B1.

screenshot

\$\endgroup\$
3
  • 1
    \$\begingroup\$ For 35 you could be explicit about your range of elements using =INDEX(A:A,MAX(XMATCH(A1:A17,A:A))), and if we assume there is not going to be a pretty much endless string, then for 27 =CHOOSEROWS(UNIQUE(A:A),-2) \$\endgroup\$
    – JvdV
    Commented Jul 28 at 18:06
  • \$\begingroup\$ @JvdV yes... but I don't want to hardcode the range, nor assume that the data never fills the whole sheet down to the last row. \$\endgroup\$ Commented Jul 28 at 19:14
  • \$\begingroup\$ Yeah it feels better your way for sure. 👍 \$\endgroup\$
    – JvdV
    Commented Jul 29 at 6:05
5
\$\begingroup\$

Vyxal, 2 bytes

Ut

Try it Online!

 t # last
U  # unique element
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Answered when the question was on 1 view :D \$\endgroup\$
    – aeh5040
    Commented Jul 28 at 9:52
5
\$\begingroup\$

C (tcc), 57 bytes

k;f(char*s){for(int v[128]={};*s;s++)k=v[*s]++?k:*s;k=k;}

Try it online!

\$\endgroup\$
0
5
\$\begingroup\$

Uiua SBCS, 3 bytes

⊢⇌◴

Try it!

⊢⇌◴­⁡​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌­
  ◴  # ‎⁡deduplicate
⊢⇌   # ‎⁢last
\$\endgroup\$
5
\$\begingroup\$

JavaScript (Node.js), 58 45 38 bytes

s=>[...s].map(a=e=>a[e]?0:a[e]=b=e)&&b

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can use the callback function as your object (38 bytes). \$\endgroup\$
    – Arnauld
    Commented Jul 28 at 20:20
4
\$\begingroup\$

PowerShell, 27 bytes

($args|% *ay|select -u)[-1]

Try it online!

Ungolfed:

($args | ForEach-Object -Member ToCharArray | Select-Object -Unique)[-1]

Converts the input string to a char array by calling the string's member "ToCharArray", then selecting only unique characters, and picking the last char.

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

K (ngn/k), 4 bytes

The last *| unique ? element.

*|?:

Try it online!

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

Brachylog, 2 bytes

dt

Try it online!

Nekomata, 2 bytes

ul

Attempt This Online!

More boring banal nub-tail solutions.

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

Excel ms365, 22 bytes

=@TAKE(UNIQUE(A:A),-2)

enter image description here

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

R 4.4.0, 21 bytes

\(x)tail(unique(x),1)

Attempt This Online!

Takes as input a vector of utf-8 code points. Really not fancy, basically just a port of Arnauld's JS answer (and several others as well).

Although R's base::unique() is not documented to guarantee insertion order, the implementation will do so. It loops through every value of a vector in order and checks if it has been seen before, appending to a new vector any which have not been. While I suppose it's possible this implementation will not remain forever, it will work in R 4.4.0. Also, the git blame indicates this has been part of the R source for 26 years - I don't imagine it would be changed lightly in future versions.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ This is 22 bytes and guaranteed to work \$\endgroup\$
    – Giuseppe
    Commented Jul 31 at 20:00
  • \$\begingroup\$ @Giuseppe I think this is also guaranteed to work isn't it? At least in this and previous versions of R and until they change they R source. Though your approach is really nice. \$\endgroup\$
    – SamR
    Commented Aug 1 at 7:36
  • \$\begingroup\$ Yeah, I think yours will work, but I offer the 22 bytes as an alternative you could include in your answer as well; I can post it as my own as well if you don't want to add it here. \$\endgroup\$
    – Giuseppe
    Commented Aug 1 at 15:29
  • \$\begingroup\$ @Giuseppe it's really nice but I can't take credit for it - it's a pretty different approach to mine I think (and more elegant as a solution) so feel free to post it as your own. \$\endgroup\$
    – SamR
    Commented Aug 1 at 15:41
4
\$\begingroup\$

Perl 5 -MList::Util=uniq -pF, 15 bytes

$_=(uniq@F)[-1]

Try it online!

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

Perl 5 + -0513pF, 22 bytes

-3 bytes thanks to @Xcali!

$\=chop;/${\}/&&redo}{

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Slightly shorter, and doesn't use an additional module like my posted answer: Try it online! \$\endgroup\$
    – Xcali
    Commented Jul 29 at 18:15
  • \$\begingroup\$ Oh amazing work, thank you! Your solution is super clever too, nice - +1! \$\endgroup\$ Commented Jul 29 at 20:19
3
\$\begingroup\$

Python 3, 36 bytes

f=lambda x:list({a:0for a in x})[-1]

Try it online!

\$\endgroup\$
1
  • 7
    \$\begingroup\$ No need for f= here since it's not recursive. Save three using list splatting (list(...) -> [*...]), and another forming the dictionary from the sequence of elements paired with themselves ({a:0for a in x} -> {a:a for a in x} -> dict(zip(x,x))) - TIO \$\endgroup\$ Commented Jul 28 at 15:35
3
\$\begingroup\$

Retina 0.8.2, 8 bytes

D`.
!`.$

Try it online! Takes input as a string. Explanation:

D`.

Keep only the first of each duplicated character.

!`.$

Keep the last remaining character.

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

Haskell + hgl, 5 bytes

gj<nb

Attempt This Online!

Explanation

Nub and get the last element.

Parser, 16 bytes

gk$(h'>~nxy)<*h'

Attempt This Online!

Since this challenge is pretty trivial to do using the normal library, I thought I'd try a parser only version.

Explanation

We create a parser which matches all characters that are not preceded by a copy of themselves.

  • h': Get some prefix.
  • nxy: Parse a character not present in the prefix.
  • h': Parse some number of characters.
  • gk: Get the highest priority parse.

The priority here is determined by h' with the longest parse having the highest priority.

Reflection

The normal version of this can't reasonably be improved. Improvements can be made based on the parser version, but it will never be on par with the other version for this task.

  • gk gets the first complete parse. There should be a parser consumer which just gets the first parse. This would make the <*h' unnecessary and save a bunch of bytes here.
  • (h'*>) and (<*h') could probably use shortcuts. I use the former here. This would be superseded here by the above improvement, but would probably be useful in the long term.
  • I use (h'>~) here and here and the very similar (h_>~) here and here (the latter is now superseded by (h_<~)). There is some sort of common pattern here that seems likely to continue to pop up. I should have shortcuts for a bunch of these variants.

There are also some things I noticed which wouldn't save bytes here but should be done.

  • and nxy could use versions precomposed with my and so.
\$\endgroup\$
3
\$\begingroup\$

Charcoal, 8 bytes

§θ⌈Eθ⌕θι

Try it online! Link is to verbose version of code. Explanation: Turned out to be a port of @xnor's answer.

    θ      Input string
   E       Map over characters
     ⌕     Index of
       ι   Current character
      θ    In input string
  ⌈        Take the maximum
§          Index into
 θ         Input string
           Implicitly print
\$\endgroup\$
3
\$\begingroup\$

MATL, 3 bytes

uJ)

Try it at matl.io

Explanation

     % Implicitly fetch input
u    % Find unique elements 
J)   % Get the last element
     % Print implicitly 
\$\endgroup\$
3
\$\begingroup\$

Setanta, 65 bytes

gniomh(s){le i idir(fad@s-1,-1)ma i<=aimsigh@s(s[i]) toradh s[i]}

try-setanta.ie link

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

Desmos, 26 bytes

f(L)=U[U.count]
U=L.unique

Try It On Desmos!

Try It On Desmos! - Prettified

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

R, 22 bytes

\(x)x[max(match(x,x))]

Attempt This Online!

A 1 byte longer solution than SamR's, but not implementation-dependent.

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

Vyxal 3, 2 bytes

ut

try

  • t last of
  • u unique elements
  • of the input
\$\endgroup\$
2
\$\begingroup\$

Arturo, 15 bytes

$=>[last∪<=&]

running the code in arturo interpreter

Explanation

$=>[]  ; a function where input is assigned to &
last   ; last element of...
∪      ; union between...
<=&    ; input and itself              

This is two bytes shorter than last unique&, but requires the latest version for , hence it won't work online yet.

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

Japt v2.0a0 -h, 1 byte

â

Try it

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

Java 21, 35 bytes

s->new LinkedHashSet<>().getLast()

A Function<List<T>, T> for some T. Requires Java 21 which does not seem to be available yet on Try It Online or Attempt This Online.

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

K (ngn/k), 14 bytes

{x@|/x?!1+|/x}

Try it online!

Explanation

{x@|/x?!1+|/x}
{            } function
       !1+     enumerate from 0 to
          |/x  the max element of the list
     x?        find every element index
   |/          pick the newest element index
 x@            index
\$\endgroup\$
1
  • \$\begingroup\$ 6? \$\endgroup\$
    – ASCII-only
    Commented Aug 5 at 12:18
2
\$\begingroup\$

Stack control, 3 characters:

∪⟄⟸

Explanation:

∪ - union (removes all duplicates)
⟄ - pop last element from array
⟸ - hard shift (removes original array)
\$\endgroup\$
2
\$\begingroup\$

J, 5 bytes

_1{~.

Nothing new.

Attempt This Online!

_1{~.
   ~.   NB. nub removes duplicates
_1{     NB. take the last item
\$\endgroup\$

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.