扁平足为什么不能当兵| 什么什么不安| 13颗珠子的手串什么意思| 办理生育登记有什么用| 结节是什么病| 基围虾是什么虾| 为什么身上会出现淤青| 什么让生活更美好作文| cmv是什么病毒| 宫颈多发潴留囊肿是什么意思| 牙周康又叫什么名字| 腰疼是什么原因引起的男性| 社恐到底在害怕什么| b27是什么检查| 1985年出生是什么命| 毛细血管扩张是什么原因引起的| 加拿大现在是什么时间| 临床是什么意思| 什么好像什么| 疾控中心是干什么的| 赛马不相马什么意思| 心慌是什么感觉| 脾胃不和吃什么药| 心脏早博吃什么药好| 对食什么意思| 下午五点半是什么时辰| 呆呆的笑是什么笑| 表虚自汗是什么意思| 血糖高吃什么主食| 穿刺是什么手术| 白带异常是什么原因| 肾虚吃什么| 鳕鱼是什么鱼| 2月9日什么星座| 老是掉发是什么原因| 夏天什么时候最热| 医学检验技术是什么| 男人眉心有痣代表什么| 夏天喝什么茶最好| 姑奶奶是什么意思| 胃体息肉是什么意思| 眼底出血是什么症状| 人头什么动| 一个马一个襄念什么| 缘起缘灭是什么意思| 旅游有什么好处| 尿肌酐低是什么原因| 什么是匝道图片| 膑是什么意思| 吃什么助睡眠| 嘴里有粘液是什么原因| 玄胡又叫什么| 最大的罩杯是什么杯| 中国国鸟是什么鸟| 黄金是什么药材| bella是什么意思| 公关是什么意思| 动车跟高铁有什么区别| 淋病和梅毒有什么区别| 病毒感冒吃什么消炎药| 手腕比喻什么| 先兆流产什么意思| 湿气重不能吃什么| 洋葱对肝脏有什么好处| 自闭症是什么原因引起| 睡前一杯牛奶有什么好处| 胸口疼痛是什么原因| 桃子不能和什么一起吃| 朵字五行属什么| 套话是什么意思| 新疆人是什么民族| 低密度脂蛋白高是什么原因| 馐什么意思| 精子什么味| 幽门螺旋杆菌的症状吃什么药| 室性期前收缩是什么意思| 北极熊的毛是什么颜色| 直是什么意思| 庸人自扰是什么意思| 自然流产的症状是什么样的| 气管小憩室是什么意思| 什么是围绝经期| 19年是什么年| 肚子疼看什么科| 小孩走路迟是什么原因| 遥遥相望是什么意思| 厚颜无耻是什么生肖| 干咳吃什么药效果好| 儿童鸡胸挂什么科| 睡觉后腰疼是什么原因引起的| 阴道瘙痒是什么原因造成的| 黑松露什么味道| 什么饮料解暑| bgm网络语什么意思| 杠杆炒股是什么意思| 甘肃天水有什么好玩的地方| 为什么会得静脉曲张| 冰心原名是什么| o和ab型生的孩子是什么血型| 口出狂言是什么生肖| 泻盐是什么东西| 侬是什么意思| 随大流什么意思| 独角兽是什么意思| 肝区回声密集是什么意思| 光纤和宽带有什么区别| 糖尿病可以喝什么饮料| 空调水滴是什么模式| 天气一热身上就痒是什么原因| 经期头疼是什么原因怎么办| 来例假喝红糖水有什么好处| 履什么意思| s925银是什么意思| 查传染病四项挂什么科| 翻车了是什么意思| 点痣挂什么科室| h是什么意思| 屁股长痘痘是什么原因| 范字五行属什么| 为什么总是流鼻血| 睾丸是什么| 气山读什么| 蔓字五行属什么| 无妄是什么意思| 肚脐有分泌物还发臭是什么原因| 南乳是什么| 唐氏筛查和无创有什么区别| 蚊子喜欢什么味道| 扁桃体发炎吃什么药好得快| 蚊子怕什么气味| 月经不调吃什么药效果好| 吃蒲公英有什么好处| 抹胸是什么| 肝内血管瘤是什么意思| 他将是你的新郎是什么歌| 网黄什么意思| 什么是gdp| 小孩老是肚子疼是什么原因| 6月26日是什么日子| 肺炎吃什么药有效| 冠冕堂皇是什么意思| 一吃东西就肚子疼是什么原因| 花心大萝卜是什么意思| 两个叉念什么| 高校是什么意思| 包皮开裂用什么药| 荷花的别称是什么| 招待是什么意思| 咖啡色配什么颜色好看| 丁火是什么意思| 十月一日是什么日子| 缺维生素a吃什么食物| 卤蛋是什么意思| 福晋是什么意思| ntl是什么意思| 女性喝红茶有什么好处| 有什么植物| 钧字五行属什么| cl是什么牌子| 肮脏是什么意思| 总是放响屁是什么原因| 浮躁的意思是什么| 4月18号是什么星座| 后背长痘痘用什么药膏| 地铁和高铁有什么区别| 肌酐高了会出现什么问题| 大哥是什么生肖| 沈阳有什么特产| 倒牙是什么意思| 什么的月光| 阴气重是什么意思| 舌头疼吃什么药| 肛门痒痒的是什么原因| 什么样的脚好看| 100元人民币什么时候发行的| 干细胞是什么东西| 足跟血筛查什么疾病| 肠胃炎可以喝什么饮料| 缠腰蛇是什么原因引起的| 痄腮是什么意思| 冥想是什么| 性功能下降是什么原因| 拉肚子吃什么药好使| 瘢痕子宫是什么意思| 骨密度高是什么意思| 吃大虾不能吃什么| 莫逆之交什么意思| 6月7日是什么星座| 夏至有什么习俗| 缺维生素a吃什么食物| 狮子是什么生肖| 一级护理是什么意思| 虎口长痣代表什么| 寄生虫长什么样| kinghome是什么牌子| dha什么时候吃最好| 三点水山今读什么| 出虚恭什么意思| 什么是民间故事| 痛风吃什么药| 神经性皮炎用什么药膏| 美国人的祖先是什么人| 鼻后滴漏吃什么药| 忽然心口疼是什么原因| cross是什么牌子| 鸡蛋价格为什么这么低| 什么是水洗棉| 三岁属什么生肖| 四个火念什么字| 肿瘤吃什么中药能消除| 吽是什么意思| 什么是穿堂风| 贫血的人适合喝什么茶| 万象更新是什么意思| 尿频尿急挂什么科| 鱼油对身体有什么好处| 四面八方什么生肖| 脾的作用和功能是什么| 子宫肌瘤是什么原因引起的| 吃什么能补蛋白| cor是什么意思| 芡实不能和什么一起吃| 罡是什么意思| 6月27是什么星座| 打屁很臭是什么原因| 子宫肌腺症是什么病| 蜱虫是什么虫| 七月什么星座| 降噪是什么意思| hiv弱阳性是什么意思| 胎儿fl是什么意思| 什么食物去湿气效果好| 忻字五行属什么| 过堂是什么意思| 草龟吃什么蔬菜| 脾肾气虚的症状是什么| 四大皆空是什么意思| 分心念什么| 海狗是什么动物| 骨密度减少是什么意思| 送老师送什么礼物好| 疱疹吃什么药见效快| 梦见大蟒蛇是什么征兆| 西楼是什么意思| 肩颈疼痛挂什么科| 小孩子记忆力差是什么原因| 胃炎是什么原因引起的| 正局级什么级别| 晚上吃芒果有什么好处和坏处| 袋鼠喜欢吃什么食物| 什么是硬盘| 高压正常低压低是什么原因| 胆囊大是什么原因| 流清鼻涕打喷嚏吃什么药| 双子座的幸运花是什么| 翻墙是什么| 总是打嗝是什么原因引起的| 美国属于什么洲| 甲状腺发炎有什么症状| 骨碎补有什么功效| 帝女花讲的是什么故事| 生肖猴和什么生肖最配| 硬膜囊前缘受压是什么意思| 卸妆用什么最好| 百度

