# 解 Perl Weekly Challenge 092 -- 同構字串與合併範圍

Perl Weekly Challenge 092 感覺是有點實用的兩個題目。

## TASK #1 › Isomorphic Strings

You are given two strings \$A and \$B.

Write a script to check if the given strings are Isomorphic. Print 1 if they are otherwise 0.

Example 1:

``````Input: \$A = "abc"; \$B = "xyz"
Output: 1
``````

Example 2:

``````Input: \$A = "abb"; \$B = "xyy"
Output: 1
``````

Example 3:

``````Input: \$A = "sum"; \$B = "add"
Output: 0
``````

## 解 #1 › Isomorphic Strings

``````sub isomorphic (Str \$A, Str \$B) {
my %trans;
return False unless \$A.chars == \$B.chars;

# [1]
for 0..^\$A.chars -> \$i {
my \$a = \$A.substr(\$i, 1);
my \$b = \$B.substr(\$i, 1);

if %trans{"ab"}{\$a}:exists and %trans{"ab"}{\$a} ne \$b {
return False
}
%trans{"ab"}{\$a} = \$b;

if %trans{"ba"}{\$b}:exists and %trans{"ba"}{\$b} ne \$a {
return False
}
%trans{"ba"}{\$b} = \$a;
}
return True;
}``````

``````    for \$A.comb Z \$B.comb -> (\$a, \$b) {
...
}``````

``````my @S = (1,1,2,3,5,8,13,21,34);
for @S -> \$a,\$b,\$c {
say "\$a, \$b, \$c";
}
## Output
# 1, 1, 2
# 3, 5, 8
# 13, 21, 34``````

`Z` 算符會建出的的是雙層序列，所以得多加一層小括號，才能讓 `\$a`, `\$b` 接到第二層序列之內的元素。沒加那層括號的話，`\$a`, `\$b` 會接到第二層序列本身。可參考下列兩版本之區別。

``````my @S = (1,1,2,3,5,8,13,21);
my @T = (1,2,3,5,8,13,21,34);

# [2]
for @S Z @T -> \$a,\$b {
say "\$a, \$b";
}

# [3]
for @S Z @T -> (\$a,\$b) {
say "\$a, \$b";
}

## Output of [2]
# 1 1, 1 2
# 2 3, 3 5
# 5 8, 8 13
# 13 21, 21 34

## Output of [3]
# 1, 1
# 1, 2
# 2, 3
# 3, 5
# 5, 8
# 8, 13
# 13, 21
# 21, 34``````

``````say (@S Z @T).gist;
#=> ((1 1) (1 2) (2 3) (3 5) (5 8) (8 13) (13 21) (21 34))

say (@S Z @T).raku;
#=> ((1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21), (21, 34)).Seq``````

## TASK #2 › Insert Interval

You are given a set of sorted non-overlapping intervals and a new interval.

Write a script to merge the new interval to the given set of intervals. Example 1:

``````Input \$S = (1,4), (8,10); \$N = (2,6)
Output: (1,6), (8,10)
``````

Example 2:

``````Input \$S = (1,2), (3,7), (8,10); \$N = (5,8)
Output: (1,2), (3,10)
``````

Example 3:

``````Input \$S = (1,5), (7,9); \$N = (10,11)
Output: (1,5), (7,9), (10,11)
``````

## 解 #2 › Insert Interval

``````sub insert-intervals (@S is copy, \$N) {
# [1]
my \$i = @S.first(-> \$s { \$s[0] <= \$N[0] <= \$s[1] }, :k);
my \$j = @S.first(-> \$s { \$s[0] <= \$N[1] <= \$s[1] }, :k);

# [2]
if \$i.defined {
@S[\$i] = (@S[\$i][0], max(@S[\$i][1], \$N[1]));
}

# [3]
if \$j.defined {
@S[\$j] = (@S[\$j][0], max(@S[\$j][1], \$N[1]));

# [4]
if \$i.defined and @S[\$i][0] <= @S[\$j][0] <= @S[\$i][1] {
@S[\$i] = (@S[\$i][0], @S[\$j][1]);

for \$i^..\$j -> \$x {
@S[\$x] = Nil;
}
}
}

# [5]
if none(\$i.defined, \$j.defined) {
@S.push(\$N);
@S = @S.sort({ \$^a[0] <=> \$^b[0] });
}

# [6]
return @S.grep({ .defined });
}``````