Minifierを書きましょう


14

バックグラウンド

JavaScriptをWebブラウザに提供する場合、一般的に縮小子が使用されます。通常、送信する必要のあるバイト数を減らすために使用されます。帯域幅を節約することは、明らかな理由で役立ちます。一部の人々は難読化ツール(意図的にコードを読みにくくする)を使用していますが、私はそれらについて話していません。

Python 2を縮小します

JavaScriptまたはPythonを縮小化の経験として使用するかどうかを議論していましたが、2つの理由でPythonを決定しました。空白が重要であり、それが興味深いダイナミックな問題を追加すると思います。また、Pythonの2.7を使用して、このような削除余分として、別の動的に提供する()プリント時(すなわちprint("Hello world")print"Hello world")。個人的には、任意の言語で開くことを望んでいましたが、一部の言語では、このプロセスはあまり意味がありません。また、縮小する言語はスコアに直接影響します(言語を縮小できる場合もあります)。

スペック

あなたの目標は、とにかく機能を変更しない方法でのみコードを変更することです。もちろん、出力に影響を与えない限り、変数名を(縮小プログラム内で)変更できます(スコープを追跡します)。特定のプログラムを提供していますが、すべての標準的な抜け穴は禁止されているため、テストケース用に最適化しないでください。

スコア:縮小した後のプログラムの長さ。

入力:任意のPython 2.7プログラム(エラーなし)

出力:縮小版。

コードはすべての有効なPython 2.7入力に対応できる必要がありますが、有効性を証明するためにスクリプトを何かに対してテストする必要があります。

サンプルプログラムを表示するには、ここをクリックしてください

問題をより親しみやすくする

ソリューション内にあるコードを自由に使用または変更してください(以下を参照)。見積もりの​​基本的な見積もり処理を開始するためにこれを行いました。ただし、インデントなどに拡張できます。

Pythonを縮小する方法の例

すべての空白は最小限の量に置き換えることができます(Pythonではtabsを使用していくつかのトリッキーなことを行うことができますが、実装するかどうかはあなたに任せます)。

以下:

def print_a_range(a):
    for i in range(a):
        print(i)

になり得る:

def print_a_range(a):
 for i in range(a):
  print(i)

技術的には、ループ内に1行しかない場合は、さらに圧縮できます。

def print_a_range(a):
 for i in range(a):print(i)  #Note, you can also remove the `()` here.

ただし、Pythonで空白を縮小できる別の方法があります。

以下:

print ([a * 2 for a in range(20) if a % 2 == 0])

になり得る:

print([a*2for a in range(20)if a%2==0])

2との間にスペースは必要ないことに注意してくださいfor。変数、関数、およびキーワード数字で始めることはできません。したがって、Pythonインタープリターは<num><keyword>、スペースなしで問題ありません。また、)との間にスペースを入れる必要はありませんif

プログラムの出力を変更しないでください!そう:

print"f(x)=x*2 is a great equation!"

上記のprint文は、間にスペースを取り除くため、同じとどまるべき2is出力を変更します。



追記:NOプログラムが存在しないことを出力することができる最短あたり任意の入力プログラムの等価、この議論
漏洩ヌン

既にいくつかのPythonミニファイヤツールがあります。この質問が既に終了しているツールよりも優れた解決策になるとは思わない。
tsh

変化している'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111''1'*100許可されていますか?動作が同じであるために必要ですか?
l4m2

回答:


2

Python 2.7、2013スコア

このプログラムは参照として使用できます。次のコードを取得して変更し、独自のソリューションに投稿することができます。

後知恵では、おそらく引用符の処理にも正規表現を使用する必要がありましたが、現在の状態では、人々を問題に飛び込ませるのに十分であると思います。

Python 2.7を選択した理由:execキーワードを使用してプログラムをクラッシュさせたかどうかをテストする方が簡単だと思いました。

このコードは、プログラムをとして取り込みin.txtます。

クォートパーサー(コメントを処理することもあります)と、正規表現をクォートパーサーと組み合わせて実際にゲームを変更する方法の簡単な例を書くことで、少なくとも参加したい人のためにボールを転がす必要があると考えましたこの問題の複雑さ。

注:このミニファイヤにはまだ改善の余地があります。あなたがインデント、変数名を使って遊んで、カッコを使用しているときにカッコを削除することができるように、私のキーワード、printまたはなどyield

import re

