--- 20240809
I've been working on bringing in Arbitrary to rust-bitcoin lately. In so doing, I'm now exploring some performance related ideas I wanted to remember. Primarily that the venerable Inline Attribute can be used to annotate so called upstream methods such that their method body's are included natively in calling methods across crate boundaries. A better explanation is here.


20240924
      Upgrade base OS:
        freebsd-update fetch
        freebsd-update install

      Check available kernel:
        freebsd-version -k

      Check running kernel:
        uname -r

      Upgrade binaries:
        pkg update
        pkg upgrade

      Check for binary vulnerabilities:
        pkg audit -F
      


---
20240112
Formatting USB drive with ext4 on FreeBSD.
        444  sudo pkg install e2fsprogs-core
        445  gpart show
        447  sudo gpart destroy -F da1
        448  sudo gpart create -s GPT da1
        449  sudo mke2fs -L tirana_storage -F -E discard -t ext4 /dev/da1
        451  sudo mount -t ext2fs /dev/da1 /mnt
      
Note to self, ext4 is super slow on FreeBSD compared to UFS. I wish I could get UFS to copy on linux.

---
20240101
Happy New Year!

---
20240101
         echo "~/mutt/muttrc"
        # About Me
        set from = "redacted-email-address"
        set realname = "Yancy"

        # My credentials
        set smtp_url = "smtp://redacted-email-address@mail.redacted-mail-server-name.net:587/"
        set smtp_pass = "redacted-password"
        set imap_user = "redacted-email-address"
        set imap_pass = "redacted-password"

        # My mailboxes
        set folder = "imaps://mail.redacted-mail-server-name.net:993"
        set spoolfile = "+INBOX"

        # Where to put the stuff
        set header_cache = "~/.mutt/cache/headers"
        set message_cachedir = "~/.mutt/cache/bodies"
        set certificate_file = "~/.mutt/certificates"

        # Etc
        set mail_check = 30
        set move = no
        set imap_keepalive = 900
        set sort = threads
        set editor = "vim"

        # Shortcut for checking on new messages
        bind index G imap-fetch-mail
        set sort_aux = last-date-received
      

20231130
         echo "~/.tmux.conf"
        # depends on apm for the battery status and ifconfig to fetch the current ip addr.
        set -g status-right "#(ifconfig | grep wlan0 -A 2 | grep inet | awk '{print $2}') | #(apm | grep 'Remaining battery life' | awk '{print $4}') %| %a %h-%d"
        run '~/.tmux/plugins/tpm/tpm'
      

20231116

After watching Lecture 1A of SICP, I wrote the recursive algorithm for finding the square root of a number in Rust. The algorithem implements Heron's method , named after the Greek mathematician Hero of Alexandria (what a name, right?). Although, the method was known prior to Hero. See: babylonian mathematics 1800 - 1600 BC.

        const S: f32 = 2.0;

        fn good_enough(guess: f32, x: f32) -> bool {
            (guess * guess - x).abs() < 0.0001
        }

        fn improve(guess: f32, x: f32) -> f32 {
             //average guess and x / guess.
            (guess + x / guess) / 2.0
        }

        fn try(guess: f32, x: f32) -> f32 {
            if good_enough(guess, x) {
                guess
            } else {
                try(improve(guess, x), x)
            }
        }

        fn square_root(x: f32) -> f32 {
            try(1.0, x)
        }

        fn main() {
            let square_root = square_root(S);
            println!("square root: {}", square_root);
        }
      
Recursive representation:
        x(0) ~ sqrt(S)
        x(n + 1) = 1 /2 ( x(n) + S/x(n) ) 
      
---
20231115

