Rijndael Encryption Algorithm

Rijndael Encryption Algorithm

Title: Rijndael Encryption Algorithm
Language: C
Author: Philip J. Erdelsky

Date: September 3, 2002
Usage: Public domain; no restrictions on use
Portability: Any C environment, also compiles as C++
Keywords: rijndael, cryptography
Abstract: A C package for the Rijndael Encryption Algorithm
Source code: rijndael.txt

The Rijndael encryption algorithm has been designed to replace the
aging DES algorithm. Like DES, it is a block cipher. It uses 128-bit,
192-bit or 256-bit keys. This implementation encrypts 128-bit blocks.
(DES used 56-bit keys and 64-bit blocks.)

The code in this package is a modified version of an implementation
placed in the public domain by the following persons:

The original code has been posted as rijndael.zip.

The modified code is easier to use than the original, and it compiles
as either C or C++.

The modified code resides in the files rijndael.h and rijndael.c,
which have been combined into the single file
rijndael.txt
. Download this file and then use a text editor to
separate the two components. Then #include the file rijndael.h in
any module that uses Rijndael encryption, and compile and link the
file rijndael.c to the application.

To perform Rijndael encryption or decryption,
first set up a buffer for encryption or decryption:

     nrounds = rijndaelSetupEncrypt(rk, key, keybits);  for encryption
     nrounds = rijndaelSetupDecrypt(rk, key, keybits);  for decryption

     unsigned long *rk;   pointer to encryption/decryption buffer,
                          required space:
                            keybits  32-bit words required
                            128      44
                            192      52
                            256      60

     const unsigned char *key;  key, where length in bytes is:
                                  keybits  number of bytes
                                  128      16
                                  192      24
                                  256      32

     int keybits;         number of bits in key, must be 128, 192 or
                          256

     int nrounds;         number of rounds:
                            keybits  nrounds
                            128      10
                            192      12
                            256      14

The package provides three macros to convert the keybits value to closely
related values:

     KEYLENGTH(keybits) number of bytes in key[] array
     RKLENGTH(keybits)  number of 32-bit words in rk[] array
     NROUNDS(keybits)   number of rounds

Encryption and decryption are performed, a block at a time, with the
following two functions:

     rijndaelEncrypt(rk, nrounds, plaintext, ciphertext);
     rijndaelDecrypt(rk, nrounds, ciphertext, plaintext);

     const unsigned long *rk;
                          pointer to encryption/decryption buffer which
                          was filled by rijndaelSetupEncrypt() or
                          rijndaelSetupDecrypt()

     int nrounds;         number of rounds, as computed by
                          rijndaelSetupEncrypt(),
                          rijndaelSetupDecrypt() or NROUNDS

     [const] unsigned char plaintext[16];
     [const] unsigned char ciphertext[16];
                          pointers to 16-byte buffers to be encrypted
                          or decrypted; the source buffer has a const
                          qualifier

To satisfy the truly paranoid user, it is probably advisable to clear
and delete the buffers after the process is finished.

In the file rijndael.c, a preprocessor macro FULL_UNROLL has been defined.
This causes the compiler to generate inline code instead of loops in some
places. This produces faster but larger code. You may want to remove this
definition if you are programming for an environment that needs smaller
but slower code.

The downloaded source code also includes a simple file encryption program
and its corresponding decryption program.

The encryption program is called as follows:

     encrypt  password  cryptofile

It encrypts the standard input (padding it with spaces, if necessary),
and writes the result to the specified cryptofile.

The decryption program is called as follows:

    decrypt  password  cryptofile

It decrypts the cryptofile contents and sends the result (padded with
spaces, if necessary) to the standard
output.

These programs should be used
only for demonstration purposes, because the use of a password as a key
gives an effective key length much shorter than the 256-bit key passed
to the Rijndael encryption package.

The programs also have another shortcoming that some users may object to.
They encrypt and decrypt each 128-bit block separately. If the plaintext
contains identical 128-byte blocks, as many text files do, the blocks will be
encrypted identically. This makes some of the plaintext structure
visible in the ciphertext, even to someone who does not have the key. The
usual practice is to combine each block after the first with the previous
blocks (usually by some kind of XOR operation) before encrypting it. This
hides repeated blocks very effectively, but it can wreak havoc if even
one block of
ciphertext is corrupted. The corrupted block AND
ALL SUBSEQUENT BLOCKS will become unreadable.

基于用户投票的排名算法(五):威尔逊区间 – 阮一峰的网络日志

迄今为止,这个系列都在讨论,如何给出"某个时段"的排名,比如"过去24小时最热门的文章"。

但是,很多场合需要的是"所有时段"的排名,比如"最受用户好评的产品"。

这时,时间因素就不需要考虑了。这个系列的最后两篇,就研究不考虑时间因素的情况下,如何给出排名。

