Mẹo chơi gôn trong Python


248

Bạn có lời khuyên chung nào cho việc chơi golf trong Python? Tôi đang tìm kiếm những ý tưởng có thể áp dụng cho các vấn đề về golf-code và ít nhất cũng hơi cụ thể đối với Python (ví dụ: "xóa bình luận" không phải là một câu trả lời).

Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


27
Ồ, tôi có thể thấy một loạt các câu hỏi như thế này cho mỗi ngôn ngữ ...
R. Martinho Fernandes

4
@Marthinho Tôi đồng ý. Chỉ cần bắt đầu một C ++ tương đương . Tôi không nghĩ rằng đó là một điều xấu, miễn là chúng ta không thấy những câu trả lời giống nhau được đăng lại trên nhiều loại câu hỏi này.
marcog

50
Yêu câu hỏi nhưng tôi phải tự nhủ "đây chỉ là niềm vui KHÔNG dành cho mã sản xuất"
Greg Guida

2
Không phải câu hỏi này là một bài viết wiki cộng đồng?
dorukayhan

3
@dorukayhan Không; đó là một câu hỏi mẹo chơi golf mã hợp lệ , yêu cầu các mẹo về rút ngắn mã trăn cho mục đích CG'ing. Những câu hỏi như vậy là hoàn toàn hợp lệ cho trang web và không có thẻ nào trong số này nói rõ ràng rằng câu hỏi phải là CW, không giống như SO, yêu cầu các thách thức CG phải là CW'd. Ngoài ra, viết một câu trả lời hay và tìm ra những lời khuyên như vậy luôn xứng đáng với điều gì đó, điều đó sẽ bị lấy đi nếu câu hỏi là wiki cộng đồng (đại diện).
Erik the Outgolfer

Câu trả lời:


152

Sử dụng a=b=c=0thay vì a,b,c=0,0,0.

Sử dụng a,b,c='123'thay vì a,b,c='1','2','3'.


2
Đó là mẹo hay nói chung :)

28
Lưu ý rằng điều này sẽ không nhất thiết phải làm việc để xác định các đối tượng có thể thay đổi mà bạn sẽ sửa đổi tại chỗ. a = b = [1] thực sự khác với a = [1]; b = [1]
isaacg

6
Điều thú vị về mẹo đầu tiên là nó cũng hoạt động trong Java.
Justin

1
@Justin Có, nhưng chỉ với các loại nguyên thủy
HyperNeutrino

11
Nhưng KHÔNG BAO GIỜ sử dụng a = b = c = [] hoặc bất kỳ sự thay đổi đối tượng nào vì tất cả các biến sẽ trỏ đến cùng một thể hiện. Đó có lẽ không phải là những gì bạn muốn.
PhE

146

Điều kiện có thể dài. Trong một số trường hợp, bạn có thể thay thế một điều kiện đơn giản bằng (a,b)[condition]. Nếu conditionlà đúng, sau đó bđược trả lại.

So sánh

if a<b:return a
else:return b

Để điều này

return(b,a)[a<b]

37
Chúng không giống hệt nhau. Cái đầu tiên chỉ đánh giá biểu thức được trả về trong khi cái thứ hai luôn đánh giá cả hai. Những cái này làm ngắn mạch: a if a<b else ba<b and a or b
bến

3
(lambda(): b, lambda(): a)[a < b]()thực hiện ngắn mạch của riêng bạn với lambdas
Ming-Tang

3
@marinus, chúng không bằng nhau: chỉ cần xem xét P and A or Bcho bất kỳ A nào đưa ra bool(A)=False. Nhưng (P and [A] or [B])[0]sẽ làm được việc. Xem diveintopython.net/power_of_introspection/and_or.html để tham khảo.
kgadek

6
Lambdas dài hơn một biểu thức có điều kiện.
dùng2357112

18
@ user2357112 Nhưng chúng làm bạn trông ngầu hơn rất nhiều khi bạn sử dụng chúng. :]
Chase Ries

117

Một điều tuyệt vời tôi đã làm một lần là:

if 3 > a > 1 < b < 5: foo()

thay vì:

if a > 1 and b > 1 and 3 > a and 5 > b: foo()

Toán tử so sánh của Python đá.


Sử dụng mọi thứ đều có thể so sánh trong Python 2, bạn cũng có thể tránh andtoán tử theo cách này. Ví dụ, nếu a, b, cdlà các số nguyên,

if a<b and c>d:foo()

có thể được rút ngắn bởi một ký tự để:

if a<b<[]>c>d:foo()

Điều này sử dụng rằng mọi danh sách đều lớn hơn bất kỳ số nguyên nào.

Nếu cdlà danh sách, điều này thậm chí còn tốt hơn:

if a<b<c>d:foo()

22
Tất nhiên, nếu điều này thực sự được đánh gôn thì đó là3>a>1<b<5
Rafe Kettler

