32
\$\begingroup\$

This is a challenge of practicing golf optimization in Python -- reusable tricks and shortcuts to shave off a few characters. Many will be familiar to Python golfers and use common ideas from the Python Tips. Some of these use Python-specific features that you might not know exist unless you've seen them, so do take a look at the tips if you're stuck.

Goal: There are ten problems, each a reference snippet of Python code for you to optimize and a description of the code does. Your goal is rewrite it to be shorter but still functionally-equivalent.

Your score, which you're trying to minimize, is the total length of your code all the snippets. The length of the reference snippets is 150. Tiebreaker is earliest post.

Posting answers: For each problem, post your code and its character count. You can post the reference snippet if you didn't find something shorter. It's intended that you don't look at others' answers when you post yours. Please spoiler-tag each individual problem including the individual character counts. You can leave the total count revealed. Feel free now to unspoiler your solution or post new unspoilered solutions.

Details on legality: Functional equivalence means the code can be replaced in a program without affecting its behavior (ignoring things like memory usage and operator precedence as part of an expression). Expressions should produce values that are equivalent by ==. Note that 1.0==1==True. Your code should have no side-effects unless otherwise stated. I don't intend the problems to be version-specific, but just in case, you can specify a Python version for each problem.

Problem 1: Keep iterating as long as the list L has at least 7 elements

# 16 chars
while len(L)>=7:

Problem 2: Check whether two floats x and y are both positive.

# 11 chars
x>0 and y>0

Problem 3: If Boolean b is true, remove the first element of L. Otherwise, leave it unchanged.

# 12 chars
if b:L=L[1:]

Problem 4: Check if all elements of a non-empty list L of numbers are equal. For this problem, it's OK to modify the list.

# 22 chars
all(x==L[0]for x in L)

Problem 5: Append a number n to the end of a list L only if L already contains that number.

# 16 chars
if n in L:L+=[n] 

Problem 6: Express the sign of a float x: +1 for positive, 0 for 0, -1 for negative.

# 20 chars
abs(x)/x if x else 0

Problem 7 Continue a loop as long as the first element of L, a list of Booleans, is True. Also stop if L is empty.

# 17 chars
while L and L[0]:

Problem 8: Continue a loop as long as n is greater than 1. The number n is guaranteed to be a positive integer.

# 10 chars
while n>1:

Problem 9: Check if an integer represented as a string s is negative (i.e, starts with '-').

# 9 chars
s[0]=='-'

Problem 10: Convert a Boolean b to "Win"/"Lose", with True->"Win" and False->"Lose".

# 17 chars
["Lose","Win"][b]

Warning: Spoilers below, don't scroll down if you want to solve these yourself.

If you just want to know the optimal score for a problem:

Problem 1:

12

Problem 2:

5

Problem 3:

7

Problem 4:

13

Problem 5:

13

Problem 6:

8

Problem 7:

12

Problem 8:

9

Problem 9:

5

Problem 10:

15

\$\endgroup\$
7
  • 3
    \$\begingroup\$ I voted to close, since this challenge provokes duplicate answers and effectively is many questions in one, since there is no interaction between the individual challenges whatsoever. I think that if we have such questions, there should only be one answer, which is a community wiki. \$\endgroup\$
    – Wrzlprmft
    Commented Nov 18, 2014 at 12:18
  • 2
    \$\begingroup\$ @Wrzlprmft: Somehow it's an interesting challenge. But after having 7 great contributions, now, I'd suggest relaxing the rules and allowing unspoilered solutions to single problems, because otherwise perfect submissions might remain hidden behind overall mediocre total scores. \$\endgroup\$
    – Falko
    Commented Nov 18, 2014 at 16:32
  • 2
    \$\begingroup\$ I think this is a cool idea and that we should have golf practices for more languages. \$\endgroup\$
    – Robin
    Commented Nov 18, 2014 at 21:54
  • 2
    \$\begingroup\$ @Wrzlprmft there is now a discussion regarding this on meta. Please voice your opinion there, for easier discussion without polluting this question's comments. \$\endgroup\$
    – FireFly
    Commented Nov 18, 2014 at 21:55
  • 3
    \$\begingroup\$ I'm voting to close this question as off-topic because multi-part challenges with no interaction between the parts are disallowed. meta.codegolf.stackexchange.com/a/8464/45941 \$\endgroup\$
    – user45941
    Commented Mar 22, 2016 at 18:04

