programming

SINGLETON factory

You can define Singleton class manually, but if you want to create multiple different Singleton classes on the fly then you can use the function below :

#Factory : to create Singleton classes
def singleton(new_klass, klass): 

	def new(cls, *args, **kvargs):
		if not hasattr(cls, 'instance'):
			cls.instance = klass(*args, **kvargs)
		return cls.instance

	globals()[new_klass] = type(new_klass, (object,), {'__new__' : new})

Progress bar

def progress(percent=0, width=30):
    left = width * percent // 100
    right = width - left
    print('\r[', '#' * left, ' ' * right, ']',
          f' {percent:.0f}%',
          sep='', end='', flush=True)

Bi-directional dictionary

import os
import json

class BiDict(dict):
	def __init__(self, *args, **kwargs):
		super().__init__(*args, **kwargs)
		self.inverse = {}
		for key, value in self.items():
			self.inverse.setdefault(value,key) 

	def __setitem__(self, key, value):
		if key in self : del self.inverse[self[key]]
		super().__setitem__(key, value)
		self.inverse.setdefault(value,key)		

	def __delitem__(self, key):
		value = self[key]
		if value in self.inverse : del self.inverse[value]
		super().__delitem__(key)

	def pop(self,key):
		value = super().pop(key)
		self.inverse.pop(value)
		return value

	def load(self, path, name):
		assert os.path.isdir(path), f'dir: {path} does not exists'

		full = f'{path}/{name}'
		with open(full,'r') as fh : self.__init__(json.load(fh))


	def save(self, path, name):
		assert os.path.isdir(path), f'dir: {path} does not exists'

		full = f'{path}/{name}'
		with open(full,'w') as fh :
			json.dump(self, fh, sort_keys=True, indent=2)

class AttrBiDict(BiDict):
	def __init__(self, *args, **kwargs):
		super(AttrBiDict, self).__init__(*args, **kwargs)
		self.__dict__ = self

	def __hash__(self): return hash(str(self))
	def __eq__(self,other): return self.__hash__() == other.__hash__()

Generate all permuted pairs in all positions

The question is how to generate all permutations of sequence of numbers. The caveat is to generate the numbers in all positions i.e. [X,Y] and [Y,X], but best to show how it works …

:- initialization(main).

%% for list of items
ppairs(Lst,[A,B]) :- 
   is_list(Lst), length(Lst,N), 
   between(1,N,X), between(1,N,Y), nth1(X,Lst,A), nth1(Y,Lst,B).
%% for numbers
ppairs(N,Pair) :- integer(N), ppairs(1,N,Pair).
ppairs(From, To, [X, Y]) :- between(From, To, X), between(From, To, Y).

main :- 
  %% all pairs of 1 .. 3
  findall(P,ppairs(3,P),L), write(L), write('\n'),
  %% all pairs of a,b,c
  findall(P2,ppairs([a,b,c],P2),L2), write(L2).


----

[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
[[a,a],[a,b],[a,c],[b,a],[b,b],[b,c],[c,a],[c,b],[c,c]]

Java : chop and chomp

Perl have very handy Functions to clean up trailing garbage in Strings …

  • chop : deletes the last character of a string. Useful when you append delimiter in a loop, so that the last addition has to be cleaned up
  • chomp : removes trailing sequence of the same character. if the character/s at the end do not match the specs nothing is deleted. Useful to cleanup new-lines/s at the end. Normally happens when reading from file.

Here are those useful Functions implemented for Java :

public class Main {
  
  public static <ARG> void say(ARG arg) { System.out.println(arg); }

  //removing trailing characters
  public static String chomp(String str, Character repl) {
    int ix = str.length();
    for (int i=ix-1; i >= 0; i-- ){
      if (str.charAt(i) != repl) break;
      ix = i;
    }
    return str.substring(0,ix);
  }
  
  //default case, removing trailing newlines
  public static String chomp(String str) {
    return chomp(str,'\n');
  }  

  //hardcut  
  public static String chop(String str) {
    return str.substring(0,str.length()-1);
  }
  
  public static void main(String[] args) {
    say(chomp("hi...",'.'));
    say(chomp("hello\n\n",'\n'));
    say(chomp("hello\n\n"));
    say(chop("howdy."));
    say(chomp("hi...++",'.'));      
  }
}

------

hi
hello
hello
howdy
hi...++

Timing code

This one is quick.

Java

Here is how you do it :

import java.lang.Thread;  

public class Main {
  public static void main(String[] args)  throws Exception {
        
    long startTime = System.nanoTime();
    Thread.sleep(3000);
    long endTime = System.nanoTime();
    //divide by 1000000 to get milliseconds.
    int duration = (int) ((endTime - startTime) / (1000000 * 1000));  

    System.out.println("it took: " + duration + " secs");
  }
}

-----

it took: 3 secs

Prolog

?- numlist(1, 100, L).
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].

