Skip to main content
Do some actual golfing.
Source Link
user76878
user76878

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)).

Try it online!Try it online!

% 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)
    ).

SWI-Prolog, 165 bytes

h(I):-h(I,[],1).
h([],X,_):-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(R,[[H,N]],S),O is N+1,h(T,S,O).

Try it online!

% The rule that prints the grouped duplicates. It's a wrapper because we need
% some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% If we've gone through the entire input, print our constructed output result:
enumerate([], Result, _Index) :- write(Result).
% Otherwise...
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
    % "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:
    NextIndex is Index + 1,
    % And continue with the rest of our input:
    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,
    % Continue with the rest of the input:
    enumerate(Tail, NextResult, NextIndex).

SWI-Prolog, 165 117 bytes

-48 bytes thanks to Prolog golfing tips.

h(I):-I+[]-1.
[H|T]+R-N:-(select([H|A],R,[H|L],S),!,append(A,[N],L);append(R,[[H,N]],S)),O is N+1,(T+S-O,!;write(S)).

Try it online!

% The predicate that prints the grouped duplicates. It's a wrapper because we
% need some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% In the golfed code, operators are used to represent this predicate.
% See https://codegolf.stackexchange.com/a/153160
% Go through the input, build up the 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 "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)
    % Use ; instead of separate predicate rules.
    % See https://codegolf.stackexchange.com/a/67032
    ;
        % 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,
    (
        % And continue with the rest of our 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)
    ).
Source Link
user76878
user76878

SWI-Prolog, 165 bytes

h(I):-h(I,[],1).
h([],X,_):-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(R,[[H,N]],S),O is N+1,h(T,S,O).

Try it online!

Explanation

% The rule that prints the grouped duplicates. It's a wrapper because we need
% some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% If we've gone through the entire input, print our constructed output result:
enumerate([], Result, _Index) :- write(Result).
% Otherwise...
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
    % "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:
    NextIndex is Index + 1,
    % And continue with the rest of our input:
    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,
    % Continue with the rest of the input:
    enumerate(Tail, NextResult, NextIndex).