前陣子 Adobe 和 Google 聯手各自用不同的名字釋出了一款新的中文黑體字形,Source Han Sans 思源黑體,也叫做 Noto Sans (反腐字?)。開心試用之後,把系統字形都換過來,也開始想要怎麼樣才可以達到最佳的顯示效果,尤其是 Adobe 和 Google 曾經給 FreeType 貢獻了 CFF 字形引擎的改進,思源黑體也是以 CFF 技術設計,終於可以試試看中文的效果怎麼樣了啊!
PUSHB[000] # Push one byte onto the stack.
3 # Value for loop variable.
SLOOP[] # Set the loop count to 3.
PUSHB[002] # Push three bytes onto the stack.
5 # Point number.
46 # Point number.
43 # Point number.
ALIGNRP[] # Align the points 5, 46 and 43 with rp0 (point 8). This will
# align the height of the two lower serifs.
有人問說:那為什麼不乾脆隨時打開 Hinting 就好?據我所知目前的自由 PDF Viewer 都是預設關閉 Hinting 的,除了上述的理由外,我猜大概是因為 Hinting 有可能大幅度的改變一個字符的寬度,如下圖:
可以發現三種顯示方式的寬度都不一樣,而 PDF 是一種接近印刷品質的檔案格 式,有可能在輸出 PDF 的時候已經丟失動態改變寬度的能力,kern 的修正也已 經沒辦法修改,這時候如過還讓 Hinting 去改變字符的寬度的話,很有可能得到 不理想的結果。不過以上只是我的猜想,還沒有找各 PDF Viewer 的作者證實。 至於封閉的商業 PDF Viewer 又是怎麼做的就更不得而知了。
結論:快升級到最新的 FreeType 吧!如果還有遇到顯示錯誤的 PDF 可以寄給 我,如果以上筆記有疏漏錯誤的地方歡迎指正 ?
#include <stdio.h>
#include <math.h>
int factorCount (long n)
{
double square = sqrt (n);
int isquare = (int) square;
int count = isquare == square ? -1 : 0;
long candidate;
for (candidate = 1; candidate <= isquare; candidate ++)
if (0 == n % candidate) count += 2;
return count;
}
int main ()
{
long triangle = 1;
int index = 1;
while (factorCount (triangle) < 1001)
{
index ++;
triangle += index;
}
printf ("%ld\n", triangle);
}
我的執行時間約為 5.48s
% gcc -lm -o euler12.bin euler12.c
% time ./euler12.bin
842161320
./euler12.bin 5.48s user 0.00s system 99% cpu 5.484 total
手癢想看看據說可以編譯出不錯的機器碼的 Common Lisp 速度怎麼樣,於是第 一個版本如下 (用 sbcl 執行):
(defun factor-count (n)
(let* ((square (sqrt n))
(squaref (floor square))
(count (if (eql squaref square) -1 0)))
(loop
for cand from 1 to squaref
count (eql 0 (rem n cand)) into c
finally (return (+ count c c)))))
(defun first-triangle-over (n)
(loop
for idx from 1
sum idx into triangle
until (>= (factor-count triangle) n)
finally (return triangle)))
;; (time (first-triangle-over 1000))
;; Evaluation took:
;; 11.192 seconds of real time
;; 11.184699 seconds of total run time (11.184699 user, 0.000000 system)
;; 99.94% CPU
;; 30,135,882,489 processor cycles
;; 32,912 bytes consed
;;
;; 842161320
還不錯,11.192s,這個版本採用原文中給 haskell 的建議,使用 rem 而不是 mod,可以 加快一點速度。再給一點關於型別的提示,然後把第一個 function inline,第 二版可以跑出和 C 版本差不多的成績 5.563s 🙂
(declaim (inline factor-count)) ;; <----
(defun factor-count (n)
(let* ((square (sqrt n))
(squaref (floor square))
(count (if (eql squaref square) -1 0)))
(loop
for cand from 1 to squaref
count (eql 0 (rem n cand)) into c
finally (return (+ count c c)))))
(defun first-triangle-over (n)
(loop
for idx of-type fixnum from 1 ;; <----
sum idx into triangle of-type fixnum ;; <----
until (>= (factor-count triangle) n)
finally (return triangle)))
;; (time (first-triangle-over 1000))
;; Evaluation took:
;; 5.563 seconds of real time
;; 5.556347 seconds of total run time (5.556347 user, 0.000000 system)
;; 99.87% CPU
;; 14,970,270,903 processor cycles
;; 32,768 bytes consed
;;
;; 842161320
Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
<<分割欄位>>=
txt_field_lines = [line.split() for line in lines]
@
這篇 blog 經過 notangle 的處理,會變成以下的 python 程式:
# notangle -R'接受字串的 function' literate-programming.mdwn
def mul_n_sum(data):
lines = data.strip().split('\n')
txt_field_lines = [line.split() for line in lines]
field_lines = [[int(field1), int(field2)] for field1, field2 in txt_field_lines]
return sum([field1 * field2 for field1, field2 in field_lines])