4
Yêu sự đối xứng. Nhắc nhở tôi về thủ thuật đánh gôn Perl cũ để tìm số tiền tối thiểu $ a và $ b: [$a => $b]->[$b <= $a]:)
Simon Whitaker

Lưu ý rằng ví dụ thứ hai (không có danh sách) cũng có thể được thực hiện vớiif(a<b)+(c>d):foo()
WorldSEnder

6
+ Nên là một * . An orsẽ là+
WorldSEnder

1
foo()if 3>a>1<b<5
Erik the Outgolfer

103

Nếu bạn đang sử dụng chức năng tích hợp nhiều lần, việc đặt tên mới sẽ hiệu quả hơn về không gian, nếu sử dụng các đối số khác nhau:

r=range
for x in r(10):
 for y in r(100):print x,y

6
Mặc dù vậy, không thực sự lưu bất kỳ byte nào.
dùng2357112

4
r = phạm vi và hai r còn lại là 9 ký tự; sử dụng phạm vi hai lần là 10 ký tự. Không phải là một khoản tiết kiệm lớn trong ví dụ này, nhưng tất cả những gì nó cần là thêm một lần sử dụng phạm vi để thấy một sự tiết kiệm đáng kể.
Frank

13
@Frank Dòng mới bổ sung là một nhân vật khác.
L3viathan

2
Thật vậy, hai lần lặp lại là quá ít để lưu vào một tên hàm dài năm. Bạn cần: độ dài 2: 6 reps, độ dài 3: 4 reps, độ dài 4 hoặc 5: 3 reps, chiều dài> = 6: 2 reps. AKA (chiều dài-1) * (đại diện-1)> 4.
Ørjan Johansen

Lưu ý điều này có thể áp dụng cho tất cả các ngôn ngữ có chức năng hạng nhất.
bfontaine

94

Đôi khi mã Python của bạn yêu cầu bạn phải có 2 cấp độ thụt. Điều rõ ràng cần làm là sử dụng một và hai khoảng trắng cho mỗi cấp độ thụt đầu dòng.

Tuy nhiên, Python 2 coi các ký tự tab và dấu cách là các mức thụt lề khác nhau.

Điều này có nghĩa là mức thụt đầu tiên có thể là một khoảng trắng và mức thứ hai có thể là một ký tự tab.

Ví dụ:

if 1:
 if 1:
\tpass

Đâu \tlà nhân vật tab.


1
Thật tuyệt, tôi chưa bao giờ nghĩ về điều này!
Jules Olléon

97
Điều này thất bại trong python3: bạn không thể trộn lẫn các khoảng trắng và tab (một điều tồi tệ cho codegolf, nhưng là một điều tốt trong tất cả các trường hợp khác).
Bakuriu

1
Trong python 3,4 điều này dường như hoạt động tốt.
trichoplax

3
@trichoplax , Trong python 3.4.3 tôi nhận đượcTabError: inconsistent use of tabs and spaces in indentation.
ceilingcat

Để tham khảo, một tab có giá trị 8 khoảng trắng.
Erik the Outgolfer

87

Sử dụng thay thế chuỗi và execđể đối phó với các từ khóa dài như thế lambdađược lặp lại thường xuyên trong mã của bạn.

a=lambda b:lambda c:lambda d:lambda e:lambda f:0   # 48 bytes  (plain)
exec"a=`b:`c:`d:`e:`f:0".replace('`','lambda ')    # 47 bytes  (replace)
exec"a=%sb:%sc:%sd:%se:%sf:0"%(('lambda ',)*5)     # 46 bytes  (%)

Chuỗi đích rất thường xuyên 'lambda ', dài 7 byte. Giả sử đoạn mã của bạn chứa các nlần xuất hiện 'lambda 'và là sbyte dài. Sau đó:

  • Các plaintùy chọn làsbyte dài.
  • Các replacetùy chọn làs - 6n + 29byte dài.
  • Các %tùy chọn là s - 5n + 22 + len(str(n))byte dài.

Từ một chuỗi các byte được lưu trongplain ba tùy chọn này, chúng ta có thể thấy rằng:

  • Cho n <5 lambdas, tốt hơn hết là bạn không nên làm bất cứ điều gì lạ mắt cả.
  • Với n = 5 , viếtexec"..."%(('lambda ',)*5) tiết kiệm 2 byte và là lựa chọn tốt nhất của bạn.
  • Đối với n> 5 , viết exec"...".replace('`','lambda ')là lựa chọn tốt nhất của bạn.

Đối với các trường hợp khác, bạn có thể lập chỉ mục bảng dưới đây:

          1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 (occurences)
       +---------------------------------------------------------
     3 |  -  -  -  -  -  -  -  -  -  -  -  -  -  -  r  r  r  r  r  
     4 |  -  -  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  
     5 |  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  
     6 |  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     7 |  -  -  -  -  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     8 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     9 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    10 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    11 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    12 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r = replace
    13 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   % = string %
    14 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   - = do nothing
    15 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
  (length)

