Perl Weekly Challenge 382.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 382.
Task 1: Hamiltonian Cycle
Submitted by: Peter Campbell Smith
You are given a target number.
Write a script to arrange all the whole numbers from 1 up to
the given target number into a circle so that every pair of
side-by-side numbers adds up to a perfect square. Please
make sure, the last number and the first must also add up to
a square.
Example 1
Input: $n = 32
Output: 1, 8, 28, 21, 4, 32, 17, 19, 30, 6, 3, 13, 12, 24,
25, 11, 5, 31, 18, 7, 29, 20, 16, 9, 27, 22, 14, 2,
23, 26, 10, 15
1 + 8 = 9
8 + 28 = 36
28 + 21 = 49
21 + 4 = 25
4 + 32 = 36
32 + 17 = 49
17 + 19 = 36
19 + 30 = 49
so on, all the way through the sequence.

Example 2
Input: $n = 15
Output: ()
No valid circular list of numbers exists.

Example 3
Input: $n = 34
Output: 1, 8, 28, 21, 4, 32, 17, 19, 6, 30, 34, 15, 10, 26,
23, 2, 14, 22, 27, 9, 16, 33, 31, 18, 7, 29, 20, 5,
11, 25, 24, 12, 13, 3

[2026-07-13 11:45]: Output was incorrect, corrected by E. Choroba.
A very inneficient but simple solution is to keep a list of remaining numbers and try to recursively construct a list by adding unused numbers that add to a square until all numbers are used or failure is detected. The result fits a 3-liner.
Examples:
perl -E '
for(@ARGV){say"$_ -> @{f([1],[2..$_])}"}sub f($i, $r){my$l=$i->[-1];@$r||return
g($l+$i->[0])?$i:0;for(0..@$r-1){g($l+$r->[$_])||next;$o=f([@$i,$r->[$_]],
[@$r[0..$_-1,$_+1..@$r-1]]);return $o if $o;}0;}sub g($x){$x==floor(sqrt($x))**2}
' 32 15 34
Results:
32 -> 1 8 28 21 4 32 17 19 30 6 3 13 12 24 25 11 5 31 18 7 29 20 16 9 27 22 14 2 23 26 10 15
15 ->
34 -> 1 3 13 12 4 32 17 8 28 21 15 34 30 19 6 10 26 23 2 14 22 27 9 16 33 31 18 7 29 20 5 11 25 24
By the way, this problem has multiple solutions. My code shows the first one it finds.
The full code follows:
1 # Perl weekly challenge 382
2 # Task 1: Hamiltonian Cycle
3 #
4 # See https://wlmb.github.io/2026/07/13/PWC382/#task-1-hamiltonian-cycle
5 use v5.40;
6 use feature qw(try);
7 use Scalar::Util qw(looks_like_number);
8 die <<~"FIN" unless @ARGV;
9 Usage: $0 N0 N1...
10 to build a Hamiltonian cycle that visits all numbers 1..Nn
11 such that two consecutive numbers in the cycle add to a perfect square.
12 FIN
13 for(@ARGV){
14 try {
15 die "Expected a number: $_"
16 unless looks_like_number $_;
17 say"$_ -> (@{hamiltonian([1],[2..$_])||[]})"
18 }
19 catch($e){warn $e; }
20 }
21 sub hamiltonian($so_far, $rest){
22 my $last=$so_far->[-1];
23 return is_square($last + $so_far->[0])?
24 $so_far : () unless @$rest; # all consumed
25 for(0..@$rest-1){
26 next unless is_square($last + $rest->[$_]);
27 my $result =
28 hamiltonian(
29 [@$so_far, $rest->[$_]],
30 [@$rest[0..$_-1, $_+1..@$rest-1]]
31 );
32 return $result if $result;
33 }
34 return 0;
35 }
36 sub is_square($x){
37 $x==floor(sqrt($x))**2;
38 }
Example:
./ch-1.pl 32 15 34
Results:
32 -> (1 8 28 21 4 32 17 19 30 6 3 13 12 24 25 11 5 31 18
7 29 20 16 9 27 22 14 2 23 26 10 15)
15 -> ()
34 -> (1 3 13 12 4 32 17 8 28 21 15 34 30 19 6 10 26 23 2
14 22 27 9 16 33 31 18 7 29 20 5 11 25 24)
Task 2: Replace Question Mark
Submitted by: Simon Green
You are given a string that contains only 0, 1 and ? characters.
Write a script to generate all possible combinations when
replacing the question marks with a zero or one.
Example 1
Input: $str = "01??0"
Output: ("01000", "01010", "01100", "01110")

Example 2
Input: $str = "101"
Output: ("101")

Example 3
Input: $str = "???"
Output: ("000", "001", "010", "011", "100", "101", "110", "111")

Example 4
Input: $str = "1?10"
Output: ("1010", "1110")

Example 5
Input: $str = "1?1?0"
Output: ("10100", "10110", "11100", "11110")
A simple solution is recursively substituting each question mark by 1 and by 0 until there are no more question marks. I use the option r to return the susbtitutions leaving the original string untouched. This yields a two-liner.
Examples:
perl -E '
for(@ARGV){say "$_ -> ", join " ", f($_);}sub f($s){for($s){
return ($_) unless /\?/;return (f(s/\?/0/r), f(s/\?/1/r));}}
' 01??0 101 ??? 1?10 1?1?0
Results:
01??0 -> 01000 01010 01100 01110
101 -> 101
??? -> 000 001 010 011 100 101 110 111
1?10 -> 1010 1110
1?1?0 -> 10100 10110 11100 11110
I guess there might be some more efficient solution in which the regular expression machine could perform the recursive replacements, but I didn’t pursue it.
The full code is
1 # Perl weekly challenge 382
2 # Task 2: Replace Question Mark
3 #
4 # See https://wlmb.github.io/2026/07/13/PWC382/#task-2-replace-question-mark
5 use v5.36;
6 use feature qw(try);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 S0 S1...
9 to substitute the each question mark (?) by 0 and by 1
10 in the strings Sn.
11 FIN
12 for(@ARGV){
13 try {
14 die "Only 1, 0 and ? are allowed: $_" unless /^[01\?]*$/;
15 say "$_ -> (", join(" ", replace($_)), ")";
16 }
17 catch($e){warn $e}
18 }
19 sub replace ($s){
20 for($s){
21 return ($_) unless /\?/;
22 return (replace(s/\?/0/r), replace(s/\?/1/r));
23 }
24 }
Example:
./ch-2.pl 01??0 101 ??? 1?10 1?1?0
Results:
01??0 -> (01000 01010 01100 01110)
101 -> (101)
??? -> (000 001 010 011 100 101 110 111)
1?10 -> (1010 1110)
1?1?0 -> (10100 10110 11100 11110)
/;