Product of consecutive Fib numbers - how to cache?

So, if I understand your post correctly:

  1. TCO is the optimal way to solve this issue
  2. ETS cache
  3. normal use of memory

Did I get it right? ( first time seeing a mix profile script, I don’t know what ACC nor OWN mean and I may have gotten the wrong conclusions )

Also, I don’t get it. My naive solution uses TCO, why is it not as fast as yours?

    defp fibonacci(0), do: 0
    defp fibonacci(1), do: 1
    defp fibonacci(n) do
        fibonacci(n-1) + fibonacci(n-2)
    end

I also tried that but the cache was being lost among the stack. Really a hard problem to solve so I had to abandon it.

As for your 1st solution:

  1. Why use Map.fetch instead of Map.get?
  2. Community recommends n = input |> String.to_integer should be n = String.to_integer(input)

As for the second:

  1. Why use an Agent? Agents are mini GenServers, which are used to receive and send async messages over several processes. Did you really need one here?

Yes, the speed is horrible, but I find the fact that I have more exercises and a somewhat active community more enticing than trying Exercism.io, which has just dropped the mentorship program for half its exercises …

I mean, the whole point of Exercism is the mentor program, if you can’t be mentored, then why bother to download and run things locally on my machine when I can do it online without any hassle in the competition?

On the other hand, Codewars is not slow for the paying customers. Not sure if I agree, but if you want speed,joining the Red tier definitely is the only solution. However since I didn’t try it I can’t recommend it and I don’t think that putting a paywall between a user and an acceptable user experience is a good thing either. Good UX should be the default.

Not to mention the random crashes. Most of the time I am afraid to click a link. I am curious though, are you a DEV in CodeWars?
CW is still generating money with the Red tier ( apparently ) shouldn’t it be enough to at least give most users a decent user experience?

@Qqwy

## Examples:


    iex> Sequences.fibonacchi |> Enum.take(5)
    [1, 1, 2, 3, 5]