I finished ex1-16 yesterday. To this point, malloc and heap allocation hasn't been described, although I don't think it would be worthwhile to try to store the contents on the stack, so I used malloc and remalloc.

          /* Excercise 1-16
         *
         * Revise the main routine of the longest-line program so
         * it will correctly print the length of arbitrary long
         * input lines, and as much as possible of the text.
         */

        #include 

        #define MAXLINE 1000 /* maximum input line size */

        int max;
        char line[MAXLINE];
        char longest[MAXLINE];

        int get_line(char line[], int maxline);
        void copy(char to[], char from[]);

        /* print longest input line */
        int main()
        {
            int len;    /* current line length */
            int max;    /* maximum length seen so far */
            char line[MAXLINE]; /* current input line */

            char *longest = malloc(0); /* longest */
            char *complete = malloc(0); /* complete */

            max = 0;
            while ((len = get_line(line, MAXLINE)) > 0) {
                int line_len = strlen(line);
                int complete_len = strlen(complete);
                complete = (char *) realloc(complete, strlen(line) + strlen(complete));
                strcat(complete, line);

                if (line[len - 1] == '\n') {
                    if (strlen(complete) > max) {
                        longest = (char *) realloc(longest, strlen(complete));
                        max = strlen(complete);
                        strcpy(longest, complete);
                    }
                    complete[0] = '\0';
                }
            }

            if (max > 0) /* there was a line */
                printf("%s", longest);

            return 0;
        }

        /* get_line: read a line into s, return length */
        int get_line(char s[], int lim) {
            int c, i;

            for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
                s[i] = c;
            }

            if (c == '\n') {
                s[i] = c;
                ++i;
            }

            s[i] = '\0';
            return i;
        }
          

Addendum, after reading 1-16 again, I think the question assumes you don't know about malloc, and instead to just print as much of the line as possible. Here's a re-work of the problem without malloc:

        /*print the longest line */
        main()
        {
            int len;            /* current line length */
            int total_len;      /* the total length when line spans multiple reads */
            int copied_size;    /* the size of the line copied */
            int max;            /* maximum length seen so far */
            char line[MAXLINE];     /* current input line */
            char longest[MAXLINE];  /* longest line saved here */

            max = 0;
            total_len = 0;
            copied_size = 0;
            while ((len = get_line(line, MAXLINE)) > 0) {
                total_len += len;
                if (total_len > max) {
                    max = total_len;
                    if (len > copied_size) {
                        copy(longest, line);
                        copied_size = len;
                    }
                }

                if (line[len - 1] == '\n') {
                    total_len = 0;
                }
            }

            if (max > 0) /* there was a line */
                printf("%d: %s", max, longest);

            return 0;
        }
      



20231109
The K&R book contains the example code snippet:
        /* copy: copy 'from' into 'to'; assume to is big enough */
        void copy()
        {
          int i;

          i = 0;
          while ((to[i] = from[i]) != '\0')
            ++i;
        }
      
This seems to imply to[i] = from[i] has the side-effect of returning the value from[i].

Consider:
        #include

        int main()
        {
            int a = 0;
            int b = 1;

            printf("%d", a = b );
        }
      
The results print 1 to stdout, showing the assignment of the value b is printed.