?- time(numlist(1, 100, L)).
% 105 inferences, 0.000 CPU in 0.000 seconds (94% CPU, 1126344 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].

Python

For Python look at this post : Timing code execution

Split a List in pieces

How would you SPLIT a List in pieces of specified length ? …. Here is how :

:- initialization(main).

say(L) :- write(L), write('\n').

%%this illustrates how to pick part of a List
firstN(Lst,N,FirstN) :- length(FirstN,N), append(FirstN,_Rest,Lst).

split([],_,[]) :- !.
split(Lst, N, [FirstN|Res]) :- 
   length(FirstN, N), append(FirstN, Rest, Lst), !, split(Rest, N, Res).
%%when the last piece is smaller than the requested size
split(Lst, N, [Lst]) :- length(Lst, Len), Len < N.

main :- 
L = [1,2,3,4,5,6], say(L),
firstN(L,5,F), say(F),
split(L,2,L2), say(L2),
split(L,3,L3), say(L3),
split(L,4,L4), say(L4).

----

[1,2,3,4,5,6]
[1,2,3,4,5]
[[1,2],[3,4],[5,6]]
[[1,2,3],[4,5,6]]
[[1,2,3,4],[5,6]]

Arrays in Prolog

Prolog variables are immutable. for this reason there is no builtin array type.

For Arrays implemented using Prolog OOP check here

Think about it to support backtracking Prolog have keep the state at every point. First arrays can be big and vector operations can involve elements all over the place. So keeping track is not just inefficient, but also very complex.

For this and other reasons Prolog does not support standard type of arrays.

That is all good and stuff, but what if you still need simple small array !?
The obvious way to implement it is to use Lists, but because the access to elements is sequential the implementation will be slow.

Instead we will do it in a more hacky, no-no method, by using Terms instead of Lists. We do that by employing arg and setarg. The difference is that they allow direct access ergo implementation will be fast.

Below you have simple API that support 1D and 2D arrays.

:- initialization(main).

say(X) :- write(X), write('\n').
say(D,X) :- write(D), write(X), write('\n').

ary1d_new(Size,Sym,Ary) :- 
	functor(Ary,a1,Size), 
	forall(arg(X,Ary,_), nb_setarg(X,Ary,Sym)).
ary1d_get(Pos,Ary,Val) :- arg(Pos,Ary,Val).
ary1d_set(Pos,Ary,Val) :- nb_setarg(Pos,Ary,Val).

ary2d_new(Rows,Cols,Sym,Ary) :- 
	functor(Ary,a2,Rows), 
	ary1d_new(Cols,Sym,Row),
	forall(arg(X,Ary,_), nb_setarg(X,Ary,Row)).
ary2d_get(X,Y,Ary,Val) :- arg(X,Ary,Row), arg(Y,Row,Val).
ary2d_set(X,Y,Ary,Val) :- arg(X,Ary,Row), nb_setarg(Y,Row,Val).

