5
\$\begingroup\$

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
\$\endgroup\$
  • 1
    \$\begingroup\$ This never terminates. Is that OK? \$\endgroup\$ – xnor May 7 '15 at 19:08
  • \$\begingroup\$ Yes. In fact, it will automatically end when x=a and y=b \$\endgroup\$ – xaxa May 7 '15 at 19:11
  • \$\begingroup\$ 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() \$\endgroup\$ – KSab May 8 '15 at 13:13
  • \$\begingroup\$ it's really too bad they got rid of cmp() in python 3, this is a perfect use case. \$\endgroup\$ – sirpercival May 9 '15 at 11:35
5
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

Theres a shorter way to strip():

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

saves two characters.

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • 3
    \$\begingroup\$ You dont even need list(), simply a,b,x,y=map(int,input().split()) \$\endgroup\$ – DenDenDo May 7 '15 at 19:27
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thank you but how do you use the function cmp ? \$\endgroup\$ – xaxa May 7 '15 at 19:55
  • \$\begingroup\$ "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 \$\endgroup\$ – Bonsaigin May 7 '15 at 20:23
  • \$\begingroup\$ @Bonsaigin That's a Python 2 documentation link. \$\endgroup\$ – isaacg May 7 '15 at 20:34
  • \$\begingroup\$ 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. \$\endgroup\$ – Martin Ender May 9 '15 at 11:42
  • \$\begingroup\$ cc: @isaacg see above comment \$\endgroup\$ – Martin Ender May 9 '15 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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