Obfuscating "Hello world!"

百度 此前还有3个世界气象中心,分别位于美国华盛顿、俄罗斯莫斯科和澳大利亚墨尔本。

Update (November 1, 2017): Added Python 3 support.

A few months ago, I got first place in this Code Golf contest to create the weirdest obfuscated program that prints the string “Hello world!”. I decided to write up an explanation of how the hell it works. So, here’s the entry, in Python 2.7:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ << ________,
            (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __)
            - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ <<
            __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______
            << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) <<
            ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) <<
            __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______
            << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) +
            _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) <<
            (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ <<
            _))) + (_____ << ______) + (_ << ___)
        )
    )
)(
    *(lambda _, __, ___: _(_, __, ___))(
        (lambda _, __, ___:
            [__(___[(lambda: _).func_code.co_nlocals])] +
            _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
        ),
        lambda _: _.func_code.co_argcount,
        (
            lambda _: _,
            lambda _, __: _,
            lambda _, __, ___: _,
            lambda _, __, ___, ____: _,
            lambda _, __, ___, ____, _____: _,
            lambda _, __, ___, ____, _____, ______: _,
            lambda _, __, ___, ____, _____, ______, _______: _,
            lambda _, __, ___, ____, _____, ______, _______, ________: _
        )
    )
)