Ví dụ: nếu chuỗi lambda x,y:(độ dài 11) xảy ra 3 lần trong mã của bạn, tốt hơn hết bạn nên viết exec"..."%(('lambda x,y:',)*3).


4
Điều này sẽ nhận được nhiều phiếu bầu hơn, đó là một mẹo rất hữu ích.
bigblind

7
cực kỳ hiếm khi nó hoạt động. chi phí replacerất lớn.
gian hàng

4
Khi nó làm việc, mặc dù, nó giúp rất nhiều.
undergroundmonorail

Thật thú vị, thậm chí không bao giờ nghĩ về điều này!
Claudiu

Tôi đã thêm một toán tử mới cho lambda trong ngôn ngữ của tôi dựa trên python: =>chỉ là chuỗi = lambda . Ví dụ, f=>:0sẽ là f = lambda: 0.
NoOneIsHãy là

78

Sử dụng lát cắt mở rộng để chọn một chuỗi từ nhiều chuỗi

>>> for x in 0,1,2:print"fbboaaorz"[x::3]
... 
foo
bar
baz

đấu với

>>> for x in 0,1,2:print["foo","bar","baz"][x]
... 
foo
bar
baz

Trong trường hợp hai chuỗi Boolean này, người ta cũng có thể viết

b*"string"or"other_string"

cho

["other_string","string"][b]

Không giống như xen kẽ, điều này hoạt động cho các chuỗi có độ dài bất kỳ, nhưng có thể có các vấn đề ưu tiên toán tử nếu bthay vào đó là một biểu thức.


Lưu ý rằng ví dụ đầu tiên có độ dài chính xác nhưfor x in ("foo","bar","baz"): print x
Mateen Ulhaq

1
@MateenUlhaq, Đó chỉ là một ví dụ về cách các giá trị khác nhau xđược hiển thị. Phần golfed là "fbboaaorz"[x::3]vs ["foo","bar","baz"][x]Làm thế nào các xgiá trị có nguồn gốc sẽ là một phần của giải pháp golf của bạn.
gnibbler

72

Sử dụng `n`để chuyển đổi một số nguyên thành một chuỗi thay vì sử dụng str(n):

>>> n=123
>>> `n`
'123'

38
Đẹp, nhưng không hoạt động với Python3.
Alexandru

2
Chú ý: thực sự hoạt động cho số nguyên, nhưng không phải cho chuỗi, ví dụ.
Nakilon

41
btw. `` là viết tắt của repr
Alexandru

9
Các số nguyên nhỏ hơn -2 ** 31 hoặc lớn hơn 2 ** 31-1 (Longs) được xử lý 'L' ở cuối.
hallvabo

6
Điều này cũng có thể được sử dụng để in phao đến độ chính xác đầy đủ
gnibbler

69

Lưu trữ bảng tra cứu dưới dạng số ma thuật

Giả sử bạn muốn mã hóa bảng tra cứu Boolean, giống như trong số mười hai số tiếng Anh đầu tiên có chứa một n.

0: False
1: True
2: False
3: False
4: False
5: False
6: False
7: True
8: False
9: True
10:True
11:True
12:False

Sau đó, bạn có thể triển khai bảng tra cứu này một cách chính xác như sau:

3714>>i&1

với kết quả 0hoặc 1là bằng Falseđể True.

Ý tưởng là số ma thuật lưu trữ bảng dưới dạng một chuỗi bit bin(3714)= 0b111010000010, với nchữ số -th (từ cuối) tương ứng với nmục nhập bảng thứ. Chúng tôi truy cập nmục thứ bằng cách bẻ khóa các nkhông gian số ở bên phải và lấy chữ số cuối cùng bằng &1.

Phương pháp lưu trữ này rất hiệu quả. So sánh với các lựa chọn thay thế

n in[1,7,9,10,11]
'0111010000010'[n]>'0'

Bạn có thể có bảng tra cứu lưu trữ nhiều mục nhập có thể được trích xuất như

 340954054>>4*n&15

để trích xuất khối bốn bit có liên quan.


Chúng ta có thể có một kết quả ví dụ cho khối bốn bit không? Bạn đã sử dụng quy tắc cho khối n-bit?
JeromeJ

8
Hex đôi khi có thể còn nhỏ hơn.
Joonazan

4
Điều này rất hữu ích cho rất nhiều ngôn ngữ.
Cyoce

1
@Joonazan Hex nhỏ hơn cho các số trên 999 999 .
Mateen Ulhaq

60

Thu gọn hai vòng số thành một

Giả sử bạn đang lặp lại trên các ô của m*nlưới. Thay vì hai forvòng lặp lồng nhau , một vòng cho hàng và một trong các cột, thường sẽ ngắn hơn để sử dụng một vòng lặp duy nhất để lặp qua các m*nô của lưới. Bạn có thể trích xuất hàng và cột của ô bên trong vòng lặp.

Mã gốc:

for i in range(m):
 for j in range(n):
  do_stuff(i,j)

