英文原文:Solving easy problems the hard way,翻譯:外刊IT評論
這段時間網際網路上火熱的流傳著一個智力測試題。題目出現的形式有多種,但大多看起來是這個樣子:
如果是學齡前兒童,5-10分鐘能解決這個問題,普通程式設計師要1個小時,受過更高教育的人 …
8809=6
7111=0
2172=0
6666=4
1111=0
3213=0
7662=2
9313=1
0000=4
2222=0
3333=0
5555=0
8193=3
8096=5
7777=0
9999=4
7756=1
6855=3
9881=5
5531=0
2581=?
謎底揭示 …
.
.
.
.
.
.
.
答案跟每個數字裡有多少個圈圈有關。在形狀上,8有2個圈,所以記兩次。0是一個大圈,記1次。所以2581=2。很有趣,不是嗎?這是一種通過隱含的計算方式得出的另一種數值對應關係。而困擾著我的卻是如何能以一種不基於數字形狀的方法來找到這種數值對應關係。我如何能程式設計讓計算機來解決這個問題?我認真思考了一下,因為我喜歡自認為是一個計量經濟學家,這道題看起來頗像一個可以通過一個OLS(ordinary least squares)表示式來解決的聯立方程式。那麼,如何能講將這個問題和涉及到的資料轉化成一個小小的OLS表示式呢?我需要將每行的數字佇列轉換成一個描述數字出現頻率的表格。這樣,對於8809=6來說,我需要重構出來的資料應該類似於這樣:1,0,0,0,0,0,0,0,2,1 = 6
在這種形式的公式中,10個數字分別代表著數字0-9在每串資料中出現的次數。我不知道如何得出這張頻次表,於是,按照我的習慣,我把這個問題做了一個簡潔的描述,張貼在StackOverflow.com上,如我願的得到了一個極好的方案。一旦我建好了頻次表,問題就變成了一個簡單的關於10個獨立變數的線性表示式。
我的整個運算指令碼——如果你十分感興趣的話——就是下面這些,你可以把它貼上到R語言直譯器裡執行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
## read in the training data ## more lines than it should be because of the https requirement in Github temporaryFile <- tempfile() download.file("https://raw.github.com/gist/2061284/44a4dc9b304249e7ab3add86bc245b6be64d2cdd/problem.csv",destfile=temporaryFile, method="curl") series <- read.csv(temporaryFile) ## munge the data to create a frequency table freqTable <- as.data.frame( t(apply(series[,1:4], 1, function(X) table(c(X, 0:9))-1)) ) names(freqTable) <- c("zero","one","two","three","four","five","six","seven","eight","nine") freqTable$dep <- series[,5] ## now a simple OLS regression with no intercept myModel <- lm(dep ~ 0 + zero + one + two + three + four + five + six + seven + eight + nine, data=freqTable) round(myModel$coefficients) |
Created by Pretty R at inside-R.org
最終的輸出結果如下:
1 2 3 4 |
> round(myModel$coefficients) zero one two three four five six seven eight nine 1 0 0 0 NA 0 1 0 2 1 |
你可以看到,0,6和9對應的值是1,而8對應的值是2。其它數字對應的都是0。而4得出的是NA,這是因為數字序列中沒有出現4。
哈哈。我也跟學齡前兒童一樣聰明瞭。而且我還用程式做了驗證。