I need help with a kata

Hi, I’m really confused about this problem and why my code is wrong.

First, here is the link: https://www.codewars.com/kata/5ca3ae9bb7de3a0025c5c740/train/python

Here is my code that has errors:

from fractions import Fraction
def point(a, b):
    foo = (a,b)
    return foo
def fst(pt):
    return pt[0] 
def snd(pt):
    return pt[1]
def sqr_dist(pt1, pt2):
    return (pt2[0] - pt1[0]) **2 + (pt2[1] - pt1[1])**2
def line(pt1, pt2):
    slope = ((pt2[1] - pt1[1])/(pt2[0] - pt1[0]))
    slop1 = Fraction((pt2[1] - pt1[1])/(pt2[0] - pt1[0]))
    print(slop1.denominator)
    n = (pt2[1] - (pt2[0] * slope)) 
    l = slope 
    m = 1 
    return [l, m, n]
1 Like

Your point function doesn’t need a variable. Simply return the two parameters. They will be packed in a tuple…

def point(a, b):
    return a, b

def distance(a,b):
    x1, y1 = a
    x2, y2 = b
    return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5

def slope(a, b):
    x1, y1 = a
    x2, y2 = b
    return (y2 - y1) / (x2 - x1)

def yintercept(a, m):
    x, y = a
    return y - m * x

def xintercept(m, b):
    return -b / m

A = point(3, 6)
B = point(8, 12)

d = distance(A, B)
m = slope(A, B)
b = yintercept(A, m)
r = xintercept(m. b)

What other information do you need?

slope can be written to return the fraction,

>>> def slope(a, b):
    x1, y1 = a
    x2, y2 = b
    return Fraction((y2 - y1), (x2 - x1))

>>> slope(A, B)
Fraction(6, 5)
>>> m = slope(A, B)
>>> delta_y = m.numerator
>>> delta_x = m.denominator
>>> delta_y, delta_x
(6, 5)
>>> float(delta_y) / delta_x
1.2
>>> 
1 Like

For some reason I keep getting “The points should be callable”

It wants

print(callable(point(3,4))) —-> True
>>> def a(x, y):
	def f():
	    return x, y
	return f

>>> b = a(3, 4)
>>> b()
(3, 4)
>>> callable(a(3, 4))
True
>>>
2 Likes

It actually works! Is it because the function a is a reference to the function f?

2 Likes

The function a is a factory for f, the returned function that stores the parameters as constants.

If we wanted we could have that function take parameters of its own, but that will take a little thought to drum up a decent example.


>>> def mod(d):
	def f(x):
		return x % d    # d is a constant in f(x)
	return f

>>> parity =  mod(2)
>>> parity(15)
1
>>> parity(12)
0
>>> quad = mod(4)
>>> quad(22)
2
>>> quad(24)
0
>>> 

Of course we wouldn’t want to have a soup kitchen full of various mod functions. In fact this sort of function is most useful when it is transient (very short lived) in nature. A one-off sort of thing. We could call it from within an expression or another function where it would dynamically suit its purpose and be done with.

Pretty sure I’ve explored this last year, or earlier this year. Will dig around and attempt to find the topic.


The article may need some fixing up or better examples, but all in good time. For instance, is this a factory function, or a function factory? Or are they both the same thing. Something to read up on.

Function Factory Basics

In the example I used f as a list of numbers within the returned foo map that are all divisible by some number x.

foo has no real meaning other than to generate the same list over a given range.

The equation itself is just random, and may or may not even have any zeroes (I’ve never checked, edit: it has three zeroes and is symmetrical about both axes, as it turns out. My algebra is rusty, these days. It’s actually 2x^3 - 4x, when simplified.).

Factory functions sound complicated! And indeed a soup kitchen. And how how could I write a function that returns the x coordinate, but the original point function must be passed in as an argument with a coordinate for example:

Def xcord(pt):

#returns x coordinate 

#call

print(xcord(point(3,7))) ——>  3

Don’t ask me why. The exercise I’m doing likes making things complicated. Like, why not just pass in a coordinate by itself and return x or y.

There is every likelihood these are in frequent use in production code due to their dynamic nature as we saw earlier.

BTW

Factory functions return an Object, Function factories return a function. Granted, functions are objects, but objects are not necessarily functions.

def xcoord(a):
    def f():
        x, y = a()
        return x
    return f

The call would look like,

x = xcoord(point(3, 7))
print (x())

Not tested, but try it out and see what happens.

>>> def point(x, y):
	def f():
	    return x, y
	return f

>>> def xcoord(a):
        def f():
            x, y = a()    # invoke point_f
            return x
        return f

>>> x = xcoord(point(3, 7))
>>> x()
3
>>> 
def point(x, y):
	def z():
	    return x, y
	return z

def xcoord(a):
    def f(x):
        x, y = a()
        return x
    return f
    