String literals weren’t allowed, but I set some other restrictions for fun: it had to be a single expression (so no print statement) with minimal builtin usage and no integer literals.

Getting started

Since we can’t use print, we can write to the stdout file object:

import sys
sys.stdout.write("Hello world!\n")

But let’s use something lower-level: os.write(). We need stdout’s file descriptor, which is 1 (you can check with print?sys.stdout.fileno()).

import os
os.write(1, "Hello world!\n")

We want a single expression, so we’ll use __import__():

__import__("os").write(1, "Hello world!\n")

We also want to be able to obfuscate the write(), so we’ll throw in a getattr():

getattr(__import__("os"), "write")(1, "Hello world!\n")

This is the starting point. Everything from now on will be obfuscating the three strings and the int.

Stringing together strings

"os" and "write" are fairly simple, so we’ll create them by joining parts of the names of various built-in classes. There are many different ways to do this, but I chose the following:

  • "o" from the second letter of bool: True.__class__.__name__[1]
  • "s" from the third letter of list: [].__class__.__name__[2]
  • "wr" from the first two letters of wrapper_descriptor, an implementation detail in CPython found as the type of some builtin classes’ methods (more on that here): ().__class__.__eq__.__class__.__name__[:2]
  • "ite" from the sixth through eighth letters of tupleiterator, the type of object returned by calling iter() on a tuple: ().__iter__().__class__.__name__[5:8]

We’re starting to make some progress!

1
2
3
4
5
getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(1, "Hello world!\n")

"Hello world!\n" is more complicated. We’re going to encode it as a big integer, which will be formed of the ASCII code of each character multiplied by 256 to the power of the character’s index in the string. In other words, the following sum:

$$\sum_{n=0}^{L-1} c_n(256^n)$$

where \(L\) is the length of the string and \(c_n\) is the ASCII code of the \(n\)th character in the string. To create the number:

>>> codes = [ord(c) for c in "Hello world!\n"]
>>> num = sum(codes[i] * 256 ** i for i in xrange(len(codes)))
>>> print num
802616035175250124568770929992

Now we need the code to convert this number back into a string. We use a simple recursive algorithm:

