把一個python程式改寫成Julia

lt發表於2017-03-25

Julia程式碼臃腫了不少,速度兩者差不多.
兩種語言還有下列不同:
1.字典對於不存在的鍵值,julia沒有預設值,必須用hashkey函式判斷,直接訪問報錯,python預設0。
2.對於整數和Bool兩種型別的變數。julia不能相加,python可以加。
3.對於BigInt型別,julia必須用賦值顯式宣告變數型別,python可以自動判斷並設定。
4.Bool型別常量,julia全小寫,Python首字母大寫,其餘小寫。
5.for迴圈的上下邊界,julia都包含,Python的Range包含下限,不包含上限。
6.'或','否'條件運算子,julia用||,==0 ,Python用or和not
7.遍歷字典時,Julia必須定義一個遊標型別,Python可以直接用變數代表鍵值。
8.判斷迴圈正常結束,沒有中途退出。Python有一個else語法,Julia只能用標誌變數。
python

from collections import defaultdict

def f(l):
    d = defaultdict(int)
    for i in range(1, 10):
        d[1<<(i%l), 0, i%l==0] += 1
    for i in range(l-1):
        d, d2 = defaultdict(int), d
        for (bm,dbm,bl), cn in d2.items():
            for j in range(10):
                nbm = ndbm = 0
                t = bl
                for k in range(l):
                    c = (k==0) + ((bm&(1<<k))!=0) + ((dbm&(1<<k))!=0)
                    if not c: continue
                    z = (k * 10 + j) % l
                    if z==0:
                        if t+c>1: break
                        t = True
                    if (nbm & (1<<z)) or c>1:
                        ndbm |= 1<<z
                    nbm |= 1 << z
                else:
                    d[nbm, ndbm, t] += cn
    return sum(c for (bm, dbm, bl), c in d.items() if bl)

def go(N):
    return sum(map(f, range(1, N+1)))

go(15)

julia

function f(l::Int)
    d=Dict{Tuple{Int,Int,Bool},BigInt}()
    for i in 1:10-1
       a=(1<<(i%l),0,i%l==0)
       if haskey(d, a) d[a]+=1 else d[a]=1 end 
    end   
    for i in 0:l-1-1
         d, d2 = Dict{Tuple{Int,Int,Bool},BigInt}(), d
         for x in d2
            (bm,dbm,bl), cn = x.first,x.second
            #println(bm)
            for j in 0:10-1
                nbm = ndbm = 0
                t = bl
                flag =0
                for k in 0:l-1
                    c = (k==0) + ((bm&(1<<k))!=0) + ((dbm&(1<<k))!=0)
                    if c==false  
                        continue 
                    end
                    z = (k * 10 + j) % l
                    if z==0 
                        if t+c>1 
                           flag=1 
                           break 
                        end
                        t = true
                    end
                    if ((nbm & (1<<z))!=0) || c>1 
                        ndbm |= 1<<z 
                    end
                    nbm |= 1 << z
                #else: k not break out
                end #k
                   if flag==0 
                       a=(nbm, ndbm, t)
                       if haskey(d, a) d[a]+=cn else d[a] = cn  end
                       #println(d[a])
                   end
           end #j
        end #x
    end #i
    sumc=BigInt(0)
    for x in d
          (bm,dbm,bl), c1 = x.first,x.second
          if bl sumc+=c1 end 
    end   
    return sumc
end 

function go(N::Int)
    #return sum(map(f, 1:N+1-1))
    sumc=BigInt(0)
    for x in 1:N+1-1
       sumc+=f(x)
    end
    return sumc
end

go(15)

把上述julia程式碼中的BigInt都修改為Int128,其他不動,速度提高了20%.

julia> @time go128(19)
 39.090864 seconds (245.53 M allocations: 3.208 GB, 6.47% gc time)
3079418---040719

julia> @time go(19)
 51.460135 seconds (301.17 M allocations: 3.782 GB, 11.80% gc time)
3079418---040719

相關文章