g | x | w | all
Bytes Lang Time Link
013Japt P250509T165656ZShaggy
031J250512T112856ZGalen Iv
01405AB1E250512T081152ZKevin Cr
049JavaScript ES10250509T102126ZArnauld
146Excel250510T212814ZCalfordM
013Nekomata250512T025436Zalephalp
021K ngn/k250509T152845Zatt
037JavaScript Node.js250511T110650Zl4m2
116Excel250511T095938Zz..
109Google Sheets250511T092506Zz..
037JavaScript ES9250511T090224ZNeil
018Retina 0.8.2250511T085524ZNeil
097Nim250511T055714ZjanAkali
040Ruby p250509T143610ZJordan
010Jelly250509T185234ZJonathan
065Red250509T162928ZGalen Iv
064Haskell250509T140421ZWheat Wi
048Python250509T133308ZAlbert.L
098Python 3250509T130727Zislptng
015Charcoal250509T115333ZNeil

Japt -P, 13 bytes

å+ ËsDðDÌ gJÑ

Try it or run all test cases

å+ ËsDðDÌ gJÑ     :Implicit input of string
å+                :Cumulatively reduce by concatenation
   Ë              :Map each D
    s             :  Slice from index
     Dð           :    0-based indices in D of
       DÌ         :      Last character of D
          g       :    Get the element at 0-based modular index
           J      :      -1
            Ñ     :      Multiplied by 2
                  :Implicitly join and output

J, 31 bytes