Mã đánh gôn:

for k in range(m*n):
  do_stuff(k/n,k%n)

Thực tế, bạn đang lặp lại sản phẩm của Cartesian trong hai phạm vi, mã hóa cặp (i,j)x=i*n+j. Bạn đã lưu một rangecuộc gọi tốn kém và một mức độ thụt vào trong vòng lặp. Thứ tự lặp không đổi.

Sử dụng //thay vì /trong Python 3. Nếu bạn tham khảo ijnhiều lần, có thể nhanh hơn để gán giá trị của chúng i=k/n, j=k%nbên trong vòng lặp.


5
Điều này thật tuyệt. Tôi chưa bao giờ nhận ra điều này là có thể!
theonlygusti

Tôi đã thấy điều này trong các mẹo cho JavaScript. Đây là một mẹo khá hữu ích trong hầu hết các ngôn ngữ.
Cyoce

7
Để tham khảo, để mở rộng này thành 3 vòng:for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o)
mbomb007

3
Đối với ncác vòng lặp: repl.it/EHwa
mbomb007

Trong một số trường hợp, itertools.productcó thể ngắn gọn hơn nhiều so với các vòng lặp lồng nhau, đặc biệt là khi tạo ra các sản phẩm cartesian. a1, a2, b1, b2là những ví dụ về sản phẩm cartesian của 'ab''12'
Aaron3468 16/03/18

54

Trừ khi các mã thông báo sau bắt đầu bằng ehoặc E. Bạn có thể loại bỏ không gian sau một số.

Ví dụ:

if i==4 and j==4:
    pass

Trở thành:

if i==4and j==4:
    pass

Sử dụng điều này trong các câu lệnh một dòng phức tạp có thể lưu khá nhiều ký tự.

EDIT: như @marcog đã chỉ ra, 4or asẽ hoạt động, nhưng không phải a or4vì điều này bị nhầm lẫn với một tên biến.


37
if(i,j)==(4,4):thậm chí còn ngắn hơn và trong trường hợp đặc biệt nàyif i==j==4:
gnibbler

3
Liên quan: 4or ahoạt động, nhưng khônga or4
marcog

17
0orcũng không hoạt động ( 0olà tiền tố cho số bát phân).
Nabb

5
@Nabb Không phải là vấn đề gì, vì 0 or xluôn luôn quay trở lại x. Cũng có thể cắt ra 0 or.
12:30

5
0orcũng tốt như là một phần của một số dài hơn. 10 or xtương đương với10or x .
trichoplax

54

Đối với số nguyên n, bạn có thể viết

  • n+1 như -~n
  • n-1 như ~-n

bởi vì bit lật ~xbằng -1-x. Điều này sử dụng cùng một số ký tự, nhưng có thể gián tiếp cắt các khoảng trắng hoặc parens cho quyền ưu tiên của toán tử.

So sánh:

while n-1:  #Same as while n!=1 
while~-n:

c/(n-1)
c/~-n

or f(n)+1
or-~f(n) 

(n-1)/10+(n-1)%10
~-n/10+~-n%10

Các toán tử ~và unary -được ưu tiên cao hơn* , /, %, không giống như nhị phân +.


11
Một biến thể của thủ thuật này tôi đã chạy vào ngày hôm nay: -~-xlưu một byte so với (1-x).
Lynn

4
Một ứng dụng hữu ích khác là a+b+1có thể được viết chính xác hơn như a-~b.
Strigoides

n-i-1chỉ là n+~i.
ruohola

51

Một cách hay để chuyển đổi một iterable thành danh sách trên Python 3 :

hãy tưởng tượng bạn có một số lần lặp lại, như

i = (1,2,3,4)
i = range(4)
i = (x**2 for x in range(5))

Nhưng bạn cần một danh sách:

x=list(i)  #the default way
*x,=i      #using starred assignment -> 4 char fewer

Nó rất hữu ích để tạo một danh sách các ký tự ra khỏi chuỗi

s=['a','b','c','d','e']
s=list('abcde')
*s,='abcde'