一种常见的错误算法是:

  得分 = 赞成票 – 反对票

假定有两个项目,项目A是60张赞成票,40张反对票,项目B是550张赞成票,450张反对票。请问,谁应该排在前面?按照上面的公式,B会排在前面,因为它的得分(550 – 450 = 100)高于A(60 – 40 = 20)。但是实际上,B的好评率只有55%(550 / 1000),而A为60%(60 / 100),所以正确的结果应该是A排在前面。

Urban Dictionary就是这种错误算法的实例。

  

另一种常见的错误算法是

  得分 = 赞成票 / 总票数

如果"总票数"很大,这种算法其实是对的。问题出在如果"总票数"很少,这时就会出错。假定A有2张赞成票、0张反对票,B有100张赞成票、1张反对票。这种算法会使得A排在B前面。这显然错误。

Amazon就是这种错误算法的实例。

  

那么,正确的算法是什么呢?

我们先做如下设定:

  (1)每个用户的投票都是独立事件。

  (2)用户只有两个选择,要么投赞成票,要么投反对票。

  (3)如果投票总人数为n,其中赞成票为k,那么赞成票的比例p就等于k/n。

如果你熟悉统计学,可能已经看出来了,这是一种统计分布,叫做"两项分布"(binomial distribution)。这很重要,下面马上要用到。

我们的思路是,p越大,就代表这个项目的好评比例越高,越应该排在前面。但是,p的可信性,取决于有多少人投票,如果样本太小,p就不可信。好在我们已经知道,p服从"两项分布",因此我们可以计算出p的置信区间。所谓"置信区间",就是说,以某个概率而言,p会落在的那个区间。比如,某个产品的好评率是80%,但是这个值不一定可信。根据统计学,我们只能说,有95%的把握可以断定,好评率在75%到85%之间,即置信区间是[75%, 85%]。

这样一来,排名算法就比较清晰了:

  第一步,计算每个项目的"好评率"(即赞成票的比例)。

  第二步,计算每个"好评率"的置信区间(以95%的概率)。

  第三步,根据置信区间的下限值,进行排名。这个值越大,排名就越高。

这样做的原理是,置信区间的宽窄与样本的数量有关。比如,A有8张赞成票,2张反对票;B有80张赞成票,20张反对票。这两个项目的赞成票比例都是80%,但是B的置信区间(假定[75%, 85%])会比A(假定[70%, 90%])窄得多,因此B的置信区间的下限值(75%)会比A(70%)大,所以B应该排在A前面。

置信区间的实质,就是进行可信度的修正,弥补样本量过小的影响。如果样本多,就说明比较可信,不需要很大的修正,所以置信区间会比较窄,下限值会比较大;如果样本少,就说明不一定可信,必须进行较大的修正,所以置信区间会比较宽,下限值会比较小。

二项分布的置信区间有多种计算公式,最常见的是"正态区间"(Normal approximation interval),教科书里几乎都是这种方法。但是,它只适用于样本较多的情况(np > 5 且 n(1 − p) > 5),对于小样本,它的准确性很差。

1927年,美国数学家 Edwin Bidwell Wilson提出了一个修正公式,被称为"威尔逊区间",很好地解决了小样本的准确性问题。

  

在上面的公式中,表示样本的"赞成票比例",n表示样本的大小,表示对应某个置信水平的z统计量,这是一个常数,可以通过查表或统计软件包得到。一般情况下,在95%的置信水平下,z统计量的值为1.96。

威尔逊置信区间的均值为

  

它的下限值为

  

可以看到,当n的值足够大时,这个下限值会趋向。如果n非常小(投票人很少),这个下限值会大大小于。实际上,起到了降低"赞成票比例"的作用,使得该项目的得分变小、排名下降。

Reddit的评论排名,目前就使用这个算法。

  

[参考文献]

  * How Not To Sort By Average Rating

(完)

海外购攻略 » 什么值得买

伴随着人民币升值以及国内物价上涨,“海外购”正逐渐成为国内消费者关注焦点。目前,多家转运公司竞争激烈,促使其服务日臻完善和便捷。

“什么值得买”撰写本文,旨在帮助网友们依托转运公司购买海外商品。总体而言,海外购是一种DIY形式的自助海外购物行为,不依赖代购商家,主要流程为转运公司网站注册、获取海外地址->国外网站购物->转运公司海外地址收取货物并发货到国内->清关并快递到消费者手中,风险较低而且比代购商家便宜。实际上,不少代购商家也是通过转运公司进行操作。以下是海外购攻略教程,建议准备尝试海外购的网友仔细阅读后再操作。

1、注册“转运”

