#!/usr/bin/perl use strict; use warnings; use List::MoreUtils 'first_index'; my @terms = (); # Instructions my @list = (); # AoA my $last = undef; # last read. while (my $line = ) { chomp($line); # We need to reprocess all instructions to keep old orders push @terms, $line; foreach my $item (@terms) { if ($item eq 'Start') { # nothing before start. $last = undef; next; } my ($last_position,$item_position); if (defined $last) { ($last_position) = grep { grep { $_ eq $last } @{$_} } @list; } ($item_position) = grep { grep { $_ eq $item } @{$_} } @list; if ($last_position && !$item_position) { my $idx = first_index { $_ == $last_position } @list; $list[$idx+1] ||= []; push @{$list[$idx+1]}, $item; } elsif ($last_position && $item_position) { my $idx = first_index { $_ == $last_position } @list; my $idx2 = first_index { $_ == $item_position } @list; if ($idx == $idx2) { # disambiguation my $idx = first_index { $_ == $last_position } @list; @{$last_position} = grep { $_ ne $item } @{$last_position}; $list[$idx+1] ||= []; push @{$list[$idx+1]}, $item; } elsif ($idx > $idx2) { # complex disambiguation @{$item_position} = grep { $_ ne $item } @{$item_position}; $list[$idx+1] ||= []; push @{$list[$idx+1]}, $item; } } elsif (!$last_position && !$item_position) { $list[0] ||= []; push @{$list[0]}, $item; } $last = $item; } } my @ambiguous = grep {defined $_->[1]} @list; if (@ambiguous) { warn 'Ambiguous items: '.join ', ', map { join '|', @{$_} } @ambiguous; } print join ', ', map { join '|', @{$_} } @list; print "\n";