text:
Enumerate each series of identical numbers in-place
Given a list of strictly positive integers, go through each distinct number and replace all occurrences of it with successive indices (zero or one based) of a new series.
Examples
[] → []/[]
[42] → [0]/[1]
[7,7,7] → [0,1,2]/[1,2,3]
[10,20,30] → [0,0,0]/[1,1,1]
[5,12,10,12,12,10] → [0,0,0,1,2,1]/[1,1,1,2,3,2]
[2,7,1,8,2,8,1,8,2,8] → [0,0,0,0,1,1,1,2,2,3]/[1,1,1,1,2,2,2,3,3,4]
[3,1,4,1,5,9,2,6,5,3,5,9] → [0,0,0,1,0,0,0,0,1,1,2,1]/[1,1,1,2,1,1,1,1,2,2,3,2]

So basically the number of times it has appeared the sequence so far?

@JoKing Yes, that's another way to state it, but "so far" implies zero-based, and "until and including this" implies one-based. I wanted to keep the choice.

JavaScript (ES6), 26 bytes
1-indexed.
a=>a.map(o=x=>o[x]=-~o[x])

Try it online!
Commented
a =>                // a[] = input array
  a.map(o =         // assign the callback function of map() to the variable o, so that
                    // we have an object that can be used to store the counters
    x =>            // for each value x in a[]:
      o[x] = -~o[x] //   increment o[x] and yield the result
                    //   the '-~' syntax allows to go from undefined to 1
  )                 // end of map()

I have no idea how that works, but it sure looks elegant.

I've not seen -~ before - that is an absolute gem.

Alternatively, it's possible to use a to store the values, but it's required to -/~ the index so no byte is saved.

@DaveMongoose Tips for golfing in JavaScript

Too bad this isn't C++, otherwise something like a=>a.map(x=>++(a[-x]|=0)) would save a byte.

@DaveMongoose -~ is actually a commonly used alternative to +1 (since it has different precedence) in many languages

@ASCII-only Thanks for the info. I also like how the bitwise negation bulldozes through undefined

R, 27 bytes
function(x)ave(x,x,FUN=seq)

Try it online!
Explanation :
ave(x,x,FUN=seq) splits vector x into sub-vectors using values of x as grouping keys.
Then seq function is called for each group and each result is re-arranged back in the original group position.
Better see an example :
x <- c(5,7,5,5,7,6)
ave(x, x, FUN=seq) # returns 1,1,2,3,2

 ┌───┬───┬───┬───┬───┐
 │ 5 │ 7 │ 5 │ 5 │ 7 │
 └───┴───┴───┴───┴───┘
   |   |   |    |  |
   ▼   |   ▼    ▼  |
 GROUP A : seq(c(5,5,5)) = c(1,2,3)
   |   |   |    |  |
   ▼   |   ▼    ▼  |
 ┌───┐ | ┌───┬───┐ |
 │ 1 │ | │ 2 │ 3 │ |
 └───┘ | └───┴───┘ |
       ▼           ▼
 GROUP B : seq(c(7,7)) = c(1,2)
       |           |
       ▼           ▼
     ┌───┐       ┌───┐
     │ 1 │       │ 2 │
     └───┘       └───┘

   |   |   |   |   |
   ▼   ▼   ▼   ▼   ▼
 ┌───┬───┬───┬───┬───┐
 │ 1 │ 1 │ 2 │ 3 │ 2 │
 └───┴───┴───┴───┴───┘

Note :
seq(y) function returns a sequence 1:length(y) in case y has length(y) > 1, but returns a sequence from 1:y[1] if y contains only one element.
This is fortunately not a problem because in that case R - complaining with a lot of  warnings - selects only the first value which is incidentally what we want :)

Brilliant! I'll add a bounty for this. Never seen ave before.

I'm honored, thanks a lot ! :)

MATL, 4 bytes
&=Rs

This solution is 1-based
Try it out at MATL Online!
Explanation
Uses [1,2,3,2] as an example
    # Implicitly grab the input array of length N
    #
    #   [1,2,3,2]
    #
&=  # Create an N x N boolean matrix by performing an element-wise comparison
    # between the original array and its transpose:
    #
    #     1 2 3 2
    #     -------
    # 1 | 1 0 0 0
    # 2 | 0 1 0 1
    # 3 | 0 0 1 0
    # 2 | 0 1 0 1
    #
R   # Take the upper-triangular portion of this matrix (sets below-diagonal to 0)
    #
    #   [1 0 0 0
    #    0 1 0 1
    #    0 0 1 0
    #    0 0 0 1]
    #
s   # Compute the sum down the columns
    #
    #   [1,1,1,2]
    #
    # Implicitly display the result

ah, I knew there was an old problem that made me think of something similar, it's Unique is Cheap, and the MATL solution there is one character different!

J, 7 bytes
1#.]=]\

Try it online!
1-indexed.
Explanation:
]\ all the prefixes (filled with zeros, but there won't be any 0s in the input):
   ]\ 5 12 10 12 12 10
5  0  0  0  0  0
5 12  0  0  0  0
5 12 10  0  0  0
5 12 10 12  0  0
5 12 10 12 12  0
5 12 10 12 12 10

]= is each number from the input equal to the prefix:
   (]=]\) 5 12 10 12 12 10
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 1 0 1 0 0
0 1 0 1 1 0
0 0 1 0 0 1

