/Pseudolog

My personal collection of open source projects and ideas.

/code/CLM_LIBS

CLM_LIBS.h is set of public domain libraries implemented as code-generating macros.

You can find the CLM_LIBS.h file and all the documentation in the CLM_LIBS repository.

IMPORT_CLM_TIME: time and date related functions

double  
time_elapsed
(clock_t crono)

void    
time_pause
(char* message)

char   *
time_stamp
(int format)

IMPORT_CLM_RAND: random related functions

int     
rand_int
(int n)

size_t  
rand_size_t
(size_t n)

double  
rand_double
(double n)

double  
rand_halton
(size_t base, size_t n)

void    
rand_color
(int *r, int *g, int *b)

IMPORT_CLM_PRINTF: printf helper functions

void    
printf_reset
()

void    
printf_delete
()

void    
printf_set_bold
()

void    
printf_set_light
()

void    
printf_set_strike
()

void    
printf_set_underline
()

void    
printf_move
(int dx, int dy)

void    
printf_set_text_grey
(int grey)

void    
printf_set_back_grey
(int grey)

void    
printf_set_text_color
(int r, int g, int b)

void    
printf_set_back_color
(int r, int g, int b)

IMPORT_CLM_DAMM: checksum functions

char    
damm_dec
(char *txt)

char    
damm_hex
(char *txt)

IMPORT_CLM_ARC4: unsafe cryptographic functions

char   *
arc4_hash
(char *txt, size_t length, size_t drop)

char   *
arc4_encrypt
(char *txt, char *key, size_t drop)

char   *
arc4_decrypt
(char *txt, char *key, size_t drop)

IMPORT_CLM_ITER: combinatorial iterator functions

void    
iter_rand_prod
(size_t **prod, size_t length, size_t *base)

void    
iter_next_prod
(size_t **prod, size_t length, size_t *base)

void    
iter_rand_perm
(size_t **perm, size_t length, size_t base, bool rep)

void    
iter_next_perm
(size_t **perm, size_t length, size_t base, bool rep)

void    
iter_rand_comb
(size_t **comb, size_t length, size_t base, bool rep)

void    
iter_next_comb
(size_t **comb, size_t length, size_t base, bool rep)

IMPORT_CLM_FRACTAL: spacefilling curves

size_t  
fractal_van_der_corput
(size_t base, size_t digits, size_t n)

void    
fractal_lebesgue_coord
(size_t dim, size_t bits, size_t *L)

void    
fractal_lebesgue_index
(size_t dim, size_t bits, size_t *L)

void    
fractal_hilbert_coord
(size_t dim, size_t bits, size_t *H)

void    
fractal_hilbert_index
(size_t dim, size_t bits, size_t *H)

IMPORT_CLM_ARRAY: generic array functions

typedef type *
array

array   
array_new
(size_t length)

void    
array_sort
(array A, size_t length)

void    
array_shuffle
(array A, size_t length)

type    
array_select
(array A, size_t length, size_t rank)

size_t  
array_bisect
(array A, size_t length, type data)

IMPORT_CLM_CLIST: generic singly-linked circular list container

typedef struct clist_s *
clist

bool    
clist_push_front
(clist *list, type data)

bool    
clist_push_back
(clist *list, type data)

type    
clist_pop_front
(clist *list)

type    
clist_front
(clist *list)

type    
clist_back
(clist *list)

IMPORT_CLM_STREE: generic splay tree container

typedef struct stree_s *
stree

type    
stree_root
(stree *tree)

type    
stree_min
(stree *tree)

type    
stree_max
(stree *tree)

type    
stree_pop
(stree *tree)

bool    
stree_next
(stree *tree)

bool    
stree_prev
(stree *tree)

bool    
stree_find
(stree *tree, type data)

bool    
stree_insert
(stree *tree, type data)

IMPORT_CLM_WTREE: generic weight-balanced tree container

typedef struct wtree_s *
wtree

size_t  
wtree_size
(wtree *tree)

size_t  
wtree_find
(wtree *tree, type data)

size_t  
wtree_insert
(wtree *tree, type data)

type    
wtree_select
(wtree *tree, size_t rank)

type    
wtree_remove
(wtree *tree, size_t rank)

/code/MedianSort

An iterative constant-space variant of QuickSort called MedianSort.

void median_sort(type_t *A, const size_t length) {
    size_t left, right, rank, step;
    for (step   = 1; step <  length; step <<= 1);
    for (step >>= 1; step >= 1;      step >>= 1) {
        for (rank = step; rank < length; rank += (step << 1)) {
            left  = (rank-step);
            right = (rank+step) > length ? length : (rank+step);
            quick_select(A+left, right-left, step);
        }
    }
}
/code/PseudoSorting

A pseudosorting algorithm takes a sequence and returns a permutation of that sequence that is more sorted than the previous one. The precise definition of more sorted it is not important as long as we guarantee that:

  1. Repeated independent aplications of the same pseudosorting algorithm will eventually sort any sequence.
  2. Applying a pseudosorting algorithm to a sorted sequence leaves it sorted.

