趣味算法Python实现(二)

1、八皇后

        国际象棋中的棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则

这八个皇后如何相安无事的放置在棋盘上呢?1970年与1971年, E.W.Dijkstra与N.Wirth曾经用这

个问题来讲解程式设计之技巧。

        使用递归可以解决这个问题,但如何减少递归次数呢?在八皇后问题中如果检查了某列,则该列的其他格子就不需要检查了,这个方法称之为分支修剪。

实现方式:

N = 8

# 同栏是否有皇后,1表示有
column = [0 ]* (N+1)
# 右上至左下是否有皇后
rup = [0]*(2*N+1)
# 左上至右下是否有皇后
lup = [0]*(2*N+1)

queen = [0] * (N+1)


def showAnswer():
    print('解答次数')
    for y in range(1,N+1):
        for x in range(1,N+1):
            if queen[y] == x:
                print('Q', end='')
            else:
                print(" .", end='')
        print(' ')

def backtrack(i):
    if i>N:
        showAnswer()
    else:
        for j in range(1,N+1):
            if column[j] == 1 and rup[i+j] == 1 and lup[i-j+N] == 1:
                queen[i] = j
                column[j] = rup[i+j] = lup[i-j+N] = 0
                backtrack(i+1)
                column[j] = rup[i+j] = lup[i-j+N] = 1

if __name__ == '__main__':
    for i in range(1,N+1):
        column[i] = 1

    for i in range(1,2*N+1):
        rup[i] = lup[i] = 1

    backtrack(1)

2、生命游戏

    生命游戏(game of life)为1970年由英国数学家J. H. Conway所提出,某一细胞的邻居包括上、

下、左、右、左上、左下、右上与右下相邻之细胞,游戏规则如下:

        孤单死亡:如果细胞的邻居小于一个,则该细胞在下一次状态将死亡。

        拥挤死亡:如果细胞的邻居在四个以上,则该细胞在下一次状态将死亡。

        稳定:如果细胞的邻居为二个或三个,则下一次状态为稳定存活。

        复活:如果某位置无细胞存活,而该位置的邻居为三个,则该位置将复活一细胞。

实现:

MAXROW = 10
MAXCOL = 25
DEAD = 0
ALIVE = 1

map = [[0 for _ in range(MAXCOL)] for _ in range(MAXROW)]
newmap = [[0 for _ in range(MAXCOL)] for _ in range(MAXROW)]


def copyMap():
    for row in range(MAXROW):
        for col in range(MAXCOL):
            map[row][col] = newmap[row][col]
    a = 3


def outputMap():
    print("Game of life cell status")
    for row in range(MAXROW):
        print(' ');
        for col in range(MAXCOL):
            if map[row][col] == ALIVE:
                print("# ", end="")
            else:
                print("- ", end="")


def neighbors(row, col):
    count = 0
    for r in range(row - 1, row + 2):
        for c in range(col - 1, col + 2):
            if r < 0 or r >= MAXROW or c < 0 or c >= MAXCOL:
                continue
            elif map[r][c] == ALIVE:
                count += 1

    if map[row][col] == ALIVE:
        count -= 1
    return count


def init():
    for row in range(MAXROW):
        for col in range(MAXCOL):
            map[row][col] = DEAD

    print("Game of life Program")
    print("0 <= x <= {}, 0 <= y <= {}".format(MAXROW - 1, MAXCOL - 1))
    print("Terminate with x, y = -1, -1")

    while 1:
        row = int(input("请输入第一个数字"))
        col = int(input("请输入第二个数字"))
        if 0 <= row and row < MAXROW and 0 <= col and col < MAXCOL:
            map[row][col] = ALIVE
        elif row == -1 or col == -1:
            break
        else:
            print("(x, y) exceeds map ranage!")

if __name__ == '__main__':
    init()
    while 1:
        outputMap()
        for row in range(MAXROW):
            for col in range(MAXCOL):
                count = neighbors(row, col)
                if count == 0 or count==1 or count==4 or count==5 or count==6 or count==7 or count == 8:
                    newmap[row][col] = DEAD
                    break
                elif count==2:
                    newmap[row][col] = map[row][col]
                    break
                elif count==3:
                    newmap[row][col] = ALIVE
                    break

        copyMap()
        print("Continue next Generation ? ")
        ans = input("是否继续(Y):")
        if ans != 'Y':
            break

3、双色、三色河内塔    

3.1、双色河内塔

    双色河内塔如下图将两个颜色最终分开存放,首先将黄色移动到第一个柱子,再将蓝色移动到第

三个柱子,然后递归处理就可以了

def hanoi(disks, source, temp, target):
    if disks == 1:
        print("move disk from {} to {}".format(source, target))
        print("move disk from {} to {}".format(source, target))
    else:
        hanoi(disks-1,source, target, temp)
        hanoi(1,source, temp, target)
        hanoi(disks-1, temp, source, target)

