2019独角兽企业重金招聘Python工程师标准>>>
Q1. (0) For-loop
- 创建一个基于 for 的简单的循环。使其循环 10 次,并且使用 fmt 包打印出计数 器的值。
- 用 goto 改写 1 的循环。关键字 for 不可使用。
- 再次改写这个循环,使其遍历一个 array,并将这个 array 打印到屏幕上。
Q2. (0) FizzBuzz
- 解决这个叫做 Fizz-Buzz[23] 的问题: 编写一个程序,打印从 1 到 100 的数字。
当是3的倍数就打印 “Fizz” 代替数字,当是5的倍数就打印 “Buzz”。
当数字同时是3和5的倍数 时,打印 “FizzBuzz”。
Q3. (1) 字符串
- 建立一个 Go 程序打印下面的内容(到 100 个字符):
A
AA
AAA
AAAA
AAAAA
AAAAAA
AAAAAAA
… - 建立一个程序统计字符串里的字符数量:
asSASA ddd dsjkdsjs dk
同时输出这个字符串的字节数。
提示: 看看 unicode/utf8 包。 - 扩展/修改上一个问题的程序,替换位置 4 开始的三个字符为 “abc”。
- 编写一个 Go 程序可以逆转字符串,例如 “foobar” 被打印成 “raboof”。
Q4. (1) 平均值
- 编写计算一个类型是 float64 的 slice 的平均值的代码。在稍候的练习 Q5 中 将会改写为函数。
Q5. (0) 平均值
- 编写一个函数用于计算一个 float64 类型的 slice 的平均值。
Q6. (0) 整数顺序
- 编写函数,返回其(两个)参数正确的(自然)数字顺序:
f(7,2) → 2,7
f(2,7) → 2,7
Q7. (1) 作用域
- 下面的程序有什么错误?
package main
import "fmt"
func main() {
for i := 0 ; i < 10 ; i++ {
fmt.Printf("%v\n", i)
}
fmt.Printf("%v\n", i)
}
Q8. (1) 栈
- 创建一个固定大小保存整数的栈。它无须超出限制的增长。定义 push 函数—— 将数据放入栈,和 pop 函数——从栈中取得内容。栈应当是后进先出(LIFO) 的。
- 更进一步。编写一个 String 方法将栈转化为字符串形式的表达。可以这样的 方式打印整个栈:
fmt.Printf("My stack %v\n", stack)
栈可以被输出成这样的形式:
[0:m] [1:l] [2:k]
Q9. (1) 变参
- 编写函数接受整数类型变参,并且每行打印一个数字。
Q10. (1) 斐波那契
- 斐波那契数列以:
1, 1, 2, 3, 5, 8, 13, . . . 开始。
或者用数学形式表达:
x1 = 1; x2 =1; xn = xn−1 + xn−2 ∀n > 2。
编写一个接受 int 值的函数,并给出这个值得到的斐波那契数列。
Q11. (1) map 函数
map() 函数是一个接受一个函数和一个列表作为参数的函数。函数应用于列表中的每个元素,而一个新的包含有计算结果的列表被返回。因此:
map(f(),(a1, a2, . . . , an−1, an)) = (f(a1), f(a2), . . . , f(an−1), f(an))
- 编写 Go 中的简单的 map() 函数。它能工作于操作整数的函数就可以了。
- 扩展代码使其工作于字符串列表。
Q12. (0) 最小值和最大值
- 编写一个函数,找到 int slice ([]int) 中的最大值。
- 编写一个函数,找到 int slice ([]int) 中的最小值。
Q13. (1) 冒泡排序
-
编写一个针对 int 类型的 slice 冒泡排序的函数。
它在一个列表上重复步骤来排序,比较每个相䩪的元素,并且顺序错误的时候,交换它们。
一遍一遍扫描列表,直到没有交换为止,这意 味着列表排序完成。
算法得名于更小的元素就像 “泡泡” 一样冒到列表的別端。这里有一个过程代码作为示例:
procedure bubbleSort( A : list of sortable items )
do
swapped = false
for each i in 1 to length(A) - 1 inclusive do:
if A[i-1] > A[i] then
swap( A[i-1], A[i] )
swapped = true
end if
end for
while swapped
end procedure
Q14. (1) 函数返回一个函数
- 编写一个函数返回另一个函数,返回的函数的作用是对一个整数 +2。函数的名称叫做 plusTwo。然后可以像下面这样使用:
p := plusTwo()
fmt.Printf("%v\n", p(2))
应该打印 4 - 使 1 中的函数更加通用化,创建一个 plusX(x) 函数,返回一个函数用于对整 数加上 x。
Q15. (0) stack 包
- 参考 Q8 练习。在这个练习中将从那个代码中建立一个独立的包。为 stack 的实现创建一个合适的包,Push、Pop 和 Stack 类型需要被导出。
- 为这个包编写一个单元测试,至少测试 Push 后 Pop 的工作情况。
Q16. (2) 计算器
- 使用 stack 包创建逆波兰计算器
Q17. (1) 指针运算
- 在正文的第 54 页有这样的文字: …这里没有指针运算,因此如果这样写:p++,它被解释为 (p)++: 首先解析引用然后增加值。 当像这样增加一个值的时候,什么类型可以工作?
- 为什么它不能工作在所有类型上?
Q18. (2) 使用 interface 的 map 函数
- 使用练习 Q11 的答案,利用 interface 使其更加通用。让它至少能同时工作于int 和 string。
Q19. (1) 指针
- 假设定义了下面的结构:
type Person struct {
name string
age int
}
下面两行之间的区别是什么?
var p1 Person p2 := new(Person) - 下面两个内存分配的区别是什么?
func Set(t *T) {
x = t
}
和
func Set(t T) {
x= &t
}
Q20. (1) Linked List
- Make use of the package container/list to create a (doubly) linked list. Push the values 1, 2 and 4 to the list and then print it.
- Create your own linked list implementation. And perform the same actions as in question 1
Q21. (1) Cat
- 编写一个程序,模仿 Unix 的 cat 程序。对于不知道这个程序的人来说,下面的调用显示了文件 blah 的内容: % cat blah
- 使其支持 n 开关,用于输出每行的行号。
- 上面问题中,1 提供的解决方案存在一个 Bug。你能定位并修复它吗?
Q22. (2) 方法调用
- 假设有下面的程序。要注意的是包 container/vector 曾经是 Go 的一部分,但是 当内建的 append 出现后,就被移除了。然而,对于当前的问题这不重要。这个 包实现了有 push 和 pop 方法的栈结构。
package main
import "container/vector"
func main() {
k1 := vector.IntVector{ }
k2 := &vector.IntVector{ }
k3 := new(vector.IntVector)
k1.Push(2)
k2.Push(3)
k3.Push(4)
}
k1,k2 和 k3 的类型是什么? - 当前,这个程序可以编译并且运行良好。在不同类型的变量上 Push 都可以工作。
Push 的文档这样描述:
func (p *IntVector) Push(x int) Push 增加 x 到向量的末尾。
那么接受者应当是 *IntVector 类型,为什么上面的代码(Push 语句)可以正确工作? above (the Push statements) work correct then?
Q23. (1) 接口和编译
- 在第 72 页的代码 5.3 编译正常——就像文中开始描述的那样。但是当运行的时候,会得到运行时错误,因此有些东西有错误。为什么代码编译没有问题呢?
Q24. (1) 指针和反射
- 在第 “自省和反射” 节,第 76 页的最后一段中,有这样的描述:
"右边的代码没有问题,并且设置了成员变量 Name 为 “Albert Einstein”。"
当然,这仅仅工作于调用 Set() 时传递一个指针参数。
为什么是这样的情况?
Q25. (2) 接口和 max()
- 在练习 Q12 中创建了工作于一个整形 slice 上的最大函数。现在的问题是创建一个显示最大数字的程序,同时工作于整数和浮点数。虽然在这里会相当困难, 不过还是让程序尽可能的通用吧。
Q26. (1) Channel
- 修改在练习 Q1 中创建的程序,换句话说,主体中调用的函数现在是一个goroutine 并且使用 channel 通讯。
不用担心 goroutine 是如何停止的。 - 在完成了问题 1 后,仍有一些待解决的问题。其中一个麻烦是 goroutine 在main.main() 结束的时候,没有进行清理。
更糟的是,由于 main.main() 和main.shower() 的竞争关系,不是所有数字都被打印了。
本应该打印到 9,但是有时只打印到 8。
添加第二个退出 channel,可以解决这两个问题。
试试吧。
Q27. (2) 斐波那契 II
- 这是类似的练习,第一个在第 34 页的练习 10。完整的问题描述:
斐波那契数列以:
1, 1, 2, 3, 5, 8, 13, . . . 开头。
或用数学形式:
x1 = 1; x2 = 1; xn = xn−1 + xn−2 ∀n > 2。
编写一个函数接收 int 值,并给出同样数量的斐波那契数列。 但是现在有额外条件:必须使用 channel。
Q28. (2) 进程
-
编写一个程序,列出所有正在运行的进程,并打印每个进程执行的子进程个数。 输出应当类似:
Pid 0 has 2 children: [1 2]
Pid 490 has 2 children: [1199 26524]
Pid 1824 has 1 child: [7293]
• 为了获取进程列表,需要得到 ps -e -opid,ppid,comm 的输出。
输出类 似:
PID PPID COMMAND
9024 9023 zsh
19560 9024 ps
• 如果父进程有一个子进程, 就打印 child, 如果多于一个, 就打印 children;
• 进程列表要按照数字排序,这样就以 pid 0 开始,依次展示。
这里有一个 Perl 版本的程序来帮助上手(或者造成绝对的混乱)。!/usr/bin/perl -l
my (%child, $pid, $parent) ;
my @ps=`ps -e -opid,ppid,comm` ; # Capture the output from `ps`
foreach ([@ps][1..$#ps]) { # Discard the header line
($pid, $parent, undef) = split ; # Split the line,discard 'comm'
push @{$child{$parent} }, $pid ; # Save the child PIDs on a list
}# Walk through the sorted PPIDs
foreach (sort { $a <=> $b } keys %child) {
print "Pid ", $, " has ", @{$child{$} }+0, " child", @{$child{$} } == 1 ? ": " : "ren: ", "\[@{$child{$} }\]" ;
}
Q29. (0) 单词和字母统计
- 编写一个从标准输入中读取文本的小程序,并进行下面的操作:
- 计算字符数量(包括空格);
- 计算单词数量;
- 计算行数。 换句话说,实现一个 wc(1)(参阅本地的手册页面),然而只需要从标准输入读 取。
Q30. (0) Uniq
-
编写一个 Go 程序模仿 Unix 命令 uniq 的功能。程序应当像下面这样运行,提供一个下面这样的列表:
'a' 'b' 'a' 'a' 'a' 'c' 'd' 'e' 'f' 'g'
它将打印出没有后续重复的项目:
'a' 'b' 'a' 'c' 'd' 'e' 'f'
下面列出的 是 Perl 实现的算法。/# !/usr/bin/perl
my @a = qw/a b a a a c d e f g/ ;
print my $first = shift @a ;
foreach (@a) {
if ($first ne $) { print ; $first = $ ; }
}
附加题:
Q31. (2) Quine Quine 是一个打印自己的程序。
- 用 Go 编写一个 Quine 程序。
Q32. (1) Echo 服务
- 编写一个简单的 echo 服务。使其监听于本地的 TCP 端口 8053 上。它应当可以读取一行(以换行符结尾),将这行原样返回然后关闭连接。
- 让这个服务可以并发,这样每个请求都可以在独立的 goroutine 中进行处理。
Q33. (2) 数字游戏
• 从列表中随机选择六个数字:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100
数字可以多次被选中;
• 从 1 . . . 1000 中选择一个随机数 i;
• 尝试用先前的六个数字(或者其中的几个)配合运算符 +,−,∗ 和 /,计算出 i;
例如,选择了数字:1,6,7,8,8 和 75。并且 i 为 977。
可以用许多方法来实现,其 中一种:
((((1 ∗ 6) ∗ 8) + 75) ∗ 8) − 7 = 977
或者
(8 ∗ (75 + (8 ∗ 6))) − (7/1) = 977
- 实现像这样的数字游戏。使其打印像上面那样格式的结果(也就是说,输出应 当是带有括号的中序表达式)
- 计算全部可能解,并且全部显示出来(或者仅显示有多少个)。在上面的例子 中,有 544 种方法。
Q34. (1) *Finger 守护进程
-
编写一个 finger 守护进程,可以工作于 finger(1) 命令。 来自 Debian 的包描述: Fingerd 是一个基于 RFC 1196 [28] 的简单的守护进程,它为许多站点提供了 “finger” 程序的接口。这个程序支持返回一个友好的、面向用户的系统或用户当前ⱥ况的详细报告。 最基本的只需要支持用户名参数。如果用户有 .plan 文件,则显示该文件内容。 因此程序需要能够提供:
• 用户存在吗?
• 如果用户存在,显示 .plan 文件的内容。格式编辑挺繁琐的,后续再回给出参考答案