main :-
say('1D example : '),
ary1d_new(5,0,A1D),say('new(5) : ', A1D),
ary1d_set(2,A1D,1),say('set(2,1) : ', A1D),
ary1d_get(2,A1D,Val),say('get(2) : ', Val),
say('2D example : '),
ary2d_new(3,3,0,A2D),say('new(3,3) : ', A2D),
ary2d_set(2,2,A2D,1),say('set(2,2,1) : ', A2D),
ary2d_get(2,2,A2D,Val),say('get(2,2) : ', Val),
ary2d_get(X,Y,A2D,1),say('find coord of 1 : ', [X,Y]).

-----

1D example : 
new(5) : a1(0,0,0,0,0)
set(2,1) : a1(0,1,0,0,0)
get(2) : 1
2D example : 
new(3,3) : a2(a1(0,0,0),a1(0,0,0),a1(0,0,0))
set(2,2,1) : a2(a1(0,0,0),a1(0,1,0),a1(0,0,0))
get(2,2) : 1
find coord of 1 : [2,2]
true.

The implementation of 2D array above uses as storage mechanism 1D array for every row.

But there is also possible to use single 1D array for this purpose. In this case to access a cell we would need to transform the 2D coordinate to 1D.

One problem with this is there is no way to guess the dimensions of the 2D array if we use 1D array to represent it. For this reason we will use the first 2 elements of the storage to store those dimensions.

Here is how an implementation will look like :

%% 2D array using 1D storage
a2d_new(Rows,Cols,Sym,Ary) :- 
	Size is Rows * Cols + 2, 
	ary1d_new(Size,Sym,Ary), 
	nb_setarg(1,Ary,Rows), nb_setarg(2,Ary,Cols).
a2d_get(X,Y,Ary,Val) :- 
	arg(2,Ary,Cols), Pos is (X-1) * Cols + Y + 2,
	arg(Pos,Ary,Val).
a2d_set(X,Y,Ary,Val) :- 
	arg(2,Ary,Cols), Pos is (X-1) * Cols + Y + 2,
	nb_setarg(Pos,Ary,Val).
a2d2lst(Ary,Lst) :- Ary =.. [ _,_,_ | Lst].

For Arrays implemented using Prolog OOP check here

Autovivify in Python

Autovivify is simply fancy word for the behavior of creating a dictionary key-value automatically the moment an element is accessed. Python throws an error if the kv-pair was not already created.

Perl hashes/dictionaries are auto-vivified by default, not so for Python, which could be annoying, because you have to do additional checks thus breaking the normal flow of coding.

Here is how you make a auto vivifying Python dictionary and at the same time quick way to create a Tree structure :

from collections import defaultdict
from pprint import pprint

def Tree():
    return defaultdict(Tree)

tree = Tree()
tree['mammal']['ape']['chimp'] = 'bobo'

pprint(tree,indent=2,compact=True)

-----

defaultdict(...,
  { 'mammal': defaultdict(...,
    { 'ape': defaultdict(...,
      { 'chimp': 'bobo'})})})

Even better, if you want cleaner print :

from collections import defaultdict
from pprint import pprint

def Tree(): return DD(Tree)

class DD(defaultdict):
    __repr__ = dict.__repr__

tree = Tree()
tree['mammal']['ape']['chimp'] = 'bobo'

pprint(tree,indent=2,compact=True)

------

{'mammal': {'ape': {'chimp': 'bobo'}}}

Numpy: Filtering by multiple conditions

Apart from using np.where() a different way to filter a numpy array is to use the following syntax :

ary[ condition ]

for example :

ary[ ary > 10 ]

So far so good, but how do you apply multiple conditions. To do this you need to surround all the conditions in brackets as shown below. Also for logical operators you should use the bitwise operators instead.

import numpy as np

a = np.arange(5,15)

print(a)

#one condition
print(a[a > 10])
#multiple conditions
print(a[(a > 10) & (a < 13)])
print(a[(a == 10) | (a == 13)])

-----

[ 5  6  7  8  9 10 11 12 13 14]
[11 12 13 14]
[11 12]
[10 13]