1
*s,='abcde'và sau đó làm shỏng python3 tương tác của tôi với một segfault :(
daniero

@daniero Wow. Chỉ trên bảng điều khiển tương tác? Nghe rất lạ. Dùng thử trên bảng điều khiển sạch hoặc báo cáo lỗi
JBernardo

1
Python 3.5 của tôi hoạt động tốt.
NoOneIsHãy là

for i = (x ** 2 cho x trong phạm vi (5)) Tôi nhận được mã này được trả về <đối tượng trình tạo <genexpr> tại 0x03321690>
george

7
Và nếu bạn đang làm điều này trong một biểu thức, bạn có thể làm [*'abcde'].
Esolanging Fruit

46

Thay vì range(x), bạn có thể sử dụng *toán tử trong danh sách mọi thứ, nếu bạn không thực sự cần sử dụng giá trị của i:

for i in[1]*8:pass

như trái ngược với

for i in range(8):pass

Nếu bạn cần thực hiện việc này nhiều hơn hai lần, bạn có thể gán bất kỳ lần lặp nào cho một biến và nhân biến đó với phạm vi bạn muốn:

r=1,
for i in r*8:pass
for i in r*1000:pass

Lưu ý : điều này thường dài hơn exec"pass;"*8, vì vậy thủ thuật này chỉ nên được sử dụng khi đó không phải là một tùy chọn.


@proudhaskeller Tôi nghĩ rằng điểm của dòng bạn đã xóa là "Ngoài khoản tiết kiệm ký tự rõ ràng bạn nhận được vì [1]*8ngắn hơn range(8), bạn cũng có thể tiết kiệm một khoảng trống vì không for i in[...hợp pháp trong khi for i in range...không hợp pháp ".
undergroundmonorail

oh, phải, tôi đã không hiểu điều đó. cố định ngay bây giờ
tự hào

7
exec"pass;"*8ngắn hơn đáng kể.
DJMcMayhem

1
nếu r=1, r*8là 8 và bạn không thể lặp qua một số. Tôi đoán ý của bạn làr=[1]
Artemis Fowl

1
@ArtemisFowl, không sao cả, dấu phẩy sau số 1 tạo ra một bộ dữ liệu có thể lặp lại được.
Sasha

43

Bạn có thể sử dụng khuôn mặt cười người ngoài hành tinh cũ tốt để đảo ngược trình tự:

[1, 2, 3, 4][::-1] # => [4, 3, 2, 1]

38

Giải nén lặp lại mở rộng ("gán sao", chỉ Python 3)

Cách tốt nhất để giải thích điều này là thông qua một ví dụ:

>>> a,*b,c=range(5)
>>> a
0
>>> b
[1, 2, 3]
>>> c
4

Chúng ta đã thấy một cách sử dụng cho việc này - biến một iterable thành một danh sách trong Python 3 :

a=list(range(10))
*a,=range(10)

Dưới đây là một vài cách sử dụng.

Lấy phần tử cuối cùng từ danh sách

a=L[-1]
*_,a=L

Trong một số trường hợp, điều này cũng có thể được sử dụng để có được phần tử đầu tiên để lưu vào parens:

a=(L+[1])[0]
a,*_=L+[1]

Chỉ định một danh sách trống và các biến khác

a=1;b=2;c=[]
a,b,*c=1,2

Xóa phần tử đầu tiên hoặc cuối cùng của danh sách không trống

_,*L=L
*L,_=L

Chúng ngắn hơn các lựa chọn thay thế L=L[1:]L.pop() . Kết quả cũng có thể được lưu vào một danh sách khác.

Mẹo lịch sự của @grc


Ồ Tôi đã viết a=1;L=[]rất nhiều lần. Thật đáng kinh ngạc khi bạn có thể lưu ký tự vào một cái gì đó đơn giản như thế này.
xnor

@xnor Đó là nhờ có grc. Chỉ với một yếu tố khác, nó không tốt bằng ( a,*L=1,), nhưng nó vẫn tiết kiệm được một char :)
Sp3000

đừng quên bạn cũng có thể nhận được cả yếu tố đầu tiên và cuối cùng của danh sách vớia,*_,b=L
Cyoce 3/03/2016

36

đặt chữ trong Python2.7

Bạn có thể viết các bộ như thế này S={1,2,3}Điều này cũng có nghĩa là bạn có thể kiểm tra tư cách thành viên bằng cách sử dụng {e}&Sthay vì e in Slưu một ký tự.


4
Và điều này cũng lưu nhân vật trong ifs vì không có khoảng trắng ( if{e}&S:)
Artyer

1
Lưu ý rằng bạn có thể thay thế not inbằng {e}-Sthủ thuật đó
Black Owl Kai

35

Trong nhiều năm, điều đó làm phiền tôi rằng tôi không thể nghĩ ra một cách ngắn để có được toàn bộ bảng chữ cái. Nếu bạn sử dụng rangeđủ có R=rangegiá trị trong chương trình của bạn, thì

[chr(i+97)for i in R(26)]

ngắn hơn ngây thơ

'abcdefghijklmnopqrstuvwxyz'

, nhưng nếu không thì nó dài hơn bởi một ký tự. Nó ám ảnh tôi rằng một người thông minh đòi hỏi một số kiến ​​thức về các giá trị ascii cuối cùng lại dài dòng hơn là chỉ gõ tất cả các chữ cái.

Cho đến khi tôi thấy câu trả lời này cho Bảng chữ cái của con gái tôi . Tôi không thể theo dõi lịch sử chỉnh sửa đủ tốt để tìm hiểu xem thiên tài này là công việc của OP hay nếu đó là một gợi ý của một nhà bình luận, nhưng đây là (cách tôi tin) là cách ngắn nhất để tạo ra một lần lặp trong 26 chữ cái trong bảng chữ cái La Mã.

map(chr,range(97,123))

