Perl Weekly Challenge 224.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 224.
Task 1: Special Notes
Submitted by: Mohammad S Anwar
You are given two strings, $source and $target.
Write a script to find out if using the characters (only once) from source,
a target string can be created.
Example 1
Input: $source = "abc"
$target = "xyz"
Output: false
Example 2
Input: $source = "scriptinglanguage"
$target = "perl"
Output: true
Example 3
Input: $source = "aabbcc"
$target = "abc"
Output: true
I can keep a hash with the characters of the source as keys and the value 1 if the character has not been seen in target, or less if it has already been seen. The special notes are those whose characters correspond to the (initial) value 1. This may be coded in a simple one liner.
Example 1:
perl -MList::Util=all -E '
print "@ARGV->"; $s{$_}=1 for split "", shift; say +(all {$s{$_}-->0} split "", shift)?"True":"False"
' abc xyz
Results:
abc xyz->False
Example 2:
perl -MList::Util=all -E '
print "@ARGV->"; $s{$_}=1 for split "", shift; say +(all {$s{$_}-->0} split "", shift)?"True":"False"
' scriptinglanguage perl
Results:
scriptinglanguage perl->True
Example 3:
perl -MList::Util=all -E '
print "@ARGV->"; $s{$_}=1 for split "", shift; say +(all {$s{$_}-->0} split "", shift)?"True":"False"
' aabbcc abc
Results:
aabbcc abc->True
The full code is similar
1 # Perl weekly challenge 224
2 # Task 1: Special Notes
3 #
4 # See https://wlmb.github.io/2023/07/03/PWC224/#task-1-special-notes
5 use v5.36;
6 use List::Util qw(all);
7 die <<~"FIN" unless @ARGV==2;
8 Usage: $0 source target
9 to find out if target may be written with non-repeated characters from source.
10 FIN
11 my ($source, $target)=@ARGV;
12 my %available;
13 $available{$_}=1 for split "", $source; # initialize available character counts
14 my $output=(all {$available{$_}-- > 0} split "", $target)?"True":"False";
15 say "source: $source, target: $target -> $output";
Examples:
./ch-1.pl abc xyz
./ch-1.pl scriptinglanguage perl
./ch-1.pl aabbcc abc
Results:
source: abc, target: xyz -> False
source: scriptinglanguage, target: perl -> True
source: aabbcc, target: abc -> True
Task 2: Additive Number
Submitted by: Mohammad S Anwar
You are given a string containing digits 0-9 only.
Write a script to find out if the given string is additive number. An additive number
is a string whose digits can form an additive sequence.
A valid additive sequence should contain at least 3 numbers. Except the first 2 numbers,
each subsequent number in the sequence must be the sum of the preceding two.
Example 1:
Input: $string = "112358"
Output: true
The additive sequence can be created using the given string digits: 1,1,2,3,5,8
1 + 1 => 2
1 + 2 => 3
2 + 3 => 5
3 + 5 => 8
Example 2:
Input: $string = "12345"
Output: false
No additive sequence can be created using the given string digits.
Example 3:
Input: $string = "199100199"
Output: true
The additive sequence can be created using the given string digits: 1,99,100,199
1 + 99 => 100
99 + 100 => 199
I can test a given choice for the first two numbers and generate
the remaining numbers in the sequence until I have success (I get to
the end of the string) or failure (I generate a number that doesn’t
follow in the sequence), in which case, I can test the next pair of
generating numbers. I go on until I succeed and the result is true
or until I consume all generating number pairs. I’ll leave some
optimization to the full code. The solution may be coded into a
three-liner.
Examples:
perl -E '
L: for(@ARGV){$l=length; for my $x(1..$l){$c=$_; $f=substr $c,0,$x,""; for my $y(1..$l){
$d=$c; $g=substr $d,0,$y,""; $h=$f+$g; while($d=~s/^$h//){say("$_ -> True"), next L if
length $d==0; ($g, $h)=($h, $g+$h)}}} say "$_ -> False";}
' 112358 12345 199100199
Results:
112358 -> True
12345 -> False
199100199 -> True
Other examples:
perl -E '
L: for(@ARGV){$l=length; for my $x(1..$l){$c=$_; $f=substr $c,0,$x,""; for my $y(1..$l){
$d=$c; $g=substr $d,0,$y,""; $h=$f+$g; while($d=~s/^$h//){say("$_ -> True"), next L if
length $d==0; ($g, $h)=($h, $g+$h)}}} say "$_ -> False";}
' 1001002003005008001300 101102203305 991100101201
Results:
1001002003005008001300 -> True
101102203305 -> True
1 # Perl weekly challenge 224
2 # Task 2: Additive Number
3 #
4 # See https://wlmb.github.io/2023/07/03/PWC224/#task-2-additive-number
5 use v5.36;
6 use List::Util qw(max min);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 S1 [S2...]
9 to check if the strings S1 S2... correspond to additive numbers.
10 FIN
11 INPUT: for(@ARGV){
12 say("String should contain digits only: $_"), next INPUT unless /^\d+$/;
13 my $length=length;
14 FIRST: for my $length1(1..$length/2){ # no need to consider larger first numbers
15 my $copy=$_; # make a copy of input string
16 my $previous=substr $copy, 0, $length1, ""; # choose the starting number
17 for my $length2(1..$length/2){
18 # ignore numbers that are too large:
19 next FIRST if 2*max($length1,$length2) > $length - min($length1, $length2);
20 my $copy_of_copy=$copy;
21 my $current=substr $copy_of_copy, 0, $length2, "";
22 my $next=$previous + $current;
23 while($copy_of_copy=~s/^$next//){ # found next number in sequence?
24 say("$_ -> True"), next INPUT if length $copy_of_copy==0; # Finished?
25 ($current, $next)=($next, $current+$next)
26 }
27 }
28 }
29 say "$_ -> False";
30 }
31
Examples:
./ch-2.pl 112358 12345 199100199 1001002003005008001300 101102203305 991100101201
Results:
112358 -> True
12345 -> False
199100199 -> True
1001002003005008001300 -> True
101102203305 -> True
991100101201 -> True
/;