람다 할당을위한 Python 해결 방법


34

이것은 파이썬에서 골프를하기위한 팁 질문입니다.

파이썬 골프에서는 제출이 람다로 정의 된 함수 인 것이 일반적입니다. 예를 들어

f=lambda x:0**x or x*f(x-1)

x 의 계승계산합니다 .

람다 형식에는 두 가지 큰 장점이 있습니다 .

  • 의 보일러 f=lambda x:...또는 lambda x:...댄 짧은 def f(x):...return...또는x=input()...print...
  • 적은 바이트 오버 헤드로 루프를 재귀 호출을 사용할 수 있습니다.

그러나 람다는 하나의 표현 만 허용하고 문장은 허용하지 않는다는 큰 단점이 있습니다. 특히 이것은와 같은 과제가 없음을 의미합니다 c=chr(x+65). 값이 두 번 (또는 그 이상) 참조되어야하는 긴 표현식이있는 경우 문제가됩니다.

할당은 같은 E=enumerate기능을 외부 또는 선택적 인수로 가능하지만, 함수 입력에 의존하지 않는 경우에만 가능합니다. 정의시 평가시 f=lambda n,k=min(n,0):...입력 n이 정의되지 않았기 때문에 실패 와 같은 선택적 인수 k입니다.

결과는 때로는 램다에서 긴 표현을 반복해서 빨아 들일 수 있습니다.

lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]

중단 짝수 지점은 약 11 자 ( 세부 사항 )이며, 이전으로 def또는로 전환합니다 program. 반복 표현을 위해 이것을 길이 5의 일반적인 손익 분기점과 비교하십시오.

range(a)+range(b)
r=range;r(a)+r(b)

print s[1:],s[1:]*2
r=s[1:];print r,r*2

다른 언어에는 해결 방법 이 있습니다 (예 : Octave) . 파이썬에는 알려진 속임수가 있지만 길고, 어색하고, 사용이 제한적입니다. 람다에서 할당을 시뮬레이션하는 짧고 범용적인 방법은 파이썬 골프에 혁명을 가져올 것입니다.


파이썬 골퍼가이 한계를 극복하거나 해결하는 방법은 무엇입니까? 람다에서 긴 표현이 두 번 반복되는 것을 볼 때 어떤 잠재적 아이디어를 염두에 두어야합니까?

이 팁 질문에 대한 나의 목표는이 문제에 대해 깊이 탐구하고

  • 람다 내부의 가짜 할당을위한 골프 해결 방법 카탈로그 및 분석
  • 더 나은 방법을위한 새로운 리드 탐색

각 답변은 해결 방법 또는 잠재 고객을 설명해야합니다.


나는 이것이 파이썬에서 잘 할 수없는 것들 중 하나라고 생각합니다. JavaScript는 이것에 대한 다리가 있습니다.
mbomb007

orlp의 답변과 마찬가지로 중첩 람다 사용에 대한 Neil의 (삭제 된) 제안은 어쨌든 중첩 람다가 필요한 경우 def보다 길지 않습니다. 더 철저한 분석이 필요하다고 생각합니다.
Martin Ender

2
역 소문자 문자열 연결로 주어진 정확한 예제를 위해 그냥 갈 수 있습니다 lambda s:(s+s[::-1]).lower(). 물론 이것은 실제 질문에 대답하지 않습니다.
Jonathan Allan

@JonathanAllan 좋은 지적으로 변경했습니다 strip.
xnor

답변:


6

eval

이것은 그 자체로는 그다지 크지 않지만 솔루션이 이미 eval어떤 방식이나 형태로 사용하는 경우 일반적 으로이 기술을 사용할 수 있습니다.

eval("%f*%f+%f"%((5**.5,)*3))

와우, 똑똑하다! 왜 이런 종류의 코드를 보지 못합니까?
z0rberg의

6
@ z0rberg 's 아마도 eval은 악하기 때문입니다.
HyperNeutrino

나는이 코드를 구독하지 않습니다. #EvalLivesMatter ...하지만 진지하게, 간단한 dll 주입보다 어떻게 나쁜가요?
z0rberg의

6

파이썬 3.8에서 대입 식

Python 3.8 ( TIO )에는 식의:= 일부로 변수를 인라인으로 지정하는 데 사용되는 대입식이 도입되었습니다 .

>>> (n:=2, n+1)
(2, 3)

이것은 내부에서 사용할 수있는 lambda과제는 일반적으로 허용되지 않는 곳. 비교:

lambda s:(t:=s.strip())+t[::-1]
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();return t+t[::-1]

자세한 내용은 이 팁 을 참조하십시오 .


2

내부 람다

이를 통해 여러 변수를 한 번에 정의 할 수 있습니다.

lambda s:s.strip()+s.strip()[::-1]

vs.

lambda s:(lambda t:t+t[::-1])(s.strip())

훨씬 더 길지만 여러 변수 또는 더 긴 변수가있는 경우 여러 번 반복됩니다.

lambda a,b,c:a.upper()*int(c)+b.lower()*int(c)+a.upper()[::-1]+b.lower()[::-1]+a.upper()*int(c)+a.lower()*int(c)

vs.