All sorting algorithms are pseudosorting algorithms by definition, but the only pseudosorting algorithms that are of any interest are the ones that perform in O(N) time, so they can be applied while performing other O(n) tasks over the sequence (such as looking for an element or copying it to another location).

A single pass of Bubble Sort is a simple pseudosorting algorithm that could be used to improve the sortedness of an array every time we need to scan it for whatever the reason:

void BubblePseudoSort(int *array, size_t length) {
    for (size_t i = 1; i < length; i++) {
        if (array[i-1] > array[i]) {
            int aux    = array[i-1];
            array[i-1] = array[i];
            array[i]   = aux;
        }
    }
}

An optimal pseudosorting algorithm is a pseudosorting algorithm such that if we apply it to the same sequence iteratively is guaranteed to sort it in O(N*log(N)) total time.

A single pass of Natural Merge Sort is an optimal pseudosorting algorithm that we can use to improve the sortedness of an array each time we need to copy it for whatever the reason:

void NaturalMergePseudoSort(int *array, size_t length) {

    size_t x,   y,   z   = 0;                   // Index variables: indices
    size_t ini, mid, end = 0;                   // Index variables: limits
    size_t size = sizeof(int);                  // Size of content type
    int   *aux = (int *) malloc(length*size);   // Same type of array content

    // Make a single pass over the data merging pairs of adjacent runs:
    while (end < length) {

        // Find new ini:
        ini = end;

        // Find new mid:
        for (mid = ini+1; mid < length && array[mid-1] <= array[mid]; mid++);

        // If we have reached the end of the array we can exit now:
        if (mid == length) { break; }

        // Find new end:
        for (end = mid+1; end < length && array[end-1] <= array[end]; end++);

        // Merge array[ini, mid) with array[mid, end) into aux[z, z+end-ini):
        x = ini;
        y = mid;
        while (x < mid && y < end) {
            if (array[x] <= array[y]) { aux[z++] = array[x++]; }
            else                      { aux[z++] = array[y++]; }
        }
        if (x < mid) { memcpy(&aux[z], &array[x], (mid-x)*size); z += mid-x; }
        if (y < end) { memcpy(&aux[z], &array[y], (end-y)*size); z += end-y; }
    }

    // Copy aux[0, end) back into array:
    memcpy(array, aux, end*size);

    // De-allocate aux:
    free(aux);
}

Since NaturalMergePseudoSort requires O(N) additional space, the existence of an optimal in-place pseudosorting algorithm is still an open question.

You can find more information about pseudosorting algorithms and some examples in the PseudoSort repository.

/math/EgyptianTangram

This is a new tangram design with nice mathematical properties.

Publications:

The Egyptian Tangram design is Copyright © 2019 Carlos Luna Mota. All Rights Reserved.

/math/GeometryCheatSheet

/game/TriangularDeck

/game/T3CS

/nice/quotes
Las cosas evolucionan hacia o desde la nada. Cuando el anochecer se acerca a los valles, el viajero se pregunta dónde buscar cobijo para pasar la noche. Ve altos juncos creciendo por todos lados, los junta en una brazada, erguidos tal y como se mantienen en el campo, y los ata por arriba. Presto, una choza de hierba viva. A la mañana siguiente, antes de embarcarse en una nueva jornada de viaje, desata los juncos y presto, la choza se deconstruye, desaparece y vuelve a convertirse en una parte prácticamente indiferenciale del amplio campo de juncos. El paisaje original parece restaurarse de nuevo, pero quedan trazas minúsculas del refugio. Algún junco doblado o entrelazado aquí y allá. Queda también la memoria de la choza en la mente del viajero, y en la mente del lector que lee la descripción. El Wabi-sabi, en su forma más pura e idealizada, se refiere precisamente a estas delicadas trazas, a esta evidencia evanescente, en las fronteras de la nada.

From Wabi-Sabi para Artistas, Diseñadores, Poetas y Filósofos by Leonard Koren.


I have been intending to write this essay for months. Why am I finally doing it? Because I finally found some uncommitted time? Wrong. I have papers to grade, textbook orders to fill out, an NSF proposal to referee, dissertation drafts to read. I am working on this essay as a way of not doing all of those things. This is the essence of what I call structured procrastination, an amazing strategy I have discovered that converts procrastinators into effective human beings, respected and admired for all that they can accomplish and the good use they make of time. All procrastinators put off things they have to do. Structured procrastination is the art of making this bad trait work for you. The key idea is that procrastinating does not mean doing absolutely nothing. Procrastinators seldom do absolutely nothing; they do marginally useful things, like gardening or sharpening pencils or making a diagram of how they will reorganize their files when they get around to it. Why does the procrastinator do these things? Because they are a way of not doing something more important. If all the procrastinator had left to do was to sharpen some pencils, no force on earth could get him do it. However, the procrastinator can be motivated to do difficult, timely and important tasks, as long as these tasks are a way of not doing something more important.

From Structured Procrastination by John Perry

/nice/books