7 Answers 7

21
\$\begingroup\$

Total: 104 101 99 chars

Problem 1

12 chars
while L[6:]:

Problem 2

5 chars
x>0<y

Problem 3

7 chars
L=L[b:]

Problem 4

13 chars
len(set(L))<2
L[1:]==L[:-1]

Problem 5

13 chars
L+=set(L)&{n}

Problem 6

11 chars
(x>0)-(x<0)

8 chars (Python 2)
cmp(x,0)

Problem 7

12 chars
while[.5]<L:

Problem 8

9 chars
while~-n:

Problem 9

5 chars
s<'.'

Problem 10

15 chars
'LWoisne'[b::2]

\$\endgroup\$
3
  • \$\begingroup\$ @FryAmTheEggman Can you explain the side effect? I intended that to be a valid solution. \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 2:34
  • \$\begingroup\$ @xnor Nevermind, I was entirely wrong. I learned something today :) \$\endgroup\$ Commented Nov 18, 2014 at 3:15
  • \$\begingroup\$ I believe these solutions to be optimal, given the multiple 99 solutions and the fact that I can't find anything better. I'd be happy to see an improvement though. Since this was the first 99, I'm accepting it. \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 21:11
7
\$\begingroup\$

Total size: 128 122 120 117 116 115 111 107 104

Problem 1

Keep iterating as long as the list L has at least 7 elements.

15 chars
while len(L)>6:
(Yes, I could save 3 bytes on this, but I accidentally saw the solution Sp3000's answer, so I won't claim those three bytes.)

Problem 2

Check whether two floats x and y are both positive.

5 chars
x>0<y

Problem 3

If Boolean b is true, remove the first element of L. Otherwise, leave it unchanged.

7 chars
L=L[b:]

Problem 4

Check if all elements of a non-empty list L of numbers are equal. For this problem, it's OK to modify the list.

13 chars
L[1:]==L[:-1]

Problem 5

Append a number n to the end of a list L only if L already contains that number.

15 chars
L+=[n]*(n in L)
or
L+=[n][:n in L]

Problem 6

Express the sign of a float x: +1 for positive, 0 for 0, -1 for negative.

8 chars, Python 2
cmp(x,0)
According to docs this might return any positive/negative value, but consensus is it always returns -1, 0, 1.

Problem 7

Continue a loop as long as the first element of L, a list of Booleans, is True. Also stop if L is empty.

12 chars
while[1]<=L:

Problem 8

Continue a loop as long as n is greater than 1. The number n is guaranteed to be a positive integer.

9 chars
while~-n:

Problem 9

Check if an integer represented as a string s is negative (i.e, starts with '-').

5 chars
s<'.'

Problem 10

Convert a Boolean b to "Win"/"Lose", with True->"Win" and False->"Lose".

15 chars
"LWoisne"[b::2]

\$\endgroup\$
2
  • \$\begingroup\$ Could you please spoiler the individual lengths too? \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 0:30
  • \$\begingroup\$ @xnor No problem, done. \$\endgroup\$ Commented Nov 18, 2014 at 0:32
7
\$\begingroup\$

Total: 106 104 102 chars

Problem 1

12 chars
while L[6:]:

Problem 2

5 chars
x>0<y
Huzzah for comparison chaining

Problem 3

7 chars
L=L[b:]
Good old implicit conversion

Problem 4

13
len(set(L))<2

Alternatively:
L[1:]==L[:-1]

Stupid way to get the negation of what we want in Python 2:
","in`set(L)`

I'm not sure what the relevance of "it's OK to modify the list" is though, because the best I can think of is 14 chars (and is actually wrong):
L==[L.pop()]+L

Problem 5

13 chars
L+={n}&set(L)
Doing funky things with sets

Problem 6

11 chars
(x>0)-(x<0)

Problem 7

12 chars
while[1]<=L:
Uses lexicographical order of lists

Problem 8

9 chars
while~-n:

Problem 9

5 chars
s<"."
Uses lexicographical ordering of strings

Problem 10