1#. sum each row:
   (1#.]=]\) 5 12 10 12 12 10
1 1 1 2 3 2

K (oK), 11 10 bytes
-1 byte thanks to ngn!
{+/'x=,\x}

Try it online!

Heh, you're happy that I made the data strictly positive…

@Adám Yes, otherwise I'd need to box the prefixes :)

in k: =' -> =

APL (Dyalog Unicode), 7 bytes
Many, many thanks to H.PWiz, Adám and dzaima for all their help in debugging and correcting this.
+/¨⊢=,\

Try it online!
Explanation
The 10-byte non-tacit version will be easier to explain first
{+/¨⍵=,\⍵}

{         } A user-defined function, a dfn
      ,\⍵  The list of prefixes of our input list ⍵
           (⍵ more generally means the right argument of a dfn)
           \ is 'scan' which both gives us our prefixes
           and applies ,/ over each prefix, which keeps each prefix as-is
    ⍵=     Checks each element of ⍵ against its corresponding prefix
           This checks each prefix for occurrences of the last element of that prefix
           This gives us several lists of 0s and 1s
 +/¨       This sums over each list of 0s and 1s to give us the enumeration we are looking for

The tacit version does three things

First, it removes the instance of ⍵ used in ,\⍵ as ,\ on the right by itself can implicitly figure out that it's supposed to operate on the right argument.
Second, for ⍵=, we replace the ⍵ with ⊢, which stands for right argument
Third, now that we have no explicit arguments (in this case, ⍵), we can remove the braces {} as tacit functions do not use them

AWK, 14

1 byte saved thanks to @NahuelFouilleul

{print++a[$1]}

Try it online!
The above does one-based indexing.  If you prefer zero-based indexing, its an extra byte:
{print a[$1]++}

Try it online!

note that second can save one byte {print++a[$1]} without space seems to be working

@NahuelFouilleul Thanks!

Python 2, 48 bytes
lambda a:[a[:i].count(v)for i,v in enumerate(a)]

Try it online!

05AB1E, 4 bytes
ηε¤¢

Try it online!
or as a Test Suite
Explanation
ηε     # apply to each prefix of the input list
  ¤¢   # count occurrences of the last element

BQN, 1 byte
⊒

Try it here!, All tests
I don't know much about BQN, but I learned from this answer that this is a built-in.

C# (Visual C# Interactive Compiler), 44 bytes
x=>x.Select((y,i)=>x.Take(i).Count(z=>z==y))

Try it online!

22 bytes

You have the inversed of the challenge right now.. [7,7,7] should output [0,1,2], and not [0,0,0].

@KevinCruijssen - Thanks :) Looks like I misread things, it should be fixed now.

Ruby, 35 bytes
->a{f=Hash.new 0;a.map{|v|f[v]+=1}}

It's pretty mundane, unfortunately - build a hash that stores the total for each entry encountered so far.
Some other, fun options that unfortunately weren't quite short enough:
->a{a.dup.map{a.count a.pop}.reverse}   # 37
->a{i=-1;a.map{|v|a[0..i+=1].count v}}  # 38

Perl 6, 15 bytes
*>>.&{%.{$_}++}

Try it online!
You can move the ++ to before the % for a one based index.
Explanation:
*>>.&{        }  # Map the input to
      %          # An anonymous hash
       .{$_}     # The current element indexed
            ++   # Incremented

Python 2, 47 43 bytes
f=lambda a:a and f(a[:-1])+[a.count(a[-1])]

Try it online!
A recursive 'one-based' solution.

Jelly, 4 bytes
ċṪ$Ƥ

Try it online!
For each prefix of the input list, it counts the number of occurrences of its last element in itself.

Alternatively the old-school ;\ċ" is also 4.

R, 41 bytes
function(x)diag(diffinv(outer(x,x,"==")))

Try it online!
Oddly, returning a zero-based index is shorter in R.

Once again Giuseppe, your superior knowledge of R has beaten me. I had a decently ingenious method at 60 bytes, but alas, it wasn't enough!

@Sumner18 post it anyway! I always learn a lot from other peoples' approaches, and getting feedback is the fastest way to learn!

thanks for the encouragement! I've posted mine now and am always open to suggestions for improvement!

R, 62 43 bytes
x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z

-19 bytes thanks to Giuseppe, by removing which, and table, and only slight changes to the implementation
Original
x=z=scan();for(i in names(r<-table(x)))z[which(x==i)]=1:r[i];z

I can't compete with Giuseppe's knowledge, so my submission is somewhat longer than his, but using my basic knowledge, I felt that this solution was rather ingenious.
r<-table(x) counts the number of times each number appears and stores it in r, for future reference
names() gets the values of each unique entry in the table, and we iterate over these names with a for loop.
The remaining portion checks which entries are equal to the iterations and stores a sequence of values (from 1 to the number of entries of the iteration)
Try it online!

you can remove the which() to save 7 bytes.

Your use of 1:r[i] gave me the idea to just remove table() entirely: x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z is 43 bytes! This is a nice approach!

Looks like neither of us can compete with digEmAll's R knowledge!

I saw that and was absolutely flabbergasted!

Haskell, 44 bytes
([]#)
x#(y:z)=sum[1|a<-x,a==y]:(y:x)#z
_#e=e

Try it online!
Explanation
Traverses the list from left to right keeping the list x of visited elements, initially []:
For every encounter of a y count all equal elements in the list x.

A bit longer but maybe nevertheless interesting: (#(0*));(x:r)#g=g x:r# \y->0^abs(y-x)+g y;e#g=e Try it online!

@Laikoni: How did you even come up with that, you should totally post it!

Done: https://codegolf.stackexchange.com/a/178629/56433

Haskell, 47 46 bytes
(#(*0))
(x:r)#g=g x:r# \y->0^(y-x)^2+g y
e#g=e

Try it online!
A different approach than BMO's answer which turned out a bit longer. (And kindly borrows their nice test suit.)
The idea is to iterate over the input list and keep track of the number of times each element has occurred by updating a function g. Ungolfed:
f (const 0)
f g (x:r) = g x : f (\ y -> if x==y then 1 + g y else g y) r
f g []    = []

Two interesting golfing opportunities arose. First for the initial value of g, a constant function which disregards its argument and returns 0:
const 0  -- the idiomatic way
(\_->0)  -- can be shorter if parenthesis are not needed
min 0    -- only works as inputs are guaranteed to be non-negative
(0*)     -- obvious in hindsight but took me a while to think of

And secondly an expression over variables x and y which yields 1 if x equals y and 0 otherwise:
if x==y then 1else 0  -- yes you don't need a space after the 1
fromEnum$x==y         -- works because Bool is an instance of Enum
sum[1|x==y]           -- uses that the sum of an empty list is zero
0^abs(x-y)            -- uses that 0^0=1 and 0^x=0 for any positive x
0^(x-y)^2             -- Thanks to  Christian Sievers!

There still might be shorter ways. Anyone got an idea?

You can use 0^(x-y)^2.

Java (JDK), 76 bytes
a->{for(int l=a.length,i,c;l-->0;a[l]=c)for(c=i=0;i<l;)c+=a[l]==a[i++]?1:0;}

Try it online!
Credits

-2 bytes thanks to Kevin Cruijssen

-2 bytes by changing for(c=0,i=l;i-->0;)c+=a[l]==a[i]?1:0; to for(c=i=0;i<l;)c+=a[l]==a[i++]?1:0;.

bash, 37 24 bytes
f()(for x;{ r+=$[a[x]++]\ ;};echo $r)

TIO
if valid, there is also this variation, as suggested by DigitalTrauma
for x;{ echo $[a[x]++];}

TIO

Pass the list as command line args - https://tio.run/##S0oszvj/Py2/SKHCuporNTkjX0ElOjG6IlZbO5ar9v///8b/Df@bALHpf8v/Rv/NgLQxiA0A - only 24 bytes.

@DigitalTrauma, thanks however i don't know if it broke the rules. also as it was asked to replace list and maybe should be something like https://tio.run/##NUtLCoMwFNz3FFPJIkEKJtrWEgIuvUPIIpWKBVGILoSQs9skUB7z5sPM227TeY6UefSKMjmvg51xW@AU4RLj6nDgu4D4q9OdCdLD6cMoonudhClLI4MM577tlMHDKko6FpewEp9hWlEQb9O0kAiXWEtAIzI902XFK4gKdZXNHVykJP0kcihil6ON3P4553V0TcQdr5g9ItdJnz8

@NahuelFouilleul It's fine, full programs are allowed too, and that's a valid method of inputting/outputting a list (IMO)

Tcl, 48 bytes
proc C L {lmap n $L {dict g [dict inc D $n] $n}}

Try it online!

Ruby, 34 bytes
->a{r=[];a.map{|x|(r<<x).count x}}

Try it online!

I can't believe I tried ->a{i=-1;a.map{|v|a[0..i+=1].count v}} and didn't think of just building a new array, lol. Nice work.

Perl 5, 11 bytes
$_=$h{$_}++

TIO
explanations following comment

$_ perl's  special variable containing current line when looping over input (-p or -n switches)
$h{$_}++ autovivifies the map %h and creates an entry with key $_ and increments and gives the value before increment
the special variable is printed because of -p switch, -l switch removes end of line on input and adds end of line on output

That looks amazing. Care to explain?

@Adám, thank you for your feedback, sure, done

C (gcc), 65 62 bytes
c,d;f(a,b)int*a;{for(;c=d=b--;a[b]=d)for(;c--;d-=a[c]!=a[b]);}

Try it online!
-2 bytes thanks to ASCII-only

This felt too straightforward, but I couldn't seem to get any shorter with a different approach.

63

@ASCII-only is this a valid answer? No header included, no declarations, it's a snippet plus many warnings although it outputs.

@AZTECCO warnings are fine (stderr is ignored), as long as it does what it should it's acceptable. note that this is a function declaration, plus some variable declarations - you can put it anywhere as a top level expression and it will compile fine. a lot of c answers (and those in languages with less strict syntax) do generally have quite a few warnings because of bytesaves that aren't good code style

Ok I can understand, but there's still something not right to me. If we want to test with a different set(in size) we have to modify the code, even in the print loop, plus the input should be just the set, not its size."Given a list of strictly positive integers..." so I think input should be just the list.

@AZTECCO not sure if this discussion should belong in this answer's comments, but you might want to take a look at meta - specifically on I/O and answer formats.

Ok thank you both two for helping me understand the rules here at codegolf. Short solution btw!+1

Pari/GP, 32 bytes
a->p=0;[polcoeff(p+=x^t,t)|t<-a]

The \$k\$-th element in the answer is the coefficient of the \$x^{a_k}\$ term in the polynomial \$\sum_{i=1}^kx^{a_i}\$.
Try it online!

Wolfram Language (Mathematica), 21 bytes (@att)
_g=g/@#-(--g[#]&/@#)&

Try it online!

Wolfram Language (Mathematica), 28 bytes
(Clear@g;g@a_=0;++g[#]&/@#)&

Based on @att's answer to another challenge.
Try it online!

Wolfram Language (Mathematica), 32 bytes
-1 byte thanks to @att.
Accumulate[p=x^#]~Coefficient~p&

The \$k\$-th element in the answer is the coefficient of the \$x^{a_k}\$ term in the polynomial \$\sum_{i=1}^kx^{a_i}\$.
Try it online!

-1 byte on the first, and -2 bytes on the second

Roman had a good insight that saves -2 bytes on the second, and probably all other answers that used Clear as well.

I just realized that this specific golf isn't actually valid here (nor on your AoCG17; I'm not sure about your AoCG16), since the function won't be reusable on the same input. Sorry about that, I jumped the gun.

24 on the second

_g=0Clear@g could've saved 1 otherwise

21

Attache, 23 bytes
{`~&>Zip[_,_[0:#_::0]]}

Try it online!
Explanation
{`~&>Zip[_,_[0:#_::0]]}
{                     }    _: input (e.g., [5, 12, 10, 12, 12, 10])
             0:#_          range from 0 to length of input (inclusive)
                           e.g., [0, 1, 2, 3, 4, 5, 6]
                 ::0       descending range down to 0 for each element
                           e.g., [[0], [1, 0], [2, 1, 0], [3, 2, 1, 0], [4, 3, 2, 1, 0], [5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]
           _[       ]      get input elements at those indices
                           e.g., [[5], [12, 5], [10, 12, 5], [12, 10, 12, 5], [12, 12, 10, 12, 5], [10, 12, 12, 10, 12, 5], [nil, 10, 12, 12, 10, 12, 5]]
     Zip[_,          ]     concatenate each value with this array
                           e.g., [[5, [5]], [12, [12, 5]], [10, [10, 12, 5]], [12, [12, 10, 12, 5]], [12, [12, 12, 10, 12, 5]], [10, [10, 12, 12, 10, 12, 5]]]
   &>                      using each sub-array spread as arguments...
 `~                            count frequency
                               e.g. [12, [12, 10, 12, 5]] = 12 ~ [12, 10, 12, 5] = 2

K (ngn/k), 18 bytes
(,/.!'#'=x)@<,/.=x

Try it online!

OLD APPROACH
K (ngn/k), 27 23 22 bytes
{x[,/.=x]:,/.!'#'=x;x}

Try it online!

this is not pretty... quick and dirty solution, i will be refining this later when i get the chance to think of a better approach
explanation:

=x returns a dict where keys are items of x and values are their indices (3 1 4 5 9 2 6!(0 9;1 3;,2;4 8 10;5 11;,6;,7))
i: assign dict to i
#:' count values for each key (3 1 4 5 9 2 6!2 2 1 3 2 1 1)
!:' enumerate each value (3 1 4 5 9 2 6!(0 1;0 1;,0;0 1 2;0 1;,0;,0))
,/.: extract values and flatten list (0 1 0 1 0 0 1 2 0 1 0 0)
x[,/.:i]: extract indices from i, flatten, and assign each value from the right-side list at these indices

annoyingly, the list is updated but a null value is returned by the assignment, so i need to return the list after the semicolon (;x)
edit: removed extraneous colons
edit2: removed unnecessary assignment

Vyxal, 4 bytes
KƛtO

Try it Online!
KƛṫO is also valid for 4 bytes
Simply count the number of occurrences of the tail of each prefix in each prefix.

Factor, 48 bytes
[ dup [ head [ = ] with count ] with map-index ]

Try it online!

Husk, 4 bytes
z#ḣ¹

Try it online!
Explanation
one-indexed
z#ḣ¹  transforms to z#ḣ⁰⁰
z     zip
  ḣ⁰  prefixes of input
    ⁰ and input
 #    with count

PowerShell Core, 25 bytes
$t=@{}
$args|%{(++$t.$_)}

Try it online!

Retina 0.8.2, 30 bytes
\b(\d+)\b(?<=(\b\1\b.*?)+)
$#2

Try it online! Link includes test cases. 1-indexed. Explanation: The first part of the regex matches each integer in the list in turn. The lookbehind's group matches each occurrence of that integer on that line up to and including the current integer. The integer is then substituted with the number of matches.

Batch, 61 bytes
@setlocal
@for %%n in (%*)do @set/ac=c%%n+=1&call echo %%c%%

1-indexed. Because variable substitution happens before parsing, the set/a command ends up incrementing the variable name given by concatenating the letter c with the integer from the list (numeric variables default to zero in Batch). The result is then copied to another integer for ease of output (more precisely, it saves a byte).

Japt, 8 bytes
£¯YÄ è¶X

Try it here
£¯YÄ è¶X
             :Implicit input of array U
£            :Map each X at 0-based index Y
 ¯           :  Slice U to index
  YÄ         :    Y+1
     è       :  Count the elements
      ¶X     :    Equal to X

awk 46 31 bytes
-15 bytes thanks to @Dennis
{for(;i++<NF;)$i=a[$i]++;print}

TIO

I think {for(;i++<NF;)$i=a[$i]++;print} works. delete(a); is only needed for the test suite, no?

@Dennis, thank you for your feedback, however DigitalTrauma's version is still shorter

Haxe, 58 bytes
l->{var x=[0=>0];l.map(e->++x[(x[e]==null?x[e]=0:0)+e]);};

(Requires arrow functions, so 4.0+)
var x=[0=>0] declares a new IntMap, with 0 as its only key (since the question say inputs are strictly positive). Unfortunately most targets throw when adding null to a number, hence the explicit check to make sure each key is in the map before incrementing.
Also a cheeky rip off based on the JS answer:
Haxe (JS target), 41 bytes
l->{var x=[0=>0];l.map(e->x[e]=-~x[e]);};

Try both online

GO 121 Bytes (Not included new lines and tabs)
func cg(a []int) []int{
    var m = make(map[int]int)
    var r = make([]int, len(a))
    for i,v := range a{
        r[i] = m[v]
        m[v]++
    }
    return r
}

Accepts integer array and returns integer array.

Welcome to PPCG. Rare to see Go represented here. You do need to count necessary newlines, but you also have a lot of spaces that can be removed, and you can also shorten cg to c. I recommend using TIO to generate the main part of your post: Try it online!

Python 2, 44 bytes
a=[]
for x in input():print a.count(x);a+=x,

Try it online!
The first thing I wrote tied Chas Brown's 43, so here's a different solution that's one byte longer.

Reticular, 17 bytes
L[ddc@c~]~*$qlbo;

Try it online!
The input list of integers is assumed to already be pushed to the stack. Run the following code to test input:
'2''7''1''8''2''8''1''8''2''8'lbL[ddc@c~]~*$qlbo;

Explanation
The pop instruction c which is supposed to: pop a list from the stack, pop the last element from that list and push this element to the stack. However, if the list occurs at more than 1 place in the stack (if it has been duplicated for example), all of the duplicated lists in the stack will also have their last element popped contrary to what one might think will happen. This is fortunately used in our favor in this puzzle.
L                 # Push length of input list to the stack.
 [      ]         # Push the following function:
  dd              # Duplicate top of stack twice.
    c             # Pop the list at top of the stack,
                    pop the last element in the list (which will pop the element of every list!)
                    and finally push it to the stack.
     @c           # Pop two items at the top of the stack (list + last element in that list).
                    then push the number of occurrences of that element in the list.
       ~          # Swap top two items in the stack (so that the popped list is on top again).
         ~        # Swap top two items in the stack.
          *       # Call the above function the same number of times as length of the input list.
           $      # Remove the item at the top of the stack (which by now is an empty list).
            q     # Reverse stack.
             lb   # Push size of stack and put that many items from the stack into a list.
               o; # Output resulting list and exit.

SNOBOL4 (CSNOBOL4), 63 bytes
 T =TABLE()
R I =INPUT :F(END)
 T<I> =OUTPUT =T<I> + 1 :(R)
END

Try it online!

C++ (gcc), 122 bytes
#import<vector>
using V=std::vector<int>;V f(V x){for(int i,t,z=x.size();t=i=z--;x[z]=t)for(;i--;)t-=x[z]!=x[i];return x;}

Try it online!
Saved 2 more bytes thanks to @ceilingcat

C# (.NET Core), 172 bytes
Without LINQ.  0 indexed int[] arrays.
p=>{int h=0,m=0,l=p.Length,j;var k=new int[l];if(l>0){foreach(int z in p){h=z>h?z:h;m=z<m?z:m;}for(j=m;j<=h;j++,m=0)for(int z=0;z<l;z++)k[z]=p[z]==j?m++:k[z];}return k;}

Try it online!

Gema, 32 characters
<D>=@set{$1;@add{${$1;};1}}${$1}

Outputs 1 based indexes.
Sample run:
bash-5.0$ gema '<D>=@set{$1;@add{${$1;};1}}${$1}' <<< '[5,12,10,12,12,10]'
[1,1,1,2,3,2]

Try it online!
Gema, 34 characters
<D>=${$1;0}@set{$1;@add{${$1;};1}}

Outputs 0 based indexes.
Sample run:
bash-5.0$ gema '<D>=${$1;0}@set{$1;@add{${$1;};1}}' <<< '[5,12,10,12,12,10]'
[0,0,0,1,2,1]

Try it online!

Pyth, 7 bytes
.e/<Qkb

Try it online!
.e     Q # enumerated map over (implicit) Q (input): lambda k,b: (k=index, b=element)
  /   b  # number of occurences of b in
   <Qk   # Q[:k]

Alternative 1-based solution (7 bytes)
m/ded._

Try it online!
m    ._ # map over all prefixes of (implicit) Q (input): lambda d:
 / ed   # Number of occurences of d[-1] in
  d     #                                  d

SAP ABAP, 174 bytes
FORM f TABLES t.DATA r TYPE int_tab1.LOOP AT t.DATA(i) = 0.DATA(x) = sy-tabix.LOOP AT t.CHECK:sy-tabix < x,t = t[ x ].i = i + 1.ENDLOOP.APPEND i TO r.ENDLOOP.t[] = r.ENDFORM.

Subroutine which takes a table of integers and replaces all values with zero-based indices. ABAP has no array type, so a table of integers is the closest thing we have. It uses the builtin table type int_tab1 to save some bytes over declaring TYPE TABLE OF i and abuses obsolete (but still functional) internal tables with header lines, which allows us to use LOOP AT t and read t at the implicit index sy-tabix without declaring additional variables for keeping the value.

Full program with some test cases from OP can be found here. Output below:

Forgot to add the two edge cases of [ ] and [42], but they work, too:
[ ] => An empty input table stays empty as the outer loop gets skipped completely
[42] => A single value in the table means table line 1 in the inner loop is skipped, since sy-tabix is equal to x - therefore i stays 0 and the output is [0].

Explanation:
FORM f TABLES t.              "Subroutine, TABLES parameters are references
  DATA r TYPE int_tab1.       "A temporary internal table for results
  LOOP AT t.                  "Go over each line in table t
    DATA(i) = 0.              "Set count to 0            (inline declaration)
    DATA(x) = sy-tabix.       "Set x to current index    (inline declaration)
    LOOP AT t.                "Go over each line in table t again
      CHECK:                  "Check whether... (works like a CONTINUE if not true)
        sy-tabix < x,         "1) ...inner LOOP index is smaller than outer index (= only check lines up to outer index - 1)
        t = t[ x ].           "2) ...value of t at inner index (implicit) is equal to value of t at outer index (x)
      i = i + 1.              "If both are true, increase the counter by 1
    ENDLOOP.
    APPEND i TO r.            "Add the count for this value to temporary results table
  ENDLOOP.
  t[] = r.                    "Fill referenced table t with the values in r.
ENDFORM.

Go, 85 bytes
package main
func main(){
m:=make(map[int]int)
for i,n:=range a{
a[i]=m[n]
m[n]++
}
}

Create a map to store the count, loop through input list (a), replacing each item with the count for that item before incrementing.

[APL (Dyalog Unicode)], 13 bytes
(+/⊃⍷⊢)⍤⌽¨,\⎕

Thunno 2, 4 bytes
ƒıṪc

Try it online!
Explanation
ƒıṪc  # Implicit input
ƒ     # Get the prefixes of the input list
 ı    # Map over this list of lists:
  Ṫ   #  Remove the last item and push it separately
   c  #  Count the occurrences of this letter
      # Implicit output


text:
An Séimhiú agus an tUrú
An Séimhiú agus an tUrú
In Irish Gaelic (Gaeilge) there are a number of ways that the start of a word can be changed. The most common of these are lenition (an séimhiú) and eclipsis (an t-urú)
Lenition involves adding the letter h as the second letter. For example, the word "bean" (woman) would be lenited to "bhean".
Eclipsing adds a prefix to the word. The prefix is determined by the first letter of the word. For example, the word "capall" (horse) starts with a c. Its eclipsis is g. So when the word "capall" is eclipsed it becomes "gcapall".
Challenge
Write a function or program that takes a word and returns both its lenited and eclipsed forms.
Lenition
Only words beginning with:
b
c
d
f
g
m
p
s
t

are lenited. Words beginning with other letters are not changed.
Some examples:
bean       bhean
capall     chapall
Sasana     Shasana
lón        lón
Ífreann    Ífreann

Eclipsis
If a word starts with any of the following letters, it is prefixed by its respective eclipsis:
Letter   Eclipsis
b        m
c        g
d        n
f        bh
g        n
p        b
t        d

Words that don't start with those letters remain unchanged.
Examples:
bean        mbean
capall      gcapall
cailín      gcailín
doras       ndoras
fuinneog    bhfuinneog
Gaeilge     nGaeilge
Sasana      Sasana

There are other changes that can happen to the start of a word, but we'll just focus on these ones.
Rules
The input is only one word. Words will only contain a-z, A-Z or the fada vowels á, Á, é, É, í, Í, ó, Ó, ú and Ú.
To make it a bit more simple the word itself doesn't necessarily need to be an Irish word, just that it is treated like one in the code. So inputting delta should return dhelta and ndelta.
For this challenge you can assume that the input words have not already been lenited or eclipsed (in Irish, a word is only lenited or eclipsed once. You would never end up with "bhhean" or "ngcapall").
Standard rules apply, including the default I/O rules. Similarly, default loopholes are forbidden.
Finally, this is code-golf so shortest answer in bytes wins.
Test cases
Input      Lenited     Eclipsed
bean       bhean       mbean
capall     chapall     gcapall
fuinneog   fhuinneog   bhfuinneog
Sasana     Shasana     Sasana
Gaeilge    Ghaeilge    nGaeilge
lón        lón         lón
áthas      áthas       áthas
Ífreann    Ífreann     Ífreann

Sandbox post.

what does the title mean?

@Giuseppe I think it means lenition and eclipsis. Now, the special thing about Gaelic, is that it's hard to understand even once translated into English. :p

@Arnauld Google Translate gives "The Lenition and the Turu" for the first time and "The Sharing and the Substance" afterwards... "agus" translates to "and".

"(The) Lenition and (the) Eclipsis". I'm not a fluent speaker, so I don't know if it's correct to specify them with the definite article (an). Séimhiú is lenition and urú is eclipsis. In the title Urú takes a 't' at the start, because it starts with a vowel and is preceded by the definite article. When it's a capital letter there's no hyphen between them. Hence: "There are other changes that can happen to the start of a word, but we'll just focus on these ones."

JavaScript (ES6),  98  97 bytes
Returns an array [lenited, eclipsed].
s=>[(x=[...'2n1111gbnd1m1','bh',2][parseInt(c=s[0],30)*17%22])>'1'?c+'h'+s.slice(1):s,x>{}?x+s:s]

Try it online!
How?
We define the following lookup table:
A = [ ...'2n1111gbnd1m1', 'bh', 2 ]

//     0    1    2    3    4    5    6    7    8    9    10   11   12   13  14
A = [ '2', 'n', '1', '1', '1', '1', 'g', 'b', 'n', 'd', '1', 'm', '1', 'bh', 2 ]

where:

a single character (or the string "bh") is used for eclipsis; all letters that trigger eclipsis also trigger lenition
\$1\$ means that there's no eclipsis and no lenition
\$2\$ means that there's no eclipsis but there is lenition

The first letter of the input word is converted from Base30 to decimal, multiplied by \$17\$ and then reduced with a modulo \$22\$. The result is used to pick the correct value from \$A\$.
Any result above \$14\$ yields undefined, and so does any letter in the range u-z or any fada vowel. An undefined value is interpreted the same way as \$1\$ (no eclipsis, no lenition).
  1st letter | from Base30 | * 17 | mod 22 | A[n]
-------------+-------------+------+--------+-----------
      a      |      10     |  170 |   16   | undefined
      b      |      11     |  187 |   11   | 'm'
      c      |      12     |  204 |    6   | 'g'
      d      |      13     |  221 |    1   | 'n'
      e      |      14     |  238 |   18   | undefined
      f      |      15     |  255 |   13   | 'bh'
      g      |      16     |  272 |    8   | 'n'
      h      |      17     |  289 |    3   | '1'
      i      |      18     |  306 |   20   | undefined
      j      |      19     |  323 |   15   | undefined
      k      |      20     |  340 |   10   | '1'
      l      |      21     |  357 |    5   | '1'
      m      |      22     |  374 |    0   | '2'
      n      |      23     |  391 |   17   | undefined
      o      |      24     |  408 |   12   | '1'
      p      |      25     |  425 |    7   | 'b'
      q      |      26     |  442 |    2   | '1'
      r      |      27     |  459 |   19   | undefined
      s      |      28     |  476 |   14   | 2
      t      |      29     |  493 |    9   | 'd'
 u-z or fada |     NaN     |  NaN |  NaN   | undefined

Perl 6, 83 77 bytes
-6 bytes thanks to Jo King
{S:i/^<[bcdfgmpst]>/$/h/,{S/0/bh/}({$_ x tr/dbcfptg/nmg0bd/}($= m/./.lc))~$_}

Try it online!
Returns a two-element list.

05AB1E, 45 44 bytes
.•1˜3WÓƵ•sнlk©diн'hI¦JI®7‹i.•B}в •S„bhš®èì]‚

Ended up longer than I anticipated beforehand.. Can probably be golfed some more, though.
Try it online or verify all test cases.
Explanation:
.•1˜3WÓƵ•                   # Push compressed string "fbcdgptms"
s                           # Swap to take the (implicit) input-string
 н                          # Get its first character
  l                         # Convert it to lowercase
   k                        # Get the index in the string (-1 if not found)
    ©                       # Store it in the register (without popping)
     di                     # If the index is non-negative (>= 0):
       н                    #  Get the first character of the (implicit) input-string again
        'h                 '#  Push a "h"
          I                 #  Push the input
           ¦                #  And remove its first character
            J               #  Join all three strings together
       I                    #  Then push the input-string again
        ®7‹i                #  If the index from the register is smaller than 7:
            .•B}в •         #   Push compressed string "mgnnbd"
                   S        #   As a list of characters: ["m","g","n","n","b","d"]
                    „bhš    #   And prepend "bh" to this list: ["bh","m","g","n","n","b","d"]
                        ®è  #   Then use the index from the register in this list
                          ì #   And prepend it in front of the input-string
      ]                     # Close both if-statements
       ‚                    # Pair the two strings at the top of the stack
                            # (uses the input implicitly if we haven't entered the first if)
                            # (and output this pair of strings implicitly)

See this 05AB1E tips of mine (section How to compress strings not part of the dictionary?) to understand why .•1˜3WÓƵ• is "fbcdgptms" and .•B}в • is "mgnnbd".
Alternative for .•B}в •S„bhš with the same byte-count can be .•„Å'ÀāÊˆÑ•#, where .•„Å'ÀāÊˆÑ• is the compressed string "bh m g n n b d" and # will split on spaces.

Python 3, 100 bytes
lambda w,l='bBcCdDgGpPtTfF':(w[0]+'h'*(w[0]in'msMS'+l)+w[1:],[*'mgnnbd','bh',''][l.find(w[0])//2]+w)

Try it online!
-3 thanks to Black Owl Kai.

Stax, 41 bytes
ü≤↔y╩▓╤:ï{╪Θ↨ë24¿→Äw↔t⌠íΘq↕:pWhg2╗P♦_}éBb

Run and debug it

PowerShell, 121 122 116 98 Bytes
-24 bytes thanks to @mazzy
param($a)$a-replace'^[bcdfgmpst]','$&h';@{b='m';c='g';d='n';g='n';f='bh';p='b';t='d'}[''+$a[0]]+$a

Try it online!
Uses a simple regex for the lenition and a switch statement far superior hashtable thanks to @mazzy for the eclipsis. This can probably get a lot shorter.

maybe you should think about: 1) replace a first letter only, 2) switch as expression $(switch -r($a[0]){'b'{'m'}'c'{'g'}....})+$a, 3) hashtable instead the switch.

Thanks, @mazzy, but I'm not sure how to use a hashtable in this situation. Could you give me an idea of what this might look like?

param($a)$a-replace'^[bcdfgmpst]','$&h';@{b='m';c='g';d='n';g='n';f='bh';p='b';t='d'}[''+$a[0]]+$a

C# (Visual C# Interactive Compiler), 151 bytes
x=>{var p=(char)(x[0]%32+96);return(x.Insert(1,(a+"ms").Contains(p)?"h":""),p==102?"bh"+x:"mgnnbd "[a.IndexOf(p)<0?6:a.IndexOf(p)]+x);};var a="bcdgpt";

It's really long, and there are probably ways to golf it more. But I'm just too lazy.
Try it online!

Your answer only covers lowercase inputs, so Gaeilge is for example incorrect. PS: Since you only use b once, you can golf string a="bcdgpt",b="mgnnbd "; to var a="bcdgpt"; and b[ to "mgnnbd "[.

@Kevin Cruijssen Fixed

Nice, +1 from me. Two small things to golf: put the var a="bcdgpt"; inside the method, because you don't have to count the trailing semi-colon of lambda functions. And you can change the %32+96 to |32 to convert to lowercase. Try it online 147 bytes

Yeah, I forgot about that last string.Thanks!

Java 10, 140 135 bytes
s->{var h=s.charAt(0);int i="fbcdgptms".indexOf(h|32);return(i<0?s:h+"h"+s.substring(1))+" "+",bh,m,g,n,n,b,d,,".split(",",10)[i+1]+s;}

Port of my 05AB1E answer.
-5 bytes thanks to @OlivierGrégoire.
Try it online.
Explanation:
s->{                              // Method with String as both parameter and return-type
  var h=s.charAt(0);              //  Get the first character of the input
  int i="fbcdgptms".indexOf(h     //  Get its index in the string "fbcdgptms"
                            |32); //  After converting it to lowercase
  return(i<0?                     //  If the index is -1 (not found):
          s                       //   Return the input unchanged
         :                        //  Else:
          h                       //   Return the first character
          +"h"                    //   Appended with an "h"
          +s.substring(1))        //   Appended with the rest of the string
         +" "                     //  Then append a space delimiter
         +",bh,m,g,n,n,b,d,,".split(",",10)
                                  //  Push {"","bh","m","g","n","n","b","d","",""}
          [i+1]                   //  and append the character at index `i+1`
         +s;}                     //  And append the input-string

135 bytes: s->{var h=s.charAt(0);int i="fbcdgptms".indexOf(h|32);return(i<0?s:h+"h"+s.substring(1))+" "+" bh m g n n b d  ".split(" ",10)[i+1]+s;}

@OlivierGrégoire Ah, smart use of ",bh,m,g,n,n,b,d,,".split(",",10)[i+1] (I've changed the spaces to commas, since it's a bit more readable)! Would have never thought about that.

C# (.NET Core), 165, 131, 126 bytes
Edit:  ASCII-only with -34 bytes.  Puts everything into one string.
Edit2:  Kevin Cruijssen with the 5 byte golf to ToUpper()!
p=>{var s="BCDFGMPSTMGN N B D";var k=s.IndexOf(p.ToUpper()[0]);return(p.Insert(1,k<0?"":"h"),k<0?p:s[k]==70?"bh"+p:s[k+9]+p);}

Try it online!

131

126 bytes Removed the +p.ToUpper() from the string s, so you can use p.ToUpper()[0] and k<0 instead of s[18] and k>17.

Perl 6, 101 bytes
{.subst(/:i ^<[bcdfgmpst]>/,{$_~'h'}),.subst(/^./,{(%(<b m c g d n f bh g n p b t d>){.lc}//'')~$_})}

Try it online!

Python 3, 118 bytes
s='fbcdgpt'
def f(w):a=w[0].lower();return w[0]+'h'*(a in'ms'+s)+w[1:],dict(zip(s,'bmgnnbd')).get(a,'')+'h'*(a=='f')+w

Try it online!

I'm afraid it returns the wrong elipses for 'bean', 'capall' and 'fuinneog'.

@Ciaran_McCarthy Fixed

Retina 0.8.2, 77 bytes
i`^[bcdfgmpst]
$&h$'¶$&$&
T`L`l`¶.
¶f
¶ph
T`\ptcb\dgms`b\dgmnn_`¶.
^.+$
$&¶$&

Try it online! Link includes test cases. Explanation:
i`^[bcdfgmpst]
$&h$'¶$&$&

If the word can be lenited, create the lenition, and make a copy for the eclipsis with a duplicate first letter.
T`L`l`¶.

Lowercase the duplicate letter.
¶f
¶ph

If it's an f then change it to ph; it will get fixed to bh later.
T`\ptcb\dgms`b\dgmnn_`¶.

Fix or remove the eclipsis (m and s have a lentition but no eclipsis).
^.+$
$&¶$&

If there was no lentition then duplicate the word anyway.

JAVASCRIPT 131 bytes
Implementing Kevin Cruijssen answer in javaScript:
(w,i='bcdfgmpst'.indexOf(w.toLowerCase()[0]))=>(i>=0?[w,w[0]+'h'+w.substr(1),'m,g,n,bh,n,,b,,d'.split(',')[i]+w]:[w,w,w]).join(' ')

(
 w,                                                          // the input (string)
 i='bcdfgmpst'.indexOf(w.toLowerCase()[0])                   // the index of the lenited word
)=>(
i>=0?                                                        // if index greater or equals 0
 [w,w[0]+'h'+w.substr(1),'m,g,n,bh,n,,b,,d'.split(',')[i]+w] // return Array(input, lenited, eclipsis)
:                                                            // else
 [w,w,w]                                                     // return Array(input, input, input)
).join(' ')                                                  //Join array items with spaces

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Range interval insert which should split into unique ranges
Given a range and a list thereof, while keeping the existing intervals in the list unchanged, split the additional range into sub-intervals and add them to the list, such that all the ranges in the final list are disjoint and contain all numbers present in the input ranges.
The goal is to create an insertInterval(intervals, newInterval) function which returns a new interval list if there are any changes.
Pre-condition:
Interval range is sorted smallest to larger [[0, 1], [3, 5]].
Examples:
Input and output:
assert.deepEqual(
  insertIntervalSec([[1,5],[10,15],[20,25]], [12,27]),
  [[1,5],[10,15],[15,20],[20,25],[25, 27]]
);

assert.deepEqual(
  insertIntervalSec([[1,5],[10,15],[20,25]], [-3,0]),
  [[-3,0],[1,5],[10,15],[20,25]]
);

assert.deepEqual(
  insertIntervalSec([[1,5],[10,15],[20,25]], [-3,3]),
  [[-3,1],[1,5],[10,15],[20,25]]
);

assert.deepEqual(
  insertIntervalSec([[0,5],[10,15],[20,25]], [15,15]),
  [[0,5],[10,15],[20,25]]
);
assert.deepEqual(
  insertIntervalSec([[0,5],[10,15],[20,25]], [20,21]),
  [[0,5],[10,15],[20,25]]
);
assert.deepEqual(
  insertIntervalSec([[0,5],[10,15],[20,25]], [26,27]),
  [[0,5],[10,15],[20,25],[26, 27]]
);
assert.deepEqual(
  insertIntervalSec([[0,5],[10,15],[20,25]], [25,27]),
  [[0,5],[10,15],[20,25],[25,27]]
);
assert.deepEqual(insertIntervalSec([], [25,27]), [[25,27]]);
assert.deepEqual(insertIntervalSec([[1,1]], [1,1]), [[1,1]]);
assert.deepEqual(insertIntervalSec([[1,1]], [1,3]), [[1, 1], [1, 3]]);
assert.deepEqual(insertIntervalSec([[2,2]], [1,3]), [[1, 2], [2, 2], [2, 3]]);

All programming languages are welcome.

Should the intervals in the old list be preserved and not concatenated together in the new list?

Intervals in the old list should remain as is, the new inserted ranges should have same end value as the next start value [[1, 2], [2, 5]]

I'm a bit surprised nobody has mentioned The Sandbox where you can get feedback on your challenges before posting to main. I think this is a good challenge, as soon as I can figure out what it's asking.

Would it be possible to have a different explanation of the task? I don't understand what "Given a range and a list thereof" even means. A list of a range? What? :)

Japt, 44 bytes
rò
íU c ò@Vc øX ©X¥YÃke@V®ròÃc øXÃ®gJõ0ÃcV n

Try it online!
Reworked it, at the cost of 1 byte.
Now handles the [[2,2]],[1,3] test case properly.
Explanation:
rò                                           #Turn the second input into a range
íU c                                         #Duplicate each item in that range
     ò@      ©X¥YÃ                           #Split in the middle of the duplicates that:
       Vc øX                                 # Appear in the first input
                  k                          #Remove the segments where:
                   e@       øXÃ              # Every item in the segment is in...
                     V®ròÃc                  # A range from the first input
                               ®    Ã        #For the remaining segments:
                                gJõ0         # Get the first and last items
                                     cV      #Add those pairs to the first input
                                        n    #Sort the whole thing

Worked Example:
Input: [[2,2],[5,7]],[1,8]
Second input as a range: [1,2,3,4,5,6,7,8]
Duplicate each item: [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8]
Numbers that appear in the first input: [2,5,7]
After splitting: [[1,1,2],[2,3,3,4,4,5],[5,6,6,7],[7,8,8]]
Numbers within the first input's ranges: [2,5,6,7]
Segments using only those numbers:[[5,6,6,7]]
Remaining segments after those are removed: [[1,1,2],[2,3,3,4,4,5],[7,8,8]]
First and last item of each: [[1,2],[2,5],[7,8]]
Merge with the first input: [[1,2],[2,5],[7,8],[2,2],[5,7]]
Sort it: [[1,2],[2,2],[2,5],[5,7],[7,8]]
Which matches the actual output of the code

Nice answer, which is actually pretty similar to mine, so obvious +1 from me. I've also added the test cases [[1,1]], [3,3] and [[2,2]], [1,3] now (and fixed the code for [[1,1]], [3,3] since it was previously failing).

Nice answer, working with ranges can be tricky in Japt. I originally thought there was no way to improve on £[XÎXÌ]Ã, but it turns out you can do ®gJõ0Ã to save 2 bytes :-)

@ETHproductions Nice find, I always forget the other overloads of g

05AB1E, 34 33 30 bytes
ŸεI˜yåiðy)]˜#ʒI€Ÿ˜KgĀ}εнyθ‚}«ê

Created a port of @KamilDrakari's Japt answer, in order to fix the new test case [[2,2]], [1,3] (which golfed 4 bytes at the same time). So make sure to upvote him as well!
Try it online or verify all test cases.
Explanation:
Ÿ            # Get the ranged list of the first (implicit) input
             #  i.e. [1,8] → [1,2,3,4,5,6,7,8]
 ε           # Map each number `y` to:
  I˜yåi      #  If the second input flattened contains the current map-number:
             #    i.e. [[2,2],[5,7]] and `y`=2 → 1 (truthy)
       ðy    #   Push a space character, and value `y` again
         )   #   Wrap `y`, space, `y` into a list
 ]           # Close the if-statement and the map
             #  i.e. [1,2,3,4,5,6,7,8] and [[2,2],[5,7]]
             #   → [1,[2," ",2],3,4,[5," ",5],6,[7," ",7],8]
  ˜          # Flatten the list
             #  i.e. [1,[2," ",2],3,4,[5," ",5],6,[7," ",7],8]
             #   → [1,2," ",2,3,4,5," ",5,6,7," ",7,8]
   #         # Split the list on spaces
             #  i.e. [1,2," ",2,3,4,5," ",5,6,7," ",7,8] → [[1,2],[2,3,4,5],[5,6,7],[7,8]]
ʒ       }    # Filter this list of lists by:
 I€Ÿ         #  Push the second input, and create a range of each pair
             #   i.e. [[2,2],[5,7]] → [[2],[5,6,7]]
    ˜        #  Flatten this list of lists
             #   i.e. [[2],[5,6,7]] → [2,5,6,7]
     K       #  Remove these numbers from the current filter-list
             #   i.e. [2,3,4,5] and [2,5,6,7] → [3,4]
             #   i.e. [5,6,7] and [2,5,6,7] → []
      g      #  Take the length of this list
             #   i.e. [3,4] → 2
             #   i.e. [] → 0
       Ā     #  And truthify it (0 remains 0; everything else becomes 1)
             #   i.e. 2 → 1 (truthy)
             #   i.e. 0 → 0 (falsey)
             #  i.e. [[1,2],[2,3,4,5],[5,6,7],[7,8]] and [[2,2],[5,7]]
             #   → [[1,2],[2,3,4,5],[7,8]]
ε    }       # Map each inner list to:
 н           #  Take the first value
             #   i.e. [2,3,4,5] → 2
  yθ         #  And the last value
             #   i.e. [2,3,4,5] → 5
    ‚        #  And pair them together
             #   i.e. 2 and 5 → [2,5]
             #  i.e. [[1,2],[2,3,4,5],[7,8]] → [[1,2],[2,5],[7,8]]
«            # Merge this list of pairs with the second (implicit) input
             #  i.e. [[2,2],[5,7]] and [[1,2],[2,5],[7,8]]
             #   → [[2,2],[5,7],[1,2],[2,5],[7,8]]
 ê           # Sort the list of pairs, and remove any duplicated pairs at the same time
             #  i.e. [[2,2],[5,7],[1,2],[2,5],[7,8]]
             #   → [[1,2],[2,2],[2,5],[5,7],[7,8]]
             # (and output the result implicitly)

Python 2, 119 118 116 bytes
lambda l,A,B:sum([[[max(A,b),min(c[0],B)],c][max(A,b)>=min(c[0],B):]for(a,b),c in zip([[A,A]]+l,l+[[B,B]])],[])[:-1]

Try it online!

If I/O can be flat lists (of even length):
Python 2, 112 bytes
lambda l,A,B:sum([[a]+[max(A,a),min(B,b)]*(max(A,a)<min(B,b))+[b]for a,b in zip(*[iter([A]+l+[B])]*2)],[])[1:-1]

Try it online!

Python 3, 111 bytes
lambda l,A,B:sum([[a]+[max(A,a),min(B,b)]*(max(A,a)<min(B,b))+[b]for a,b in zip(*[iter([A,*l,B])]*2)],[])[1:-1]

Try it online!

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Nested lists as printable 2D objects
I don't know if something like this exists already (and I'm not finding the right key words) but if not, it felt like it could be an interesting coding puzzle.
The challenge is, to take an arbitrarily nested list (no more than 2 deep), and display the content in a terminal in 2 dimensions in a 'pretty' manner. Each 'top level' dictionary element should read left - right, and the nested content for each top level index should be displayed vertically in line with its index position.
Example input:
[["A"], ["B", "C"], ["D"], ["E", "F", "G"], ["H"]]

Expected output (option 1):
 A B D E H
   C   F
       G

Expected output (option 2):
In this case, 'stacks' should be as close to centralised as possible, so there is a similar amount of content above and below the top level left-to-right content.
       E
 A B D F H
   C   G

Example input 2
List contents (for the purpose of this challenge) can be any length, but will always be the same length. e.g.
[["ABC"], ["BCD", "CDE"], ["DEF"], ["EFG", "FGH", "GHI"], ["HIJ"]]

Would also be valid, and should be rendered in similar fashion to example 1:
                                             EFG
ABC BCD DEF EFG HIJ      or      ABC BCD DEF FGH HIJ
    CDE     FGH                      CDE     GHI
            GHI

Other input considerations (updated in response to comments):

The indexes of the top level, and nested lists will never be empty.

Criteria:

The solution should take a list of lists (nested 1 deep).
The format of the output is flexible, but it should be clear which elements of the list are distinct at the top level (left to right, in my example separated by spaces) and which elements of the sublists are which (top to bottom, separated vertically on successive lines in my example).
Each item in a sublist inside the list should be printed aligned with each other in the vertical direction.
I don't care about speed/complexity/byte count, so at the highest level the criteria will be considered met by any code that can produces the desired 2D output. The winner is therefore a popularity-contest, in that most votes wins (edit: now that answers have started being added the winner will be the answer with the most votes 1 week from today, but new answers would always be welcome).

Bonus points:

How 'pretty' the output is, I'll leave to you. Whether you want it to 'cascade' from the top most character as example 1, or a pseudo-centrally aligned output as example 2. Any other creative solutions are also welcomed.
Code which can handle variable length strings in any position.

I'm particularly interested in Python solutions, but anything goes.

Welcome to PPCG! There are a couple of issues with this post: 1) All challenges here must have an objective winning criterion. How pretty the output is, on the other hand, is rather subjective. 2) "in a 'pretty' manner" is unclear. Just how flexible is the output? What rules must the pretty-print version abide to? 3) I recommend using the Sandbox in the futute to get feedback prior to posting to the main site.

Welcome to PPCG! You have found the right place to ask a question like this, but this site is mainly focused on challenges as opposed to questions. And challenges require a winning condition. The most common one is code-golf, where the solution with the fewest bytes wins. If your intention was to make a challenge, I'd advice you to allow any languages, as it will increase the popularity. You can still add a request that you'd like to see a Python answer.

Until the question is reopened, you could do something like this to generate the text above in Python.

Why would the "C" align under the "A" (and "F" under "D") in the option 1 example? (Shouldn't there be leading spaces, like this?)

In addition to @JonathanAllan comment above, where did theD go in the output of option 2?

Hi all thanks for the feedback, sorry - this is my first post on this SE. Thought I'd met most of the criteria but evidently not! Well spotted with the outputs, I must have made a couple of mistakes, but I've fixed them now. I'll try to flesh out some more specific output criteria and hopefully that will solve the 'objective winning criteria'. I wasn't aware of the sandbox, I'll bear that in mind for the future!

I think this might be a bit close to this question, but with each line reversed

Is simply being able to display the list in that format (regardless of prettyness/robustness etc) considered an objective criteria in that case? The crux of the challenge really is the conversion from the nested list to a 2D representation. Would the question be on topic if I just removed those qualifiers?

To clarify what is meant by winning criteria: every question/challenge post on PPCG should have one of these winning criteria tags. For a challenge like this, I would personally go with code-golf. Also, I would remove the [python] tag. Mentioning you'd like to see a Python answer in your challenge is fine, as you did at the bottom. But challenges only for a specific language are frowned upon here on PPCG, and challenges are almost always open to all possible programming languages.

Great thanks!. I've updated the post now accordingly. Please let me know if anything else is missing. I've decided on popularity-contest since I'm not concerned by speed/bytes etc, but also tagged with the generic code-challenge because (to my mind) the primary aspect of the challenge is just generating working code that perfoms the list transformation. Let me know if I'm misusing this in any way, otherwise hopefully this can be opened again!

[tag:code-challenge] actually means that you're using a winning criterion not covered by any other tag, so it is superfluous if you're using [tag:popularity-contest]

I realise that but I figured there is a difference between a 'winning' answer and a 'correct' answer. I'm happy to run with just popularity-contest to adhere to the rules though.

Another thing worth specifying - may we assume all the sub-lists are non-empty? Or may we assume at least one will be non-empty?

I'll update the OP. There will never be an empty index at either level of the list.

Is this considered ready to be taken off hold?

This should not be reopened yet. Popularity contests do have the winner decided on votes, but they still need an objective winning criterion (for pop cons, it should be what you should vote based on). What makes an answer 'good'? 'Pretty' output? Aesthetically pleasing code? or what? You need to provide a guideline of how what makes answers vote-worthy, or this lacks an objective win criterion.

If we accept for now the popularity contest winning criterion, I still think there's the issue that answers are being judged on the aesthetic value of the output representation and not the code or algorithm that produces it, putting it outside of site scope. It seems to me that once one has decided on a nice presentation of the output, it shouldn't be hard for experienced coders to write code that implements it. I think this could be made more programming-focused with complex multilayered inputs that are hard to present in a clean human-readable way.

I should also warn you that at this point in the site, [tag:popularity-contest] might just be a historical relic  that tends to lure newbs into posting challenges that get downvoted or closed. And, there might not be anything you can do to make a pop-con palatable to a good fraction of the site audience. Also, past pop-cons suggest that if the challenge does take off, there's a good chance you'll get mostly (or exclusively) solutions that are not in the spirit of what you ask for, even if you've clearly explained what that is.

JavaScript (Node.js), 112 107 105 bytes
-1 byte thanks to @Kevin
Despite the controversy in the comments, I gave it a shot. It's my first ever codegolf submission and I had a lot of fun making it.
Tips & tricks are more than welcome!
a=>{o=['','',''];for(b of a)for(c=3;c--;)o[c]+=(b[c]?b[c]:' '.repeat(b[0].length))+' ';return o.join`\n`}

Try it online!

I'm not skilled in JS codegolfing, so I'm sure a lot more can be golfed, but one thing I noticed is that you can remove the brackets around the outer loop and add a semi-colon before the return instead to save 1 byte.

@KevinCruijssen thanks for the tip! I've change my code

Yw, and welcome to PPCG! :) If you haven't seen it yet, Tips for golfing in JavaScript and Tips for golfing in  might be interesting to read through. Enjoy your stay!

05AB1E
Since this is a popularity-contest, I wasn't entirely sure how to answer (might have been best to not answer at all, but I figured I'd gave it a shot anyway). I've added two answers below: one code-golf submission I would normally post and one 'pretty output' submission with multiple options (which isn't golfed whatsoever, might do so as well later on). If the rules have been clarified I will update (or delete) accordingly.
Code-golf submission (7 bytes):
ннgð×ζ»

(Based on the current test cases, so assumes all string items are of the same length.)
Outputs in a similar matter as the first examples in the test cases of the challenge description.
Try it online or verify all test cases.
Explanation:
н        # Take the first inner list of the (implicit) input
         #  i.e. [["ABC"],["BCD","CDE"],["DEF"],["EFG","FGH","GHI"],["HIJ"]] → ["ABC"]
 н       # Pop and take the first string of that
         #  i.e. ["ABC"] → "ABC"
  g      # Pop and get it's length
         #  i.e. "ABC" → 3
   ð×    # Push a space character " " and increase it to that size
         #  i.e. 3 → "   "
     ζ   # Zip/transpose (swapping rows/columns) of the (implicit) input,
         # with the spaces-string as filler
         #  i.e. [["ABC"],["BCD","CDE"],["DEF"],["EFG","FGH","GHI"],["HIJ"]] and "   "
         #   → [["ABC","BCD","DEF","EFG","HIJ"],["   ","CDE","   ","FGH","   "],["   ","   ","   ","GHI","   "]]
      »  # Join by newlines (which implicitly joins inner lists by spaces)
         #  → "ABC BCD DEF EFG HIJ\n    CDE     FGH    \n            GHI    "
         # (and output the result implicitly)

'Pretty output' submission with options:
Here we take an additional integer input as input, and 'pretty print' the output based on the option:
1: ABC BCD DEF EFG HIJ
       CDE     FGH
               GHI

2:             GHI
       CDE     FGH
   ABC BCD DEF EFG HIJ

3:             EFG
   ABC CDE DEF FGH HIJ
       BCD     GHI

4:     CDE     EFG
   ABC     DEF FGH HIJ
       BCD     GHI

As for the code (it's not golfed or properly tested whatsoever, as can be seen quite easily XD):
i
 ннgð×ζ»
ë¹<i
 ннgð×ζR»
ë¹Íi
 ннgð×ζøε2ä}DεθR}ø»,€нø»,
ë¹4Qi
 ннgð×©ζøεD®¢._}ø»
ë
 ¹"Option ÿ is not available."

Try it online or see all options in action.

Nice with the alternative output options!

Golfed - Jelly, 4 bytes
z“”G

Try it online!
Pretty Printing with boxes - Python 3, 656 bytes
def f(matrix):
	length = max(map(len, matrix))
	lengths = []
	for index in range(len(matrix)):
		matrix[index] = ([""] * -((len(matrix[index]) - length) // 2) + matrix[index] + ([""] * ((length - len(matrix[index])) // 2)))
		hlength = max(map(len, matrix[index]))
		lengths.append(hlength)
		matrix[index] = [item.ljust(hlength) for item in matrix[index]]
	horiz = ["─" * e for e in lengths]
	print("┬".join(horiz).join("┌┐"))
	for row in list(zip(*matrix))[:-1]:
		print("│".join(row).join("││"))
		print("┼".join(horiz).join("├┤"))
	print("│".join(col[-1] for col in matrix).join("││"))
	print("┴".join(horiz).join("└┘"))

Try it online!
Pretty Printing original (even spacing) - Python 3, 371 bytes
def f(matrix):
	length = max(map(len, matrix))
	for index in range(len(matrix)):
		matrix[index] = ([""] * -((len(matrix[index]) - length) // 2) + matrix[index] + ([""] * ((length - len(matrix[index])) // 2)))
		hlength = max(map(len, matrix[index]))
		matrix[index] = [item.ljust(hlength) for item in matrix[index]]
	for row in list(zip(*matrix)):
		print(" ".join(row))

Try it online!

Very cool solutions! Particularly like the boxes.

PHP, 162 160 bytes
Even though this isn't code-golf, here's the golfed version anyway:
function($t){$r=0;while($b=array_column($t,$r,0)){if($r++==$y=0)$a=$b;foreach($a as$k=>$x)printf("% -".max(array_map('strlen',$t[$y++]))."s ",$b[$k]);echo"
";}}

Try it online!
And ungolfed:
function nested( $t ) {
	$r = 0;
	while ( $b = array_column( $t, $r, 0 ) ) {
		if ( $r++ === 0 ) $a = $b;
		$y = 0;
		foreach( $a as $k => $x ) {
			$l = max( array_map('strlen', $t[$y++] ) );
			printf( "% -". $l ."s ", $b[$k] );
		}
		echo "\n";
	}
}

Tests:
[["A"], ["B", "C"], ["D"], ["E", "F", "G"], ["H"]],
[["A"], ["B2", "C"], ["D"], ["E", "FGH", "G"], ["H"]],
[["ABC"], ["BCD", "CDE"], ["DEF"], ["EFG", "FGH", "GHI"], ["HIJ"]],
[["ABC"], ["BCD", "CDEF"], ["DEF"], ["EFG", "FGH", "GHIII"], ["HIJK"]],
[["ABC123","FOO","BCD", "CDEF","BAR"], ["BCD", "PPCG_RULEZ"], ["DEF"], ["EFG", "FGH", "GHIII","BCD", "CDE"], ["HIJK"]]

This will line up columns for strings of any length.  Also, any number of rows will display fine too.
Output:
A B D E H
  C   F
      G

A B2 D E   H
  C    FGH
       G

ABC BCD DEF EFG HIJ
    CDE     FGH
            GHI

ABC BCD  DEF EFG   HIJK
    CDEF     FGH
             GHIII

ABC123 BCD        DEF EFG   HIJK
FOO    PPCG_RULEZ     FGH
BCD                   GHIII
CDEF                  BCD
BAR                   CDE

Python 3, 153 chars
Tried desperately to get this to work with a list comprehension, but here is my attempt.
l=len;p=print
for j in range(l(max(x,key=l))):
  for i in range(l(x)):
    if(l(x[i])>j):p(x[i][j],end=' ')
    else:p(' '*l(x[i][0]),end=' ')
  p()

C# (.NET Core), 205 bytes
Without LINQ.
Takes in a jagged array and prints the junk out.
p=>{var i=p.Length;int q,j=0;for(q=0;q<i;q++){var z=p[q].Length;j=z>j?z:j;}var s="";for(q=0;q<j;q++){for(var k=0;k<i;){try{s+=p[k++][q]+" ";}catch{s+=new string(' ',p[0][0].Length+1);}}s+="\n";}return s;};

Try it online!

181 bytes


text:
What are the repeating Fibonacci Digits?
As you probably know, a Fibonacci Number is one which is the sum of the previous two numbers in the series.
A Fibonacci Digit™ is one which is the sum of the two previous digits.
For instance, for the series beginning 1,1, the series would be 1,1,2,3,5,8,13,4,7,11,2... The change occurs after the 13, where, instead of adding 8+13, you add 1+3. The series loops at the end, where 4+7=11, and 1+1=2, same as the series starts.
For another example, the series beginning 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... This one starts out uniquely, but once the digits sum to 10, you end up with 1+0=1, 0+1=1, and the series continues - and loops - the same way the 1,1 series did.

The Challenge
Given an integer input 0≤n≤99, calculate the loop in the Fibonacci Digit series beginning with those two digits. (You are certainly allowed to consider integers out of this range, but it's not required.) If given a one-digit input, your code should interpret it to denote the series beginning 0,n.
All numbers in the loop that are two-digits must be outputted as two digits. So, for instance, the loop for 1,1 would contain 13, not 1,3.
The output begins with the first number in the loop. So, based on the above restrictions, the loop for 1,1 begins with 2, since 1,1 and 11 are counted separately.
Each number of the output may be separated by whatever you want, as long as it's consistent. In all of my examples I use commas, but spaces, line breaks, random letters, etc. are all allowed, as long as you always use the same separation. So 2g3g5g8g13g4g7g11 is a legal output for 1, but 2j3g5i8s13m4g7sk11 is not. You can use strings, lists, arrays, whatever, provided that you have the correct numbers in the correct order separated by a consistent separator. Bracketing the entire output is also allowed (ex. (5,9,14) or [5,9,14], etc.).
Test Cases:
1 -> 2,3,5,8,13,4,7,11
2 -> 2,3,5,8,13,4,7,11
3 -> 11,2,3,5,8,13,4,7
4 -> 3,5,8,13,4,7,11,2
5 -> 2,3,5,8,13,4,7,11
6 -> 3,5,8,13,4,7,11,2
7 -> 14,5,9
8 -> 13,4,7,11,2,3,5,8
9 -> 11,2,3,5,8,13,4,7
0 -> 0
14 -> 5,9,14
59 -> 5,9,14

This is code-golf, so the lowest number of bytes wins.

Can we take 2 digits as input, instead of $0\le n \le 99$?

As in, take two inputs rather than one input that’s split? No.

I still don't understand why 14 and 59 give the same result. If 59 is interpreted as starting 5,9 and allowing that as part of the loop then surely 14 should be the start of its loop?

@williamporter The beginning of the sequence is 0,1,1,2,3,5,8,13,4,7,11,2,3. The first time that the loop repeats is at the second 2.

@Neil The beginning of those respective sequences is 1,4,5,9,14,5 and 5,9,14,5,9. Both of them repeat beginning with the second 5. As I said earlier, only the input is split up; later numbers keep their digits together in the sequence.

Jelly, 15 bytes
DFṫ-SṭḊ
d⁵ÇÐḶZḢ

Try it online!
How it works
d⁵ÇÐḶZḢ  Main link. Argument: n (integer)

d⁵       Divmod 10; yield [n:10, n%10].
  ÇÐḶ    Call the helper link until a loop is reached. Return the loop.
     Z   Zip/transpose the resulting array of pairs.
      Ḣ  Head; extract the first row.

DFṫ-SṭḊ  Helper link. Argument: [a, b] (integer pair)

D        Decimal; replace a and b with the digits in base 10.
 F       Flatten the resulting array of digit arrays.
  ṫ-     Tail -1; take the last two digits.
    S    Compute their sum.
      Ḋ  Dequeue; yield [b].
     ṭ   Append the sum to [b].

Perl 6, 96 78 75 bytes
-3 bytes thanks to nwellnhof
{0,|.comb,((*~*)%100).comb.sum...{my$a=.tail(2);m/(\s$a.*)$a/}o{@_};$_&&$0}

Try it online!
0 returns 0, and other number return a Match object which stringifies to the numbers separated by a space with a leading a trailing space.
Explanation:
{                                                                         }   # Anonymous code block
 0,|.comb,                    ...   # Start a sequence with 0,input
                                    # Where each element is
                          .sum      # The sum of
          (     %100).comb          # The last two digits
           (*~*)                    # Of the previous two elements joined together
                                                                         # Until
                                 {                           }o{@_}   # Pass the list into another function
                                  my$a=.tail(2); # Save the last two elements
                                                m/(\s$a.*)$a/  # The list contains these elements twice?
                                                                     # And return
                                                                   ;$_     # Input if input is 0
                                                                      &&   # Else
                                                                        $0 # The looping part, as matched

Python 3, 187 176 158 139 138 129 121 120 112 96 95 120 116 bytes
f=lambda n,m=0,z=[]:(n,m)in zip(z,z[1:])and z[z.index(m)::-1]or f((z and n//10or m%10)+n%10,z and n or n//10,(m,*z))

Try it online!
Edit: As noted by @Jules, shorter solution applies to Python 3.6+. No longer distinct solutions for Python 3 / 3.6+
Edit: Indexing of z was too verbose. Without that now there is no gain in using eval.
Edit: Simplified finding if last two elements already appeared in the sequence.
Edit: Changed output format from list to tuple + replaced lambda with def
Edit: Back to lambda but embedded t into f.
Edit: Input n can be actually interpreted as head of growing collection z which would represent tail in recursive approach. Also beats @Arbo's solution again.
Edit: Actually you can unpack two items from head which cuts another 16 bytes.
Edit: Actually 17 bytes.
Edit: As noted by @Arbo solution was giving answers for 14 and 59 cases as they were in initial test cases which were proven later to be wrong. For now this isn't so short but at least it works correctly.

Quite an abuse of f-strings and eval. Original ungolfed code although I suspect it could be done somehow easier:
def is_subsequence(l1, l2):
    N, n = len(l1), len(l2)
    for i in range(N-n):
        if l1[i:i+n]==l2:
            return True
    return False

def generate_sequence(r):
    if is_subsequence(r,r[-2:]):
        return r
    last_two_digits = "".join(map(str,r))[-2:]
    new_item = sum(int(digit) for digit in last_two_digits)
    return generate_sequence(r + [new_item])

def f(n):
    seq = generate_sequence([n,n])[::-1]
    second_to_last = seq[1]
    first_occurence = seq.index(second_to_last)
    second_occurence = seq.index(second_to_last, first_occurence + 1)
    return seq[first_occurence + 1 : second_occurence + 1][::-1]

Small correction: this is Python 3.6+. This will plainly not work in 3.5 or older.

Your testing code seems to not work; an input of 59 yields (14, 5, 9)

I see that test cases have changed since I began the challenge so that's why there was incorrect output. I've changed my solution so that it works but for now it's not so short. Nevertheless thanks for pointing that out.

JavaScript (ES6),  111 104  103 bytes
f=(n,o=[p=n/10|0,n%10])=>n^o[i=o.lastIndexOf(n=(q=p+[p=n])/10%10+q%10|0)-1]?f(n,[...o,n]):o.slice(i,-1)

Try it online!
Commented
f = (                       // f = recursive function taking:
  n,                        //    n = last term, initialized to the input
  o = [                     //    o = sequence, initially containing:
    p = n / 10 | 0,         //      p = previous term, initialized to floor(n / 10)
    n % 10 ]                //      n mod 10
) =>                        //
  n ^                       // we compare n against
  o[                        // the element in o[] located at
    i = o.lastIndexOf(      //   the index i defined as the last position of
      n =                   //     the next term:
        (q = p + [p = n])   //       q = concatenation of p and n; update p to n
        / 10 % 10           //       compute the sum of the last two digits
        + q % 10            //       of the resulting string
        | 0                 //       and coerce it back to an integer
      ) - 1                 //   minus 1
  ] ?                       // if o[i] is not equal to n:
    f(n, [...o, n])         //   append n to o[] and do a recursive call
  :                         // else:
    o.slice(i, -1)          //   we've found the cycle: return it

C (gcc), 114 112 109 bytes
f(n,s){int i[19]={};for(s=n/10,n%=10;i[s]-n;n+=n>9?-9:s%10,s=i[s])i[s]=n;for(;printf("%d ",s),i[s=i[s]]-n;);}

Try it online!
-3 from ceilingcat
Includes a trailing space.
f(n,s){
    int i[19]={};                               //re-initialize edges for each call
    for(s=n/10,n%=10;                           //initialize from input
        i[s]-n;                                 //detect loop when an edge s->n repeats
        n+=n>9?-9:s%10,s=i[s])i[s]=n;           //step
    for(;printf("%d ",s),i[s=i[s]]-n;);         //output loop
}

huh, do...while doesn't need the braces if it's a single statement O_o

Perl 5, 90 76 bytes
s/.\K/ /;s/(.?) *(.)\K$/$".($1+$2)/e until/^0|\b(.\B.|. .)\b.*(?= \1)/;$_=$&

TIO

@JoKing, fixed and optimized

Java (JDK), 194 bytes
n->"acdfinehlcdfinehfjofj".chars().map(x->x-97).skip((n="abbicbcsfibbbgqifiibbgbbbcsfbiiqcigcibiccisbcqbgcfbffifbicdqcibcbicfsisiibicfsiffbbicfsifiibicfsifii".charAt(n)%97)).limit(n<1?1:n<9?8:3)

Try it online!
Hardcoded seemed the shortest given that Python already had an answer of 187...

Python 2, 123 114 113 bytes
n=input()
p=b=l=n/10,n%10
while~-(b in p):p+=b,;l+=(b[1]/10or b[0]%10)+b[1]%10,;b=l[-2:]
print l[p.index(b)-2:-2]

Try it online!
The program builds up a tuple p of all 2-value pairs that have occurred in the sequence, which is initialised with junk to save some bytes. The sequence itself gets built in the tuple l, and the last two elements of this tuple are stored in b for easy (and short) reference. As soon as a repeat is found, we can look up the index of b in p to know where the loop began.
EDIT: Cleaned this up a bit, and shaved off one more byte... My method does seem to be nearing its byte count limit, and I really should stop working on this.

Haskell, 100 bytes
d!p@(s,t)|(_,i:h)<-span(/=p)d=fst<$>i:h|q<-d++[p]=q!(t,last$mod s 10+t:[t-9|t>9])
h x=[]!divMod x 10

Try it online!
d!p@(s,t)                -- function '!' recursively calculates the sequence
                         -- input parameter:
                         -- 'p': pair (s,t) of the last two numbers of the sequence
                         -- 'd': a list of all such pairs 'p' seen before
  |       <-span(/=p)d   -- split list 'd' into two lists, just before the first
                         -- element that is equal to 'p'
   (_,i:h)               -- if the 2nd part is not empty, i.e. 'p' has been seen
                         -- before
          =fst<$>i:h     -- return all first elements of that 2nd part. This is
                         -- the result.
  |q<-d++[p]             -- else (p has not been seen) bind 'q' to 'd' followed by 'p'
   =q!                   -- and make a recursive call to '!' with 'q' and
     (t,    )            -- make the last element 't' the second to last element
                         -- the new last element is
          [t-9|t>9]      -- 't'-9 (digit sum of 't'), if 't'>9
       mod s 10+t        -- last digit of 's' plus 't', otherwise

h x=                     -- main function
     []!divMod x 10      -- call '!' with and empty list for 'd' and
                         -- (x/10,x%10) as the pair of last numbers

Charcoal, 46 bytes
≔Ｅ◧Ｓ²ΣιθＷ¬υ≔ΦＥ⊖Ｌ⊞ＯθΣ…⮌⪫θω²✂θλＬθ¹⁼κ✂θ⊗⁻λＬθλ¹υＩυ

Try it online! Link is to verbose version of code. Explanation:
≔Ｅ◧Ｓ²Σιθ

Input the number, pad it to 2 characters, then take the digital sum of each character, and save the resulting list.
Ｗ¬υ

Repeat while the list of loops is empty.
⊞ＯθΣ…⮌⪫θω²

Calculate the sum of the two previous digits and add it to the Fibonacci list.
Ｅ⊖Ｌ...✂θλＬθ¹

Take all the nontrivial suffixes of the list.
≔Φ...⁼κ✂θ⊗⁻λＬθλ¹υ

Filter out those that don't repeat and save the result in the list of loops.
Ｉυ

Cast the list of loops to string and print.

Python 2, 149 139 bytes
s=input()
s=[s/10,s%10]
while zip(s,s[1:]).count((s[-2],s[-1]))<2:s+=[(s[-1]/10or s[-2]%10)+s[-1]%10]
print s[-s[::-1].index(s[-2],2)-1:-2]

Try it online!
Expects a non-negative integer as input. Smaller bytecount, but likely will no longer work for integers >99.
Explanation:
# get the input from STDIN
s=input()
# convert the input into two integers via a divmod operation
s=[s/10,s%10]
# count number of times the last two numbers appear in sequence in list.
# turn list into list of adjacent value pairs Ex: [1,1,2]->[(1,1),(1,2)]
      zip(s,s[1:])
                  # count number of times the last two items in list appear in entire list
                  .count((s[-2],s[-1]))
# if >1 matches, we have found a repeat.
while .................................<2:
        # the first digit of the last number, if it is >9
        # else the last digit of the second to last number
        (s[-1]/10or s[-2]%10)
                             # the last digit of the last number
                             +s[-1]%10
    # add the new item to the list
    s+=[..............................]
         # reverse the list, then find the second occurrence of the second to last item
         s[::-1].index(s[-2],2)
# get the section of the list from the second occurrence from the end, discard the final two items of the list
print s[-......................-1:-2]

Red, 189 178 164 137 bytes
func[n][b: n % 10 c: reduce[a: n / 10]until[append c e: b
b: a *(pick[0 1]b > 9)+(a: b % 10)+(b / 10)k: find c reduce[e b]]take/last k k]

Try it online!

Husk, 15 bytes
UṠ-U_2¡ȯΣ↑_2ṁd;

Try it online!
UṠ-U_2¡ȯΣ↑_2ṁd;
U                   # longest prefix of unique elements from sequence
 Ṡ-U_2              # (after removing longest prefix with
                    # all unique sublists of length 2)
      ¡ȯΣ↑_2ṁd;     # fibonacci digit sequence:
      ¡             # repeatedly apply function to list
              ;     # (starting with list formed from input):
       ȯ            # combination of 3 functions -
        Σ           # sum of
         ↑_2        # last 2 elements of
            ṁd      # digits of list

Ṡ-U_2 is an interesting function.


text:
Number of \$n\$-carbon alkanes
Given a positive number \$n\$, find the number of alkanes with \$n\$ carbon atoms, ignoring stereoisomers; or equivalently, the number of unlabeled trees with \$n\$ nodes, such that every node has degree \$\le 4\$.
This is OEIS sequence A000602.
See also: Paraffins - Rosetta Code
Example
For \$n = 7\$, the answer is \$9\$, because heptane has nine isomers:

Heptane: \$\mathrm{H_3C-CH_2-CH_2-CH_2-CH_2-CH_2-CH_3}\$

2-Methylhexane: \$\mathrm{H_3C-CH(CH_3)-CH_2-CH_2-CH_2-CH_3}\$

3-Methylhexane: \$\mathrm{H_3C-CH_2-CH(CH_3)-CH_2-CH_2-CH_3}\$

2,2-Dimethylpentane: \$\mathrm{H_3C-C(CH_3)_2-CH_2-CH_2-CH_3}\$

2,3-Dimethylpentane: \$\mathrm{H_3C-CH(CH_3)-CH(CH_3)-CH_2-CH_3}\$

2,4-Dimethylpentane: \$\mathrm{H_3C-CH(CH_3)-CH_2-CH(CH_3)-CH_3}\$

3,3-Dimethylpentane: \$\mathrm{H_3C-CH_2-C(CH_3)_2-CH_2-CH_3}\$

3-Ethylpentane: \$\mathrm{H_3C-CH_2-C(CH_2CH_3)-CH_2-CH_3}\$

2,2,3-Trimethylbutane: \$\mathrm{H_3C-C(CH_3)_2-CH(CH_3)-CH_3}\$

Note that 3-methylhexane and 2,3-dimethylpentane are chiral, but we ignore stereoisomers here.
Test cases
You don't need to handle the case \$n = 0\$.
intput	output
=============
0	1
1	1
2	1
3	1
4	2
5	3
6	5
7	9
8	18
9	35
10	75
11	159
12	355
13	802
14	1858
15	4347
16	10359
17	24894
18	60523
19	148284
20	366319

I'd be impressed if someone manages to write a solution with Alchemist!

@PeterTaylor Well It can output each time a digit

@BMO Also Alchemist looks turing complete if big number support

@l4m2: I used it before for a [tag:sequence] challenge and some [tag:number] challenges, you can also use unary output which is most likely easier. And yes, it is most likely TC (uses bignums), I haven't formally proved it though.

@BMO It looks to just able to simulate CM

set 1: { INC (r) S1->S2+r, DEC (r) S1+r->S2, JZ (r, z) S1+0r->z S1+r->S2+r}

CJam (100 98 91 89 83 bytes)
1a{_[XX]*\_{_0a*}:E~\{E\_{ff*W%{0@+.+}*}:C~.+2f/}:D~.+C.+3f/1\+}q~:I*DE1$D.-X\+.+I=

Takes input from stdin, outputs to stdout. Note that this exploits the licence to not handle input 0 to save two bytes by inlining the definitions of C and D. Online demo
NB this is very slow and memory-inefficient. By trimming arrays a much faster version is obtained (3 bytes more). Online demo.
Dissection
OEIS gives (modulo an indexing error) the generating function decomposition $$\begin{eqnarray}
A000598(x) &=& 1 + x Z(S_3; A000598(x)) \\
A000678(x) &=& x Z(S_4; A000598(x)) \\
A000599(x) &=& Z(S_2; A000598(x) - 1) \\
A000602(x) &=& A000678(x) - A000599(x) + A000598(x^2) \\
\end{eqnarray}$$ where \$Z(S_n; f(x))\$ denotes the cycle index of the symmetric group \$S_n\$ applied to the function \$f(x)\$.
I manipulated this into a slightly golfier decomposition, and then looked up the intermediate sequences and discovered that they're also in OEIS:
$$\begin{eqnarray}
A000642(x) &=& Z(S_2, A000598(x)) \\
A000631(x) &=& Z(S_2, A000642(x)) \\
A000602(x) &=& A000642(x) + x A000642(x^2) - x A000631(x)
\end{eqnarray}$$
Earlier versions reused block C (convolve two polynomials) from this answer. I've found a much shorter one, but I can't update that answer because it's from a chaining question.
1a            e# Starting from [1]...
{             e# Loop I times (see below) to build A000598 by f -> 1 + Z(S_3; f)
  _[XX]*      e#   Copy and double-inflate to f(x^3)
  \_          e#   Flip and copy: stack is f(x^3) f(x) f(x)
  {_0a*}:E~   e#   Assign copy-and-inflate to E and execute
              e#   Stack: f(x^3) f(x) f(x) f(x^2)
  \           e#   Flip
  {           e#   Define and execute block D, which applies f -> Z(S_2;f)
              e#     Stack: ... f
    E\_       e#     Stack: ... f(x^2) f(x) f(x)
    {         e#     Define and execute block C, which convolves two sequences
      ff*     e#       Multiply copies of the second sequence by each term of the first
      W%      e#       Reverse
      {       e#       Fold
        0@+.+ e#         Prepend a 0 to the first and pointwise sum
      }*
    }:C~      e#     Stack: ... f(x^2) f(x)^2
    .+2f/     e#     Pointwise average
  }:D~        e#   Stack: f(x^3) f(x) f(x^2) Z(S_2;f(x))
  .+C         e#   Stack: f(x^3) f(x)*(f(x^2) + Z(S_2;f(x)))
  .+3f/       e#   Add and divide by 3 to finish computing Z(S_3; f)
  1\+         e#   Prepend a 1
}
q~:I          e# Read input to I
*             e# Loop that many times
              e# Stack: I+1 terms of A000598 followed by junk
D             e# Stack: I+1 terms of A000642 followed by junk
E1$D          e# Stack: A000642 A000642(x^2) A000631
.-X\+.+       e# Stack: A000602
I=            e# Extract term I

Alchemist (1547 bytes)
_->In_NN+2b+al+g
al+g+0NN->ak
al+g+NN->ah
ah+b->ah+m+d+z+a
ah+0b->C+Z+Q
Z+j+z->Z+j+d
Z+j+0z->M+s
M+g+b->M+g+r
M+g+h->M+g+d
M+g+0b+0h+q->J+U
J+o+h->J+o+m
J+o+a->J+o+d
J+o+0h+0a->2C+an+Q
an+j+h->an+j+d
an+j+0h->aC+s
aC+g->e+am+P
am+l+b->am+l+d
am+l+0b->al+s
ak+b->ak+m+d
ak+0b->C+aj+Q
aj+j+h->aj+j+b
aj+j+0h->I+n
I+f+e->I+f+a
I+f+b->I+f+m+d+z
I+f+0e+0b->C+ai+Q
ai+j+h->ai+j+b
ai+j+0h->aB+n
aB+f->H
H+z->H+d
H+a+e->H
H+0z+0e->G+i
G+i+0b->ag
G+i+b->az+b+n
az+f+0b->Out_a
az+f+b->G+b+n
G+f->G+t
ag+e->ag
ag+0e->af+t
af+i+e->af+i+a
af+i+0e->Out_a
Q->F+s
F+g+b->F+g+y
F+g+A->F+g
F+g+0b+0A->av+o
av+o+0m->w
av+o+m->m+ae+A
ae+m->ae+b
ae+0m->u+n
u+f+b->u+f+m
u+f+e->u+f+E
u+f+A->u+f+k+c
u+f+0b+0e+0A->ad
ad+c->ad+A
ad+0c->ac
ac+y->ac+d+c
ac+0y->ab
ab+c->ab+y
ab+0c->V+l
V+l+0k->x
V+l+k->aa+t
aa+i+0e->W
aa+i+e->Y
Y+E->Y+D+c
Y+0E->X
X+c->X+E
X+0c->aa+i
W+D->W+e
W+0D->V+P
x+E->x
x+d->x
x+b->x+k
x+0E+0d+0b->aw
aw+h->aw+d
aw+0h->aE+s
aE+g->p
p+b->p+2r
p+k->p+d
p+B->p
p+q->p
p+0b+0k+0B+0q->r+q+av+U
w+h->w+d
w+y->w+r
w+C->w+B+q
w+0h+0y+0C->aD+U
aD+o->j
U->au+s
au+g+b->au+g+d
au+g+0b->v
v+d->d+aA+t
aA+i+k->R
aA+i+0k->at
at+B->at+k+c
at+0B->L
L+c->L+B
L+r->L+b
L+0c+0r->as+n
as+f+b->as+f+r
as+f+0b->R
R+0e->K
R+e+q->ar+D+c
ar+e+q->ar+c
ar+0q->aq
aq+c->aq+q
aq+0c->R
K+D->K+e
K+h->K+b
K+0D+0h->ap+P
ap+l+b->ap+l+h
ap+l+0b->v
v+0d+k->v
v+0d+r->v
v+0d+0k+0r->o
s+0d->g
s+d->d+ao+t
ao+i->ao+P
ao+l->s
P->O+c
O+b->2c+O
O+0b->N
N+c->b+N
N+0c+e->O
N+0c+0e->l
n+b->n+c
n+0b->T
T+c->ay
T+0c->e+n
ay+c->b+T
ay+0c->f
t+d->t+c
t+0d->S
S+c->ax
S+0c->e+t
ax+c->d+S
ax+0c->i

Online demo.
Note: this is quite slow. If testing with an interpreter which supports applying a rule multiple times at once (e.g. my one - although make sure you have the latest version which fixes a bug in the parser) then you can get a significant speed-up by adding two rules:
T+2c->b+T
S+2c->d+S

which inline a route through the existing rules
T+c->ay
ay+c->b+T
S+c->ax
ax+c->d+S

Partial dissection
At a high level, this uses the same approach as my CJam answer.
The computation model of Alchemist is essentially the Minsky register machine. However, Alchemist very nicely exposes the equivalence of code and data, and by allowing many tokens on the left hand side of a production rule effectively the state is not constrained to be represented by one atom: we can use a tuple of atoms, and this allows (non-recursive) subroutines. This is very useful for golf. The only things it's really lacking are macros and debuggability.
For arrays I'm using a pairing function which can be implemented quite golfily in RMs. The empty array is represented by \$0\$, and the result of prepending \$x\$ to array \$A\$ is \$(2A+1)2^x\$. There is one subroutine to pair: the subroutine is called P and it prepends the value of e to b. There are two subroutines to unpair: n unpairs b to e and b; and t unpairs d to e and d. This allowed me to save quite a bit of shuffling data between variables, which is important: a single "move" operation
a, b = b, 0

expands to at least 17 bytes:
S+a->S+b
S+0a->T

where S is the current state and T is the next state. A non-destructive "copy" is even more expensive, because it has to be done as a "move" from a to b and an auxiliary tmp, followed by a "move" from tmp back to a.
Obfuscation
I aliased various variables to each other and eliminated about 60 states in the process of golfing the program, and many of them didn't have particularly meaningful names anyway, but to fully golf it I wrote an minimiser so the names are now thoroughly indecipherable. Good luck reverse engineering it! Here is the minimiser (in CJam), which makes a few assumptions about the code but could be adapted to minimise other Alchemist programs:
e# Obfuscate / minimise Alchemist program

e# Tokenise
qN%[SNS]e_*S%

e# Get token frequencies for substitution purposes, special-casing the I/O ones
_["+" "0" "2" "->" "_" N "In_n" "n" "Out_tmp2" "tmp2"]-
$e`$W%1f=

e# Empirically we want a two-char input for n and a one-char one for tmp2
["In_n" "Out_tmp2" "n" "tmp2"]\+
["In_NN" "Out_a" "NN"] "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"1/:A+ A2m*:e_"NN"a-+
1$,<

er
_s,p

Wait... does that interpreter work? AFAICT... you pick a random rule, then figure out how many times that can be applied. Does that even work correctly?

Hmm. How would you improve debuggability

@ASCII-only, that would work but it's not actually what it does. It first picks a rule which is applicable and then works out how many times it can be applied. Debuggability is tricky. One of my ideas for a dissertation project back in the day was a GUI RM editor with backwards debugger.

but... rule execution order affects program order does it not

@ASCII-only, yes. That's why there are so many variables. Only about 16 of them are data: the rest are state. I've used non-determinism to golf by effectively parallelising independent "move" operations.

i meant that in some programs, if you do as many applications of a certain rule as possible when there are multiple applicable rules, the possible results may be restricted compared to the official interpreter?

@ASCII-only, oh, I thought you were worried about this program. If it's the interpreter in general, see the last point in the roadmap.

I wouldn't say it's the ability to analyse though, but if that's what you meant by "ability to analyse" then fair enough

Node.js 11.6.0,  229 223 221  218 bytes
Derived from the Java implementation suggested on Rosetta Code.
f=(N,L=1,u=[...r=[c=[],1,...Buffer(N)]],k=u[(g=(n,B,S,i,b=B,m,d=0)=>{for(;++b<5;)for(x=c[B]=(d+r[m=n])*(d++?c[B]/d:i),u[S+=n]+=L*2<S&&x,r[S]+=b<4&&x;--m;)g(m,b,S,c[B])})(L,0,1,1),L]-=~(x=r[L++/2])*x>>1)=>L>N?k:f(N,L,u)

Try it online!

Pari/GP, 118 bytes
A direct translation of Peter Taylor's CJam answer.
n->(s(k)=subst(a,x,x^k));(z()=(a^2+s(2))/2);a=O(1);for(i=0,n,a=1+x*(a*z()+(s(3)-a^3)/3));a=z();Pol(a+x*(s(2)-z()))\x^n

Try it online!