array

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

JS: Copy array vs Reference

Normally when you pass Arrays around in JavaScript and in every other language they are passed by reference. That is a sane default, but sometimes you want to use or make a copy, so that original is not modified when we do changes.

Here is how by-reference work :

a = [1,2,3,4,5]

b = a
b[2] = 55

console.log(a)

------

[ 1, 2, 55, 4, 5 ]

… changing b changes a too.

But if we copy the array a stays the same.

Below I present two ways to copy Arrays in JavaScript via slicing or using the splat/triple-dot-operator.

a = [1,2,3,4,5,[6,[7],8],9]

b = a.slice()
b[2] = 55

console.log('slice-copy : ')
console.log(a)

a = [1,2,3,4,5,[6,[7],8],9]

b = new Array(...a)
b[2] = 55

console.log('... copy : ')
console.log(a)

-----

slice-copy : 
[ 1, 2, 3, 4, 5, [ 6, [ 7 ], 8 ], 9 ]
... copy : 
[ 1, 2, 3, 4, 5, [ 6, [ 7 ], 8 ], 9 ]

This also works for objects/hashes

a = { 'key1' : 'val1', 'key2' : 'val2' }

b = a //reference

b['key1'] = 'val55'

console.log(a)

a = { 'key1' : 'val1', 'key2' : 'val2' }

b = { ... a } //copy

b['key1'] = 'val55'

console.log(a)

-----

{ key1: 'val55', key2: 'val2' }
{ key1: 'val1', key2: 'val2' }

Pretty printing 2D python/numpy array

Below I show you quick and dirty way to print 2D array Column and Row labels/indexes. It is often more convenient to have those available so you can easily track visually the results of operations.

First lets try with numpy array :

import numpy as np
import pandas as pd

a = np.random.randint(0,100,(5,5))

print(a)

print()
print(pd.DataFrame(a))


print()
print(pd.DataFrame(a,columns=['A','B','C','D','E']))
[[70 40 64 22 91]
 [82 41 35 42 19]
 [21  7 42 63 85]
 [26 43 23  1 34]
 [44 79 88 46 62]]

    0   1   2   3   4
0  70  40  64  22  91
1  82  41  35  42  19
2  21   7  42  63  85
3  26  43  23   1  34
4  44  79  88  46  62

    A   B   C   D   E
0  70  40  64  22  91
1  82  41  35  42  19
2  21   7  42  63  85
3  26  43  23   1  34
4  44  79  88  46  62

Of course it is similar for normal Python arrays :

import numpy as np
import pandas as pd

b = [[1,2],[3,4]]

print()
print(pd.DataFrame(b,columns=['A','B']))
   A  B
0  1  2
1  3  4

here if you are too lazy to type : https://onecompiler.com/python/3xm3ms6fb

Managing CSS colors with JavaScript

When you work with colors with JavaScript you have to use the rgb-format. But when you extract colors you get back the color as a string.

So I wrote several utility Functions to manage rgb colors.

function getbg(id) {// get background color
  let el = document.getElementById(id)
  let rgb = window.getComputedStyle(el).backgroundColor
  return rgb
}

function setbg(id,rgb) {// set background color
  let el = document.getElementById(id)
  el.style.backgroundColor = rgb
}

function rgb2ary(rgb_str) {
  return rgb_str.substring(4,rgb_str.length - 1).split(/,\s*/).map(a => Number(a))
}

function ary2rgb(ary){ return 'rgb(' + ary.join(',') + ')' }

function rand3() {
  return Array.from({length:3}, (_,x) => Math.floor(Math.random() * 255))
}

function rand_rgb() {return ary2rgb(rand3())}

here are some examples of how to use them :

> rand3()
[251, 1, 161]

> rand_rgb()
'rgb(25,120,161)'

> rgb2ary(rand_rgb())
[240, 137, 194]

> ary2rgb(rgb2ary(rand_rgb()))
'rgb(66,165,150)'

> setbg('abc',rand_rgb())

> getbg('abc')
'rgb(78, 43, 152)'