大多数海外的B2C商家不支持直接发货到中国,即使支持,运费也不菲。转运公司可解决这一难题,它可以提供一个消费者专属海外收货地址,在海外代收商品后转发到国内,收取一定服务费用。美国在线零售市场繁荣,人民币对美元越来越划算,目前海外购以美国商家居多,大多数转运公司提供美国转运服务。比较有名的转运公司列表见此链接。各家转运公司收费不一,清关速度略有差异,功能却大致相同。注册转运公司网站账号后,消费者可以在主页找到自己在美国的收货地址,具体方法可参考“海外购之转运手把手教程”,各家操作大同小异。

2、海外购物

海外购之前,最好准备一张国内银行发行的的双币信用卡(Master、Visa、American Express、JCB等均可)。不少海外商家支持国内信用卡支付,例如最著名的Amazon(美国亚马逊),但也有部分商家不支持国内信用卡,这些商家我们就只能放弃了。购物方式与国内B2C差不多,只是在订单支付环节略有不同。基本流程为:注册-登录-添加商品至购物车-开始结算-填写发货地址-填写支付方式-确认订单-收到订单确认邮件。发货地址需要填写转运公司提供的海外收货地址。付款方式通常是信用卡支付,填写自己的卡号、姓名、有效期、cvv安全码即可。部分网站例如Amazon不需要cvv安全码即可消费。

友情提示:部分网站会预授权1美元用来测试信用卡的有效性,不必担心,这1美元不会体现在账单中。

部分网站有自己的Gift card(礼品券)系统,可以用来抵用现金。大家接触到较多的是Amazon的Gift card。由于网络市场上存在较多黑卡(盗刷信用卡所得),我们不建议用户去淘宝购买,而且,在人民币兑美元越来越划算的情况下,购买礼品券的繁琐和风险,相比于省的那点钱已经不再有优势。另外,请仔细阅读公告:警惕不法分子利用含有Gift Card的Amazon账户行骗一文。

每个网站都有自己的免运费政策,例如Timberland官网满$100免运费,Amazon满$25免运费。Amazon提供的Free Shipping(免运费)服务,通常需要5-7天到达美国的收货地址。如果急需,可以选择试用Amazon Prime(亚马逊优先服务),该服务每个用户可以试用一个月。通常而言,这项服务以包年形式出现,年费89美元,运费全免且两天送达。

友情提示:选择试用后,一定要记得去Amazon后台的“Prime服务自动续费”处关闭自动续费,否则1个月之后信用卡就自动划走年费。Amazon免运费的办法还有多个,具体可参考“海外购Amazon.com如何免运费”一文。

Amazon是美国最大的B2C商城,产品种类繁多,价格通常较有优势,而且不对国内用户有任何限制,是海外购的首选网站。建议网友们从Amazon入手开始自己的海外购之旅,Amazon亚马逊购物手把手教程在此,建议初次海外购的网友仔细阅读。海外购需要一定的英语基础,否则容易错误操作或未理解各种优惠活动的细节,引起不必要的损失,建议在英语水平较好或有英语水平较好朋友的帮助下进行操作,使用翻译工具也可以临时解决问题。

 3、收发转运

支付订单几天后,转运公司网站可以查询海外地址仓库是否收到货物,如果不放心或者迟迟未入库,可以查询网购商家的订单详情中的快递编号,然后到相应快递网站(例如UPS等)查询快递详情,必要时记录下运单号码与转运公司核实。

友情提示:部分转运公司需要手工入库,这需要用户在转运网站的后台管理页面中手动输入自己的运单号码。

各家转运公司接下来的操作略有不同,但不外乎给转运公司的账户汇充足额转运费用、登记填写国内收货地址、确认转运公司入库单、核实称重(运费通常都以重量为依据)、提交转运申请、计算费用并扣款等。全部操作完成后,就可以等待商品到国内了。通常后台都会有一个“在途运单”页面,可以查看运单实时状态,了解送达时间。

部分转运公司按整磅数收取费用,这时候可以通过合箱节省运费。例如一个1.1磅的电子书和0.3磅的耳机,如果原箱转运需要付2磅+1磅=3磅的运费,申请合箱后,转运公司的工作人员会拆开货物包装,把两件物品放在一起后重新打包称重,这样只需要2磅的运费。但合箱操作可能会带来收货的延迟,特别是在黑色星期五等转运公司不堪重负的时候,尽量不要提交合箱操作。部分转运还提供诸如加固、塞报纸等附加服务,这些服务可能需收取一定费用。

友情提示:有的转运公司需要预先充值才能使用其服务,可以适当多充一些,预防因费用不足延误收货时间。各转运公司都有详细的流程介绍,也有相关的论坛讨论相关问题,网友们不必过于担心流程繁琐,实际操作一次就可以明了。

4、清关“入手”

海外购的产品必须清关才可进入国内配送环节。中华人民共和国海关总署《关于调整进出境个人邮递物品管理措施有关事宜》规定,自2010年9月1日起,取消过去对个人邮递物品的免税额,并且对邮递进境物品应缴进口税超过50元人民币的一律按商品价值全额征税。目前国内有3个主要进关口岸:天津、上海和重庆。上海海关对电子产品征税较高,政策也会不时调整。如果如被抽到需要缴纳关税履行义务,将延长到货时间。不过,消费者不需要懊恼,依法纳税是每个公民应尽的义务。海外购的产品通常算上关税也比国内购买的价格划算的多。如果产生关税,转运公司客服会电话或邮件通知你,充值后由转运公司代缴,货品被海关强制没收的可能性非常小。

转运公司在国内通常使用EMS作为快递方式,也有部分使用韵达、联邦快递等。通常在转运网站的后台中可以查询运单在国内的EMS单号,用户可以根据单号在特快专递网站查询到包裹的实时状态。一旦EMS能查到状态,“入手”也就是2-3天的事情了。

5、总结

海外购虽然很有诱惑力,但仅适合部分产品不在大陆销售的产品(例如Kindle电子书阅读器等)以及与国内同型号产品价差较大的商品。而一些过重的产品可能会因为转运费用抵消掉国内外的价差,海外购就不划算了。另外,请避免购买类似香水、喷雾类气压罐等海关禁运的产品。最后需要提醒的是,海外购需要耐心,路上花费一周甚至两周是非常正常的事情。另外,若产品有故障,返修不便也是不得不面对的问题。

6、相关链接

1)海外购Amazon.com如何免运费

2)海外购货品的返修流程

3)Amazon亚马逊购物手把手教程

4)海外购之转运手把手教程

5)海外购常见尺码对照表

6)Amazon.com网站退货攻略

7)百通转运协助退货攻略

“什么值得买”网站衷心希望网友们通过“海外购”淘到“真实惠”,理性消费同时享受品质生活。这,就是我们“什么值得买”的核心精神。

租房注意事项有哪些 – 北京赶集网

具体描述1、查看出租人的房产证明和有效身份证明是否一致 2、签订租房合同时,应问清房租包含的内容,水、电、暖、煤气(天然气)和物业管理费由谁承担。 3、要求出租人在房屋出租前结清水、电、暖、煤气(天然气)和其它费用。4、明确租金标准、租赁期限、房租支付时间和付款方式 ,并要求出租方提供租金收据。 5、应对能否转租做出约定;对提前终止合同做出约定;对房屋维修做出约定。 6、要明确违约责任和违约的补偿标准。 7、入住前检查屋内家具、电器、其他设施的好损情况,并约定维修责任。8、 尽量找房主直接签约9、 找中介一定找正规中介大中介,租房合同一定要签订10 .签订合同要看仔细,需要添加的就要求房主添加,有对你不利的条款要求删除,如果拒绝,这房子宁可不租免得日后麻烦11 .在中介租房一定分清房子是三方协议的居间还是完全委托代理的房屋银行。中介合约要仔细看清楚,不明白的要问,不合理的要提出来。如果有异议可以当天不签约上网问问再做打算。看房定金要谨慎,免得受骗。12 .拒绝二房东,不要从二房东处租房子,没法律保证容易出事13 .谨防中介内部人员冒充房东,你务必看到房产证和身份证原件,复印件无效(假)14 .中介签约的合同必须当天盖章,不盖章的要谨慎,可能无效。这类情况你的房租不要给他们。15 .做房屋物品清单要让对方详细写清各家电数量和型号,免得出事

回复者:匿名 2011-01-25 00:14:38

The Y Combinator explained with JavaScript

kestas.kuliukas.com

The Y Combinator explained with JavaScript

1 var y = function(le) {
2     return function(f) {
3         return f(f);
4     }(function(f) {
5         return le(
6             function(x) { return (f(f))(x); }
7         );
8     });
9 };

The Y combinator is an interesting function which only works with functional languages, showing how
recursion can still be done even without any variable or function declarations, only functions and
parameters.
Unfortunately it’s hard to figure out what it does exactly because of what it is; variable and
function declarations are what make computer code understandable, and the Y combinator is all about
trying to work without them.

I got the Y combinator in its JavaScript form above, and an awareness of it and challenge to understand it,
from the third of Douglas Crockford’s excellent lectures on JavaScript.

The approach I found the most helpful for learning how it works, which I’ll use below, is to try and
build the Y combinator using an easy example; the factorial function. (fact(4) = 4*3*2*1 = 24)

1 var fact = function(n) {
2     if( n < 2 ) return 1;
3     else return n*fact(n-1);
4 };

There it is, a very simple recursive function. If n is 1 return 1, otherwise multiply n by fact(n-1).
In order to make the Y combinator though we need to remove all declarations. The fact() function refers to fact()
within itself. But how can we recursively call the factorial function without creating a reference to the factorial
function?
We can do it by passing the factorial function as a parameter, and having a function which returns the factorial
function rather than declare it.

1 var makeFact = function(givenFact) {
2     var fact=function(n) {
3         if( n < 2 ) return 1;
4         else return n * givenFact(n-1);
5     }
6     return fact;
7 };

The problem is that without a "givenFact" function we can’t call makeFact. It seems like we can’t use this approach because we can’t use makeFact to make a factorial function without already having a factorial function!
It turns out that it is possible though, because the fact function which makeFact makes doesn’t always call givenFact. Instead of passing in a pre-made givenFact we can make givenFact itself use makeFact, until makeFact
makes a fact call which doesn’t need to call givenFact.

1 var makeRealFact = function(makeFact) {
2     var tryFact=function(n) {
3         var nextTryFact = makeFact(tryFact);
4         return nextTryFact(n);
5     };
6     return makeFact(tryFact);
7 };

We create a new function makeRealFact (our Y function) which uses makeFact to make the actual factorial function.
The tryFact function is passed to makeFact to be used as its givenFact function. If makeFact needs to
use givenFact it will call tryFact again, which will make another tryFact using makeFact and try again.
Eventually makeFact will be able to return a factorial function which doesn’t use givenFact, which can
then be used to find a givenFact, and that used to find another givenFact, and so on.

This approach is like using makeFact to keep working on the tryFact function, assuming makeFact will always need a simpler tryFact function until it finds a way to makeFact without needing tryFact. It’s still simple
recursion, but in an indirect way.

"return nextTryFact(n)" will recursively call tryFact(n)-nextTryFact(n)-tryFact(n-1)-nextTryFact(n-1)-etc until nextTryFact(1) is reached, returning a value without needing to use givenFact.

There is still a problem though; tryFact references itself ("var nextTryFact = makeFact(tryFact);"), so it doesn’t solve the problem of getting rid of
variable/function declarations.
Another function needs to be
created to keep on cycling through tryFact-nextTryFact, without tryFact having to reference itself.
The getNextTryFact function will return the next tryFact function to tryFact, so it doesn’t have to refer to itself.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function() {
03         var tryFact = function(n) {
04             var nextTryFact = getNextTryFact();
05             var result = nextTryFact(n);
06             return result;
07         };
08         var nextTryFact = makeFact(tryFact);
09         return nextTryFact;
10     };
11     return getNextTryFact();
12 };

Instead of tryFact passing itself to makeFact until it isn’t needed it calls getNextTryFact, which passes tryFact to makeFact for it.
But now getNextTryFact needs to refer to itself, so we need a way to refer to getNextTryFact
without declaring it.
This is done by passing getNextTryFact to itself as a parameter, and is the final adjustment needed to
remove all self-referencing functions.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         var tryFact = function(n) {
04             var nextTryFact = getNextTryFactRef(getNextTryFactRef);
05             var result = nextTryFact(n);
06             return result;
07         };
08         var nextTryFact = makeFact(tryFact);
09         return nextTryFact;
10     };
11     return getNextTryFact(getNextTryFact);
12 };

Now we have a function which can make a factorial function using the makeFact function recursively,
without ever needing to refer to its own variables/functions via labels; everything can be accessed
via parameters. (getNextTryFactRef is a reference to the getNextTryFact function, maintained using parameters rather than a variable declaration.)

Obviously declarations are still used though, but now we can start to factor them out to end up with
a function which only uses parameters. From here on the function gets much less readable, but we show that it truly doesn’t need variable declarations, and thus show how it is equivalent to the Y function above.

First the tryFact function is passed directly to makeFact, without being declared.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         var nextTryFact = makeFact(
04             function(n) {
05                 var nextTryFact = getNextTryFactRef(getNextTryFactRef);
06                 var result = nextTryFact(n);
07                 return result;
08             }
09         );
10         return nextTryFact;
11     };
12     return getNextTryFact(getNextTryFact);
13 };

Next the inner-most nextTryFact function is used to generate a result without being declared.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         var nextTryFact = makeFact(
04             function(n) {
05                 // Already it's becoming cryptic
06                 var result = (getNextTryFactRef(getNextTryFactRef))(n);
07                 return result;
08             }
09         );
10         return nextTryFact;
11     };
12     return getNextTryFact(getNextTryFact);
13 };

Next the result is returned without being declared.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         var nextTryFact = makeFact(
04             function(n) {
05                 return (getNextTryFactRef(getNextTryFactRef))(n);
06             }
07         );
08         return nextTryFact;
09     }
10     return getNextTryFact(getNextTryFact);
11 };

Next the outer nextTryFact function is returned directly without being declared.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         return makeFact(
04             function(n) {
05                 return (getNextTryFactRef(getNextTryFactRef))(n);
06             }
07         );
08     };
09     return getNextTryFact(getNextTryFact);
10 };

Because getNextTryFact is used twice on the same line a label is needed to refer to the same
thing twice. This has to be done by passing it to a function as a parameter, so the parameter can
be used as a label to refer to the same thing twice.

01 var makeRealFact = function(makeFact) {
02     var getNextTryFact=function(getNextTryFactRef) {
03         return makeFact(
04             function(n) {
05                 return (getNextTryFactRef(getNextTryFactRef))(n);
06             }
07         );
08     };
09     return function(getNextTryFactRef) {
10         return getNextTryFactRef(getNextTryFactRef);
11     }(getNextTryFact);
12 };

Finally the getNextTryFact function is passed directly to the nameless function which
calls getNextTryFact on itself to start the recursion going.

01 var makeRealFact = function(makeFact) {
02     return function(getNextTryFactRef) {
03         return getNextTryFactRef(getNextTryFactRef);
04     }(
05         function(getNextTryFactRef) {
06             return makeFact(
07                 function(n) {
08                     return (getNextTryFactRef(getNextTryFactRef))(n);
09                 }
10             );
11         }
12     );
13 };

We’ve got rid of the declarations of tryFact, nextTryFact, result, and getNextTryFact, leaving a
function which has no declarations, only parameters.
All that is needed now is to rename makeFact "le" (don’t know why), getNextTryFactRef "f",
the n parameter "x", and makeRealFact "y", get rid of some white-space, and we have the Y combinator
function as it was given above.

01 var y = function(le) {
02     return function(f) {
03         return f(f);
04     }(function(f) {
05         return le(
06             function(x) { return (f(f))(x); }
07         );
08     });
09 };
10 // Even when written from scratch this form is baffling

Although we made it for the factorial function the Y combinator can be used for any recursive function,
showing that recursion can be done without variables and thus without any side-effects. Below the
same y combinator function is used to make a factorial function and a fibbonaci function.

01 var makeFact = function(givenFact) {
02     return function(n) {
03         if( n < 2 ) return 1;
04         else return n * givenFact(n-1);
05     }
06 };
07 var fact=y(makeFact);
08 alert(fact(5)); // Outputs 120
09  
10 var makeFib = function(givenFib) {
11     return function(n) {
12         if( n<=2 ) return 1;
13         else return givenFib(n-1) + givenFib(n-2);
14     }
15 };
16 var fibbonaci=y(makeFib);
17 alert(fibbonaci(5)); // Outputs 5

Or, if you want to get rid of all declarations completely:

01 (function(y) {
02     alert(y(
03         function(givenFact) {
04             return function(n) {
05                 if( n < 2 ) return 1;
06                 else return n * givenFact(n-1);
07             }
08         }
09     )(5)); // Outputs 120
10      
11     alert(y(
12         function(givenFib) {
13             return function(n) {
14                 if( n<=2 ) return 1;
15                 else return givenFib(n-1) + givenFib(n-2);
16             }
17         }
18     )(5)); // Outputs 5
19      
20 })(
21     function(le) {
22         return (function(f) {
23             return f(f);
24         })(function(f) {
25             return le(
26                 function(x) { return (f(f))(x); }
27             );
28         });
29     }
30 );

Not a var in sight.
It’s inefficient and it’s ugly, but it’s clever, it proves something interesting about functional languages, and
toy problems like this should help in recognizing when anonymous functions are genuinely useful for real problems
and using them appropriately.

Since PHP 5.3 PHP has had anonymous functions, allowing the sort of function passing that makes things
like the Y combinator possible.
However PHP can’t do "($f($f))($x)", it has to do "$g=$f($f); $g($x);". This makes a callonself function necessary and prevents a true Y combinator implementation. Something that does the equivalent thing is given below,
for those who know better PHP than JavaScript.

01 function callonself($f) {
02     return $f($f);
03 };
04 function y($le) {
05     return callonself(function($f) use($le) {
06         return $le(function($x) use ($f) {
07             $g=callonself($f);
08             return $g($x);
09         });
10     });
11 }
12  
13 $makeFact=function($givenFact) {
14     return function($n) use($givenFact) {
15         return $n <= 2 ? $n : $n*$givenFact($n-1);
16     };
17 };
18 $fact=y($makeFact);
19  
20 print $fact(5)."<br>"; // Outputs 120
21  
22 $makeFib=function($givenFib) {
23     return function($n) use($givenFib) {
24         return $n <= 2 ? 1 : $givenFib($n-1) + $givenFib($n-2);
25     };
26 };
27 $fibbonaci=y($makeFib);
28  
29 print $fibbonaci(5); // Outputs 5

如何开发出成功的iPhone游戏

  iPhone游戏如此之多,设计iPhone游戏都该注意什么?又如何让让自己的游戏脱颖而出,吸引玩家并留住玩家,开发商如何从游戏中获得收入?

  不要让玩家花太多时间通关

  通常我会在短途旅行或做饭时候,忙里偷闲,玩一些像《割绳子》或者《袋鼠快跑》这样的游戏,因为这类游戏很简单,通过第一关可能只需最多10秒钟的时间,在简单关卡,在遇到挑战或游戏小把戏之前,你就能很快知道游戏的基本规则或者一些新功能,难一些的关,也最多需要几分钟就能通关,由于通关时间短,所以在成功过关以前,你可能会尝试10次以上,由于每次尝试都不会花太多时间,所以你就不会完全放弃,一试再试。

  每关章节

  通常来说,成功的iPhone游戏都有很多关,比如《割绳子》就有200关以上,每关又被分成不同的章节,每增加一个章节就加入一个新的特性,刚开始几关会比较简单,让玩家练手,很多时候,还有新武器或新目标与你互动,随着闯关的进行,游戏就变得越来越复杂,越来越具有挑战性,因为新的目标会和之前章节介绍的目标进行结合。

  当然,你也可以用一些比较奇特的方式来利用新功能,最好的例子就是《愤怒的小鸟》里边的海鹦。

  对每关成绩评分

  对玩家的成果进行等级评分可以延长游戏寿命,游戏结束了,玩家能进入下一关并不意味着游戏上一关就真的结束了,你能花更少的时间玩儿吗?能获得更高评分吗?想在某关多获得几颗星的评级吗?很多玩家都想追求完美,某一关玩过了,但如果获得星级不高,不会就此罢休,会继续玩,直到评分很高才收手,这样就延长了游戏寿命。

  与GameCentre/OpenFient绑定

  让玩家将得分或者所有成就发布到一个网站中,就为这个游戏简介增加了多玩元素,由于玩家会鼓励朋友下载并一起玩,这样无形中就帮游戏做了推广。

  经常更新

  《割绳子》游戏发布之初,只有几关,每增加一个章节就会新增一个特征,总会为游戏延长一点生命周期,一年过后,游戏超过200多关,非常受欢迎,苹果公司也会鼓励开发商改进自己的应用或游戏。

  多重主题

  《愤怒的小鸟》及《围困的英雄》两种游戏都有很多关,让游戏从一关到另一关保持新鲜的方法就是基于游戏主题改变游戏画面,比如《愤怒的小鸟》现在又20多种不同的鸟,让游戏角色稍微改变形象极有可能延长游戏寿命。

  让五岁小孩儿试玩

  简单是关键,如果一个五岁的小孩儿不理解游戏并且不能通过第一关,那么这个游戏可能就有些复杂了,最近阅读过一篇文章,一个游戏开发商就给他的孩子都配备iPhone,看着他们玩游戏。

  鼓励玩家对游戏进行评级

  评级很重要,尤其是对付费游戏来说,如果你是玩家,在购买游戏之前都想看看是否物有所值,所以评级很重要,如果没有人对你的游戏评级,那么你的买家就有限,现在很多游戏都会让玩家对之进行评级。

  应用内购买

  这现在已成为许多开发商获得收入的一种方式,听过一种叫“毒贩子”的模式吗?这其实是免费增值模式的的进阶版。游戏免费,但要求玩家在上瘾之后掏现金,看看AppStore的Top Grossing,就会发现,这种模式相当成功,第一名是《龙谷》(DragonVale),免费下载,然后提供一系列的应用内购买。

  应用内购买的另一个好处就是提供一个跳过某关的游戏币,如果玩家非常喜欢一个游戏,但遇到一个怎么也闯不过的关,就可化钱来跳过此关进入下一关。

  发布精简版

  许多Top付费游戏都有精简版,通常都可免费下载并且有一两个章节,或许还有广告,这就让玩家在买游戏之前可以试玩,这对刺激玩家玩游戏来说是一个很大的驱动力,但也有可能玩家完了之后就放弃游戏。 

  注释:本文由一位游戏开发者所撰。

  英文原文:Doad雷锋网编译。

评论《如何开发出成功的iPhone游戏》的内容…

相关文章:

微博:新浪微博腾讯微博

QQ群:186784064

月光博客投稿信箱:williamlong.info(at)gmail.com

Created by William Long www.williamlong.info

google地图经纬度偏移修正算法完美解决方案_基站定位_新浪博客