lambda a,B,c:(lambda A,b,n:A*n+b*n+A[::-1]+b[::-1]+A*n+b*c)(a.upper(),B.lower(),int(c))

문자 수

초기 : (lambda:)()(11 바이트)
첫 번째 변수 : [space]a(2 바이트)
후속 변수 : ,b,(3 바이트)
사용 : a(1 바이트).

(lambda* a*_,b_:)(*<value a>*_,<value b>_)

(또한 괄호에 저장)

따라서 이것은 3n + 10바이트 수를 차지 합니다. 여기서 n변수의 수는 어디 입니까? 초기 비용이 많이 들지만 결국에는 돈을 지불 할 수 있습니다. 심지어 내부 값을 반환하기 때문에 여러 개를 중첩 할 수 있습니다 (이것은 빨리 가치가 없습니다.)

이것은 def f():a=...;b=...;return일반적으로 짧아지기 때문에 중첩 목록 이해에서 긴 중간 계산에만 유용합니다 .

값이 1 인 경우 다음이 저장됩니다. uses * length - length - uses - 13따라서 해당 표현식이 양수인 경우에만 유용합니다.
A의 n사용 다른 표현 u들이 결합 길이가 총에 시간을 l,이 저장 :
l - (3 * n) - u - 10 ( + brackets removed )


1

리스트 사용

매개 변수로 목록을 선언하고 사용하는 .append() or값을 저장할 수 :
lambda s:s.lower()+s.lower()[::-1]
교대로
lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]

문자 수 :

,l=[]5 자
l.append()or13 자
l[-1]5 자 사용

짝수

추가 된 문자의 양은 다음과 같습니다
uses*(5-length) + 18 + length
. 이전 예제에서 명령문의 s.lower()길이는 9 자이며이 기술을 적용하여 19 자 추가 된 2 회 사용됩니다. 7 번 사용 된 경우 1 문자가 줄어 듭니다.
이 기술에 대한 최소한의 사용 가치는
min_uses = (18+length)/(length-5)

거꾸로

  • 약간의 비용 절감으로 새로운 과제 허용 (목록은 이미 선언 됨)
  • A는 list객체 그렇게 [0], .pop(), [x:y]기타리스트 기능은 트릭을 사용할 수 있습니다. 상황이 매우 높은

단점

  • 높은 초기 비용
  • 높은 사용 비용
  • 보다 길이가 긴 용도에만 사용 가능 5

사전 사용

thanks @Zgarb
위와 동일합니다. 사전을 매개 변수로 선언 .setdefault()하고 값을 저장하고 반환하는 데 사용합니다.로
lambda s:s.lower()+s.lower()[::-1]

lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
합니다. list상대 와 달리 setdefault할당 된 값을 반환합니다.

문자 수 :

,d={}5 자
d.setdefault(k,)16 자
d[k]4 자 사용

짝수

추가 된 문자의 양은 다음과 같습니다
(uses-1)*(4-length) + 21
. 이전 예제에서 명령문의 s.lower()길이는 9 자이며이 기술을 적용하여 16자를 추가했습니다. 7 번 사용 된 경우 1 문자가 줄어 듭니다.
이 기술에 대한 최소한의 사용 가치는
min_uses = 1-21/(4-length)

거꾸로

  • 기본적으로 목록과 동일
  • 보다 길이가 긴 용도에만 사용 가능 4

다른 고려 사항

  • 만약이 기술이 문자 축소에 가치가 있다면, lambda아마도 그 기술을 제거 하고 더 짧은 프로그램을 위해 def/ input로 함수를 재 작성할 수있을 것입니다 .
  • 으로 @FlipTack는 지적 목록과 딕셔너리는 KEEPT 내용입니다 이, 그것은 재귀 호출에 주로 방해 사용할 수있는 반면, 함수 호출 사이. 다시 높은 상황
  • 사전은 항상 목록보다 짧습니다.

3
기능 제출은 두 번 이상 사용할 수 있어야합니다. 현재 이것은 람다가 실행될 때마다 동일한 목록을 사용하므로 나중에 실행할 때 엉망이 될 수 있습니다.
FlipTack

@FlipTack에 관심이 없다면 메타와 같은 소스를 연결 하시겠습니까? 나는 그 규칙이 내가 아는 몇 가지 트릭에 영향을 줄 수 있다고 생각합니다.
JAD


사전으로 더 잘 할 수 있다고 생각합니다 lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]. 재사용도 가능합니다.
Zgarb

list.extend한 번에 여러 요소를 추가하는 데 사용할 수 있으며 list.append여러 번 사용하는 것보다 짧 습니다.
mbomb007

0

다음과 같이 조작 후 변수를 설정하고 데이터를 리턴하는 데 사용하십시오.

add = lambda x, y: exec("x+=y")

대안 {추가 람다 = X, Y : x.append (X [0] + Y) x.reverse () x.pop ()]}
딜란 엘리엇

0

목록 이해

이것은 너무 골치가 아니기 때문에 최후의 수단이지만
[<expression> for <variable> in <value>]
, 람다에서 변수를 의사 설정하는 것이 가능합니다. 기본적으로이 방법의 유일한 장점은 내부 표현을 읽을 수 있다는 것입니다. 이는 골프를 칠 때 가장 걱정할 사항이 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.