To jest wskazówka dotycząca gry w golfa w Pythonie.
W golfie w Pythonie podporządkowanie jest funkcją zdefiniowaną jako lambda. Na przykład,
f=lambda x:0**x or x*f(x-1)
Format lambda ma dwie duże zalety :
- Płyta kotła
f=lambda x:...
lublambda x:...
jest krótsza niżdef f(x):...return...
lubx=input()...print...
- Wywołanie rekurencyjne może być użyte do zapętlenia z niewielkim narzutem bajtowym.
Jednak lambdas mają tę wadę, że pozwalają tylko na jedno wyrażenie, bez instrukcji. W szczególności oznacza to brak zadań takich jak c=chr(x+65)
. Jest to problematyczne, gdy ktoś ma długie wyrażenie, do którego wartości należy odwoływać się dwukrotnie (lub więcej).
Takie przypisania E=enumerate
są możliwe poza funkcją lub jako opcjonalny argument, ale tylko wtedy, gdy nie zależą od danych wejściowych funkcji. Argumenty opcjonalne, takie jak f=lambda n,k=min(n,0):...
niepowodzenie, ponieważ dane wejściowe n
nie zostały zdefiniowane, gdy k
są oceniane w czasie definicji.
W rezultacie czasami ssie się powtarzanie długiego wyrażenia w lambda, ponieważ alternatywą jest długa nie-lambda.
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]
Punkt rentowności wynosi około 11 znaków ( szczegóły ), po których przełączasz się na a def
lub program
. Porównaj to ze zwykłym punktem rentowności o długości 5, aby uzyskać powtarzające się wyrażenie:
range(a)+range(b)
r=range;r(a)+r(b)
print s[1:],s[1:]*2
r=s[1:];print r,r*2
Inne języki mają obejścia, na przykład Octave . Istnieją znane triki dla Pythona, ale są one długie, niezgrabne i / lub mają ograniczone zastosowanie. Krótka, uniwersalna metoda symulacji przypisania u lambdy zrewolucjonizuje grę w golfa w Pythonie.
W jaki sposób golfista Python może pokonać to ograniczenie lub obejść go? Jakie potencjalne pomysły powinni mieć na uwadze, gdy widzą długi wyraz powtórzony dwukrotnie w lambda?
Moim celem w tym pytaniu jest zanurzenie się głęboko w ten problem i:
- Kataloguj i analizuj obejścia gry w golfa w celu sfałszowania zadania w lambda
- Odkryj nowe potencjalne szanse na lepsze metody
Każda odpowiedź powinna wyjaśniać obejście lub potencjalną potencjalną szansę.
lambda s:(s+s[::-1]).lower()
. Oczywiście to nie odpowiada na rzeczywiste pytanie.strip
.Odpowiedzi:
eval
To samo w sobie nie jest tak świetne, ale jeśli twoje rozwiązanie już używa
eval
w jakiś sposób lub formie, zwykle możesz użyć tej techniki.źródło
Wyrażenia przypisania w Pythonie 3.8
Python 3.8 ( TIO ) wprowadza wyrażenia przypisania , które służą
:=
do przypisania zmiennej inline jako części wyrażenia.Można tego użyć wewnątrz
lambda
, gdzie przypisania nie są zwykle dozwolone. Porównać:Zobacz tę wskazówkę, aby uzyskać więcej.
źródło
Lambda wewnętrzna
Umożliwiają one zdefiniowanie wielu zmiennych jednocześnie.
vs.
jest znacznie dłuższy, ale jeśli masz wiele zmiennych lub zmiennych, które są dłuższe i które są powtarzane wiele razy:
vs.
Liczba znaków
Początkowa:
(lambda:)()
(11 bajtów)Pierwsza zmienna:
[space]a
(2 bajty)Kolejne zmienne:
,b,
(3 bajty)Użyj:
a
(1 bajt).(Zapisuje również w nawiasach)
To zajmuje
3n + 10
bajty, gdzien
jest liczba zmiennych. Jest to wysoki koszt początkowy, ale ostatecznie może się opłacić. Zwraca nawet swoją wartość wewnętrzną, więc możesz zagnieździć wiele (chociaż to szybko nie będzie tego warte).Jest to naprawdę przydatne tylko w przypadku długich pośrednich obliczeń w zrozumieniu listy zagnieżdżonej, ponieważ
def f():a=...;b=...;return
zwykle będzie krótszy.Dla 1 wartości zapisuje to:,
uses * length - length - uses - 13
więc jest użyteczne tylko wtedy, gdy to wyrażenie jest dodatnie.W przypadku
n
różnych wyrażeń użytychu
w sumie razy, gdzie ich łączna długość tol
, oszczędza się:l - (3 * n) - u - 10 ( + brackets removed )
źródło
Użyj listy
Zadeklaruj listę jako parametr i użyj
.append() or
do przechowywania wartości:lambda s:s.lower()+s.lower()[::-1]
zamienia się w
lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]
Liczba znaków:
,l=[]
5 znakówl.append()or
13 znakówl[-1]
5 znaków dla każdego użyciaWychodzić na czysto
Ilość dodanego znaku wynosi:
uses*(5-length) + 18 + length
W poprzednim przykładzie instrukcja ma
s.lower()
długość 9 znaków i jest używana 2 razy, stosując tę technikę dodano 19 znaków. Jeśli zostanie użyty 7 razy, nastąpi redukcja o 1 znak.Wartość minimalnego wykorzystania tej techniki jest warta
min_uses = (18+length)/(length-5)
Plusy
list
obiekt tak[0]
,.pop()
,[x:y]
oraz inne funkcje lista może być stosowany do sztuczek. wysoce sytuacyjnyWady
5
Użyj słownika
dzięki @Zgarb
Taki sam pomysł jak powyżej Zadeklaruj słownik jako parametr i użyj go
.setdefault()
do przechowywania (i zwracania) wartości:lambda s:s.lower()+s.lower()[::-1]
zamienia się w
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
Zwróć uwagę, że w przeciwieństwie do
list
odpowiednika,setdefault
zwraca przypisaną wartość.Liczba znaków:
,d={}
5 znakówd.setdefault(k,)
16 znakówd[k]
4 znaki dla każdego użyciaWychodzić na czysto
Ilość dodanego znaku wynosi:
(uses-1)*(4-length) + 21
W poprzednim przykładzie instrukcja ma
s.lower()
długość 9 znaków i jest używana 2 razy, przy zastosowaniu tej techniki dodano 16 znaków. Jeśli zostanie użyty 7 razy, nastąpi redukcja o 1 znak.Wartość minimalnego wykorzystania tej techniki jest warta
min_uses = 1-21/(4-length)
Wady / zalety
4
Inne uwagi
lambda
prawdopodobnie można ją usunąć, a funkcję przepisać za pomocądef
/input
dla krótszego programu.źródło
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
jest również wielokrotnego użytku.list.extend
aby dodać wiele elementów jednocześnie, co będzie krótsze niżlist.append
wielokrotne użycie .Służy do ustawiania zmiennych i zwracania danych po operacji, takich jak:
źródło
Wyjaśnij listę
Jest to raczej ostatnia deska ratunku, ponieważ jest tak niegrzeczna, ale można zrobić,
[<expression> for <variable> in <value>]
aby pseudo ustawić zmienną w lambda. Zasadniczo jedyną zaletą tej metody jest to, że wewnętrzne wyrażenie może pozostać czytelne, co jest oczywiście najmniejszym problemem podczas gry w golfa.
źródło