"""

I don’t quite get streams here, but if there is one thing I know, it’s that it’s called Fibonacci and not Fibonacchi :stuck_out_tongue:

I still have to read your recommended post on the Y combinator, but so far thanks for all the help!

No mentorship programm was dropped. Only current side exercises in the queue were dropeed and the side exercises were made Opt-In. With a restriction how many side exercises can be in the queue from a single user.

This makes you able to choose which side-exercises you want to actually receive feedback for, and also priotize it. While at the same time, queuelength is less overwhelming for the mentors.

We learnt during the last months that most users do not actually care for feedback on the side exercises, so why keep them in the queue to exhaust the mentors?

So if you want feedback on a side exercise, just re-add it to the queue. If you can’t just open a ticket at GitHub - exercism/exercism: Crowd-sourced code mentorship. Practice having thoughtful conversations about code..

Sorry, I do not pay a single cent for a page which has 20+ seconds of load times between pages, which do only do a partial page load.

I won’t pay for a service that for some exercises gives me time outs after 12 seconds, sometimes with 3 tests run sometimes with 50.

I won’t pay for a service that wont give me any additional benefits for paying than having a usable site.

As far as I can tell, I can’t even put a link to my CW profile in my CV to showcase my samples.

Also some of the exercises require you to write unidiomatic code to win.

Lets just consider this one, which requires you to return a list of a fixed length, where each item has a certain meaning. In elixir this is much more idiomatically expressed in a (tagged) tuple or a struct.

CW has just added more languages and buzzwords as far as I can tell, but doesn’t seem to have considered idioms of the languages when implementing/translating the testcases. This gets even more obvious when you look at the solutions of their implementors. Those are often even more unidiomatic and simply look like python which got translated into elixir word by word.

CW, if at all, is a platform I’d only recommend to programmers that are already skilled and searching for some katas to do their daily 5 minutes of training, sideprojecting or similar, but absolutely not to a beginner who wants to learn a language from scratch

3 Likes

The idea of Exercism.io is to get mentorhsip on all. Most people don’t join it thinking “I would like to have 3 out of 100 exercises mentored”. They usually want it all. Also, side exercises make up the majority of exercises Exercism has to offer. So when I said half, I was actually being nice :stuck_out_tongue:

This is contradictory. How comes users don’t care for feedback on side exercises and yet the majority of the reviews pending were on side exercises?

An understandable choice.

I believe you actually can ( check profile badges ):

Something I hate. But good luck convincing the authors. Just like Exercism, CW is a community effort. You don’t have to do all exercises and if you want you can fork a Kata and make a better one.

Yet, the vast range of exercises make it better than Exercism IMO. I don’t even understand what half of the side exercises in Exercism want from me and when I do the classification is all over the place. I still remember the Ceaser Cipher one. Right after Hello World, they bombard you with Guards and in some cases String binaries without ever introducing them.

In CW, I can choose from a plethora of different exercises. Their difficulty was decided by the community ( an average ranking ). It doesn’t matter which ones I pick, I can always progress.

Now, I would recommend CW, but only if in conjunction with an active community, like this one. Otherwise, it can be harsh.

Because that was before making them opt in. When actually every side exercise was put into mentoring queue automatically.

2 Likes

No it isn’t, that is body recursive:

  • first fibonacci(n-1) is calculated.
  • second fibonacci(n-2) is calculated
  • both values added together once they are available and then finally that value is returned.

This is tail recursive:

defp fibonacci(_, acc, i, n) when i == n,
  do: acc
defp fibonacci(fi_2, fi_1, i, n) when i < n,
  do: fibonacci(fi_1, fi_2 + fi_1, i + 1, n)

def fibonacci(0),
  do: 0
def fibonacci(1),
  do: 1
def fibonacci(n) when n > 1 and is_integer(n),
  do: fibonacci(fibonacci(0), fibonacci(1), 1, n)
  • there is no need to put the values on the stack because it can be simply replaced with the result from the last function call.

Ultimately the proposed solution looks very similar to this.

4 Likes

There is an updated version that improved the performance of the Map version:

  • Fib.ets/2: 23.314 ms
  • Fib.mem/2: 23.493 ms
  • Fib.lco/1: 26.574 ms

Essentially adding a value at a time with Map.put/3 was too slow. It was faster to collect all the new values as key value pairs in a list and add them all at once with :maps.merge/2.

new_mem =
  kvs
  |> :maps.from_list(kvs)
  |> :maps.merge(mem)

fprof

  1. pretty sure I was using it just to make things crash while I was coding it. Other than the last one which is used for pattern matching on the function.

  2. Honestly the only reason I used an agent was as a programming exercise on how they work

1 Like

Sadly, this is not true. Paying users get some additional features, but that’s the only difference.

I work for the company behind Codewars. I didn’t develop Codewars, but I’m taking over it and will be working on a new version.
I was happy to see Codewars mentioned on ElixirForum, but was also really embarrassed about the performance at the same time and had to say something about it.

I agree. This is especially true for Elixir kata. Also, some languages have a series for beginners, but Elixir doesn’t have one yet.


@Fl4m3Ph03n1x @NobbZ Thanks for your feedback. I’m not going to reply further since this topic is about a specific kata, but I appreciate it.

2 Likes

It’s not TCO though? At all? The last operation is an addition after it’s called two functions (itself) so it can add the result, thus meaning it is not TCO’able?

If the site takes >30 seconds to load, no pay thing would help anyway as the user would never even see it to begin with. :wink:

They do say you get more speed:

Maybe it doesn’t work as advertised.

Would lose to see some news about this. If anything changes or you need feedback, feel free to create a post in this forum and mention me via the @Fl4m3Ph03n1x tag. I will be excited to pop in.

I have been a moderator in Codecademy so who knows, maybe I can help with some feedback when the time comes.

You are correct. It is not TCO. It was a mistake I did.

1 Like

of course you can make it better than O(n)

when A(n) = [[fn+1, fn] [fn, fn-1]] and A(0) = [[1,1][1,0]]

fn can be computed by the nth power of A(0) which is O(log n)

I didn’t knew. Also I’m not pretty sure if I do understand your notation. Can you please get a lit bit more into the details?

ok I’ll try to do better

f0 = 0, f1= 1, f2=1 and so forth

if the matrix A = [[1, 1], [1, 0]]
then A^n is [[fn+1, fn], [fn, fn-1]]

furthermore the mutiplication is associative and we can compute A^n like this

def power(A, 0), do: A
def power(A, 2*N), do: square(power(A, N))
def power(A, 2*N+1), do: mult(square(power(A,N), A)) # that's why we need associvity

this can be optimized of course, like here
https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Fibonacci_Number_Program#Exponentiation_by_squaring