with open("in.txt","r") as fi:
    code = fi.read()

class QuoteHandler():
    def __init__(self):
        pass
    def loadCode(self,code):
        quoteFlag = False
        currentQuoteChar = ""
        ignoreNext = False
        inEndLineComment=False
        startLocation = 0

        self.reAddStrings = []

        outStr = ""

        for i, character in enumerate(code):
            if ignoreNext:
                ignoreNext = False
            elif inEndLineComment:
                if character in "\r\n":
                    inEndLineComment=False
            elif character == "#" and not quoteFlag:
                inEndLineComment = True
            elif character in "'\"" and (currentQuoteChar == character or not quoteFlag):
                if quoteFlag:
                    self.reAddStrings.append(code[startLocation+1:i])
                else:
                    currentQuoteChar = character
                    startLocation = i
                quoteFlag = not quoteFlag
            elif character == "\\":
                ignoreNext = True

            if not inEndLineComment and not quoteFlag:
                outStr+=character                
        return outStr

    def find_all_locations(self,substr,code):
        return [m.start() for m in re.finditer(substr, code)]

    def unloadCode(self,code):
        temp = self.reAddStrings[::-1]
        for i, location in enumerate(list(self.find_all_locations('"',code))[::-1]):
            code = code[:location] + "\"" + temp[i] + code[location:]
        return code

def applyRegexes(code):#\w here?
    operatorRegexCleaner = ["([\d\/*\-\"=,'+{}:[\](\)])","[ \t]+","(\w)"]
    regexes = [
        [''.join(operatorRegexCleaner),r"\1\2"],
        [''.join(operatorRegexCleaner[::-1]),r"\1\2"],#removes whitespace between operators
        ["\n\s*\n","\n"]#removes empty lines
    ]
    for regex in regexes:
        code = re.sub(regex[0],regex[1],code)
    return code

qh = QuoteHandler()
code = qh.loadCode(code)
code = applyRegexes(code)
code = qh.unloadCode(code)
print(code)
exec(code)

プログラムの出力:

def factor(factor_number):
    for n in range(2,factor_number):
        if factor_number % n==0:    
            yield(n)
def gcd(a,b):
    """Calculate the Greatest Common Divisor of a and b.

    Unless b==0, the result will have the same sign as b (so that when
    b is divided by it, the result comes out positive).
    """
    while b:
         a,b=b,a%b 
    return a
class Apricot:
    def __init__(self):
        self.mold=False
    def get(self):
        return self.mold
    def update(self):
        self.mold=not self.mold
    def blue(self):return5
def tell_me_about_these_numbers(*a):
    print("%d is the first number!" % a[0])
    print("{} / 3 is {}".format(a[0],a[0]/3.))
    myFavorate=Apricot()
    for number in a:
        print list(factor(number))
        myFavorate.update()
    print[gcd(a,b)for a,b in zip(a[:-1],a[1:])]
    print(myFavorate.get())
tell_me_about_these_numbers(5,6,9,45,200)
print"Let's play with scope!"
a,b=10,9
def randomFunction(a):
    print(a)
randomFunction(b)
print(a)
for a in range(100):
    b+=a
print(a)
print(b)
li=[]
for i in range(10):
 li.append(i*2)
print(li)
print([i*2for i in range(10)])
a=c=b=d=e=f=g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=5
print(a)
a-=1
print(a)
g=10
print(str(10**g+5)[::-1])
def blue_fish(a):
    def blue_fish(a):
        def blue_fish(a):
            return a
        a+=1
        return blue_fish(a)
    a-=1
    return blue_fish(a)
print(blue_fish(10))
def blue_fish(a):
    if a==0:
        return"0"
    return"1" +blue_fish(a-1)
print(blue_fish(5))
blue_fish=lambda a,b,c:a*b*c
print(blue_fish(1,2,3))
blue_fish=lambda*a:reduce(lambda a,b:a*b,a)
print(blue_fish(1,2,3))
print(max([[6,1],[5,2],[4,3],[3,4],[2,5],[1,6]],key=lambda a:a[1]))
print(zip(*[[1],[2],[3],[4],[5]]))
print"Now let's test to see if you handle quotes correctly:"
print"test \'many diffent\' \"types of \" quotes, even with \' \" trailing quotes"
print"""

Multi line quotes are great too!

"""
a=""" ::
one more multi-line quote won't hurt
"""
print a
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.