Nếu trường hợp không quan trọng, bạn có thể loại bỏ một ký tự khác bằng cách sử dụng chữ hoa:

map(chr,range(65,91))

Tôi sử dụng mapquá nhiều, tôi không biết làm thế nào điều này không bao giờ xảy ra với tôi.


4
Có thể sử dụng điều này trong mã hóa thực tế, tôi cảm thấy thật ngu ngốc khi mã hóa những thứ này: ')
ToonAlfrink

37
Trong mã hóa thực tế, sử dụng string.lowercase- đó là những gì nó có.
Kevin S

1
nếu bạn cần cả hai trường hợp, cách ngắn nhất tôi biết là bộ lọc (str.alupha, map (chr, phạm vi (256))). Nó chỉ ngắn hơn s = map (chr, phạm vi (256)); s + = map (str.lower, s)
quintopia

@quintopia: Tại sao 256 thay vì 122 ( ord('z'))? Ngoài ra, nó có cùng độ dài ... Ngoài ra, nếu bạn cần chữ và số, hãy thay thế str.isalphatrong phiên bản của @ quintopia str.isalnum. (Nhưng nếu bạn chỉ cần một trường hợp, toàn bộ chuỗi 36 ký tự không dài hơn filter(str.isalnum,map(chr,range(90))).)
Tim Pederick

2
Nếu bạn không công bằng và sử dụng phạm vi như R, phiên bản của tôi ngắn hơn phiên bản gốc của bạn: '%c'*26%tuple(R(97,123))(chỉ có 24 ký tự) nếu bạn đánh vần rangenó chỉ dài bằng bảng chữ cái - phiên bản chữ hoa ngắn hơn
JBernardo 21/12/17

32

Mặc dù python không có câu lệnh chuyển đổi, bạn có thể mô phỏng chúng bằng từ điển. Ví dụ: nếu bạn muốn một công tắc như thế này:

switch (a):
    case 1:
        runThisCode()
        break
    case 2:
        runThisOtherCode()
        break
    case 3:
        runThisOtherOtherCode()
        break

Bạn có thể sử dụng các ifcâu lệnh hoặc bạn có thể sử dụng câu lệnh này:

exec{1:"runThisCode()",2:"runThisOtherCode()",3:"runThisOtherOtherCode()"}[a]

hoặc này:

{1:runThisCode,2:runThisOtherCode,3:runThisOtherOtherCode}[a]()

sẽ tốt hơn nếu tất cả các đường dẫn mã là các hàm có cùng tham số.

Để hỗ trợ một giá trị mặc định, hãy làm điều này:

exec{1:"runThisCode()"}.get(a,"defaultCode()")

(hoặc cái này :)

­­{1:runThisCode}.get(a,defaultCode)()

Một lợi thế khác của điều này là nếu bạn có dự phòng, bạn có thể thêm chúng sau khi kết thúc từ điển:

exec{'key1':'code','key2':'code'}[key]+';codeThatWillAlwaysExecute'

Và nếu bạn chỉ muốn sử dụng một công tắc để trả về một giá trị:

def getValue(key):
    if key=='blah':return 1
    if key=='foo':return 2
    if key=='bar':return 3
    return 4

Bạn chỉ có thể làm điều này:

getValue=lambda key:{'blah':1,'foo':2,'bar',3}.get(key,4)

2
Đây là một cái gì đó tôi sẽ xem xét sâu sắc sử dụng trong tự nhiên. Tôi rất nhớ những tuyên bố chuyển đổi của tôi! +1
HalosGhost

1
Mặc dù thay vì sử dụng từ điển với các khóa được đánh số trong ví dụ đầu tiên, bạn chỉ nên sử dụng một danh sách
Cyoce

1
Nếu bạn có các chuỗi làm khóa, sử dụng dict(s1=v1,s2=v2,...,sn=vn)thay vì {'s1':v1,'s2':v2,...,'sn':vn}lưu 2 * n-4 byte và tốt hơn nếu n> = 3
Black Owl Kai

31

Khi bạn có hai giá trị boolean ab, nếu bạn muốn tìm hiểu xem cả hai abcó đúng không, hãy sử dụng *thay vì and:

if a and b: #7 chars

đấu với

if a*b: #3 chars

nếu một trong hai giá trị là sai, nó sẽ đánh giá như 0trong câu lệnh đó và một giá trị nguyên chỉ đúng nếu nó không khác.


9
Hoặc bạn có thể sử dụng &: a=b=False,a&b
ɐɔɐɔʇǝɥʇʎ

3
sử dụng +cho ornếu bạn có thể đảm bảoa != -b
undergroundmonorail

2
|hoạt động trong mọi tình huống.
Máy tính dòng

1
*thay vì and/ &&lưu một số byte bằng nhiều ngôn ngữ.
lãng phí

26

Khai thác biểu diễn chuỗi Python 2

