length of the line segment

  |   Source

length-of-the-line-segment

Problem

In [4]:
# package로 인식을 못해서 어쩔 수 없이 이렇게 import함
%cd ..
from helper.war import Kata
%cd kata/
/Users/re4lfl0w/Documents/_git/codewars
/Users/re4lfl0w/Documents/_git/codewars/kata
In [5]:
kata = Kata()
2016-10-04 04:29:07: helper.war - INFO - Start func: set_access_key
INFO:helper.war:Start func: set_access_key
In [6]:
challenge_url = 'http://www.codewars.com/kata/length-of-the-line-segment/python'
description = kata.get_description_in_code_challenge(challenge_url)
print(description)
2016-10-04 04:29:08: helper.war - INFO - Start func: get_description_in_code_challenge
INFO:helper.war:Start func: get_description_in_code_challenge
2016-10-04 04:29:08: helper.war - INFO - Start func: set_code_challenge
INFO:helper.war:Start func: set_code_challenge
2016-10-04 04:29:08: helper.war - INFO - Start func: get_cleaned_challenge
INFO:helper.war:Start func: get_cleaned_challenge
2016-10-04 04:29:08: helper.war - INFO - challenge: length-of-the-line-segment
INFO:helper.war:challenge: length-of-the-line-segment
2016-10-04 04:29:09: helper.war - INFO - challenge_json: {'unresolved': {'issues': 0, 'suggestions': 0}, 'createdAt': '2015-09-10T12:32:53Z', 'description': 'Find the length between 2 co-ordinates.  The co-ordinates are made of integers between -20 and 20 and will be given in the form of a 2D array:\n\n(0,0) and (5,-7) would be [ [ 0 , 0 ] , [ 5, -7 ] ]\n\nThe function must return the answer rounded to 2 decimal places in the form of a string.\n\n```javascript\nlengthOfLine([ [ 0 , 0 ] , [ 5, -7 ] ]); => "8.60"\n```\n```python\nlength_of_line([[0, 0], [5, -7]]) => "8.60"\n```\n```ruby\nlength_of_line([[0, 0], [5, -7]]) # => "8.60"\n```\n\nIf the 2 given co-ordinates are the same, the returned length should be "0.00" \n', 'voteScore': 50, 'totalStars': 14, 'slug': 'length-of-the-line-segment', 'contributorsWanted': True, 'createdBy': {'url': 'https://www.codewars.com/users/JMurphyWeb', 'username': 'JMurphyWeb'}, 'approvedBy': {'url': 'https://www.codewars.com/users/Balkoth', 'username': 'Balkoth'}, 'id': '55f1786c296de4952f000014', 'tags': ['Fundamentals', 'Mathematics', 'Algorithms', 'Logic', 'Numbers', 'Geometry', 'Algebra'], 'category': 'reference', 'languages': ['javascript', 'python', 'ruby'], 'totalCompleted': 785, 'totalAttempts': 1805, 'publishedAt': '2015-09-10T12:32:44Z', 'name': 'Length of the line segment', 'url': 'https://www.codewars.com/kata/length-of-the-line-segment', 'approvedAt': '2015-10-07T18:32:14Z', 'rank': {'id': -7, 'name': '7 kyu', 'color': 'white'}}
INFO:helper.war:challenge_json: {'unresolved': {'issues': 0, 'suggestions': 0}, 'createdAt': '2015-09-10T12:32:53Z', 'description': 'Find the length between 2 co-ordinates.  The co-ordinates are made of integers between -20 and 20 and will be given in the form of a 2D array:\n\n(0,0) and (5,-7) would be [ [ 0 , 0 ] , [ 5, -7 ] ]\n\nThe function must return the answer rounded to 2 decimal places in the form of a string.\n\n```javascript\nlengthOfLine([ [ 0 , 0 ] , [ 5, -7 ] ]); => "8.60"\n```\n```python\nlength_of_line([[0, 0], [5, -7]]) => "8.60"\n```\n```ruby\nlength_of_line([[0, 0], [5, -7]]) # => "8.60"\n```\n\nIf the 2 given co-ordinates are the same, the returned length should be "0.00" \n', 'voteScore': 50, 'totalStars': 14, 'slug': 'length-of-the-line-segment', 'contributorsWanted': True, 'createdBy': {'url': 'https://www.codewars.com/users/JMurphyWeb', 'username': 'JMurphyWeb'}, 'approvedBy': {'url': 'https://www.codewars.com/users/Balkoth', 'username': 'Balkoth'}, 'id': '55f1786c296de4952f000014', 'tags': ['Fundamentals', 'Mathematics', 'Algorithms', 'Logic', 'Numbers', 'Geometry', 'Algebra'], 'category': 'reference', 'languages': ['javascript', 'python', 'ruby'], 'totalCompleted': 785, 'totalAttempts': 1805, 'publishedAt': '2015-09-10T12:32:44Z', 'name': 'Length of the line segment', 'url': 'https://www.codewars.com/kata/length-of-the-line-segment', 'approvedAt': '2015-10-07T18:32:14Z', 'rank': {'id': -7, 'name': '7 kyu', 'color': 'white'}}
Find the length between 2 co-ordinates.  The co-ordinates are made of integers between -20 and 20 and will be given in the form of a 2D array:

