How could I reduce the length of this code?

5

I need to reduce the length of this code in Python 3 as much as possible (even if it will be less readable):

a,b,x,y=[int(i) for i in input().split()]
while 1: 
 r=''
 if y<b:r='S';y+=1
 if y>b:r='N';y-=1 
 if x<a:r+='E';x+=1
 if x>a:r+='W';x-=1
 print(r)

It's a map: you are on (x,y) and you need to go to (a,b). S for South, N for North, NE for North East and so on. After each turn I must tell where to go using print.

Update: This is what I've got now, but is there any way to shorten it further?

a,b,x,y=map(int,input().split())
while 1:c,d=(y>b)-(y<b),(x>a)-(x<a);print((' NS'[c]+' WE'[d]).strip());y-=c;x-=d

xaxa

Posted 2015-05-07T18:59:45.373

Reputation: 221

2This never terminates. Is that OK? – xnor – 2015-05-07T19:08:03.743

Yes. In fact, it will automatically end when x=a and y=b – xaxa – 2015-05-07T19:11:24.363

How strict is the form of the input? For example if you are allowed to take input as "[4,5,1,2]" you could change the first line to a much shorter a,b,x,y=input() – KSab – 2015-05-08T13:13:06.203

it's really too bad they got rid of cmp() in python 3, this is a perfect use case. – sirpercival – 2015-05-09T11:35:22.920

Answers

5

Python 3, 107

a,b,x,y=map(int,input().split())
A=abs(a-x);B=abs(b-y)
while 1:print('SN'[b>y][:B]+'WE'[a>x][:A]);A-=1;B-=1

A different strategy to generate the directions, tracking each coordinate's absolute displacement to the goal rather than the actual location.

For the horizontal direction, finds the absolute displacement A=abs(a-x) and direction character 'WE'[a>x]. Simulates going towards the goal by decrementing A and printing the direction character as long as we haven't already reached the goal coordinate (A>0). Does the same for vertical.

xnor

Posted 2015-05-07T18:59:45.373

Reputation: 115 687

3

Theres a shorter way to strip():

(' NS'[c]+' WE'[d]).strip()
c%2*' NS'[c]+d%2*' WE'[d]

saves two characters.

KSab

Posted 2015-05-07T18:59:45.373

Reputation: 5 984

2

In Python 2, you could use cmp, which returns -1, 0, or 1. Use this result to get the correct letter.

while 1:c=cmp(y,b);d=cmp(x,a);print((' SN'[c]+' WE'[d]).strip());y-=c;x-=d

Martin Büttner suggested saving the cmp results to variables, and isaacg noted that now the whole loop can be on one line.

Unfortunately, Python 3 doesn't have cmp, but using (y>b)-(y<b) for cmp(y,b) is still shorter than the original.

Ypnypn

Posted 2015-05-07T18:59:45.373

Reputation: 10 485

Thank you but how do you use the function cmp ? – xaxa – 2015-05-07T19:55:34.150

"cmp(x,y): Compare the two objects x and y and return an integer according to the outcome. The return value is negative if x < y, zero if x == y and strictly positive if x > y." From the Python documentation. link

– Bonsaigin – 2015-05-07T20:23:27.840

@Bonsaigin That's a Python 2 documentation link. – isaacg – 2015-05-07T20:34:07.943

I decided to fix up the answer to make it relevant and undelete it, as it was an important part in reducing the size of the original. – Martin Ender – 2015-05-09T11:42:57.743

cc: @isaacg see above comment – Martin Ender – 2015-05-09T11:43:50.757

2

There's a shorter way to take the initial input:

a,b,x,y=[int(i) for i in input().split()]
a,b,x,y=map(int,input().split())

Thanks to @DenDenDo, for pointing out that you can do tuple unpacking assignment on map objects.

isaacg

Posted 2015-05-07T18:59:45.373

Reputation: 39 268

3You dont even need list(), simply a,b,x,y=map(int,input().split()) – DenDenDo – 2015-05-07T19:27:59.487