[:;((_1-[:{.@}.@I.|.={:)<@{.])\

I'm sure it can be golfed further.

Try it online!

05AB1E, 14 bytes

õIvy¡D¦θõ‚˜«yý

Try it online or verify all test cases.

Explanation:

õ              # Start with an empty string ""
 I             # Push the input
  v            # Pop and loop over its characters `y`:
   y¡          #  Split the string on the stack by the current `y`
     D         #  Duplicate this list
      ¦        #  Remove the first item
       θ       #  Then pop and keep the last string, or [] if the list is empty
        õ‚˜    #  Pair it with an empty string, and flatten
           «   #  Merge this singleton [""] or pair [substring,""] to the list
            yý #  Join it with `y` as delimiter
               # (after the loop, the result is output implicitly)

JavaScript (ES10), 49 bytes

-5 thanks to @l4m2

I/O: arrays of characters.

a=>a.flatMap((c,i)=>a.slice(a[c]-.1||i,a[c]=i+1))

Try it online!

Commented

a =>                // a[] = input array, re-used to store the
                    //       positions of the characters
a.flatMap((c, i) => // for each character c at index i in a[]:
  a.slice(          //   extract from a[]:
    a[c] - .1       //     attempt to use a[c] - 0.1:
                    //     - 1 -> 0.9, which is truthy for the test
                    //       but eventually turned into 0 by slice()
                    //     - undefined -> NaN (falsy)
    || i,           //     or use i if a[c] is undefined
    a[c] = i + 1    //     use i+1 as the ending position
                    //     and set set a[c] to i+1
  )                 //   end of slice()
)                   // end of flatMap()

Excel, (146 characters)

Named Lambda function in Module (no VBA). Assuming lowercase input.

f=LAMBDA(o,CONCAT(MAKEARRAY(1,LEN(o),LAMBDA(r,c,LET(L,MID(o,c,1),b,MAX(IFERROR(FIND(L,LEFT(o,c-1),SEQUENCE(,c-1)),0)),IF(b,MID(o,b,c-b+1),L))))));

This formula gets pasted in the Modules section of the Advanced Formula Environment. It is part of the Excel Labs add on which makes it so much easier to work with complicated formulas and named functions. Install the Excel Labs add-in through the Office Store. If you don’t see the add-in when you type Excel Labs into the Office Store search box, your version of Office may not meet the minimum system requirements. Once you have the formula saved in the Modules, Excel will recognize it as a function when you type =f("challenge") into a cell.

Here it is ungolfed:

LoopBack = LAMBDA(original_word,
    CONCAT(
        MAKEARRAY(
            1,
            LEN(original_word),
            LAMBDA(r, c,
                LET(
                    current_letter, MID(original_word, c, 1),
                    Leftward, LEFT(original_word, c - 1),
                    last_occurence, MAX(
                        IFERROR(SEARCH(current_letter, Leftward, SEQUENCE(, c - 1)), 0)
                    ),
                    snippit, IF(
                        last_occurence,
                        MID(original_word, last_occurence, c - last_occurence+1),
                        current_letter
                    ),
                    snippit
                )
            )
        )
    )
);

Nekomata, 13 bytes

p↔:CĨ→0I→T↔aj

Attempt This Online!

p↔:CĨ→0I→T↔aj
p               Find a prefix of the input
 ↔              Reverse
  :             Duplicate
   C            Split into head and tail
    Ĩ           Find the index of the head in the tail
     →          Increment by 1
      0I        Choose the first index, or 0 if such index does not exist
        →       Increment by 1
         T      Take the first n elements (of the reversed prefix)
          ↔     Reverse
           a    All possible values
            j   Join

I don't really know how it works. The semantics of the built-in I (\if) is not clear, especially when there are multiple levels of non-determinism (p introduces the first level of non-determinism, and Ĩ introduces the second). I just happened to implement the interpreter in a way that it works.

K (ngn/k), 21 bytes

,/{-[1+/2#*=|x]#x}',\

Try it online!

  {              }',\   on each prefix:
          *=|x            positions of current char from end
     1+/2#                1 + second (only one: 1 + 0)
   -[         ]#x         take from end
,/                      join

Also 21:

K (ngn/k), 21 bytes

,/_'/|(*-2#&=)'\|1,\\

Try it online!

                 1,\\   pair input chars with prefixes
  _'/|(      )'\|       drop from each prefix up to:
           &=             positions of char
       *-2#               2nd last (only one: last)
,/                      join

JavaScript (Node.js), 37 bytes

a=>a.replace(/(.)(?<=(\1.+?))/g,'$2')

Try it online!

Excel, 116 bytes

=REDUCE("",SEQUENCE(LEN(A1)),LAMBDA(a,i,LET(c,MID(A1,i,1),a&IFNA(REGEXEXTRACT(LEFT(A1,i-1),".*("&c&".*)",2),"")&c)))

(Port of my Google Sheets answer)

Google Sheets, 109 bytes

Expects input in A1

=REDUCE(,SEQUENCE(LEN(A1)),LAMBDA(a,i,LET(c,MID(A1,i,1),a&IFNA(REGEXEXTRACT(LEFT(A1,i-1),".*("&c&".*)"))&c)))

JavaScript (ES9), 37 bytes

f=
s=>s.replace(/(?<=\2(.*?(.)))/g,"$1")
<input oninput=o.textContent=f(this.value)><pre id=o>

Explanation: Port of my Retina 0.8.2 answer.

Retina 0.8.2, 18 bytes

(?<=\2(.*?(.)))
$1

Try it online! Link includes test cases. Explanation: Uses a lookbehind to find pairs of identical characters and repeat the relevant substring.

The decoder is only 15 bytes:

r`(\2.*?)(.)
$2

Try it online! Link includes test cases. Explanation: Works backwards from the end of the string, finding pairs of identical characters and collapsing the relevant substring.

Nim, 97 bytes

include re
proc(s=""):string=(for i,c in s:(let t=s[0..<i].rfind c;result&=s[[t,i][int t<0]..i]))

Try it online!

Ruby -p, 40 bytes

gsub(/./){(i=$`.rindex$&)?$`[i..]+$&:$&}

Attempt This Online!

Jelly, 10 bytes

0ị⁸ẹ-ị⁸ṫµƤ

A full program that accepts a string argument and prints to stdout.

Try it online!

How?

0ị⁸ẹ-ị⁸ṫµƤ - Main Link: list of characters, S
        µƤ - for each prefix, P, of S:
0ị         -   zero 1-index (circularly) into P
           -    -> C = last character of the prefix
  ⁸ẹ       -   1-indices of occurrences of C in P
    -ị     -   -1 1-index (circularly) into that
           -    -> I = penultimate, or only, 1-index of C in P
      ⁸ṫ   -   tail of P from 1-index I
           - implicit, smashing print

Red, 65 bytes

func[s][forall s[prin copy/part any[find/reverse s s/1 s]next s]]

Try it online!

Haskell, 66 64 bytes

(a:x)!y|(s,t)<-span(/=a)y=x!([e|e<-a:s,t>[]]++a:y)
_!y=reverse y

Attempt This Online!

I'm a bit rusty with the Haskell golf.

Python, 48 bytes

f=lambda x:x and f(z:=x[:-1])+x[z.rfind(x[-1]):]

Attempt This Online!

Python 3, 98 bytes

lambda p:"".join([p[i-p[i-1::-1].find(p[i])-1:i+1]if p[i]in p[:i]else p[i]for i in range(len(p))])

Try it online!

Ungolfed

def albuquerque(p):
    res = ""
    for i in range(len(p)):
        if p[i] in p[:i]:
            q = p[i-1::-1]      # first reverse and then pick the last i-1 characters
            q = q.find(p[i])    # find the first occurence for the letter
            res += p[i-q-1:i+1] # negate q, so that the index of reversed list can be converted back to the original index
        else: res += p[i]
    return res

Try it online!

Charcoal, 15 bytes

⭆θ✂θ⁻κ⊕⌕⮌…θκι⊕κ

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

 θ              Input string
⭆               Map over characters and join
   θ            Input string
  ✂             Sliced from
     κ          Current index
    ⁻           Subtract
       ⌕        Find index of
            ι   Current character in
          θ     Input string
         …      Truncated to length
           κ    Current index
        ⮌       Reversed
      ⊕         Incremented
              κ To current index
             ⊕  Incremented
                Implicitly print