in reply to Finding String's Neighbors By Up To 2 Differing Positions

neversaint,
Here is another solution that might should be more efficient than the one above. This solution only generates strings that are desired neighbor. Explanation for how it does that are in the comments.
#!/usr/bin/perl use strict; use warnings; use Algorithm::Loops 'NestedLoops'; # This solution says take all possible pairs of indices # Then count in base 4, replacing the value at that index my $input = $ARGV[0] || '000'; my @seed = split //, $input; # Don't replace two values with exact same two values my %seen; my $idx_iter = combo(2, 0 .. $#seed); while (my @idx = $idx_iter->()) { my $base4_iter = NestedLoops([([0..3]) x 2]); while (my @base4 = $base4_iter->()) { my @neighbor = @seed; @neighbor[@idx] = @base4; print "@neighbor\n" if ! $seen{"@neighbor"}++; } } # Taken from [id://393064] sub combo { my $by = shift; return sub { () } if ! $by || $by =~ /\D/ || @_ < $by; my @list = @_; my @position = (0 .. $by - 2, $by - 2); my @stop = @list - $by .. $#list; my $end_pos = $#position; my $done = undef; return sub { return () if $done; my $cur = $end_pos; { if ( ++$position[ $cur ] > $stop[ $cur ] ) { $position[ --$cur ]++; redo if $position[ $cur ] > $stop[ $cur ]; my $new_pos = $position[ $cur ]; @position[ $cur .. $end_pos ] = $new_pos .. $new_pos + + $by; } } $done = 1 if $position[0] == $stop[0]; return @list[ @position ]; } }

Cheers - L~R