---
20231031
        // Add a check for visitation which fixes 20231016 version.
        //
        // Note to self, visited could be a node state instead.
        fn dfs_iter(root: &Node, bound: usize) {
            let mut visited = vec![];
            let mut call_stack = vec![];
            let mut path = vec![];

            call_stack.push(root);
            visited.push(root);

            while !call_stack.is_empty() {
                let node = call_stack.pop().unwrap();

                path.push(node); 
                visited.push(node);
                let sum: usize = path.iter().map(|n| n.key).sum();

                if sum <= bound {
                    println!("* path: {:?}", path.iter().map(|n| n.key).collect::>() );

                    let descendants = &node.descendants;
            
                    for d in descendants {
                        call_stack.push(d);
                    }
                }

                if sum > bound || node.descendants.is_empty() {
                    path.pop();

                    // backtrack
                    loop {
                        let n = path.last();

                        match n {
                            None => break,
                            Some(n) => {
                                let is_explored = is_explored(n, &visited);
                                if is_explored {
                                    path.pop();
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
      


---
20231016
        // note to self, the following iterative version does not produce the same
        // results as the recursive version from 20231014.  The reason being that
        // once a leaf node is reached, only one node is popped instead of popping
        // all the way to the root for example.  One possible way to solve this is
        // to add an explored state to each node and pop if the node is explored.
        // A node is explored if all of it's descendants are explored.
        //
        // iterative dfs bound by node sum.
        fn dfs_iter(root: &Node, path: &mut Vec, bound: usize) {
            let mut call_stack = vec![];
            call_stack.push(root);

            while !call_stack.is_empty() {
                let node = call_stack.pop().unwrap();
                path.push(node.key);

                let sum: usize = path.iter().sum();

                if sum <= bound {
                    println!("path: {:?}", path);

                    let descendants = &node.descendants;

                    for d in descendants {
                        call_stack.push(d);
                    }
                }

                if sum > bound {
                    path.pop();
                } else if node.descendants.is_empty() {
                    path.pop();
                }
            }
        }
      
---
20231014
        // recursive dfs bound by node sum.
        fn dfs(node: &Node, path: &mut Vec, bound: usize) {
            path.push(node.key);
            let sum: usize = path.iter().sum();

            if sum <= bound {
                println!("path: {:?}", path);

                let descendants = &node.descendants;

                for d in descendants {
                    dfs(d, path, bound);
                }
            }   

            path.pop();
        }
      
        // dfs bound by distance. 
        fn dfs(node: &Node, distance: usize, bound: usize) {
            println!("key: {} depth: {}", node.key, distance);

            let descendants = &node.descendants;

            for d in descendants {
                let new_distance = distance + d.distance;
                  
                if new_distance <= bound {
                    dfs(d, new_distance, bound);
                }
            }   
        }
      
---
20231013
        // dfs - non binary tree that prints the distance from the root to the leaf (depth).
        fn dfs(node: &Node, distance: usize) {
            println!("key: {} depth: {}", node.key, distance);

            let descendants = &node.descendants;

            for d in descendants {
                dfs(d, distance + d.distance);
            }
        }
      
---
20231012 -
        // dfs - non binary tree that prints the depth of each node.
        fn dfs(node: &Node, depth: usize) {
            println!("key: {} depth: {}", node.key, depth);

            let descendants = &node.descendants;

            for d in descendants {
                dfs(d, depth + 1);
            }
        }
      
---
20231011
-
        // dfs - non binary tree
        fn dfs(node: &Node) {
            println!("{}", node.key);

            let descendants = &node.descendants;

            for d in descendants {
                dfs(d);
            }
        }
      
        // A Node definition.
        #[derive (Clone, Debug)]
        struct Node<\'a> {
            descendants: Vec>>,
            key: usize
        }
      
        // Building a tree to search on.
        //     5
        //   / | \
        //  3  1  4
        //  |
        //  2

        let node_five = Node {
            descendants: vec![
                Box::new(&node_three),
                Box::new(&node_one),
                Box::new(&node_four)],
            key: 5
        };

        ..
      


---
20231006
-
Introduction to Algorithms
-
        // A binary search - O(height)
        fn binary_search(node: &Node, target: usize) {
            if node.key == target {
                println!("found node that matches target: {:?}", node);
            }

            if target < node.key {
                let left_node: &Node = node.left.as_ref().unwrap();
                binary_search(left_node, target);
            }

            if target > node.key {
                let right_node: &Node = node.right.as_ref().unwrap();
                binary_search(right_node, target);
            }
        }
      
        // A Node definition.
        #[derive (Clone, Debug)]
        struct Node<'a> {
            left: Option>>,
            right: Option>>,
            key: usize
        }
      
        // Building a tree to search on.
        let node_five = Node {
            left: Some(Box::new(&node_three)),
            right: Some(Box::new(&node_seven)),
            key: 5
        };

        ..
      


---
20231002
-
Dictionary of Algorithms and Data Structures
-
Customizing Git Configuration
-
How to Write a Git Commit Message



---
20230928
-
The Tao of Programming
-
      // If the input is a tree and not a graph (without cycles), then
      // the solution becomes simpler since there is no need to maintain
      // a visitied list.
      fn dfs_tree(tree: &HashMap>, root: usize) {
          println!("visit {}", root);

          let branches: &Vec = tree.get(&root).unwrap();

          for &node in branches {
              dfs_tree(tree, node);
          }
      }

      // The iterative version
      fn dfs_tree_iter(tree: &HashMap>, root: usize) {
          let mut s = Vec::new();

          s.push(root);

          while !s.is_empty() {
              let n = s.pop().unwrap();

              println!("visit {}", n);

              let branches = tree.get(&n).unwrap();

              for &n in branches {
                  s.push(n);
              }
          }
      }
      

---
20230926
-
    // Recursive depth first search.
    fn dfs(visited: &mut HashSet, graph: &HashMap>, vertex: usize) {
        // Check if the vertex has been visited.
        if !visited.contains(&vertex) {
            println!("visit {}", vertex);

            // It hasn't been visited, so mark it as visited now.
            visited.insert(vertex);

            // Get all edges of this vertex.
            let edges: &Vec = graph.get(&vertex).unwrap();

            // For each child, visit.
            for &v in edges {

                // Recusive call.
                dfs(visited, graph, v);
            }
        }
    }
    
    // Iterative depth first search.
    fn dfs_iter(visited: &mut HashSet, graph: &HashMap>, vertex: usize) {
        let l = graph.len();

        // The stack will never be larger than the graph. 
        let mut s: Vec = Vec::with_capacity(l);
        s.push(vertex);

        while !s.is_empty() {
            let v: usize = s.pop().unwrap();

            // Check if the vertex has been visited.
            if !visited.contains(&v) {
                println!("visit {}", v);

                // It hasn't been visited, so mark it as visited now.
                visited.insert(v);

                // Get all edges of this vertex.
                let edges: &Vec = graph.get(&v).unwrap();

                for &v in edges {
                    s.push(v);
                }
            }
        }
    }
    
    // Entry point.
    fn main() {
        // A hashmap of tuples which represent a graph.  The first item is the vertex, 
        // and the second item which are edges.  
        let mut graph = HashMap::from([
            (5 , vec![3, 7]),
            (3 , vec![2, 4]),
            (7 , vec![8]),
            (2 , vec![]),
            (4 , vec![8]),
            (8 , vec![])
        ]);

        let l = graph.len();

        // Start DFS at the root node 5.
        // Set of visited (no duplicates)
        let mut visited: HashSet = HashSet::with_capacity(l);
        dfs(&mut visited, &mut graph, 5);

        ..
    }
    
-
      echo "Editing files on a remote machine with vim"
      vim scp://username@hostname/
    
-
      cat .bash_profile
      eval $(keychain --eval --agents ssh id_ed25519)
    
-
      echo "setup keychain"
      cd /usr/ports/security/keychain/ && sudo make install clean
      echo "eval $(keychain --eval --agents ssh id_rsa)" > ~/.bash_profile
    
[1]
-
---
20230925
-
      cat .vimrc 
      execute pathogen#infect()
      syntax enable 
      filetype plugin indent on

      " ctrlp
      set runtimepath^=~/.vim/bundle/ctrlp.vim

      " fix backspace
      set backspace=indent,eol,start

      " Shortcut to rapidly toggle `set list`
      nmap l :set list!

      " tabstop:          Width of tab character
      " softtabstop:      Fine tunes the amount of white space to be added
      " shiftwidth        Determines the amount of whitespace to add in normal mode
      " expandtab:        When this option is enabled, vi will use spaces instead of tabs
      set tabstop     =2
      set softtabstop =2
      set shiftwidth  =2
      set expandtab
    
-
      cat .xinitrc

      # Set background image
      feh --bg-max ./Downloads/awesome-destop.jpg

      # Start evilwm
      /usr/local/bin/evilwm -snap 10
    
-
      echo "setting up the homepage droplet"

      # Add a new user
      sudo useradd -m {username} -s /bin/bash
      sudo passwd {username}

      # Add a sudoer
      vim /etc/sudoers
      user_name ALL=(ALL)  ALL

      # Setup Git
      sudo apt-get install git
      cd ~ && git clone git@github.com:yancyribbens/homepage.git

      # Setup nginx
      sudo rm /var/www/html/index.nginx-debian.html
      sudo ln -s ~/git/homepage/index.html /var/www/html/index.nginx-debian.html

      # Enable ssh for new user (copy the keys file from root)
      cp /root/.ssh/authorized_keys /home/yancy/.ssh/authorized_keys
      chown user:user /home/user/ssh/authorized_keys