这段时间互联网上火热的流传着一个智力测试题。题目出现的形式有多种,但大多看起来是这个样子:
如果是学龄前儿童,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
在这种形式的公式中,9个数字分别代表着数字1-9在每串数据中出现的次数。我不知道如何得出这张频次表,于是,按照我的习惯,我把这个问题做了一个简洁的描述,张贴在StackOverflow.com上,如我愿的得到了一个极好的方案。一旦我建好了频次表,问题就变成了一个简单的关于10个独立变量的线性表达式。
我的整个运算脚本——如果你十分感兴趣的话——就是下面这些,你可以把它粘贴到R语言解释器里运行。
## read in the training data## more lines than it should be because of the https requirement in GithubtemporaryFile <- 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 tablefreqTable <- 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 interceptmyModel <- 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
最终的输出结果如下:
> 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。哈哈。我也跟学龄前儿童一样聪明了。而且我还用程序做了验证。
[本文英文原文链接:Solving easy problems the hard way ]