From 273702e4e4de7545653fc692179f53a6b27bf4e9 Mon Sep 17 00:00:00 2001 From: mbinary Date: Sun, 16 Dec 2018 17:09:54 +0800 Subject: [PATCH] Add number theory, string matching, dynamic programming codes --- README.md | 32 +++-- dataStructure/trie/mapSum.py | 81 ++++++++++++ dataStructure/{ => trie}/trie.py | 0 docs/string-matching.md | 110 ++++++++++++++++ dynamicProgramming/stoneGame.py | 36 ++++++ dynamicProgramming/wildcard_matching.py | 57 ++++++++ math/README.md | 32 +++++ math/euler.py | 33 +++++ math/factor.py | 43 ++++++ math/gcd.py | 33 +++++ math/isPrime.py | 120 +++++++++++++---- .../modulo_equation.py | 122 ++++++------------ .../README.md | 0 .../interplotion.py | 0 .../iteration.py | 0 .../least_square.py | 0 .../linear_equation.py | 0 .../numerical_differential.py | 0 .../numerical_integration.py | 0 .../solve-linear-by-iteration.py | 0 .../vector_norm.py | 0 string/rabin_karp.py | 2 +- string/wildcard_matching.py | 57 ++++++++ 23 files changed, 638 insertions(+), 120 deletions(-) create mode 100644 dataStructure/trie/mapSum.py rename dataStructure/{ => trie}/trie.py (100%) create mode 100644 docs/string-matching.md create mode 100644 dynamicProgramming/stoneGame.py create mode 100644 dynamicProgramming/wildcard_matching.py create mode 100644 math/README.md create mode 100644 math/euler.py create mode 100644 math/factor.py create mode 100644 math/gcd.py rename computationalMethod/tongyu_equation.py => math/modulo_equation.py (53%) rename {computationalMethod => numericalAnalysis}/README.md (100%) rename {computationalMethod => numericalAnalysis}/interplotion.py (100%) rename {computationalMethod => numericalAnalysis}/iteration.py (100%) rename {computationalMethod => numericalAnalysis}/least_square.py (100%) rename {computationalMethod => numericalAnalysis}/linear_equation.py (100%) rename {computationalMethod => numericalAnalysis}/numerical_differential.py (100%) rename {computationalMethod => numericalAnalysis}/numerical_integration.py (100%) rename {computationalMethod => numericalAnalysis}/solve-linear-by-iteration.py (100%) rename {computationalMethod => numericalAnalysis}/vector_norm.py (100%) create mode 100644 string/wildcard_matching.py diff --git a/README.md b/README.md index 29f8f7b..f819dc9 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,6 @@ So,if you wannt to view the notes which contain latex math formulas and are in m * [.](.) * [README.md](./README.md) * [backtracking](./backtracking) - * [computationalMethod](./computationalMethod) - * [README.md](./computationalMethod/README.md) - * [interplotion.py](./computationalMethod/interplotion.py) - * [iteration.py](./computationalMethod/iteration.py) - * [least_square.py](./computationalMethod/least_square.py) - * [linear_equation.py](./computationalMethod/linear_equation.py) - * [numerical_differential.py](./computationalMethod/numerical_differential.py) - * [numerical_integration.py](./computationalMethod/numerical_integration.py) - * [solve-linear-by-iteration.py](./computationalMethod/solve-linear-by-iteration.py) - * [tongyu_equation.py](./computationalMethod/tongyu_equation.py) - * [vector_norm.py](./computationalMethod/vector_norm.py) * [dataStructure](./dataStructure) * [allOone](./dataStructure/allOone) * [bTree.py](./dataStructure/bTree.py) @@ -45,7 +34,7 @@ So,if you wannt to view the notes which contain latex math formulas and are in m * [redBlackTree.py](./dataStructure/redBlackTree.py) * [redBlackTree0.py](./dataStructure/redBlackTree0.py) * [splayTree.py](./dataStructure/splayTree.py) - * [trie.py](./dataStructure/trie.py) + * [trie](./dataStructure/trie) * [winnerTree.py](./dataStructure/winnerTree.py) * [divideAndConquer](./divideAndConquer) * [min_distance_of_n_points.py](./divideAndConquer/min_distance_of_n_points.py) @@ -59,6 +48,7 @@ So,if you wannt to view the notes which contain latex math formulas and are in m * [red-black-tree.md](./docs/red-black-tree.md) * [sort.md](./docs/sort.md) * [src](./docs/src) + * [string-matching.md](./docs/string-matching.md) * [tree.md](./docs/tree.md) * [dynamicProgramming](./dynamicProgramming) * [Vec2d.hs](./dynamicProgramming/Vec2d.hs) @@ -66,15 +56,32 @@ So,if you wannt to view the notes which contain latex math formulas and are in m * [matrixChainMultiply.py](./dynamicProgramming/matrixChainMultiply.py) * [splitStripe.hs](./dynamicProgramming/splitStripe.hs) * [splitStripe.py](./dynamicProgramming/splitStripe.py) + * [stoneGame.py](./dynamicProgramming/stoneGame.py) * [testVec2d.hs](./dynamicProgramming/testVec2d.hs) + * [wildcard_matching.py](./dynamicProgramming/wildcard_matching.py) * [math](./math) + * [README.md](./math/README.md) + * [euler.py](./math/euler.py) + * [factor.py](./math/factor.py) + * [gcd.py](./math/gcd.py) * [isPrime.py](./math/isPrime.py) + * [modulo_equation.py](./math/modulo_equation.py) * [num_weight.py](./math/num_weight.py) * [permute_back_track.py](./math/permute_back_track.py) * [permute_cantor.c](./math/permute_cantor.c) * [permute_divide_and_conquer.py](./math/permute_divide_and_conquer.py) * [permute_next_arrangement.c](./math/permute_next_arrangement.c) * [primesLEn.hs](./math/primesLEn.hs) + * [numericalAnalysis](./numericalAnalysis) + * [README.md](./numericalAnalysis/README.md) + * [interplotion.py](./numericalAnalysis/interplotion.py) + * [iteration.py](./numericalAnalysis/iteration.py) + * [least_square.py](./numericalAnalysis/least_square.py) + * [linear_equation.py](./numericalAnalysis/linear_equation.py) + * [numerical_differential.py](./numericalAnalysis/numerical_differential.py) + * [numerical_integration.py](./numericalAnalysis/numerical_integration.py) + * [solve-linear-by-iteration.py](./numericalAnalysis/solve-linear-by-iteration.py) + * [vector_norm.py](./numericalAnalysis/vector_norm.py) * [search](./search) * [8Astar.py](./search/8Astar.py) * [BFS_knight.hs](./search/BFS_knight.hs) @@ -96,6 +103,7 @@ So,if you wannt to view the notes which contain latex math formulas and are in m * [rabin_karp.py](./string/rabin_karp.py) * [src](./string/src) * [sunday.py](./string/sunday.py) + * [wildcard_matching.py](./string/wildcard_matching.py) * [utils](./utils) * [config.py](./utils/config.py) * [genReadme.py](./utils/genReadme.py) diff --git a/dataStructure/trie/mapSum.py b/dataStructure/trie/mapSum.py new file mode 100644 index 0000000..832d11d --- /dev/null +++ b/dataStructure/trie/mapSum.py @@ -0,0 +1,81 @@ +#coding: utf-8 +''' mbinary +####################################################################### +# File : mapSum.py +# Author: mbinary +# Mail: zhuheqin1@gmail.com +# Blog: https://mbinary.coding.me +# Github: https://github.com/mbinary +# Created Time: 2018-12-14 23:11 +# Description: + 实现一个 MapSum 类里的两个方法,insert 和 sum。 + + 对于方法 insert,你将得到一对(字符串,整数)的键值对。字符串表示键,整数表示值。如果键已经存在,那么原来的键值对将被替代成新的键值对。 + + 对于方法 sum,你将得到一个表示前缀的字符串,你需要返回所有以该前缀开头的键的值的总和。 + + 示例 1: + + 输入: insert("apple", 3), 输出: Null + 输入: sum("ap"), 输出: 3 + 输入: insert("app", 2), 输出: Null + 输入: sum("ap"), 输出: 5 + leetcode-ch:677 https://leetcode-cn.com/problems/map-sum-pairs/ +####################################################################### +''' + +class node: + def __init__(self,ch,n=0): + self.ch = ch + self.n = n + self.children={} + def __getitem__(self,ch): + return self.children[ch] + def __setitem__(self,ch,nd): + self.children[ch]=nd + def __len__(self): + return len(self.children) + def __iter__(self): + return iter(self.children.values()) + def __delitem(self,ch): + del self.children[ch] + def __contains__(self,ch): + return ch in self.children +class MapSum: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.root = node('') + + def insert(self, key, val): + """ + :type key: str + :type val: int + :rtype: void + """ + nd = self.root + for i in key: + if i not in nd: + nd[i] = node(i) + nd = nd[i] + nd.n = val + + def visit(self,nd): + ret = nd.n + for chd in nd: + ret+=self.visit(chd) + return ret + def sum(self, prefix): + """ + :type prefix: str + :rtype: int + """ + nd = self.root + for ch in prefix: + if ch in nd: + nd = nd[ch] + else:return 0 + return self.visit(nd) + diff --git a/dataStructure/trie.py b/dataStructure/trie/trie.py similarity index 100% rename from dataStructure/trie.py rename to dataStructure/trie/trie.py diff --git a/docs/string-matching.md b/docs/string-matching.md new file mode 100644 index 0000000..207447d --- /dev/null +++ b/docs/string-matching.md @@ -0,0 +1,110 @@ +# String Matching algorithm + +![](https://upload-images.jianshu.io/upload_images/7130568-e10dc137e9083a0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +## Rabin-Karp +We can view a string of k characters (digits) as a length-k decimal number. E.g., the string “31425” corresponds to the decimal number 31,425. +- Given a pattern P [1..m], let p denote the corresponding decimal value. +- Given a text T [1..n], let $t_s$ denote the decimal value of the length-m substring T [(s+1)..(s+m)] for s=0,1,…,(n-m). +- let `d` be the radix of num, thus $d = len(set(s))$ +- $t_s$ = p iff T [(s+1)..(s+m)] = P [1..m]. +- p can be computed in O(m) time. p = P[m] + d\*(P[m-1] + d\*(P[m-2]+…)). +- t0 can similarly be computed in O(m) time. +- Other $t_1,\ldots,t_{n-m}$ can be computed in O(n-m) time since $t_{s+1} can be computed from ts in constant time. +Namely, + +$$ +t_{s+1} = d*(t_s-d^{m-1} * T[s+1])+T[s+m+1] +$$ +However, it's no need to calculate $t_{s+1}$ directly. We can use modulus operation to reduce the work of caculation. + +We choose a small prime number. Eg 13 for radix( noted as d) 10. +Generally, d\*q should fit within one computer word. + +We firstly caculate t0 mod q. +Then, for every $t_i (i>1)$ +assume +$$ + t_{i-1} = T[i+m-1] + 10*T[i+m-2]+\ldots+10^{m-1}*T[i-1] +$$ +denote $ d' = d^{m-1}\ mod\ q$ +thus, +$$ +\begin{aligned} +t_i &= (t_{i-1} - d^{m-1}*T[i-1]) * d + T[i+m]\\ +&\equiv (t_{i-1} - d^{m-1}*T[i-1]) * d + T[i+m] (mod\ q)\\ +&\equiv (t_{i-1}- ( d^{m-1} mod \ q) *T[i-1]) * d + T[i+m] (mod\ q)\\ +&\equiv (t_{i-1}- d'*T[i-1]) * d + T[i+m] (mod\ q) +\end{aligned} +$$ + +So we can compare the modular value of each ti with p's. +Only if they are the same, then we compare the origin chracter, namely $T[i],T[i+1],\ldots,T[i+m-1]$ and the pattern. +Gernerally, this algorithm's time approximation is O(n+m), and the worst case is O((n-m+1)\*m) + +**Problem: this is assuming p and ts are small numbers. They may be too large to work with easily.** + +## FSM +A FSM can be represented as (Q,q0,A,S,C), where +- Q is the set of all states +- q0 is the start state +- $A\in Q$ is a set of accepting states. +- S is a finite input alphabet. +- C is the set of transition functions: namely $q_j = c(s,q_i)$. + +Given a pattern string S, we can build a FSM for string matching. +Assume S has m chars, and there should be m+1 states. One is for the begin state, and the others are for matching state of each position of S. + +Once we have built the FSM, we can run it on any input string. +## KMP +>Knuth-Morris-Pratt method + +The idea is inspired by FSM. We can avoid computing the transition functions. Instead, we compute a prefix functi`Next` on P in O(m) time, and Next has only m entries. +> Prefix funtion stores info about how the pattern matches against shifts of itself. + +- String w is a prefix of string x, if x=wy for some string y +- String w is a suffix of string x, if x=yw for some string y +- The k-character prefix of the pattern P [1..m] denoted by Pk. +- Given that pattern prefix P [1..q] matches text characters T [(s+1)..(s+q)], what is the least shift s'> s such that P [1..k] = T [(s'+1)..(s'+k)] where s'+k=s+q? +- At the new shift s', no need to compare the first k characters of P with corresponding characters of T. +Method: For prefix pi, find the longest proper prefix of pi that is also a suffix of pi. +next[q] = max{k|k\See more details on [my blog](https://mbinary.coding.me/number-theory.html) + +## gcd.py +- gcd(a,b) +- xgcd(a,b): return gcd(a,b),x,y, where ax+by = gcd(a,b) + +## isPrime +- isPrime(n): using Miller-Rabin primalrity test. +- primeSieve + +## euler.py +- phi(n): euler function +- sigma(n): return the sum of all factors of n + +## factor.py +- factor(n): return a list of numbers that are the factorization of n + +## modulo_equation.py +Solving modulo equations + +```python +solver = solve() +res = solver.solveLinear(3,6,9) + +res = solver.solveHigh(1,8,3,11) + +res = solver.solveGroup([(5,11,2),(3,8,5),(4,1,7)]) +``` + +# Permutation + diff --git a/math/euler.py b/math/euler.py new file mode 100644 index 0000000..ea784eb --- /dev/null +++ b/math/euler.py @@ -0,0 +1,33 @@ +#coding: utf-8 +''' mbinary +####################################################################### +# File : euler.py +# Author: mbinary +# Mail: zhuheqin1@gmail.com +# Blog: https://mbinary.coding.me +# Github: https://github.com/mbinary +# Created Time: 2018-12-16 10:53 +# Description: + euler function: phi(n) + perfect num: \sigma (n) = 2n, \sigma (n) is the sum of all factors of n + eg \sigma (9) = 3+3+9 = 15 +####################################################################### +''' +from factor import factor +from collections import Counter +from functools import reduce +from operator import mul +def phi(n): + st = set(factor(n)) + return round(reduce(mul,(1-1/p for p in st),n)) + +def sigma(n): + ct = Counter(factor(n)) + return reduce(mul,(round((p**(ct[p]+1)-1)/(p-1)) for p in ct),1) + +if __name__=='__main__': + while 1: + n = int(input('n: ')) + print('phi(n):',phi(n)) + print('sigma(n):',sigma(n)) + diff --git a/math/factor.py b/math/factor.py new file mode 100644 index 0000000..5baa956 --- /dev/null +++ b/math/factor.py @@ -0,0 +1,43 @@ +#coding: utf-8 +''' mbinary +####################################################################### +# File : factorize.py +# Author: mbinary +# Mail: zhuheqin1@gmail.com +# Blog: https://mbinary.coding.me +# Github: https://github.com/mbinary +# Created Time: 2018-12-16 09:36 +# Description: factorization, using pollard's rho algorithm and miller-rabin primality test +####################################################################### +''' + +from random import randint +from isPrime import isPrime +from gcd import gcd + +def factor(n): + '''pollard's rho algorithm''' + if n<1:raise Exception('[Error]: {} is less than 1'.format(n)) + if n==1: return [] + if isPrime(n):return [n] + fact=1 + cycle_size=2 + x = x_fixed = 2 + c = randint(1,n) + while fact==1: + for i in range(cycle_size): + if fact>1:break + x=(x*x+c)%n + if x==x_fixed: + c = randint(1,n) + continue + fact = gcd(x-x_fixed,n) + cycle_size *=2 + x_fixed = x + return factor(fact)+factor(n//fact) + + +if __name__=='__main__': + while 1: + n = int(input('n: ')) + print(factor(n)) diff --git a/math/gcd.py b/math/gcd.py new file mode 100644 index 0000000..05d3334 --- /dev/null +++ b/math/gcd.py @@ -0,0 +1,33 @@ +#coding: utf-8 +''' mbinary +####################################################################### +# File : gcd.py +# Author: mbinary +# Mail: zhuheqin1@gmail.com +# Blog: https://mbinary.coding.me +# Github: https://github.com/mbinary +# Created Time: 2018-12-16 10:06 +# Description: +####################################################################### +''' + +def gcd(a,b): + while b!=0: + a,b=b,a%b + return a + +def lcm(a,b): + return int(a*b/gcd(a,b)) +def xgcd(a,b): + '''return gcd(a,b), x,y where ax+by=gcd(a,b)''' + if b==0:return a,1,0 + g,x,y = xgcd(b,a%b) + return g,y,x-a//b*y + +if __name__=='__main__': + while 1: + a = int(input('a: ')) + b = int(input('b: ')) + print('gcd :',gcd(a,b)) + print('xgcd:',xgcd(a,b)) + diff --git a/math/isPrime.py b/math/isPrime.py index f03125c..5a64a48 100644 --- a/math/isPrime.py +++ b/math/isPrime.py @@ -5,40 +5,104 @@ # Mail: zhuheqin1@gmail.com # Blog: https://mbinary.coding.me # Github: https://github.com/mbinary -# Created Time: 2018-05-19 21:34 +# Created Time: 2018-03-04 21:34 # Description: ######################################################################### ''' - -# created by mbinary @2018-3-4 -# description: judge a num if it's a prime. It will be more efficient when judging many times +from random import randint -primes = [2,3,5,7,11,13] -def isPrime(x): - global primes - if x>primes[-1]: - return genPrime(x) - return twoDivideFind(x,primes) +def quickMulMod(a,b,m): + '''a*b%m, quick''' + ret = 0 + while b: + if b&1: + ret = (a+ret)%m + b//=2 + a = (a+a)%m + return ret -def genPrime(x): - global primes - while x>primes[-1]: - left = primes[-1] - right = (left+1)**2 - lst = [] - for i in range(left,right): - for j in primes: - if i%j==0:break - else:lst.append(i) - primes+=lst - else:return twoDivideFind(x,lst) +def quickPowMod(a,b,m): + '''a^b %m, quick, O(logn)''' + ret =1 + while b: + if b&1: + ret =quickMulMod(ret,a,m) + b//=2 + a = quickMulMod(a,a,m) + return ret -def twoDivideFind(x,primes): - a,b = 0, len(primes) + +def isPrime(n,t=5): + '''miller rabin primality test, a probability result + t is the number of iteration(witness) + ''' + t = min(n-3,t) + if n<2: + print('[Error]: {} can\'t be classed with prime or composite'.format(n)) + return + if n==2: return True + d = n-1 + r = 0 + while d%2==0: + r+=1 + d//=2 + tested=set() + for i in range(t): + a = randint(2,n-2) + while a in tested: + a = randint(2,n-2) + tested.add(a) + x= quickPowMod(a,d,n) + if x==1 or x==n-1: continue #success, + for j in range(r-1): + x= quickMulMod(x,x,n) + if x==n-1:break + else: + return False + return True + +''' +we shouldn't use Fermat's little theory +Namyly: + For a prime p, and any number a where (a,n)=1 + a ^(p-1) \equiv 1 (mod p) + +The inverse theorem of it is not True. + +a counter-example: 2^340 \equiv 1 (mod 341), but 341 is a composite +''' + +class primeSieve: + '''sieve of Eratosthenes, It will be more efficient when judging many times''' + primes = [2,3,5,7,11,13] + def isPrime(self,x): + if x<=primes[-1]: + return twoDivideFind(x,self.primes) + while x>self.primes[-1]: + left = self.primes[-1] + right = (left+1)**2 + lst = [] + for i in range(left,right): + for j in self.primes: + if i%j==0:break + else:lst.append(i) + self.primes+=lst + return twoDivideFind(x,lst) + +def twoDivideFind(x,li): + a,b = 0, len(li) while a<=b: mid = (a+b)//2 - if primes[mid]x: b= mid-1 - else:return True - return False + if li[mid]x: b= mid-1 + else:return mid + return -1 + +if __name__=='__main__': + n = 100 + print('prime numbers below',n) + print([i for i in range(n) if isPrime(i)]) + while 1: + n = int(input('n: ')) + print(isPrime(n)) diff --git a/computationalMethod/tongyu_equation.py b/math/modulo_equation.py similarity index 53% rename from computationalMethod/tongyu_equation.py rename to math/modulo_equation.py index c304946..6edd7b2 100644 --- a/computationalMethod/tongyu_equation.py +++ b/math/modulo_equation.py @@ -1,58 +1,22 @@ ''' mbinary ######################################################################### -# File : tongyu_equation.py +# File : modulo_equation.py # Author: mbinary # Mail: zhuheqin1@gmail.com # Blog: https://mbinary.coding.me # Github: https://github.com/mbinary -# Created Time: 2018-10-02 21:14 +# Created Time: 2018-3-4 21:14 # Description: + `--` represents modulo symbol ######################################################################### ''' -# created by mbinary @2018-3-4 -# description: solve tongyu equation -# notice that i use -- to repr tongyu symbol - -from isPrime import isPrime,primes -from operator import mul, and_ -from functools import reduce,partial import re - -def primeFactoize(x): - '''质因数分解 , ret {p:r}''' - if isPrime(x):return {x:1} - mp={} - for i in primes: - if x==1:break - ct=0 - while x%i==0: - ct+=1 - x//=i - if ct!=0:mp[i]=ct - return mp -def xgcd(a,b): - '''ax+by=gcd(a,b) ,用辗转相除法得到gcd,x,y''' - def _xgcd(a,b): - if b==0:return a,1,0 - gcd,x,y=_xgcd(b,a%b) - return gcd,y,x-y*a//b - if a {n:indg n}''' @@ -61,22 +25,20 @@ def ind(m,g): def gs(m,num=100): '''return list of m's primary roots below num''' - phi = euler(m) - mp = primeFactoize(phi) - checkLst = [phi//i for i in mp] - return [i for i in range(2,num) \ - if reduce(and_,[(i**n-1)%m !=0 for n in checkLst])] + p = phi(m) + mp = factor(p) + checkLst = [p//i for i in mp] + return [i for i in range(2,num) if all((i**n-1)%m !=0 for n in checkLst)] def minG(m): - phi = euler(m) - mp = primeFactoize(phi) - checkLst = [phi//i for i in mp] + p = phi(m) + mp = factor(p) + checkLst = [p//i for i in mp] i=2 while 1: - if reduce(and_,[(i**n-1)%m !=0 for n in checkLst]):return i + if all((i**n-1)%m !=0 for n in checkLst):return i i+=1 - class solve: def __init__(self,equ=None): self.linearPat= re.compile(r'\s*(\d+)\s*--\s*(\d+)[\s\(]*mod\s*(\d+)') @@ -87,8 +49,6 @@ class solve: print('equation {equ} has no solution'.format(equ=self.equ)) def error(self): print("Error! The divisor m must be postive integer") - - def solveLinear(self,a,b,m): '''ax--b(mod m): solve linear equation with one unknown return ([x1,x2,...],m) @@ -100,7 +60,9 @@ class solve: return None sol=x*b//g m0 = m//g - return ([(sol+i*m0)%m for i in range(g)],m) + sols = [(sol+i*m0)%m for i in range(g)] + print('{}x--{}(mod {}), solution: {} mod {}'.format(a,b,m,sols,m)) + return (sols,m) def check(self,a,b,m): if m<=0: self.error() @@ -109,46 +71,46 @@ class solve: if b<0:b+= -b//m * m return a,b,m - - #def solvePoly(self,m,mp): - ''' mod m, mp:{index:coef} is a dict of the polynomials' coefficient and index''' - ''' g = minG(m) - ind_mp = ind(m,g) - li = [] - for i in mp: - solve - ''' - def solveHigh(self,a,n,b,m): ''' ax^n -- b (mod m) ind_mp is a dict of m's {n: indg n}''' ind_mp = ind(m,minG(m)) tmp = ind_mp[b] - ind_mp[a] if tmp < 0:tmp+=m - print(n,tmp) - sol = self.solveLinear(n,tmp,euler(m)) + sol = self.solveLinear(n,tmp,phi(m)) re_mp = {j:i for i ,j in ind_mp.items()} - print(sol) - return [re_mp[i] for i in sol[0]],m + sols = [re_mp[i] for i in sol[0]] + print('{}x^{}--{}(mod {}), solution: {} mod {}'.format(a,n,b,m,sols,m)) + return sols,m - def solveGroup(tups): + def solveGroup(self,tups): '''tups is a list of tongyu equation groups, like [(a1,b1,m1),(a2,b2,m2)...] and, m1,m2... are all primes ''' mp = {} + print('solving group of equations: ') for a,b,m in tups: + print('{}x--{}(mod {})'.format(a,b,m)) if m in mp: if mp[m][0]*b!=mp[m][1]*a: self.noSol() return else:mp[m] = (a,b) - product= reduce(lambda i,j:i*j, mp.keys(), 1) - sol = 0 + product = 1 + for i in mp.keys(): + product *=i + sol = [0] for i in mp: - x = self.solveLinear(product//i*mp[i][0],1,i) - sol+= x*product//i*mp[i][1] - sol%=m - return ([sol],m) + xs,m = self.solveLinear(product//i*mp[i][0],1,i) + new = [] + for x in xs: + cur = x*product//i*mp[i][1] + for old in sol: + new.append(old+cur) + sol = new + sol= [i%product for i in sol] + print('final solution: {} mod {}'.format(sol,product)) + return sol,product def __call__(self): s=input('输入同余方程,用--代表同于号,形如3--5(mod 7)代表3x模7同余于5') li= self.linearPat.findall(s) @@ -159,5 +121,7 @@ class solve: if __name__ == '__main__': solver = solve() res = solver.solveLinear(3,6,9) - print(res) - print(solver.solveHigh(1,8,3,11)) + print() + res = solver.solveHigh(1,8,3,11) + print() + res = solver.solveGroup([(5,11,2),(3,8,5),(4,1,7)]) diff --git a/computationalMethod/README.md b/numericalAnalysis/README.md similarity index 100% rename from computationalMethod/README.md rename to numericalAnalysis/README.md diff --git a/computationalMethod/interplotion.py b/numericalAnalysis/interplotion.py similarity index 100% rename from computationalMethod/interplotion.py rename to numericalAnalysis/interplotion.py diff --git a/computationalMethod/iteration.py b/numericalAnalysis/iteration.py similarity index 100% rename from computationalMethod/iteration.py rename to numericalAnalysis/iteration.py diff --git a/computationalMethod/least_square.py b/numericalAnalysis/least_square.py similarity index 100% rename from computationalMethod/least_square.py rename to numericalAnalysis/least_square.py diff --git a/computationalMethod/linear_equation.py b/numericalAnalysis/linear_equation.py similarity index 100% rename from computationalMethod/linear_equation.py rename to numericalAnalysis/linear_equation.py diff --git a/computationalMethod/numerical_differential.py b/numericalAnalysis/numerical_differential.py similarity index 100% rename from computationalMethod/numerical_differential.py rename to numericalAnalysis/numerical_differential.py diff --git a/computationalMethod/numerical_integration.py b/numericalAnalysis/numerical_integration.py similarity index 100% rename from computationalMethod/numerical_integration.py rename to numericalAnalysis/numerical_integration.py diff --git a/computationalMethod/solve-linear-by-iteration.py b/numericalAnalysis/solve-linear-by-iteration.py similarity index 100% rename from computationalMethod/solve-linear-by-iteration.py rename to numericalAnalysis/solve-linear-by-iteration.py diff --git a/computationalMethod/vector_norm.py b/numericalAnalysis/vector_norm.py similarity index 100% rename from computationalMethod/vector_norm.py rename to numericalAnalysis/vector_norm.py diff --git a/string/rabin_karp.py b/string/rabin_karp.py index 02b5f59..d197239 100644 --- a/string/rabin_karp.py +++ b/string/rabin_karp.py @@ -30,7 +30,7 @@ def findAll(s,p): d+=1 sm = 0 for c in p: - if c not in dic:return [-1] + if c not in dic:return [] sm = sm*d+dic[c] ret = [] diff --git a/string/wildcard_matching.py b/string/wildcard_matching.py new file mode 100644 index 0000000..3c7764d --- /dev/null +++ b/string/wildcard_matching.py @@ -0,0 +1,57 @@ +#coding: utf-8 +''' mbinary +####################################################################### +# File : wildcard_matching.py +# Author: mbinary +# Mail: zhuheqin1@gmail.com +# Blog: https://mbinary.coding.me +# Github: https://github.com/mbinary +# Created Time: 2018-12-13 22:46 +# Description: + wild card '*' matches 0 or any chars, and '?' matches any single char. +####################################################################### +''' + + +''' +idea + +dynamic programming + +dp[m+1][n+1]: bool + +i:n, j:m +dp[j][i] indicates if s[:i+1] matches p[:j+1] + +initial: dp[0][0] = True, dp[0][i],dp[j][0] = False +only if p startswith '*', dp[1][0] = True. + +if p[j] = '*': dp[j][i] = dp[j-1][i] or dp[j][i-1] +elif p[j] = '?': dp[j][i] = dp[j-1][i-1] +else : dp[j][i] = dp[j-1][i-1] and s[i] == p[j] +''' + +# leetcode: q44 https://leetcode.com/problems/wildcard-matching/description/ + +def isMatch(self, s, p): + """ + :type s: str + :type p: str pattern str including wildcard + :rtype: bool + """ + n,m = len(s),len(p) + last = [False]*(n+1) + last[0] = True + for j in range(m): + if p[j]=='*': + for i in range(n): + last[i+1] = last[i+1] or last[i] + elif p[j]=='?': + last.pop() + last.insert(0,False) + else: + li = [False] + for i in range(n): + li.append( last[i] and p[j]==s[i]) + last = li + return last[-1]