Update shellSort, Add fibnacci computation method of matrix power

This commit is contained in:
mbinary 2019-03-06 19:11:01 +08:00
parent b69b5641d0
commit 26db38a42e
6 changed files with 125 additions and 11 deletions

View File

@ -0,0 +1,29 @@
:{
''' mbinary
#######################################################################
# File : fibonacci.hs
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.github.io
# Github: https://github.com/mbinary
# Created Time: 2019-02-03 19:42
# Description: matrix pow and fast pow:
calculate big number fibonacci item. for negative item, use f(n) = f(n+2)-f(n+1)
#######################################################################
:}
module Fibonacci where
fib :: Integer -> Integer
fib n = let p = if n>0 then n-2 else 2-n
mat = if n>0 then [1,1,1,0] else [0,1,1,-1]
m = matrix_pow mat p
in m!!0+m!!1
matrix_pow mat n = if n<=0 then [1,0,0,1]
else let v = if (mod n 2==0) then [1,0,0,1] else mat
m2 = matrix_mul mat mat
remain = matrix_pow m2 (div n 2)
in matrix_mul v remain
matrix_mul a b = [ a!!0 * b!!0 +a!!1 * b!!2,a!!0 * b!!1 +a!!1 * b!!3,a!!2 * b!!0 +a!!3 * b!!2, a!!2 * b!!1+a!!3 * b!!3]

View File

@ -0,0 +1,37 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : fibonacci.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.github.io
# Github: https://github.com/mbinary
# Created Time: 2019-02-03 19:10
# Description: use matrix and fast pow to calculate big numbr fibonacci value.
#######################################################################
'''
def fib(n):
"""Calculates the nth Fibonacci number"""
mat,p = (1,1,1,0),n-2
if n<=0: # for negative fib item, use f(n) = f(n+2)-f(n-1) to calculate
mat = (0,1,1,-1),2-n
li = matrix_pow((0,1,1,-1),1-n)
return li[0]+li[1]
def matrix_pow(mat,n):
ans = (1,0,0,1) # element matrix
while n>0:
if n%2==1:
ans = matrix_mul(ans,mat)
n>>=1
mat = matrix_mul(mat,mat)
return ans
def matrix_mul(a,b):
'''a,b are four-item tuple, represent matrix [[a[0],a[1]],[a[2],a[3]]]'''
return a[0]*b[0]+a[1]*b[2], a[0]*b[1]+a[1]*b[3], a[2]*b[0]+a[3]*b[2],a[2]*b[1]+a[3]*b[3]
if __name__=='__main__':
for i in range(-5,5):
print(i,fib(i))

22
math/fibonacci/test.hs Normal file
View File

@ -0,0 +1,22 @@
module Fibonacci.Test where
import Fibonacci
import Test.QuickCheck
import Test.QuickCheck.All
prop_fib :: Int -> Bool
prop_fib x = fib n == 2
main = $(quickCheckAll)
:{
prop_fib 0 = fib 0 == 0
prop_fib 1 = fib 1 == 1
prop_fib 2 = fib 2 == 1
prop_fib 3 = fib 3 == 2
prop_fib 5 = fib 5 == 5
prop_fib 5 = fib 5 == 5
prop_fib -6 = fib -6 == -8
prop_fib -96 = fib -96 == -51680708854858323072
prop_fib 2000 = fib 2000 == 4224696333392304878706725602341482782579852840250681098010280137314308584370130707224123599639141511088446087538909603607640194711643596029271983312598737326253555802606991585915229492453904998722256795316982874482472992263901833716778060607011615497886719879858311468870876264597369086722884023654422295243347964480139515349562972087652656069529806499841977448720155612802665404554171717881930324025204312082516817125
:}

View File

@ -88,7 +88,21 @@ class primeSieve:
if i%j==0:break
else:lst.append(i)
self.primes+=lst
return twoDivideFind(x,lst)
return twoDivideFind(x,lst)
def nPrime(n):
'''return the n-th prime'''
i=n-len(self.primes)
last = self.primes[-1]
for _ in range(i):
while 1:
last +=2
for p in self.primes:
if last%p==0:
break
else:
self.primes.append(last)
break
return self.primes[n-1]
def twoDivideFind(x,li):
a,b = 0, len(li)

View File

@ -10,15 +10,26 @@
#########################################################################
'''
def shellSort(s,inc=None):
if inc is None:inc = [1,3,5,7,11,13,17,19]
num = len(s)
inc.sort(reverse=True)
for i in inc:
for j in range(i,num):
def shellSort(s,gaps=None):
if gaps is None:
gaps = [127,63,31,15,7,3,1]
n = len(s)
for gap in gaps:
for j in range(gap,n):
cur = j
while cur>=i and s[j] > s[cur-i]:
s[cur] = s[cur-i]
cur-=i
s[cur] = s[j]
num = s[j]
while cur>=gap and num < s[cur-gap]:
s[cur] = s[cur-gap]
cur-=gap
s[cur] = num
return s
if __name__=='__main__':
from random import randint
import sys
n = 20
if len(sys.argv)>1:
n = int(sys.argv[1])
nums = [randint(1,100) for i in range(n)]
print(nums)
print(shellSort(nums))

View File

@ -6,6 +6,7 @@ README = r'''
[![repo-size](https://img.shields.io/github/repo-size/mbinary/algorithm-in-python.svg)]()
[![License](https://img.shields.io/badge/LICENSE-WTFPL-blue.svg)](LICENSE)
[![Language](https://img.shields.io/badge/language-python3-orange.svg)]()
[![codebeat badge](https://codebeat.co/badges/4ef725b5-405a-4390-a860-a86deefab3f8)](https://codebeat.co/projects/github-com-mbinary-algorithm-in-python-master)
<!-- [![Build](https://travis-ci.org/mbinary/PL0-compiler.svg?branch=master)]() -->
>Notes and codes for learning algorithm and data structures :smiley: