作为一个非科班出身的程序猿,算法始终是个软肋。之前倒也抽时间断断续续看了点算法的书,但基本过目即忘,可能每个算法都实际实现以下,编写下练习代码才能更好的学习。于是在github上创建了一个仓库,用来一个个实现算法。置于语言的选择,都说语言不过是工具,算法才是核心,那么就多用几种语言来实现吧。其实我会的语言也不多,c/c++可能还好,再就是个初学者阶段的Python,在实现算法的过程中,也能练习下这些语言的使用,一箭双雕呀,哈哈,有点小激动呢。
github上的仓库地址如下:
[email protected]:haoranzeus/algorithms_study.git
既然是在世界流行的github上创建仓库,上面我也尽量使用英文,虽然我这英文水平有点惨不忍睹。
好,让我们开始吧。
算法书上面开始介绍的算法必然是排序,要排序就要有数可排,那么就先写一个生成随机数的程序吧。
需求如下:
1. 生成随机数写入文件。
2. 制定生成整数还是浮点数。
3. 指定生成的数的大小范围。
4. 指定保存到文件的数之间的分隔符。
这里我创建一个mypackage的路径,用于存放以后可能有复用价值的包,关于这种向文件里写数据的功能,就放到这里的myio.py里面。然后random_number_generator/random_number_generator.py用于实现生成随机数。
生成随机数的代码如下:
from random import uniform, randint def randNumGenerator(numbType, numMin, numMax, numb): """ numbType: an "int" for initerator, and a "float" for float number. numMin: The nimimum for the number generatored. numMax: the maximum for the number generatored. numb: the number of numbers generatored. """ if numbType == "int": generator = randint elif numbType == "float": generator = uniform else: raise AttributeError("invalid value for type: %s" % numbType) numMin = int(numMin) numMax = int(numMax) numb = int(numb) while numb > 0: yield generator(numMin, numMax); numb -= 1
这段代码采用标准标准包random中的uniform和randint分别实现生成随机浮点数和随机整数。
参数分别表示要生成的数的类型、最小值、最大值以及要生成的 数据个数。
该函数返回生成器,每次生成一个随机数,直至生成了指定的个数。
然后是该函数的单元测试:
import unittest class TestRandNumGenerator(unittest.TestCase): def test_generatorInit(self): i = 0 for n in randNumGenerator("int", 0, 10000, 20): i += 1 self.assertTrue(n >= 0) self.assertTrue(n <= 10000) self.assertTrue(isinstance(n, int)) self.assertEqual(i, 20) def test_generatorFloat(self): i = 0 for n in randNumGenerator("float", 0, 10000, 20): i += 1 self.assertTrue(n >= 0) self.assertTrue(n <= 10000) self.assertTrue(isinstance(n, float)) self.assertEqual(i, 20) def test_typeError(self): with self.assertRaises(AttributeError): g = randNumGenerator("unknowType", 0, 10000, 20) g.__next__()
unittest运行有两种方法,一种是添加代码:
if __name__ == '__main__': unittest.main()
这样就默认运行单元测试了。但是我想让他默认运行的是写入文件的功能,所以采用另一种运行单元测试的方式:
python3 -m unittest random_number_generator
接着是写入文件的操作。我将其放到mypackage/myio.py中,代码如下:
class MyIo(object): def __init__(self, path): self.path = path def writeSeperated(self, generator, separator = " "): """ generator: a generator to generate fragments to write in file separator: separator between fragments. """ with open(self.path, "w") as f: for frag in generator: f.write(str(frag)) f.write(str(separator)) f.close()
所有文件操作都放到一个MyIo的类中,初始化时会接收一个参数,表示文件路径。
这种以分隔符分隔数据写入文件的方法定义为writeSeperated,第一个参数是一个迭代器,用于生成要写入的数据,第二个参数是分隔符,默认是空格。
最后就是用生成随机数的迭代器带入到写入文件的函数中,一个交互式的生成随机数文件的函数如下:
def writeToFile(): path = input("Please input the whole path of file:\n") numType = input('You want to generate "int" or "float"?\ntype "int" or "float":\n') minNum = input('the minimum value of the generated numbers:') maxNum = input('the maximum value of the generated numbers:') numb = input('the number you want to generate:') separator = input('the separator:') import sys sys.path.append("..") from mypackage.myio import MyIo myio = MyIo(path) myio.writeSeperated(randNumGenerator(numType, minNum, maxNum, numb))
这个函数会以交互式的形式获取文件的路径、数据的类型、最大最小值、要生成的随机数的个数,以及分隔符。调用这个函数:
if __name__ == '__main__': writeToFile()
怕麻烦,C语言的实现直接一个文件搞定了,位于c/random_number_generator/main.c,代码如下:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> int main() { char path[100]; char type[10]; int min; int max; int numb; char separator[10]; printf("Please input the whole path of file:\n"); scanf("%s", path); printf("You want to generate \"int\" or \"float\"?\ntype \"int\" or \"float\":\n"); scanf("%s", type); if ( strncmp("int", type, 3) && strncmp("float", type, 5)) { printf("ERROR: unknow type : %s\n", type); return 0; } printf("the minimum value of the generated numbers:"); scanf("%d", &min); printf("the maximum value of the generated numbers:"); scanf("%d", &max); printf("the number you want to generate:"); scanf("%d", &numb); printf("the separator:"); scanf("%s", separator); FILE * f = fopen(path, "w"); srand((unsigned)time(NULL)); int range = max - min; for (int i = 0; i < numb; i++) { if ( !strncmp("int", type, 3) ) fprintf(f, "%d%s", rand() % range + min, separator); else if ( !strncmp("float", type, 5) ) { double rdnumb = (rand() % (range * 100) / 100.00) + min; fprintf(f, "%f%s", rdnumb, separator); } } fclose(f); }