(0,0) and (5,-7) would be [ [ 0 , 0 ] , [ 5, -7 ] ]

The function must return the answer rounded to 2 decimal places in the form of a string.

```javascript
lengthOfLine([ [ 0 , 0 ] , [ 5, -7 ] ]); => "8.60"
```
```python
length_of_line([[0, 0], [5, -7]]) => "8.60"
```
```ruby
length_of_line([[0, 0], [5, -7]]) # => "8.60"
```

If the 2 given co-ordinates are the same, the returned length should be "0.00" 

In [2]:
abs(-2-(-7))
Out[2]:
5
In [3]:
abs(8-(-5))
Out[3]:
13

Logic

  • 좌표평면에서 두 점 사이의 거리 | 수학방
    • 영어로 써져 있어서 엄청 어려워 보이는데 별거 없다. 그냥 중학교때 배운 좌표평면에서 두 점 사이의 거리 구하는 공식이다...
  • 첫번째 x값 - 두번째 x값
  • 첫번째 y값 - 두번째 y값
  • 그 결과값을 더하고
  • root 취해준다.
  • 이게 뭘 하는건지는 확실하지 않다...
  • 일단 로직이 이렇게 된다는 것을 알 수 있다.
In [6]:
array = [[0,0],[1,1]]
array
Out[6]:
[[0, 0], [1, 1]]
In [7]:
a, b = array
a
Out[7]:
[0, 0]
In [8]:
b
Out[8]:
[1, 1]
In [10]:
abs(0 - (1)) ** 2
Out[10]:
1
In [11]:
5 ** 2
Out[11]:
25
In [14]:
from math import sqrt
In [15]:
sqrt(5 ** 2)
Out[15]:
5.0
In [17]:
sqrt(2)
Out[17]:
1.4142135623730951
In [31]:
'{:1.3}'.format(sqrt(2))
Out[31]:
'1.41'
In [39]:
'{:1.2f}'.format(18.0555333)
Out[39]:
'18.06'

Source

My Solution

In [1]:
from math import sqrt


def length_of_line_my1(array):
#     print(array)
    a, b = array
#     print(a)
#     print(b)
    tmp = sum(abs(a[i] - b[i]) ** 2 for i in range(len(array)))
    tmp = '{:1.2f}'.format(sqrt(tmp))
#     print(tmp)
    return tmp
Refactoring
In [2]:
from math import sqrt


def length_of_line_my2(array):
    a, b = array
    tmp = sum(abs(a[i] - b[i]) ** 2 for i in range(len(array)))
    result = '{:1.2f}'.format(sqrt(tmp))
    return result
In [3]:
from math import sqrt


def length_of_line_my3(array):
    a, b = array
    tmp = sum((a[i] - b[i]) ** 2 for i in range(len(array)))
    result = '{:.2f}'.format(sqrt(tmp))
    return result