>>> def convert(num):
...     if num:
...         return chr(num % 256) + convert(num // 256)
...     else:
...         return ""
...
>>> convert(802616035175250124568770929992)
'Hello world!\n'

Rewriting in one line with lambda:

convert = lambda num: chr(num % 256) + convert(num // 256) if num else ""

Now we use anonymous recursion to turn this into a single expression. This requires a combinator. Start with this:

>>> comb = lambda f, n: f(f, n)
>>> convert = lambda f, n: chr(n % 256) + f(f, n // 256) if n else ""
>>> comb(convert, 802616035175250124568770929992)
'Hello world!\n'

Now we just substitute the two definitions into the expression, and we have our function:

>>> (lambda f, n: f(f, n))(
...     lambda f, n: chr(n % 256) + f(f, n // 256) if n else "",
...     802616035175250124568770929992)
'Hello world!\n'

Now we can stick this into our code from before, replacing some variable names along the way (f_, n__):

1
2
3
4
5
6
7
8
9
10
getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(
    1, (lambda _, __: _(_, __))(
        lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "",
        802616035175250124568770929992
    )
)

Function internals

We’re left with a "" in the body of our convert function (remember: no string literals!), and a large number that we’ll have to hide somehow. Let’s start with the empty string. We can make one on the fly by examining the internals of some random function:

>>> (lambda: 0).func_code.co_lnotab
''

What we’re really doing here is looking at the line number table of the code object contained within the function. Since it’s anonymous, there are no line numbers, so the string is empty. Replace the 0 with _ to make it more confusing (it doesn’t matter, since the function’s not being called), and stick it in. We’ll also refactor out the 256 into an argument that gets passed to our obfuscated convert() along with the number. This requires adding an argument to the combinator:

1
2
3
4
5
6
7
8
9
10
11
12
13
getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(
    1, (lambda _, __, ___: _(_, __, ___))(
        lambda _, __, ___:
            chr(___ % __) + _(_, __, ___ // __) if ___ else
            (lambda: _).func_code.co_lnotab,
        256,
        802616035175250124568770929992
    )
)

A detour

Let’s tackle a different problem for a bit. We want a way to obfuscate the numbers in our code, but it’ll be cumbersome (and not particularly interesting) to recreate them each time they’re used. If we can implement, say, range(1, 9) == [1, 2, 3, 4, 5, 6, 7, 8], then we can wrap our current work in a function that takes variables containing the numbers from 1 to 8, and replace occurrences of integer literals in the body with these variables:

1
2
3
4
5
6
7
8
(lambda n1, n2, n3, n4, n5, n6, n7, n8:
    getattr(
        __import__(True.__class__.__name__[n1] + [].__class__.__name__[n2]),
        ...
    )(
        ...
    )
)(*range(1, 9))

Even though we need to form 256 and 802616035175250124568770929992 as well, these can be created using arithmetic operations on these eight “fundamental” numbers. The choice of 1–8 is arbitrary, but seems to be a good middle ground.

We can get the number of arguments a function takes via its code object:

>>> (lambda a, b, c: 0).func_code.co_argcount
3

Build a tuple of functions with argcounts between 1 and 8:

1
2
3
4
5
6
7
8
9
10
funcs = (
    lambda _: _,
    lambda _, __: _,
    lambda _, __, ___: _,
    lambda _, __, ___, ____: _,
    lambda _, __, ___, ____, _____: _,
    lambda _, __, ___, ____, _____, ______: _,
    lambda _, __, ___, ____, _____, ______, _______: _,
    lambda _, __, ___, ____, _____, ______, _______, ________: _
)

Using a recursive algorithm, we can turn this into the output of range(1, 9):

>>> def convert(L):
...     if L:
...         return [L[0].func_code.co_argcount] + convert(L[1:])
...     else:
...         return []
...
>>> convert(funcs)
[1, 2, 3, 4, 5, 6, 7, 8]

As before, we convert this into lambda form:

convert = lambda L: [L[0].func_code.co_argcount] + convert(L[1:]) if L else []

Then, into anonymous-recursive form:

>>> (lambda f, L: f(f, L))(
...     lambda f, L: [L[0].func_code.co_argcount] + f(f, L[1:]) if L else [],
...     funcs)
[1, 2, 3, 4, 5, 6, 7, 8]

For fun, we’ll factor out the argcount operation into an additional function argument, and obfuscate some variable names:

1
2
3
4
5
6
7
(lambda _, __, ___: _(_, __, ___))(
    (lambda _, __, ___:
        [__(___[0])] + _(_, __, ___[1:]) if ___ else []
    ),
    lambda _: _.func_code.co_argcount,
    funcs
)

There’s a new problem now: we still need a way to hide 0 and 1. We can get these by examining the number of local variables within arbitrary functions:

>>> (lambda: _).func_code.co_nlocals
0
>>> (lambda _: _).func_code.co_nlocals
1

Even though the function bodies look the same, _ in the first function is not an argument, nor is it defined in the function, so Python interprets it as a global variable:

>>> import dis
>>> dis.dis(lambda: _)
  1           0 LOAD_GLOBAL              0 (_)
              3 RETURN_VALUE
>>> dis.dis(lambda _: _)
  1           0 LOAD_FAST                0 (_)
              3 RETURN_VALUE

This happens regardless of whether _ is actually defined in the global scope.

Putting this into practice:

1
2
3
4
5
6
7
8
(lambda _, __, ___: _(_, __, ___))(
    (lambda _, __, ___:
        [__(___[(lambda: _).func_code.co_nlocals])] +
        _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
    ),
    lambda _: _.func_code.co_argcount,
    funcs
)

Now we can substitute the value of funcs in, and then using * to pass the resulting list of integers as eight separate variables, we get this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(lambda n1, n2, n3, n4, n5, n6, n7, n8:
    getattr(
        __import__(True.__class__.__name__[n1] + [].__class__.__name__[n2]),
        ().__class__.__eq__.__class__.__name__[:n2] +
        ().__iter__().__class__.__name__[n5:n8]
    )(
        n1, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            256,
            802616035175250124568770929992
        )
    )
)(
    *(lambda _, __, ___: _(_, __, ___))(
        (lambda _, __, ___:
            [__(___[(lambda: _).func_code.co_nlocals])] +
            _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
        ),
        lambda _: _.func_code.co_argcount,
        (
            lambda _: _,
            lambda _, __: _,
            lambda _, __, ___: _,
            lambda _, __, ___, ____: _,
            lambda _, __, ___, ____, _____: _,
            lambda _, __, ___, ____, _____, ______: _,
            lambda _, __, ___, ____, _____, ______, _______: _,
            lambda _, __, ___, ____, _____, ______, _______, ________: _
        )
    )
)

Shifting bits

Almost there! We’ll replace the n{1..8} variables with _, __, ___, ____, etc., since it creates confusion with the variables used in our inner functions. This doesn’t cause actual problems, since scoping rules mean the right ones will be used. This is also one of the reasons why we refactored 256 out to where _ refers to 1 instead of our obfuscated convert() function. It’s getting long, so I’ll paste only the first half:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            256,
            802616035175250124568770929992
        )
    )
)

Only two more things are left. We’ll start with the easy one: 256. \(256 = 2^8\), so we can rewrite it as 1 << 8 (using a left bit shift), or _ << ________ with our obfuscated variables.

We’ll use the same idea with 802616035175250124568770929992. A simple divide-and-conquer algorithm can break it up into sums of numbers which are themselves sums of numbers that are shifted together, and so on. For example, if we had 112, we could break it up into 96 + 16 and then (3 << 5) + (2 << 3). I like using bit shifts because the << reminds me of std::cout << "foo" in C++, or print chevron (print >>) in Python, both of which are red herrings involving other ways of doing I/O.

The number can be decomposed in a variety of ways; no one method is correct (after all, we could just break it up into (1 << 0) + (1 << 0) + ..., but that’s not interesting). We should have some substantial amount of nesting, but still use most of our numerical variables. Obviously, doing this by hand isn’t fun, so we’ll come up with an algorithm. In pseudocode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func encode(num):
    if num <= 8:
        return "_" * num
    else:
        return "(" + convert(num) + ")"

func convert(num):
    base = shift = 0
    diff = num
    span = ...
    for test_base in range(span):
        for test_shift in range(span):
            test_diff = |num| - (test_base << test_shift)
            if |test_diff| < |diff|:
                diff = test_diff
                base = test_base
                shift = test_shift
    encoded = "(" + encode(base) + " << " + encode(shift) + ")"
    if diff == 0:
        return encoded
    else:
        return encoded + " + " + convert(diff)

convert(802616035175250124568770929992)

The basic idea here is that we test various combinations of numbers in a certain range until we come up with two numbers, base and shift, such that base << shift is as closest to num as possible (i.e. we minimize their absolute difference, diff). We then use our divide-and-conquer algorithm to break up best_base and best_shift, and then repeat the procedure on diff until it reaches zero, summing the terms along the way.

The argument to range(), span, represents the width of the search space. This can’t be too large, or we’ll end getting num as our base and 0 as our shift (because diff is zero), and since base can’t be represented as a single variable, it’ll repeat, recursing infinitely. If it’s too small, we’ll end up with something like the (1 << 0) + (1 << 0) + ... mentioned above. In practice, we want span to get smaller as the recursion depth increases. Through trial and error, I found this equation to work well:

$$\mathit{span} = \lceil\log_{1.5} \lvert{\mathit{num}}\lvert\rceil + \lfloor2^{4-\mathit{depth}}\rfloor$$

Translating the pseudocode into Python and making some tweaks (support for the depth argument, and some caveats involving negative numbers), we get this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from math import ceil, log

def encode(num, depth):
    if num == 0:
        return "_ - _"
    if num <= 8:
        return "_" * num
    return "(" + convert(num, depth + 1) + ")"

def convert(num, depth=0):
    result = ""
    while num:
        base = shift = 0
        diff = num
        span = int(ceil(log(abs(num), 1.5))) + (16 >> depth)
        for test_base in xrange(span):
            for test_shift in xrange(span):
                test_diff = abs(num) - (test_base << test_shift)
                if abs(test_diff) < abs(diff):
                    diff = test_diff
                    base = test_base
                    shift = test_shift
        if result:
            result += " + " if num > 0 else " - "
        elif num < 0:
            base = -base
        if shift == 0:
            result += encode(base, depth)
        else:
            result += "(%s << %s)" % (encode(base, depth),
                                      encode(shift, depth))
        num = diff if num > 0 else -diff
    return result

Now, when we call convert(802616035175250124568770929992), we get a nice decomposition:

>>> convert(802616035175250124568770929992)
(((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __) - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) << ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) << __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______ << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) + _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ << _))) + (_____ << ______) + (_ << ___)