Python 2 cho phép bạn chuyển đổi một đối tượng xthành biểu diễn chuỗi của nó `x`với chi phí chỉ bằng 2 ký tự. Sử dụng điều này cho các nhiệm vụ được thực hiện dễ dàng hơn trên chuỗi của đối tượng so với chính đối tượng.

Tham gia nhân vật

Đưa ra một danh sách các nhân vật l=['a','b','c'], người ta có thể tạo ra ''.join(l)như`l`[2::5] , giúp tiết kiệm một byte.

Lý do `l`"['a', 'b', 'c']" (với không gian), do đó người ta có thể trích xuất các chữ cái với một lát danh sách, bắt đầu rằng thứ hai nhân vật zero-lập chỉ mục a, và dùng mọi nhân vật thứ năm từ đó. Điều này không hoạt động để tham gia chuỗi nhiều ký tự hoặc thoát các ký tự được đại diện như thế nào '\n'.

Chữ số nối

Tương tự, đưa ra một danh sách các chữ số không trống như l=[0,3,5] , người ta có thể ghép chúng thành một chuỗi '035'như`l`[1::3] .

Điều này tiết kiệm làm một cái gì đó như map(str,l). Lưu ý rằng chúng phải là một chữ số và không thể có số float như1.0 trộn lẫn. Ngoài ra, điều này không có trong danh sách trống, tạo ra] .

Kiểm tra các tiêu cực

Bây giờ, cho một nhiệm vụ không phải là chuỗi. Giả sử bạn có một danh sáchl các số thực và muốn kiểm tra xem nó có chứa bất kỳ số âm nào không, tạo ra Boolean.

Bạn có thể làm

'-'in`l`

trong đó kiểm tra một dấu âm trong chuỗi đại diện. Cái này ngắn hơn một trong hai

any(x<0for x in l)
min(l+[0])<0   

Lần thứ hai, min(l)<0sẽ thất bại trong danh sách trống, vì vậy bạn phải phòng ngừa.


Ghép chuỗi cắt các chữ số đơn cũng có hiệu quả trong Python 3, mặc dù ít hơn: str(l)[2::5]là 12 byte, so với 19 đối với ''.join(map(str,l)). Một tình huống thực tế khi điều này xuất hiện (trong đó llà một câu lệnh tạo, không phải là danh sách) đã tiết kiệm cho tôi chỉ một byte ... vẫn còn giá trị!
Tim Pederick

25

Hàm một dòng có thể được thực hiện với lambda:

def c(a):
  if a < 3: return a+10
  else: return a-5

có thể được chuyển đổi thành (lưu ý thiếu không gian 3and10or)

c=lambda a:a<3and a+10or a-5

21
hoặc c=lambda a:a+[-5,10][a<3]. và / hoặc mẹo hữu ích hơn khi bạn phụ thuộc vào hành vi của shortcircuit
gnibbler

3
Trong hàm của bạn, else: có thể được loại bỏ khi returndừng thực thi hàm, vì vậy mọi thứ tiếp theo chỉ được thực hiện nếu ifđiều kiện không thành công, còn gọi là nếu elseđiều kiện là đúng. Do đó elsecó thể được an toàn. (Giải thích chi tiết cho các tân sinh viên ngoài kia)
JeromeJ

c (-10) trả về -15 trong khi nó sẽ trả về 0
Anvit

hoặcc=lambda a:a-5+15*(a<3)
JayXon

25

vòng lặp tối đa 4 mục có thể tốt hơn để cung cấp một tuple thay vì sử dụng phạm vi

for x in 0,1,2:

đấu với

for x in range(3):

24

Trần và sàn

Nếu bạn muốn lấy kết quả làm tròn cho một bộ phận, giống như bạn làm với //sàn, bạn có thể sử dụng math.ceil(3/2)cho 15 hoặc ngắn hơn nhiều -(-3//2)cho 8 byte.

math.floor(n)   : 13 bytes+12 for import
n//1            : 4  bytes

