Давайте напишемо Мініфікатор


14

Фон

Мініфери використовуються, як правило, під час обслуговування JavaScript у вашому веб-переглядачі. Зазвичай використовується для зменшення кількості байтів, які потрібно надіслати. Збереження пропускної здатності корисно з зрозумілих причин. Деякі люди використовують обфускатори (які навмисно ускладнюють читання коду), я не говорю про них.

Ми будемо мінімізувати Python 2

Я обговорював питання про те, чи використовувати JavaScript чи Python для досвіду мінімізації, і вирішив про Python з двох причин: пробіл має значення, і я думаю, що це додасть цікавої динаміки проблеми. Крім того, використання Python 2.7 забезпечить ще одну динаміку, таку як видалення зайвого ()під час друку (тобто print("Hello world")проти print"Hello world"). Я особисто хотів би відкрити його для будь-якої мови, але для деяких мов цей процес не має великого сенсу. І те, яку мову ви вирішите змінити, безпосередньо вплине на ваш показник (і якщо мова навіть може бути спрощена).

Технічні характеристики

Ваша мета - лише змінити код таким чином, який ні в якому разі не змінить його функціональність. Звичайно, ви можете змінювати імена змінних (всередині вашої програми мінімізації) до тих пір, поки це не вплине на вихід (слідкуйте за обсягом ). Хоча я даю вам конкретну програму, будь ласка, не оптимізуйте для тестового випадку, оскільки всі стандартні лазівки заборонені.

Оцінка : довжина програми після того, як ви її мінімізували.

Введення : Будь-яка програма Python 2.7 (яка не містить помилок)

Вихід : мінімізована версія.

Хоча ваш код повинен вміщувати весь дійсний вхід Python 2.7, необхідно перевірити свій скрипт на щось, щоб довести його ефективність.

Клацніть тут, щоб переглянути приклад програми.

Зробити проблему більш доступною

Не соромтеся використовувати або змінювати будь-який код, знайдений всередині мого рішення (перелічено нижче). Я зробив це для того, щоб ви почали працювати з базовими цитатами; однак ви можете розширити його до відступу тощо.

Приклади способів мінімізації Python

Весь пробіл можна замінити на мінімально можливу кількість (я визнаю, що в Python ви можете робити деякі хитрі речі з вкладками , але я залишаю це вирішувати, чи реалізувати це чи ні).

Приклад

Наступні:

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

Може бути:

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

Технічно, якщо всередині циклу є лише один рядок, ви можете стиснути його ще більше:

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!"

Наведене вище твердження про друк має залишатися незмінним, оскільки видалення проміжку між ними 2та isзмінення виводу.



Sidenote: не існує програми, яка могла б вивести найкоротший еквівалент будь-якої довільної програми введення, відповідно до цієї дискусії
Leaky Nun

Там роблять бути деякі пітона Minifier інструменти вже . Я не думаю, що це питання може отримати краще рішення, ніж інструменти, що вже виходять.
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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.