heinrichmartin <
martin....@frequentis.com> writes:
> On Thursday, April 18, 2019 at 12:59:08 PM UTC+2, Cecil Westerhof wrote:
>> I wrote a script to calculate the smallest numbers of a given
>> multiplicative persistence.¹
>
> Tcl's EIAS is definitely a benefit here, but note that this yields
> shimmering, which impacts performance. In other words: just because
> integer-number conversions are not explicitly coded, it does not mean
> they are not performed. The question is whether this back and forth is
> efficient.
>
>> One proc I wrote is:
>> proc getMultPers {number} {
>> set multPers 0
>> while {[string length ${number}] > 1} {
>
> while {9 < $number}
I do not see a performance improvement, it could even be a little
slower. I find my code more clear, so for the moment I keep my code.
Normally I find clearness more important as efficiency. Only when code
becomes a lot faster, or needs a lot less memory I would use less
clear code.
>
>> incr multPers
>> set value 1
>> foreach {digit} [split ${number} {}] {
>> set value [* ${value} ${digit}]
>
> note that not everybody imports ::tcl::mathop ...
It is part of my program. But a good point.
>
>> }
>> set number ${value}
>
> set number [::tcl::mathop::* {*}[split $number {}]]
That is much more clear. Shows that it never hurts to let someone else
give a look.
>> Can this be improved upon?
>
> What's the criterion? You mentioned "benefits of Tcl" - so I suggest
> showcasing.
I should have mentioned those.
First I want code be clear.
Only after that I am interested in CPU or memory performance. Or the
benefit should be huge.
For example my program uses sort scan and generate.
Sort is the most clear, but scan is not much less clear and needs a
little more as 50% of the time.
But when I generate potential numbers the improvement is huge.
Immediately and long term.
With sort it is O(n log n), with scan O(n) and generate O(log n).
When calculating for ** 10 10 the needed time in minutes:
888
523
1 SECOND
With generate ** 10 25 takes 22 minutes. The other two I did not run
beyond ** 10 10. ;-)
> proc getMultPers {number} {
> # TODO reject negative numbers
I generate the numbers, so in this case I do not need to check them.
> for {set res 0} {9 < $number} {incr res} {
> set number [::tcl::mathop::* {*}[split $number {}]]
> }
> return $res
> }
>
> This might even be more efficient than yours, but I have not
> benchmarked it.
The performance is about the same, but I find this solution more
elegant.