math.ceil(n)    : 12 bytes+12 for import
-(-n//1)        : 8  bytes

5
Điều này chỉ giúp tôi tiết kiệm gần 20 byte, cảm ơn bạn!
Morgan Thrapp

1
đôi khi bạn có thể thoát khỏi n//1+1thay vì trần nhưng điều đó có nghĩa là trần (n) = n + 1 nhưng nó sẽ hoạt động với tất cả các giá trị không nguyên
fejfo 23/12/17

round(x)(x+.5)//1, 1 byte nhưng cái sau bắt đầu bằng a (và nếu xlà tổng bao gồm hằng số thì nó có thể hữu ích.
dùng202729

23

Sử dụng +=thay vì appendextend

A.append(B)  

có thể rút ngắn thành:

A+=B,

B,ở đây tạo ra một bộ dữ liệu một phần tử có thể được sử dụng để mở rộng Agiống như [B]trong A+=[B].


A.extend(B)

có thể rút ngắn thành:

A+=B

5
Trong nhiều trường hợp (nhưng không phải tất cả), return 0hoặc return 1tương đương với return Falsehoặc return True.
undergroundmonorail

5
(1) chỉ hoạt động nếu bạn đã biết số đó là số âm, trong trường hợp đó bạn có thể lưu thêm 2 ký tự chỉ bằng cách sử dụng dấu trừ. -xhơn x*-1. --8.32hơn -8.32*-1. Hoặc chỉ 8.32...
trichoplax

Trích dẫn OP: Vui lòng gửi một mẹo cho mỗi câu trả lời.
nyuszika7h

Lưu ý rằng trong A+=B Blà một tuple.
Erik the Outgolfer

23

Chọn một trong hai số dựa trên một điều kiện

Bạn đã biết sử dụng lựa chọn danh sách [x,y][b]với Boolean bcho biểu thức ternary y if b else x. Các biến x, ybcũng có thể là biểu thức, mặc dù lưu ý rằng cả hai xyđược đánh giá ngay cả khi không được chọn.

Đây là một số tối ưu hóa tiềm năng khi xylà số.

  • [0,y][b] -> y*b
  • [1,y][b] -> y**b
  • [x,1][b] -> b or x
  • [x,x+1][b] -> x+b
  • [x,x-1][b] -> x-b
  • [1,-1][b] -> 1|-b
  • [x,~x][b] -> x^-b
  • [x,y][b] -> x+z*b(hoặc y-z*b), trong đó z = yx.

Bạn cũng có thể chuyển đổi xynếu bạn có thể viết lại bthành phủ định của nó thay vào đó.


22

Sử dụng ~ để lập chỉ mục từ mặt sau của danh sách

Nếu Llà một danh sách, sử dụng L[~i]để có đượci phần tử thứ từ phía sau.

Đây là iyếu tố thứ hai của sự đảo ngược của L. Phần bù bit ~ibằng -i-1, và do đó sửa lỗi từ một L[-i].


21

PEP448 - Tổng quát hóa giải nén bổ sung

Với việc phát hành Python 3.5 , việc thao tác các danh sách, bộ dữ liệu, bộ và ký tự đã trở thành golfier.

Biến một iterable thành một tập hợp / danh sách

So sánh các cặp:

set(T)
{*T}

list(T)
[*T]

tuple(T)
(*T,)

Ngắn hơn nhiều! Tuy nhiên, lưu ý rằng nếu bạn chỉ muốn chuyển đổi một cái gì đó thành một danh sách và gán nó vào một biến, thì việc giải nén lặp lại mở rộng bình thường sẽ ngắn hơn:

L=[*T]
*L,=T

Một cú pháp tương tự hoạt động cho các bộ dữ liệu:

T=*L,

giống như giải nén lặp lại mở rộng, nhưng với dấu hoa thị và dấu phẩy ở phía bên kia.

Tham gia danh sách / bộ dữ liệu

Giải nén ngắn hơn một chút so với ghép nếu bạn cần nối thêm một danh sách / bộ dữ liệu vào cả hai bên:

[1]+T+[2]
[1,*T,2]

(1,)+T+(2,)
(1,*T,2)

In nội dung của nhiều danh sách

Điều này không giới hạn print, nhưng nó chắc chắn là nơi mà hầu hết số dặm sẽ đến. PEP448 hiện cho phép nhiều lần giải nén, như vậy:

>>> T = (1, 2, 3)
>>> L = [4, 5, 6]
>>> print(*T,*L)
1 2 3 4 5 6

Cập nhật nhiều mục từ điển

Điều này có thể sẽ không xảy ra rất thường xuyên, nhưng cú pháp có thể được sử dụng để lưu vào việc cập nhật từ điển nếu bạn đang cập nhật ít nhất ba mục:

d[0]=1;d[1]=3;d[2]=5
d={**d,0:1,1:3,2:5}

Điều này về cơ bản phủ nhận bất kỳ nhu cầu cho dict.update.


6
Điều này có vẻ tệ hơn Perl, nhưng nó hoạt động ...
Mega Man

20

Thay đổi import *thànhimport*


Nếu bạn chưa nghe thấy, hãy import*tiết kiệm ký tự!

from math import*

chỉ dài hơn 1 ký tự import math as mvà bạn có thể xóa tất cả các phiên bản củam.

Ngay cả một lần sử dụng là một tiết kiệm!


19
>>> for i in range(x):s+=input()

nếu giá trị của tôi là vô dụng:

>>> for i in[0]*x:s+=input()

hoặc là

>>> exec's+=input();'*x

8
Bạn có thể tạo ví dụ thứ hai vào for i in[0]*x:s+=input()để tiết kiệm không gian khác. Ngoài ra, bạn có thể xóa khoảng trắng giữa người thực hiện và dấu ngoặc kép đầu tiên để nhậnexec's+=input();'*x
Justin Peel

không nên dòng thứ hai là:for i in[0]*x:s+=input()
micsthepick

Dupe (mới hơn nhưng nhiều
upvote
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.