#!/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 ]; } }