Your inner loop is counting (and substituting) values from 1-3, regardless of what the original value in that position was. It should instead be counting 0-3 and skipping the original value. This is why it only produces the correct output when given an all-0 seed.

Code follows.

First, a corrected version of the code as you wrote it:

#!/usr/bin/perl -w use strict; use Data::Dumper; use Carp; # If possible we prefer not to use any CPAN module # or regex. It's for my understanding my $seed = $ARGV[0] || "000"; # Seed can be longer than 3 digits but always 0,1,2,3 for (my $i = 0; $i < length($seed); $i++) { # First loop is to generate 1 position differ for (my $bs=0; $bs<=3; $bs++) { my $bval = $bs; if ( substr($seed,$i,1) == $bs) { #$bval = 0; next; } my $ns = $seed; substr($ns,$i,1,$bval); print "$ns"; # Second loop for tags in 2 positions differ for (my $j=($i+1); $j < length($seed); $j++) { for (my $cs = 0; $cs<=3;$cs++) { my $cval = $cs; if (substr($ns,$j,1) == $cs) { #$cval = $cs; next; } my $ns2 = $ns; substr($ns2,$j,1,$cval); print "\t$ns2"; } } print "\n"; } }
(Note that I also fixed the outer loop to give its variant digits in order instead of substituting 0 in the original value's place.)

Now, that works, but it's very C-accented Perl and the variable names are pretty cryptic, plus it uses a couple modules that aren't actually used in the code. Here's another version which cleans all that up:

#!/usr/bin/perl use strict; use warnings; # "use warnings" tends to be preferred over "-w" # Seed can be longer than 3 digits but always 0,1,2,3 my $seed = $ARGV[0] || "000"; if ($seed =~ /[^0-3]/) { # "If $seed contains anything other than 0,1 +,2,3" die "Invalid seed. Seed may only contain digits from 0 through 3.\n +"; } # First loop is to generate 1 position differ for my $i (0..length($seed) - 1) { for my $first_diff (0..3) { next if (substr($seed, $i, 1) == $first_diff); my $outer_variant = $seed; substr($outer_variant, $i, 1) = $first_diff; print "$outer_variant"; # Second loop for tags in 2 positions differ for my $j ($i+1..length($seed) - 1) { for my $second_diff (0..3) { next if (substr($outer_variant, $j, 1) == $second_diff); my $inner_variant = $outer_variant; substr($inner_variant, $j, 1) = $second_diff; print "\t$inner_variant"; } } print "\n"; } }
I did use one regex, even though you requested that they not be used, because it's the quickest way to verify that $seed is valid and any other way to validate it would have been much more complex.

Finally, just for fun, let's do it recursively, so that you can easily produce any number of differing positions instead of being limited to 1-2:

#!/usr/bin/perl use strict; use warnings; # Seed can be longer than 3 digits but always 0,1,2,3 my $seed = $ARGV[0] || "000"; if ($seed =~ /[^0-3]/) { die "Invalid seed. Seed may only contain digits from 0 through 3.\n +"; } my $max_differences = 2; frobnicate($seed); sub frobnicate { my ($prefix, $suffix, $difference_count) = @_; unless (defined $suffix) { $suffix = $prefix; $prefix = ''; } $difference_count++; while (length $suffix) { my $initial = substr($suffix, 0, 1); substr($suffix, 0, 1) = ''; for my $substitute (0..3) { next if $substitute == $initial; print "\t" unless $difference_count == 1; print $prefix, $substitute, $suffix; if ($difference_count < $max_differences && length $suffix) { frobnicate($prefix . $substitute, $suffix, $difference_count); } print "\n" if $difference_count == 1; } $prefix .= $initial; } }
Thanks for the Saturday afternoon diversion!

In reply to Re: Finding String's Neighbors By Up To 2 Differing Positions by dsheroh
in thread Finding String's Neighbors By Up To 2 Differing Positions by neversaint

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.