print(xcoord(point(3,4)))

It returns: <function f at 0x10c73f2e8>

Because it is a function. It needs to be invoked.

print(xcoord(point(3,4))())

I got a type error

print(xcoord(point(3,4))())

TypeError: f() takes exactly 1 argument (0 given)

1 Like

You can pass in anything at it will return 3. But you can’t pass in nothing. I hope it can pass

My mistake, f function should not have a parameter. See my earlier post where I corrected it.

def f():
1 Like

@mtf & @jaccobtw, I apologize for butting in, but I couldn’t resist sharing a new(to me) insight.

First, thanks to @mtf for the discussion on Factory Functions, something entirely new to me, and maybe tangentially, at least, related to decorators, something I’ve never really been able to retain for more than ten minutes or so. I’m definitely going in for more.

Now, for a different track, it seems to me that this exercise cries out for a Point() class that contains all the required methods, get_x(), get_y(), distance(), line(), etc. (It could obviously be extended to plot points and more),

BUT…

… that first point() thingy (ok, object) must be callable. That had me going, then I had an idea:


class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def get_self(self):   # This is what makes it work
        return self
    def get_x(self):        
        return self.x
  #  ...etc...

def point(a,b):
   return Point(a,b).get_self   # No parentheses, so a callable method

a = point(3,4)
print(callable(a))
print(a().get_x())

Output:

True
3

The methods are all straightforward. The only strange thing is using a() rather than a as an argument, but each Point() object instantiated via point(a,b) is indeed callable!

3 Likes

The thought of creating a class came up early but I opted to stick with plain functions for the sake of proving out the mechanics. there may be pros and cons, such as memory management or perhaps overkill. If we only have two points, do we need a class? (Rhetorical question.)

3 Likes

You can make the objects themselves be callable by implementing __call__ (rename your get_self)

def point(a, b)
    return Point(a, b)  # a Point is callable

except that now Point and point behave the same, so it should just be the class.
You might run into the sillyness that the return value when you call it is completely ignored, this is why you might want to use functions instead, and to instead send the information through the return value.


I solved it by letting my function accept a third value indicating whether the first or second value should be returned:

def point(a, b, msg):
    if msg == 'fst':
        return a
    if msg == 'snd':
        return b

Of course, that leaves out a whole lot of magic allowing it to be called multiple times until it has received 3 arguments:

point()()()()()(3)()()()(4)()()()()()()('fst')  # 3
point()()()()()(3)()()()(4)()()()()()()('snd')  # 4
point(3, 4)('fst')  # 3
point(3, 4, 'fst')  # 3
p = point(3, 4)
p('fst') # 3
p('snd') # 4

# trying to print this intermediary value doesn't make much sense.
point(3, 4) # functools.partial(<function curry.<locals>.deco.<locals>.wrapper at 0x7f1744d7a2f0>, 3, 4)

To that end I’ve got another function which keeps creating and returning new functions each time it is called, until all arguments have been received, at which point the answer is returned instead of another function. (Yes, it is a decorator)

def curry(...)
    ...

@curry
def point(a, b, msg):
    if msg == 'fst':
        return a
    if msg == 'snd':
        return b
2 Likes

@patrickd314 and @mtf
Hey, I really appreciate you guys help. I couldn’t have done any of this without you guys. And not just for this problem but ever since I started coding about 3 months ago. Both of you guts have helped solve and learns tons of code. I deeply appreciate it.

On another note, you’re right, point(a,b) is callable and that problem is solved (at least for now!). Now, I have to somehow get the function to return what its supposed to return but from the function itself. This is what I mean. If I am correct the exercise wants this:

xcord(point(3,4))----> 3

When I try this I’ve been getting:

xcord(point(3,4))---->  <function fst.<locals>.f at 0x7fc330f71b70> should equal 3
ycord(point(3,4))----> <function snd.<locals>.f at 0x7fc330f71bf8> should equal 4

Even when I include:

a = point(3,4)
print(callable(a))
print(a().get_x())

It doesn’t seem to register it as answer

Here is the link if you need more clarity on the problem itself:
https://www.codewars.com/kata/5ca3ae9bb7de3a0025c5c740/train/python

Thanks again

1 Like

Recall that it needs to be invoked.

Disclaimer

TBH, I did not look at the kata, and instead worked intuitively off the problem information given, and then in a vein where it wasn’t a proposed solution, as much as a pattern to follow.


Love that @ionatan has piped in with some definitive insight.

The kata doesn’t look at all at what point(3, 4) returns, meaning it can return anything you want, including no information at all. You can use that return value to pass information to fst and snd when fst/snd calls the callable point.

But your fst/snd functions should return concrete values, if you look at the string representations you have there, they do say that they’re functions. When you return from xcord/ycord it should be with the concrete value.