Realize
  • abs: 해줄 필요가 없네. 어차피 제곱이 되면 -가 모두 +로 바뀌니. 괜히 opcode만 소모하니 빼주자
  • format: 1이 안 들어가도 괜찮겠다.

Best Practice

In [4]:
from math import sqrt
def length_of_line_best(array):
    x1, y1, x2, y2 = array[0][0], array[0][1], array[1][0], array[1][1]
    return '{:.2f}'.format((sqrt((x2-x1)**2 + (y2-y1)**2)))

Clever

In [ ]:
 

Time Complexity

In [5]:
%timeit length_of_line_my1([[0,0],[1,1]])
100000 loops, best of 3: 5.02 µs per loop
In [6]:
%timeit length_of_line_my2([[0,0],[1,1]])
The slowest run took 4.22 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 4.88 µs per loop
In [7]:
%timeit length_of_line_my3([[0,0],[1,1]])
The slowest run took 4.27 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 4.41 µs per loop
In [8]:
%timeit length_of_line_best([[0,0],[1,1]])
The slowest run took 5.74 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 2.47 µs per loop

Graph

  • seaborn subplot 문제를 먼저 해결하고 적용할 수 있을듯
In [ ]:
 
In [ ]:
 
In [ ]:
 

TestCase

In [1]:
# 현재 디렉토리 확인
%pwd
Out[1]:
'/Users/re4lfl0w/Documents/_git/codewars/kata'
In [7]:
# py.test를 실행시키기 위해서 잠시 프로젝트 폴더로 갔다가 다시 돌아오기
# 특정 파일을 지정해주는 이유는 tests에 많은 파일들이 쌓이게 되면 혼란스럽게 되니 딱 내가 작성했던 파일만 정확히 작동하는지 확인
%cd ..
!py.test tests/test_length_of_the_line_segment.py
%cd kata
/Users/re4lfl0w/Documents/_git/codewars
============================= test session starts ==============================
platform darwin -- Python 3.5.0, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
rootdir: /Users/re4lfl0w/Documents/_git/codewars, inifile: pytest.ini
plugins: cov-2.3.1
collected 32 items 

tests/test_length_of_the_line_segment.py ................................

---------- coverage: platform darwin, python 3.5.0-final-0 -----------
Name                                 Stmts   Miss  Cover
--------------------------------------------------------
kata/__init__.py                         0      0   100%
kata/length_of_the_line_segment.py      19      0   100%
--------------------------------------------------------
TOTAL                                   19      0   100%


========================== 32 passed in 0.08 seconds ===========================
/Users/re4lfl0w/Documents/_git/codewars/kata
In [ ]:
# %load ../tests/test_length_of_the_line_segment.py
import pytest

from kata.length_of_the_line_segment import (length_of_line_my1, length_of_line_my2,
                                             length_of_line_my3, length_of_line_best)


test_data = [
        ([[0, 0], [1, 1]], "1.41"),
        ([[0, 0], [-5, -6]], "7.81"),
        ([[0, 0], [10, 15]], "18.03"),
        ([[0, 0], [5, 1]], "5.10"),
        ([[0, 0], [5, 4]], "6.40"),
        ([[0, 0], [-7, 4]], "8.06"),
        ([[0, 0], [0, 0]], "0.00"),
        ([[-3, 4], [10, 5]], "13.04"),
    ]


class TestClass(object):
    @pytest.mark.parametrize('input_, expected', test_data)
    def test_length_of_the_line_segment_my1(self, input_, expected):
        assert length_of_line_my1(input_) == expected

    @pytest.mark.parametrize('input_, expected', test_data)
    def test_length_of_the_line_segment_my2(self, input_, expected):
        assert length_of_line_my2(input_) == expected

    @pytest.mark.parametrize('input_, expected', test_data)
    def test_length_of_the_line_segment_my3(self, input_, expected):
        assert length_of_line_my3(input_) == expected

    @pytest.mark.parametrize('input_, expected', test_data)
    def test_length_of_the_line_segment_best(self, input_, expected):
        assert length_of_line_best(input_) == expected

Profile

In [ ]:
 

Disassemble

In [ ]:
 
In [ ]:
 
In [ ]:
 
Comments powered by Disqus