由于受到国家一些法律法规限制,所有的电子地图服务提供商都需要给地图数据加上偏移和加密,因此广受大家关注的google地图也不例外。但是作为一些用惯了免费服务的网友们,始终对google
MAP上的标注偏移很头疼,我收集了一些资料,今天在这里和大家一起分享。
所谓的地图数据加密偏移,其实就是用一个偏移算法对地图的经纬度做一个加减偏移量,从而达到与实际地图不一致。这个偏移算法本身是没有什么规律可言的,每家地图服务商都有一套自己的加密偏移算法,既然算法上没有什么规律可言,但是对于算法中生成的偏移量是否有规律呢?这个是可以肯定的,但是偏移算法中生成的偏移量是有规律而言的。偏移量的规律很难得到,要是能拿到这个偏移量,就可以说是破解了某一个地图服务商的地图加密。
那我们怎么解决这个偏差呢!我在网上找到了一个强人破解google map偏移的方法
毕竟做地图开发的都存在卫星图和地图的切换,谁不想让切换以后的地图对上呢!
后来我发现google的地图服务,ditu.gogle开始的都没有偏差,maps.google开头的服务就有偏差,我就开始查找google的取偏
移量算法,事前我还是图破解google手机版本的数据,没有成功,估计是使用了自己的压缩或加密算法,最后也没有找到规律,后来才尝试破解web版本的
不过web版本的接口我对于js不是特别熟悉,所以本次破解放弃了分析源代码的步骤,而是直接采用排除法
那就是把地图部分访问的全部地址,一个接一个封杀掉,查找那个起偏移做用的网址
http://ditu.google.cn/maps/vp?spn=0.0,0.0&z=18&
vp=39.111195,117.148067
最后找到了就是这个,记住每次测试用清理浏览器缓存哦,使用fixfox的fildder和adblock就够了 然后就是
分析每次返回内容的规律,皇天不负有心人啊,我总算是搞定了,下面是我整理的接口
Google
中国地图偏移接口

 

1. 

    
接口地址http://ditu.google.cn/maps/vp?spn=0.0,0.0&z=18&vp=39.111195,117.148067

 

     
(注:.cn和.com都可以,我用国内服务器就会选择.cn用美国服务器就会选择.com)

2. 

    
返回内容中的有效部分:

3. 

    
(39.111195, 117.148067, 18, [9,
-2, 18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -135, 1193,
-270])

4. 

    
Spn参数暂时未知实际意义,但是需要上发spn参数,任意两个小数用逗号分开Vp参数纬经度值,用逗号分隔,z参数为地图缩放级别,无实际意义

5. 

    
取回的部分中有效数字为[9, -2,
18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -134, 1192,
-268]
这个数组总共有8组数字,每两个为一组,分为别从11级到18级的地图和卫星图的偏移像素数量,我们前一组数字精确的等于后一组数字除二,我们为了得到最精确的偏移,故选择第18级的偏移量1193-2701193x方向上精度的偏移像素,-270y方向上维度偏移像素

6. 

    
经纬度的偏移转换我们需要江经纬度39.111195117.148067转化为18级像素值25620917 55392414,然后分别加上偏移量-270,1193,然后再转化为经纬度39.11231854918217 117.15446412563324,即位偏移后的经纬度

google的地图采用将地球圆表面投影成平面的方式进行贴图

假设zoom=15;

横坐标从左至右像素为0-256*2的15次幂,也就是每增加一级,地图大小横纵坐标加倍,256为一个标准图片的大小

显示-180度到+180的范围,经度越大x越大

纵坐标从上到下像素为0-256*2的15次幂,显示+85到-85度的范围,纬度越小y越大

我们先看一下经度的转换

经度的转换,我就不多说了,均匀分布,大家简单的看一下下面的公式就明白了

经度到像素X值

public static double lngToPixel(double lng, int zoom) {

return (lng + 180) * (256L <<
zoom) / 360;

}

像素X到经度

public static double pixelToLng(double pixelX, int zoom) {

return pixelX * 360 / (256L <<
zoom) – 180;

}

纬度到像素Y

public static double latToPixel(double lat, int zoom) {

double siny = Math.sin(lat * Math.PI / 180);

double y = Math.log((1 + siny) / (1 – siny));

return (128 << zoom) * (1 – y / (2
* Math.PI));

}

像素Y到纬度

public static double pixelToLat(double pixelY, int zoom) {

double y = 2 * Math.PI * (1 – pixelY / (128
<< zoom));

double z = Math.pow(Math.E, y);

double siny = (z – 1) / (z + 1);

return Math.asin(siny) * 180 / Math.PI;

}

维度的这个转换,单纯去理解不是很好理解,我也没有太深入的了解,从公式来看,采用了一种非线性变化,也就是靠近赤道的地方单位像素表现的纬度间距
大,越靠近两极越小,可能是因为 经度在靠近两极的方向均匀变化,导致纬度也要进行拉伸,否则
 

靠近两极的地方,地理形状就该发生变化了,总之上面的转换公式大家还是可以研究一下的,google维度的表示范围是-85到+85,这个可以求出来!

上面得到的像素XY是像素的坐标,并非是google地图取地图的那个XY那个XY是把像素所标除以256得到的商,也就是每张图片的大小

============================================================================

 

需要购买基站数据,或者定位能力的朋友、公司可以联系我,谢谢

联系方式:

QQ:36387586

MSN:sheqiao@hotmail.com

手机号:13581970241

基站定位技术讨论QQ群号:96647899