table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
1、42分钟42秒共有多少秒?
因为1分钟等于60秒,所以42分钟换算成秒为
42 × 60 = 2520 秒,
再加上42秒,总共是
2520 + 42 = 2562 秒。
2、10公里等于多少英里?提示:1英里等于1.61公里。
约6.21英里(10÷1.61≈6.21)
3、如果你在42分钟42秒内跑完了10公里的比赛,你的平均配速(每英里用时,以分钟和秒为单位)是多少?你的平均速度是每小时多少英里?
本题可按以下步骤计算平均配速和平均速度:
进行单位换算:
– 1英里约等于1.60934公里,所以10公里换算为英里是
10 ÷ 1.60934 ≈ 6.2137英里
– 42分钟42秒换算为秒是
42 × 60 + 42 = 2562秒
计算平均配速:
总时间除以总英里数得到每英里用时:
2562 ÷ 6.2137 ≈ 412.31秒
412.31秒换算为分钟和秒:
412.31 ÷ 60 = 6分钟余52.31秒
所以平均配速约是
6分52秒每英里
计算平均速度:
总英里数除以总小时数,总时间2562秒换算为小时是:
2562 ÷ 3600 ≈ 0.7117小时
平均速度为:
6.2137 ÷ 0.7117 ≈ 8.73英里每小时
综上:
– 平均配速约是
6分52秒每英里
– 平均速度约是
8.73英里每小时
4、编写一个名为 right_justify 的子程序,该子程序接受一个名为 input_string 的字符串作为参数,并打印该字符串,同时在字符串前添加足够的空格,使得字符串的最后一个字母位于显示界面的第 70 列。
以下是几种实现方式:
分步实现:
use v6;
sub right_justify ($input_string) {
my $str_length = $input_string.chars;
my $missing_length = 70 - $str_length;
my $leading_spaces = " " x $missing_length;
say $leading_spaces, $input_string;
}
合并部分语句和表达式:
use v6;
sub right_justify ($input_string) {
my $leading_spaces = " " x (70 - $input_string.chars);
say $leading_spaces, $input_string;
}
单行实现:
use v6;
sub right_justify ($input_string) {
say " " x (70 - $input_string.chars), $input_string;
}
5、1. 编写一个脚本并进行测试。2. 编写一个 do – twice 函数,使其接受两个参数,一个函数和一个值,并将该值作为参数传递给函数,调用该函数两次。3. 编写一个 print – twice 函数,该函数接受一个参数并将该参数打印两次。4. 使用修改后的 do – twice 函数调用 print – twice 两次,传递 “What’s up doc” 作为参数。5. 定义一个名为 do – four 的新函数,它接受一个函数和一个值,并将该值作为参数传递给函数,调用该函数四次。该函数的主体中应该只有两条语句,而不是四条。
以下是实现上述要求的代码:
# 2. 编写 do-twice 函数
sub do-twice($code, $addressee) {
$code($addressee);
$code($addressee);
}
# 测试 do-twice 函数
sub greet(Str $addr) {
say "Hello $addr!";
}
do-twice &greet, "World";
# 3. 编写 print-twice 函数
sub print-twice($value) {
say $value;
say $value;
}
# 4. 使用修改后的 do-twice 调用 print-twice
do-twice &print-twice, "What’s up doc";
# 5. 定义 do-four 函数
sub do-four($code, $message) {
do-twice($code, $message);
do-twice($code, $message);
}
do-four &print-twice, "What’s up doc";
6、1. 编写一个子程序,绘制如下所示的网格:+ – – – – + – – – – +| | || | || | || | |+ – – – – + – – – – +| | || | || | || | |+ – – – – + – – – – +2. 编写一个子程序,绘制一个类似的四行四列的网格。
以下是绘制给定网格的子程序代码:
use v6;
my $four_dashes = '- ' x 4;
my $dotted_line = ('+ ' ~ $four_dashes ) x 2 ~ '+';
my $spaces = ' ' x 9;
my $empty_line = ('|' ~ $spaces ) x 2 ~ '|';
sub say_four_times($value) {
say $value;
say $value;
say $value;
say $value;
}
sub print_grid {
say $dotted_line;
say_four_times $empty_line;
say $dotted_line;
say_four_times $empty_line;
say $dotted_line;
}
print_grid;
绘制四行四列网格的思路:先修改用于打印行的字符串,再编写
do_four_times
子例程以实现代码复用。示例代码如下:
use v6;
my $four_dashes = '- ' x 4;
my $dotted_line = ('+ ' ~ $four_dashes ) x 4 ~ '+';
my $spaces = ' ' x 9;
my $empty_line = ('|' ~ $spaces ) x 4 ~ '|';
sub do_four_times(&action) {
for 1..4 {
&action();
}
}
sub say_four_times($value) {
do_four_times( { say $value } );
}
sub print_grid_4x4 {
do_four_times( {
say $dotted_line;
say_four_times $empty_line;
} );
say $dotted_line;
}
print_grid_4x4;
7、如果你有三根棍子,你可能能也可能不能将它们摆成一个三角形。例如,如果其中一根棍子长12英寸,另外两根各长1英寸,你将无法让短棍子在中间相接。对于任意三个长度,有一个简单的测试来判断是否可以组成一个三角形:如果三个长度中的任何一个大于另外两个长度之和,那么你就不能组成一个三角形。否则,你可以。(如果两个长度之和等于第三个长度,它们组成所谓的“退化”三角形。)1. 编写一个名为is_triangle的函数,它接受三个正数作为参数,并根据给定长度的棍子是否能组成一个三角形,打印“Yes”或“No”。2. 编写一个函数,提示用户输入三根棍子的长度,并使用is_triangle函数来检查给定长度的棍子是否能组成一个三角形。
以下是实现
is_triangle
函数的代码:
perl
sub is_triangle ( Numeric $x, Numeric $y, Numeric $z) {
my $valid = True;
$valid = False if $x > $y + $z;
$valid = False if $y > $x + $z;
$valid = False if $z > $x + $y;
if $valid {
say "Yes";
} else {
say "No";
}
}
以下是提示用户输入三根棍子长度并使用
is_triangle
函数检查的代码:
perl
my ($a, $b, $c) = split " ", prompt "Please enter three lengths (separated by spaces): ";
is_triangle $a.Int, $b.Int, $c.Int;
8、斐波那契数列由13世纪的意大利数学家莱昂纳多·斐波那契(又名比萨的莱昂纳多,简称斐波那契)提出。斐波那契数列是这样一系列数字:前两个数字等于1,并且该数列中的每个后续数字都定义为前两个数字之和。用数学符号表示,斐波那契数列可以通过递归来定义。1. 编写一个使用for循环的程序,在屏幕上打印前20个斐波那契数。2. 编写一个程序,提示用户输入一个数字n,并使用for循环计算并显示第n个斐波那契数。
1. 打印前20个斐波那契数的程序:
```perl
sub n_fibonacci (Int $n) {
my $fib1 = 1;
my $fib2 = 1;
say $_ for $fib1, $fib2;
for 3..$n {
my $new_fib = $fib1 + $fib2;
say $new_fib;
($fib1, $fib2) = $fib2, $new_fib;
}
}
n_fibonacci 20;
提示用户输入数字n并计算第n个斐波那契数的程序:
my $n = prompt "Enter the searched Fibonacci number: ";
$n = $n.Int;
say fibo($n);
sub fibo (Int $n) {
my ($fib1, $fib2) = 1, 1;
for 3..$n {
my $new_fib = $fib1 + $fib2;
($fib1, $fib2) = $fib2, $new_fib;
}
return $fib2;
}
##9、1. 将这些子程序输入到一个名为palindrome.pl6的文件中并进行测试。如果用包含两个字母的字符串调用middle_l会发生什么?一个字母的字符串呢?空字符串(写为''且不包含任何字母)又会怎样?已知.chars方法可返回字符串的长度,如何添加签名约束来拒绝无效输入?2. 编写一个名为is - palindrome的子程序,它接受一个字符串参数,如果该字符串是回文则返回True,否则返回False。记住可以使用内置的.chars方法来检查字符串的长度。
1. 当使用两个字母的字符串调用 `middle_l` 时,会返回一个空字符串;使用一个字母的字符串调用时,会出现不符合逻辑的结果;使用空字符串调用时,也会出现不符合逻辑的结果。可以在 `middle_l` 的子程序签名中添加约束,如 `sub middle_l(Str $word where $word.chars >= 2)` 来拒绝无效输入。
2. 以下是实现 `is_palindrome` 子程序的代码:
```perl
sub is_palindrome(Str $word) {
return $word eq $word.flip;
}
或使用递归方式:
sub is_palindrome(Str $word) {
return True if $word.chars <= 1;
return False if substr($word, 0, 1) ne substr($word, * - 1, 1);
return is_palindrome(substr($word, 1, * - 1));
}
10、a和b的最大公约数(GCD)是能同时整除它们且没有余数的最大数。一种求两个数最大公约数的方法基于这样的观察:如果r是a除以b的余数,那么a和b的最大公约数等于b和r的最大公约数。作为基本情况,当其中一个数为0时,另一个数就是它们的最大公约数。编写一个名为gcd的函数,它接受参数a和b并返回它们的最大公约数。
以下是几种实现gcd函数的方式:
使用取模运算:
sub gcd(Int $a, Int $b) {
return $a if $b == 0;
return $b if $a == 0;
return gcd($b, $a mod $b);
}
使用减法实现欧几里得算法(考虑修改以处理特殊情况):
sub gcd(Int $a is copy, Int $b is copy) {
$a = -$a if $a < 0;
$b = -$b if $b < 0;
return $a if $b == 0;
return $b if $a == 0;
return gcd($b, $a - $b) if $a > $b;
return gcd($a, $b - $a) if $b > $a;
return $a;
}
分离检查和递归调用:
sub gcd1(Int $c, Int $d) {
return gcd1($d, $c - $d) if $c > $d;
return gcd1($c, $d - $c) if $d > $c;
return $c;
}
sub gcd(Int $a is copy, Int $b is copy) {
$a = -$a if $a < 0;
$b = -$b if $b < 0;
return $a if $b == 0;
return $b if $a == 0;
return gcd1 $a, $b;
}
11、数学家斯里尼瓦瑟·拉马努金发现了一个可以用来生成π数值近似值的无穷级数。编写一个名为 estimate_pi 的函数,使用这个公式来计算并返回π的近似值。该函数应使用 while 循环来计算级数的各项,直到最后一项小于 1e – 15 。你可以通过将结果与内置常量 pi 进行比较来验证结果。
以下是实现该功能的代码:
sub factorial(Int $n) {
return 1 if $n == 0;
return $n * factorial($n - 1);
}
sub estimate_pi {
my $factor = 2 * 2.sqrt / 9801;
my $k = 0;
my $sum = 0;
while (True) {
my $num = factorial(4 * $k) * (1103 + 26390 * $k);
my $den = factorial($k)**4 * 396**(4 * $k);
my $term = $factor * $num / $den;
last if abs($term) < 1e - 15;
$sum += $term;
$k++;
}
return 1 / $sum;
}
print estimate_pi();
这段代码定义了
factorial
函数用于计算阶乘,
estimate_pi
函数使用拉马努金的公式计算π的近似值,通过
while
循环累加级数项,直到最后一项小于 1e – 15,最后返回π的近似值。
12、编写一个正则表达式,用于匹配并捕获较长字符串中连续的10位数字
可以使用以下两种方式:
使用捕获括号:
perl
my $string = "567867 8778689 6765432 0123456789 897898";
say ~$0 if $string ~~ /(d ** 10)/;
省略括号从匹配对象中获取:
perl
my $string = "567867 8778689 6765432 0123456789 897898";
say ~$/ if $string ~~ /d ** 10/;
若要精确匹配10位数字序列(不多于10位),可使用非数字字符类:
my $string = "567867 87786896765432 0123456789 897898";
say ~$0 if $string ~~ /D (d ** 10) D/;
更好的解决方案是使用单词边界锚点:
my $string = "5678670001 87786896765432 0123456789 897898";
say ~$0 if $string ~~ /<< (d ** 10) >>/;
13、编写一个子程序,在循环中使用
index
函数来计算字符串
banana
中字符
a
的数量。修改该子程序,使其能够计算作为参数传递给该子程序的任何单词中任何字母的数量。再编写一个使用
substr
函数来计算给定单词中给定字母数量的子程序。
index
banana
a
substr
使用
index
函数计算
banana
中
a
的数量的子程序:
sub count_a {
my $word = "banana";
my $count = 0;
my $idx = 0;
while (1) {
$idx = index($word, 'a', $idx);
last unless defined $idx;
$idx++;
$count++;
}
return $count;
}
修改后计算任意单词中任意字母数量的子程序:
sub count_index (Str $word, Str $letter) {
my $count = 0;
my $idx = 0;
while (1) {
$idx = index($word, $letter, $idx);
last unless defined $idx;
$idx++;
$count++;
}
return $count;
}
使用
substr
函数计算给定单词中给定字母数量的子程序:
sub count_substr (Str $word, Str $letter) {
my $count = 0;
for (0..$word.chars - 1) {
$count++ if $letter eq substr($word, $_, 1);
}
return $count;
}
14、字符类<[a..z]>匹配任何小写字符(仅为普通 ASCII 小写字符,而非 Unicode 字符)。以下子程序:sub is – lower (Str $input) { return so $input ~~ /^<[a..z]>$/ } 如果其参数是 ASCII 小写字母则应返回 True,否则返回 False。so 函数将正则表达式匹配的结果转换为布尔值。现列出了多个检查字符串是否包含小写字母的子程序,手动分析每个子程序,判断其是否正确,并描述它实际的功能(假设参数是一个字符串)。然后用各种输入字符串进行测试,检查你的分析是否正确。注意:以下有些子程序是错误的。
只有
any_lowercase5
和
any_lowercase7
能正确检查输入字符串是否至少包含一个小写字母。
–
any_lowercase5
在循环前将
$flag
设为
False
,若字符串中有字符为小写则将其改为
True
,循环结束后返回
$flag
。
–
any_lowercase7
若有字符为小写则返回
True
,只有遍历完整个字符串都没有小写字符时才返回
False
。
其他子程序错误如下:
–
any_lowercase1
只检查参数的第一个字符,然后退出循环;
–
any_lowercase2
调用
is-lower
子程序时传入的是字符串
"char"
而非
$char
变量,且和
any_lowercase1
有相同缺陷;
–
any_lowercase3
仅根据输入字符串的最后一个字符返回
True
或
False
;
–
any_lowercase4
存在运算符优先级问题,修改赋值语句可解决;
–
any_lowercase6
算法接近正确,但返回的是字符串
"True"
或
"False"
而非布尔值;
–
any_lowercase8
和
any_lowercase9
若有字符不是小写则返回
False
。
15、凯撒密码是一种弱加密形式,它将每个字母按固定位数“旋转”。旋转一个字母意味着将其在字母表中移动,如果必要则绕回到开头,例如“A”旋转3位是“D”,“Z”旋转1位是“A”。旋转一个单词时,对每个字母进行相同的旋转。例如,“cheer”旋转7位是“jolly”,“melon”旋转 – 10位是“cubed”。在电影《2001太空漫游》中,飞船的计算机名为HAL,它是IBM旋转 – 1位得到的。编写一个名为rotate_word的函数,该函数接受一个字符串和一个整数作为参数,并返回一个新字符串,其中包含原字符串中的字母按给定数量旋转后的结果。你可能需要使用内置函数ord(将字符转换为数字代码,即Unicode码点)和chr(将数字代码转换回字符)。字母表中的字母按字母顺序编码,例如:ord(‘c’) – ord(‘a’)结果为2,因为“c”是字母表中“a”之后的第二个字母。但要注意:大写字母的数字代码不同。互联网上一些可能冒犯人的笑话有时会用ROT13编码,ROT13是旋转位数为13的凯撒密码。由于13是字母表中字母数量的一半,旋转13位两次会得到原始单词,因此相同的过程可用于旋转13位的编码和解码。
以下是实现
rotate_word
功能的代码:
sub rotate_one_letter (Str $letter, Int $shift) {
my $upper_end = 'Z'.ord; # last uppercase letter
my $lower_end = 'z'.ord; # last lowercase letter
my $rotated_ord = $letter.ord + $shift;
if $letter ~~ /<[a..z]>/ { # lowercase
$rotated_ord -= 26 if $rotated_ord > $lower_end;
} elsif $letter ~~ /<[A..Z]>/ { # uppercase
$rotated_ord -= 26 if $rotated_ord > $upper_end;
} else {
return $letter;
}
return $rotated_ord.chr;
}
sub rotate_word (Str $word, Int $shift is copy) {
$shift = $shift % 26;
$shift = 26 + $shift if $shift < 0;
my $rotated_word = "";
for 0..$word.chars - 1 {
$rotated_word ~= rotate_one_letter substr($word, $_, 1), $shift;
}
return $rotated_word;
}
16、编写一个程序,读取 words.txt 文件并仅打印长度超过 20 个字符的单词。
可以使用以下代码实现:
for 'words.txt'.IO.lines -> $line {
say $line if $line.chars > 20
}
也可以在操作系统命令行使用单行命令:
$ perl6 -ne '.say if .chars > 20' words.txt
如果在 Windows 系统下,需将单引号替换为双引号:
C:UsersLaurent>perl6 -ne ".say if .chars > 20" words.txt