I saw this tweet over the weekendโ
// Detect dark theme
var iframe = document.getElementById('tweet-929715470655254535-889');
if (documen...
For further actions, you may consider blocking this person and/or reporting abuse
I managed to reduce the number of divisions by throwing some mathematics on it. Put very short:
The improvements are:
The computation time for the search up to 10^8 is reduced to 4 % compared to my original code.
I love seeing the iterations of your solutions. Not that this challenge was intended to have any "winners," but if we had to choose...
Do you have any ideas for new #challenge posts?
Thanks. I enjoyed learning about Kaprekar number as well as I enjoyed iterating my solutions as I digged deeper into it.
You encouraged me to pose a challenge, hoping it's not too easy and not too hard. dev.to/heikodudzus/challenge---pri...
BTW: I saw a possible error in my last iteration. takeWhile (<n) is not proven to be correct. It's better to do it that way:
Also, it's nicer to use upper and lower bounds for divisors before computing the devisions. This is proven to be correct now, but I lost speed. ;-) The speed improvement by melting construction and restriction together is only 86% instead of 96%.
Some last improvements:
The improvement steps were: 1000s - 500s - 90s - 60s - 19s - 13s - 9s. Quite funny to squeeze the algorithm like that. :-) This is what I came up with:
I wanted to have it in C for reference. Even expressed imperatively, it is now a very simple and nice algorithm. (2-3s)
C profited more by the additional division, it reduced the execution time by 75%, Haskell profited only by 50 %.
I hope, I'm really done, now. :)
Time to get my repl up and running. Not very clean, but gets the job done. Here's some Clojure:
Thanks to Richard Orelup' tip to zero-pad the number if its length is odd.
Taking inspiration from Thomas Much's answer, I refactored my code to be more functional-esque and idiomatic:
I'm not pretty good at coding but I tried in my own way :) just for fun and I hope is ok.
Here is my JS version:
Here is the JSFiddle link:
jsfiddle.net/kw95nv45/2/
Solution in Haskell:
I didn't want to take the route to String representation and back, I considered it as a computational problem and I wanted to find a purely computational solution. So I used digit values. Drawbacks: It appends number 1 as being kaprekar by convention. Benefit: It works for all bases (although output is decimal).
f is like:
f returns a list of sums of quotient and remainder. Now filter in the solution function, if n is an element of f n.
I tried to compute the Kaprekar numbers up to 108. A simple improvement in taking the interesting part and dropping the rest: If quotient or remainder are > n the sum of both must be > n. This reduced execution time by 50 %.
Could I trouble someone to comment this code? Oops, I guess that's in the parent comment, thanks!I don't know Haskell but I'm interested in it. Does this solution work for the 'strange' ones like 4789, 5292?Trying to wrap my head around how to interpret the definition of a Kaprekar number, in a way that includes these oddball numbers.
I'm currently studying Ruby -- I'll necro-post my Ruby solution if I manage to get it working with the oddballs.
For those a fan of Guile:
As far as I can see, most (if not all) programs use the strategy to convert the square to a string, pad it with 0 if the length is not even, and split it in the middle.
This seems to work for the range of Kaprekar numbers in the given range [1..999]. However, when I tried to speed up my program by splitting in the middle, I found out a problem with 5292. It is a Kaprekar number:
But to recognize it, you have to split 2 and 6 of 8 digits.
The implicit assumption about the Kaprekar property to show up when the number is split in the middle seems to be wrong. I tested some Javascript programs of this challenge with 5292 and it is not recognized as Kaprekar number.
Dang, that's a great point. I should have made the OP more detailed to clarify that the "split" isn't always right down the middle โ even if it happens to work in the [1...999] range.
I definitely didn't think of that possibly while creating the post, or while working on my personal solution.
What does your approach to this look like? Now you've got me curious about how you're going about solving it.NVM, now I see your other comment.Is anyone interested in finding another 'strange' Kaprekar number like 5292?
I searched among the first 91 Kaprekar numbers in the range [ 1..108 ]. So far, 5252 is the only one you have to split asymmetrically.
What makes 5292 so special?
4879 is 'strange', too:
4879 = 238 + 04641
Ok, I see. I've missed it because of the leading zero in the second part.
I think your OP is really ok. I also didn't expect something like this. I think I will inspect some higher Kaprekar number.
But I am looking forward to see how the JS/Java/Clojure/LISP-like solutions get fixed (and I apologize for beeing such a killjoy ;-)
Here is my Javascript version of Kaprekar numbers
OK - this was way more of a rabbit hole than I thought... :) Here's two, new (F#) and old (COBOL). Both of these work within the constraints of the initial challenge, but will fail outside of that; had I not spent the amount of time I already spent on these, I might have at least made the F# version be able to handle others.
p.s. 0 also fits the description from the tweet! (02 = 0; 00 = 0 + 0 = 0; 0 = 0)
F#
COBOL
(Free format, "*>" denotes a comment)
OK - fixed format, just for grins...
(Fixed format: col 1-6 reserved, usually line numbers or blank; col 7 - "*" = comment, blank otherwise; col 8-11 - division/section identifiers, paragraph names, top-level data items; col 12-72 - executable code, data item sub-definitions; col 73+ - ignored)
Holy cow - the formatter knows COBOL! If I'd used fixed format, it wouldn't even look weird.
This was a lot harder than I thought mainly because I had to look up why some numbers were and weren't Kaprekar numbers because the above description doesn't include all the details. First gotcha is the second part of the split numbers must be positive (no zeros). The second part was that you add a zero to the front if the length is odd.
And I already refactored my answer. I'm happier with this one.
Awesome job refactoring, and apologies for not including the pertinent info re: zeros in the OP!! I'll add that info to the main post.
Ok, here's a Java 8 version:
As Heiko points out, the solution was incorrect, because the split was always done in the middle of the string...
So, here's a (hopefully correct) Java 9 solution (Java 9 because I use takeWhile):
I chose to output the first 16 numbers so we can see the output includes numbers 4879 and 5292.
I really like to see your use of Streams and lambdas solving this problem. Nice occasion for me to learn a little bit more about them.
Seems I'm pretty late for this, but anyway, here's some Rust solution:
And if you consider that parts of a number should not necessarily be of equal size, the solution becomes a bit more wordy (suppose, a lot can be improved here):
I have much sympathy for LISP and Clojure but have not that much experience with it. So, to stay in touch with it, here is my Clojure program, mostly a one-to-one translation of my latest Haskell program:
I really like the threading macros. :-) Computing up to 10^8 , the execution time of the jar file is ten times the execution time of the compiled Haskell. Did I make a serious mistake, performance-wise? Of course, there is the JVM, but I didn't expect this program to be slower with factor 10.
Here's my Ruby novice solution -- Works for the known oddballs (4879, 5292, 38962). Prepending '0' to odd-sized numbers inspired by others here.
I don't like the exceptions (4879, 5292, 38962...) -- it feels like they don't belong in the sequence. And look how pretty the code is without them!
Because I haven't done Groovy for a while. I miss it!
Something like this in python
Pythonic mine's:
Usage:
python script.py max
max
is the maximum integer to look up to (3037000499):Figure it's only fair to throw my answer into the ring. Clearly very novice and verbose ๐. Added a number of comments for the other #beginners out there.