Friday, 24 June 2022

You actually CAN print multiple lines into a file using (a single, meaningful line of) bash

But why it's got to get so complicated ... :)

 

Anyway, note:

echo -e "Hello \nWorld \n" >> greetings.txt

 

Or, alternatively just output each line with a separate echo statement and printing to append with the >> piper.

SO: shell - how to pipe commands in ubuntu


Sunday, 19 December 2021

Note to self: Don't slack out because "it's just a prototype"

At least when it's near-trivial to come up with some good design concerns, applying them is effortless...

... well, it turns out just now that about 5 minutes of thinking could have saved - albeit hypothetical - hours of a future DB migration. Even thinking about it I lost like a good 10 minutes :)

There are mitigating circumstances (it's just a "plug-in" until it turns out whether it's worth buying the proper dedicated tech or not - maybe won't ever be needed), but things could be much better too easily.

A poor design/bad implementation can spread in the form of bad practice afterwards... better choices are less likely to end up doing that. 

Even if not doing two ful lrounds, think 1½ times at least 😏

Sunday, 14 November 2021

When you don't know something, but ...

 ... virtually nobody uses it.

Should remind myself that one GitHub search  can save a lot of sanity for the rest of the day :) Before I get stuck in "how come I never heard about it? what else don't I know? Google up something else to be worried about + repeat  👍" mode.

So this thing from the defer module was mentioned in relation to the Python generators' .send() method .. hm ... actually now I (believe I) see that's a package! Last released in 2012. Right, good. Move on.

https://github.com/search?q=inline_callbacks+language%3Apy&type=code

Thursday, 4 November 2021

Not posting too often anyway these days :)

Doing some katas, prime factorization of n! is once again a small fun problem to have a go at. I wonder how many equal solutions are out there :) anyway, creating a max prime divisor map instead of the standard Eratosthenes' was an interesting twist of mine (?) so I thought I'd capture it. For the betterment of my audience of 0 people I guess : ))

from collections import Counter

from typing import Dict, List, Tuple
from functools import lru_cache
import math


def max_prime_divisors(n) -> List[int]:
    # A slight variation of Erathosthenes' algorithm

    # Find and return max_prime_divisor[i], i = 0..n
    # true divisors: 1 and n itself are excluded
    # could be nicer with numpy arrays? :)
    ans = [None] * (n + 1)

    for k in range(2, len(ans) // 2 + 1):
        if ans[k] is None:
            i = k * 2
            while i < len(ans):
                ans[i] = k
                i += k

    return ans


def decomp_nr(n, mpd) -> Dict[int, int]:
    # return value is in prime -> count form
    ans = []
    while mpd[n]:
        d = mpd[n]
        ans.append(d)
        n = n // d
    if n >= 1:
        ans.append(n)

    return Counter(ans)


def format_decomp(d):
    factors = [f"{key}^{count}" if count > 1 else f"{key}"
               for key, count in sorted(d.items())]
    return " * ".join(factors)


def decomp(n):
    # decompose factorial
    mpd = max_prime_divisors(n)

    total_decomp = sum([decomp_nr(k, mpd) for k in range(2, n + 1)], Counter())

    # print("tdc is:", total_decomp)

    return format_decomp(total_decomp)
 
---
 

Update: hm... and despite its appeal to me, that wasn't fast enough :) then went the one with much fewer tiny reusable cogs, and sorted things out.


I'll decide later whether to decide now or later that I'm disappointed. Possibly I'm not :)

 
--- 
 
from collections import Counter
from typing import Dict, List, Tuple, Optional
from functools import lru_cache
import math


def erathosthenes(n) -> List[bool]:
# return is_prime[i], i = 0..n
ans = [True] * (n + 1)

# by convention
ans[0] = False
ans[1] = False

for k in range(2, len(ans) // 2 + 1):
if ans[k]:
i = k * 2
while i < len(ans):
ans[i] = False
i += k

return ans


def decomp_n_fac(n, erat: List[bool]) -> Dict[int, int]:
ans = {}

for p in range(n + 1):
exp = 0

if not erat[p]:
continue

p_pow = p
while p_pow <= n:
exp += n // p_pow
p_pow *= p

ans[p] = exp

return ans


def format_decomp(d):
factors = [f"{key}^{count}" if count > 1 else f"{key}"
for key, count in sorted(d.items())]
return " * ".join(factors)


def decomp(n):
# decompose factorial
erat_map = erathosthenes(n)

total_decomp = decomp_n_fac(n, erat_map)

return format_decomp(total_decomp)
 

 


Python + mutable return + caching: careful

Let's say

from functools import lru_cache                                         
@lru_cache(5) def cached(n): return {}

Beware then, as:

In [3]: cached(1) == cached(1)                                                  
Out[3]: True

In [4]: cached(1) is cached(1)                                                  
Out[4]: True

In [5]: cached(1)[2] = 3                                                        

In [6]: cached(1)                                                               
Out[6]: {2: 3} 
 
So I suppose - further from the attention paid with parameter default mutability - there are times when it's a good idea to put in the effort and return immutable results whenever there's the slightest chance of caching right at the moment or later on (and being inattentive :) never happens, of course).

Friday, 22 October 2021

No exception "bubbling up" from PySide slots

Demo code:

from PySide2.QtCore import Signal
from PySide2.QtWidgets import QApplication, QDialog


class MyDialog(QDialog):

mySignal = Signal()


def mySignal_handler():
raise Exception("bocs")


app = QApplication()
dialog = MyDialog()
dialog.mySignal.connect(mySignal_handler)
dialog.mySignal.connect(mySignal_handler)

try:
dialog.mySignal.emit()
except Exception as ex:
print("It is still the same exception context.")

Now try to guess the output ... :)

Monday, 5 April 2021

Today's dilemma: PyCharm hints unregister as a typo

 


OK, so of course since it's a completely irrelevant one, I dug into the problem relatively heavily ... cause what else would you do? :D

And here's one debate (2011) with a lot of interesting comments:

meaning - "Unregister" vs "Deregister" - English Language & Usage Stack Exchange


One pulls some good logic in:



it's convention in programming to call an object that hasn't been 'initialised' as 'uninitialised', not 'deinitialised'.

And since what's deregistered has already been registered, it wouldn't be in the same shoes as those things which never had been registered, and would thus be called unregistered.

But then there's some properly defying statistic there ...!
https://i.stack.imgur.com/cMMOS.png



As evidenced, unregister received a substantial boost shortly after the dot-com boom/bust of the late 90s, while deregister usage has been more or less the same throughout.

[...]

Additionally, both the
un- and de- prefixes can be defined as a reversal of action.

Despite the similarities, I'd go with popular usage and use unregister.

I really like that approach in a way. Quantified. Cold, hard facts in this very emotional problem that gets so many carried away. Numbers do tell a lot. Personally, I always 'knew' unregister to be The Word, but as I noticed due to the PyCharm editor hint, I could have equally naturally said deregister right now (outside the context)... so let's move over this bad infection.

Let's get up to date and context specific:

Final word: GitHub says ... yes!

Search · unregister · GitHub vs. Search · deregister · GitHub!

n

Unregister 👍

Deregister 👎

Repos

196

95

Commits

10M+

1.8M+

 

Without looking at the further candidate metrics, I think there's a clear winner here. And that is, the procrastination of actual work ;)