15 chars
"LWoisne"[b::2]

Alternatively:
b*"Win"or"Lose"

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I had not considered your alternative to #10 before. It means that one can get the same character savings as the usual interleaving trick regardless of the length of the strings, barring precedence issues in the bool. I'll add this to the tips. \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 22:58
  • 1
    \$\begingroup\$ @xnor Ahaha yeah, I thought it was pretty nice. It's not as good when you have more strings though, which is downside (e.g. b is 0, 1 or 2, and all you can do is (b-1)*"Hello"or b*"Goodbye"or"Good Afternoon") \$\endgroup\$
    – Sp3000
    Commented Nov 18, 2014 at 23:03
  • \$\begingroup\$ Tip: codegolf.stackexchange.com/a/407/20260 \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 23:03
  • \$\begingroup\$ That's actually not bad for three strings. You can remove the parens with ~b*"Hello". \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 23:06
  • \$\begingroup\$ @xnor At that point, ["Good Afternoon","Goodbye","Hello"][b] would win :P \$\endgroup\$
    – Sp3000
    Commented Nov 18, 2014 at 23:11
6
\$\begingroup\$

Total: 99 bytes

Problem 1

12 bytes
while L[6:]:

Problem 2

5 bytes
x>0<y

Problem 3

7 bytes
L=L[b:]

Problem 4

13 bytes
len(set(L))<2

14 byte alternatives
min(L)==max(L)
set(L)=={L[0]}

Problem 5

13 bytes
L+=set(L)&{n}

Problem 6

8 bytes
cmp(x,0)

Problem 7

12 bytes
while[1]<=L:

Problem 8

9 bytes
while~-n:

Problem 9

5 bytes
s<'.'

Problem 10

15 bytes
b*"Win"or"Lose"
- or -
"LWoisne"[b::2]

\$\endgroup\$
4
\$\begingroup\$

1: 12
while L[6:]:
2: 5
y>0<x
3: 7
L=L[b:]
4: 15
L==L[:1]*len(L)
5: 15
L+=[n]*(n in L) or L+=[n][:n in L]
6: 11
This is the only one for which an idiomatic expression did not immediately leap to my mind, but I think I found the right answer. Edit: Nope, it was horrible.
(x>0)-(x<0)
7: 12
while[1]<=L:
Or if the program is completed after that, while L[0] is nice.
8: 9
while~-n:
9: 5
Many strings would work here but the "naive method" is funny.
s<'0'
10: 15
'LWoisne'[b::2]

Total: 106

\$\endgroup\$
3
  • \$\begingroup\$ Wouldn't your #4 have to use [L[0]]? \$\endgroup\$
    – FireFly
    Commented Nov 18, 2014 at 17:56
  • \$\begingroup\$ @FireFly Whoops. It's not as bad as that, but does cost one byte. \$\endgroup\$
    – feersum
    Commented Nov 18, 2014 at 20:29
  • 2
    \$\begingroup\$ Your #9 is a wonderful golfing pun! \$\endgroup\$
    – xnor
    Commented Nov 18, 2014 at 22:56
3
\$\begingroup\$

Total size: 123 121 120 116

#1

(12) while L[6:]:

#2

(10) min(x,y)>0

#3

(7) L=L[b:]

#4

(13) len(set(L))<2 or L[1:]==L[:-1]

#5

(15) L+=[n]*(n in L)

#6

(14) x and abs(x)/x or (inspired by Claudiu's solution after giving up) x and(x>0)*2-1

#7

(15) while[0]<L[:1]:

#8

(9) while~-n:

#9

(5) s<'.'

#10

(15) b*"Win"or"Lose"

\$\endgroup\$
1
\$\begingroup\$

Total: 121

First attempts:

Problem 1

15 chars
while len(L)>6:

Problem 2

5 chars
x>0<y

Problem 3

7 chars
L=L[b:]

Problem 4

13 chars
len(set(L))<2

Problem 5

16 chars
if n in L:L+=[n]

Problem 6

16 chars
x and(1,-1)[x<0]

Problem 7

16 chars
while(L+[0])[0]:

Problem 8

10 chars
while n>1:

Problem 9

8 chars
s[0]<'0'

Problem 10

15 chars
"LWoisne"[b::2]

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.