SWI-Prolog, 165165 117 bytes
-48 bytes thanks to Prolog golfing tips.
h(I):-h(I,[],I+[]-1).
h([],X,_):[H|T]+R-write(X).
h([H|T],R,N):-(select([H|A],R,[H|L],S),!,append(A,[N],L),O is N+1,h(T,S,O).
h([H|T],R,N):-append;append(R,[[H,N]],S)),O is N+1,h(TT+S-O,!;write(S,O)).
% The rulepredicate that prints the grouped duplicates. It's a wrapper because we need
% need some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).
% IfIn we'vethe gonegolfed throughcode, theoperators entireare input,used printto ourrepresent constructedthis outputpredicate.
% resultSee https://codegolf.stackexchange.com/a/153160
enumerate([],% ResultGo through the input, _Index)build :-up write(Result).
%the Otherwise..result on the way and print it.
enumerate([Head|Tail], Result, Index) :-
(
% If our current Result already contains a list that starts with the
% current first element in our input, Head, NewIndexes will become the new
% new "tail" of that list in our next result list:
select([Head|OldIndexes], Result, [Head|NewIndexes], NextResult),
% Don't backtrack before this if goals below this fail:
!,
% The as-yet-unknown NewIndexes above should in fact be the same as
% OldIndexes with our current Index appended:
append(OldIndexes, [Index], NewIndexes),
% Increment our index counter:
Use ; NextIndexinstead isof Indexseparate +predicate 1,rules.
% And continue with the rest of ourSee inputhttps://codegolf.stackexchange.com/a/67032
enumerate(Tail, NextResult, NextIndex).;
enumerate([Head|Tail], Result, Index) :-
% If our current Result did not already contain Head, append a new list
% for it with the current index:
append(Result, [[Head, Index]], NextResult)
),
% Increment our index counter:
NextIndex is Index + 1,
(
% ContinueAnd continue with the rest of theour input:
enumerate(Tail, NextResult, NextIndex),
% Don't backtrack if the above succeeded:
!
;
% If Tail is no longer a multi-element list, we're done. Print:
write(NextResult)
).