Stick this in as a replacement for 802616035175250124568770929992, and put all the parts together:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ << ________,
            (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __)
            - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ <<
            __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______
            << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) <<
            ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) <<
            __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______
            << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) +
            _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) <<
            (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ <<
            _))) + (_____ << ______) + (_ << ___)
        )
    )
)(
    *(lambda _, __, ___: _(_, __, ___))(
        (lambda _, __, ___:
            [__(___[(lambda: _).func_code.co_nlocals])] +
            _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
        ),
        lambda _: _.func_code.co_argcount,
        (
            lambda _: _,
            lambda _, __: _,
            lambda _, __, ___: _,
            lambda _, __, ___, ____: _,
            lambda _, __, ___, ____, _____: _,
            lambda _, __, ___, ____, _____, ______: _,
            lambda _, __, ___, ____, _____, ______, _______: _,
            lambda _, __, ___, ____, _____, ______, _______, ________: _
        )
    )
)

And there you have it.

Addendum: Python 3 support

Since writing this post, several people have asked about Python 3 support. I didn’t think of it at the time, but as Python 3 continues to gain traction (and thank you for that!), this post is clearly long overdue for an update.

Fortunately, Python 3 (as of writing, 3.6) doesn’t require us to change much:

  • The func_code function object attribute has been renamed to __code__. Easy fix with a find-and-replace.
  • The tupleiterator type name has been changed to tuple_iterator. Since we use this to extract the substring "ite", we can get around this by changing our indexing in ().__iter__().__class__.__name__ from [_____:________] to [_:][_____:________].
  • os.write() requires bytes now instead of a str, so chr(...) needs to be changed to bytes([...]).

