Author Topic: Password generation and some more C/C++  (Read 831 times)

0 Members and 1 Guest are viewing this topic.

artymig

  • Guest
Password generation and some more C/C++
« on: December 20, 2012, 06:01:38 am »
A password generator: http://alexeilebedev.com/mdpass/
Plus its got some nice explanatory text and a snippet of the code.

Dirlist, a... Whatever you call it: http://alexeilebedev.com/dirlist/

The next is made by the same guy, but the actual URL is lost in the depths of his website.

Code: [Select]
It is an execution model that accomodates multiple exceptions.

a basic block of a program looks like this:

{
a;
atexit d;
b;
atexit e;
c;
}

where a,b,c,d are some statements. control flow enters the top, proceeds down and executes every statement. then it reaches the closing curly brace, turns around, and goes backwards, executing all statements marked atexit. (in my post, which i cant find, i called them "anti statements"). when control flow reaches top again, the block is executed.

the coolness of this idea becomes clear when you consider a program that cannot continue, for some reason. for instance, you needed to open a file but the OS returned an error, so you have nothing more to do. but you've already allocated some memory, wnich you need to free. what to do? the anti-statement style requires that you pair each such statement with an immediately following anti-statement which undoes the action. for instance:

{
alloc mem;
atexit free it;
open file;
atexit close it;
process file;
}

if execution cannot get past "open file", it turns around early. frees the memory, since that anti-statement has been passed on the way down, and exits up from the top.

and now i can describe an exception handling model with multiple simultaneosly active exceptions. such a model is needed because when you write distributed software, you cannot be sure two errors will not occur simultaneously on two remote computers. so you need to not panic when you have multiple errors!

we extend the runtime state of a program to include, in addition to the instruction pointer and various registers, an error list. each exception is an error code, error message, or simply a bool indicating that error occured.
when you enter a new block of curly braces, the old value of the list is saved and the list is cleared.
execution proceeds forward if list is empty; it proceeds backwards if it is non-empty.
when an error occurs, it is appended to the list (this is equivalent to "throwing" an exception)
when exiting a block, the error list is appended to enclosing block's error list.
there are statements that can remove certain types of errors from the list, or clear the list. (this is " catching").

This is just some code to figure out the number of possible combinations on an Android "typical" lockscreen (Same guy):

Code: [Select]
#include <stdio.h>
#include <assert.h>

// compile with gcc -O3 codes.c -o codes
/*
poikilo:~ alexei$ gcc codes.c -o codes && ./codes
paths of length 4: 1624
paths of length 5: 7152
paths of length 6: 26016
paths of length 7: 72912
paths of length 8: 140704
paths of length 9: 140704
total is 389112
*/
// cells:
// 1 2 3
// 4 5 6
// 7 8 9
// cells are numbered from 1 to 9, corresponding to bits 1 through
// 9 inclusively. bit 0 is unused.

static const int MIN_LENGTH=4;

// this represents blockage.
// you can't go from cell 1 to cell 3
// unless cell 2 is already taken.
struct Block {
    int from,block,to;
};
struct Block blocks[] = {
    {1,2,3}
    ,{4,5,6}
    ,{7,8,9}
    ,{1,4,7}
    ,{2,5,8}
    ,{3,6,9}
    ,{1,5,9}
    ,{3,5,7}
};

typedef unsigned long long u64;

// State is a bitset representing visited cells
typedef int State;

// input:   current state, cell index
// returns: whether the given cell has been visited.
//
int is_visited(State state, int cell) {
    assert(cell>=1 && cell<=9);
    return state & (1<<cell);
}

// input: current state, cell index
// returns: new state with given cell marked as visited
//
State mark_visited(State state, int cell) {
    assert(cell>=1 && cell<=9);
    assert(!is_visited(state,cell));
    return state | (1<<cell);
}

// input: source and destination cells (from, to), current state.
// returns: 1 if it's possible to go from source to destination cell
// and zero otherwise.
int is_blocked(int from, int to, State state) {
    int i;
    for (i=0; i<sizeof(blocks)/sizeof(struct Block); i++) {
        struct Block *block = &blocks[i];
        if ((block->from == from && block->to == to)
            || (block->to == from && block->from == to)) {
            return !is_visited(state, block->block);
        }
    }
    return 0;
}

// input: current state, starting cell index, number of steps remaining.
// returns: number of paths possible.
// note that at least one path is already possible, the one
// corresponding to current state;
u64 count_paths(State state, int start_cell, int steps) {
    assert(is_visited(state,start_cell));
    if (steps==0) {
        return 1;
    }
    int next_cell;
    u64 paths=0;
    for (next_cell=1; next_cell<=9; next_cell++) {
        if (is_visited(state,next_cell)) {
            continue;
        }
        if (is_blocked(start_cell,next_cell,state)) {
            continue;
        }
        paths += count_paths(mark_visited(state, next_cell), next_cell, steps-1);
    }
    return paths;
}

// returns total number of codes that can be entered on an android screen.
// note that some starting points are equivalent -- for instance, all 
// corners and all edges. this fact is ignored; the function uses brute
// force to count all combinations.
u64 count_codes() {
    u64 total=0;
    int length;
    for (length=MIN_LENGTH; length<=9; length++) {
        int start_cell;
        u64 paths=0;
        for (start_cell=1; start_cell<=9; start_cell++) {
            paths += count_paths(mark_visited(0, start_cell), start_cell, length-1);
        }
        printf("paths of length %d: %lld\n", length, paths);
        total+=paths;
    }
    return total;
}

int main() {
    u64 total = count_codes();
    printf("total is %lld\n", total);
    return 0;
}