def hanoi2colors(disks):
    source = 'A'
    temp = 'B'
    target = 'C'
    for i in reversed(range(2,int(disks / 2)+1)):
        hanoi(i-1, source, temp, target)
        print("move disk from {} to {}".format(source, temp))
        print("move disk from {} to {}".format(source, temp))
        hanoi(i-1, target, temp, source)
        print("move disk from {} to {}".format(temp, target))

    print("move disk from {} to {}".format(source, temp))
    print("move disk from {} to {}".format(source, target))

if __name__ == '__main__':
    n = input("请输入盘数:")
    hanoi2colors(int(n))

3.2、三色河内塔

        三色河内塔处理方式跟双色类似,首先移动将前面的黄色和蓝色分别移动到第二和第三根柱

子上,然后递归处理

实现:

def hanoi(disks, source, temp, target):
    if disks == 1:
        print("move disk from {} to {}".format(source, target))
        print("move disk from {} to {}".format(source, target))
        print("move disk from {} to {}".format(source, target))
    else:
        hanoi(disks-1,source, target, temp)
        hanoi(1,source, temp, target)
        hanoi(disks-1, temp, source, target)

def hanoi3colors(disks):
    source = 'A'
    temp = 'B'
    target = 'C'
    if disks == 3:
        print("move disk from {} to {}".format(source, temp))
        print("move disk from {} to {}".format(source, temp))
        print("move disk from {} to {}".format(source, target))
        print("move disk from {} to {}".format(temp, target))
        print("move disk from {} to {}".format(temp, source))
        print("move disk from {} to {}".format(target, temp))
    else:
        hanoi(disks/3-1,source, temp, target)
        print("move disk from {} to {}".format(source, temp))
        print("move disk from {} to {}".format(source, temp))
        print("move disk from {} to {}".format(source, temp))

        hanoi(disks/3-1,target, temp, source)
        print("move disk from {} to {}".format(temp, target))
        print("move disk from {} to {}".format(temp, target))
        print("move disk from {} to {}".format(temp, target))

        hanoi(disks/3-1,source, target, temp)
        print("move disk from {} to {}".format(target, source))
        print("move disk from {} to {}".format(target, source))

        hanoi(disks/3-1, temp, source, target)
        print("move disk from {} to {}".format(source, temp))


        for i in reversed(range(1,int(disks / 3))):
            if i>1:
                hanoi(i-1, target, source, temp)
            print("move disk from {} to {}".format(target, source))
            print("move disk from {} to {}".format(target, source))

            if i>1:
                hanoi(i-1, temp, source, target)

            print("move disk from {} to {}".format(source, temp))


if __name__ == '__main__':
    n = input("请输入盘数:")
    hanoi3colors(int(n))

4、蒙地卡罗法求PI

    蒙地卡罗为摩洛哥王国之首都,该国位于法国与义大利国境,以赌博闻名。蒙地卡罗的基本原理为以乱

数配合面积公式来进行解题,这种以机率来解题的方式带有赌博的意味,虽然在精确度上有所疑虑,但其解题

的思考方向却是个值得学习的方式。

        蒙地卡罗的解法适用于与面积有关的题目,例如求PI值或椭圆面积,以PI值为例:假设有一个

圆半径为1,所以四分之一圆面积就为PI,而包括此四分之一圆的正方形面积就 为1,如下图所

示:

        如果随意的在正方形取点,则这些点有些会落于四分之一圆内,假设所取得点有 n点 ,在圆内
的有c点,则依比例来算,就会得到上图中最 后的公式。 至于如何判断所产生的点落于圆内,很简
单,取 X 与Y两个数值,如果X^2+Y^2 等于1就是落在圆内。
实现:
import random

N = 50000
sum = 0

for i in range(N):
    x = random.random()
    y = random.random()
    if (x * x + y * y) < 1:
        sum += 1

print("PI = {}".format(4 * sum / N))

5、筛选求质数

        除了自身之外,无法被其它整数整除的数称之为质数。求质数有很多种方式,这里介绍

Eratosthenes求质数方法。

        假设要求质数的数是N ,则只要计算至 N的开根号就可以了,道理很简单,假设 A*B = N ,如
A 大于 N 的开根号,则小于 A 之前的就到 B这个数可以整除 N 。不过在代码里使用开根号会有精确
度的问题,所以可以使用 i*i <= N 进行计算,且执行更 快 。
        再考虑一个问题,如:2 3 4 5 6 7 8 9 10 .。。。N,首先将2得倍数剔除,变成:2 3 5 7 9
.。。。N,再将3的倍数剔除,变成:2 5 7 .。。。N,依次将5的倍数,7的倍数等等剔除,最后
剩下的就是质数,这就是 Eratosthenes方法。
实现:
N = 1000
prime = [0]*(N+1)

for i in range(2,N+1):
    prime[i] = 1

i = 2
while i*i<=N:
    if prime[i] == 1:
        j = 2*i
        while j <= N:
            if j%i==0:
                prime[j] = 0
            j += 1
    i += 1

for i in range(2,N):
    if prime[i] == 1:
        print("{} ".format(i),end="")
    if i%16==0:
        print("")

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苜蓿花乐园

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值