Here is the full Python 3 version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_:][_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                bytes([___ % __]) + _(_, __, ___ // __) if ___ else
                (lambda: _).__code__.co_lnotab,
            _ << ________,
            (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __)
            - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ <<
            __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______
            << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) <<
            ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) <<
            __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______
            << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) +
            _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) <<
            (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ <<
            _))) + (_____ << ______) + (_ << ___)
        )
    )
)(
    *(lambda _, __, ___: _(_, __, ___))(
        (lambda _, __, ___:
            [__(___[(lambda: _).__code__.co_nlocals])] +
            _(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []
        ),
        lambda _: _.__code__.co_argcount,
        (
            lambda _: _,
            lambda _, __: _,
            lambda _, __, ___: _,
            lambda _, __, ___, ____: _,
            lambda _, __, ___, ____, _____: _,
            lambda _, __, ___, ____, _____, ______: _,
            lambda _, __, ___, ____, _____, ______, _______: _,
            lambda _, __, ___, ____, _____, ______, _______, ________: _
        )
    )
)

Thank you for reading! I continue to be amazed by this post’s popularity.

果实是什么意思 alp医学上是什么意思 今天是什么节日吗 夏天脚底出汗是什么原因 孕妇喝什么汤
氯胺酮是什么 尿正常是什么颜色 省军区司令员是什么级别 长痘是什么原因 海绵肾是什么意思
阑尾有什么用 爆栗什么意思 思维什么意思 是什么品牌 开门杀是什么意思
梦见买袜子是什么意思 什么样的荷叶 腋下出汗多是什么原因 每天喝酸奶有什么好处和坏处 红线女是什么意思
地接是什么意思hcv7jop7ns2r.cn br是什么元素hcv9jop7ns9r.cn 失眠吃什么药效果最好hcv9jop0ns9r.cn 什么终于什么造句hcv8jop5ns1r.cn 谷草谷丙偏高是什么意思hcv8jop7ns0r.cn
自相矛盾的道理是什么hcv8jop9ns5r.cn 南岳什么山aiwuzhiyu.com 乙肝e抗原阳性是什么意思0297y7.com 影子虫咬伤后用什么药jinxinzhichuang.com 猪肉炒什么菜好吃hcv8jop5ns5r.cn
什么奶茶好喝aiwuzhiyu.com 手指甲有黑色条纹是什么原因hcv9jop5ns2r.cn 下一年是什么生肖hcv9jop8ns3r.cn 梦到吃屎是什么意思hcv7jop7ns4r.cn 丈二和尚摸不着头脑是什么意思hcv8jop0ns8r.cn
胆囊息肉是什么原因造成的hcv9jop6ns6r.cn 唾液腺是什么组织hcv8jop6ns3r.cn 做梦梦到老婆出轨是什么意思hcv9jop4ns7r.cn 腰椎生理曲度变直什么意思hcv9jop4ns4r.cn 天麻长什么样子图片cj623037.com
百度