Functions and Fractals - Recursive Trees - Bash!

  • + 0 comments

    I looked at the top few, and most basically hardcoded the tree. That's weak.

    I was happy with my fairly unique answer. I can be cleaned up better, but I've already spent a few hours on this.

    The basic idea was to form each tree based on a base row. At first the tree function was done in 3 parts - trunk, branch left, and branch right - but I was able to roll them into the same loop after I had all three working independantly.

    From the base row, the trunk just copies the previous row (if there was a 1 at "base, col)" then you put a 1 at "trunkcur,col"). For the branches you look at the base row plus the offset so "base, col +/- i" (where i is the row difference from branchcur to base) to put a 1 in "branchcur, col +/- (base - branchcur)".

    You add an additional 64th row that is just a 1 at "64,50" and now the trees can be built off that single starting point. frac() takes the number of iterations, starting line, and depth of the tree (starting line is always 63 and depth always starts at 16). Each recursive call decreaments iteration number (base case of 0 where nothing is printed at it returns), calculates a new starting row (decrementing 2 * length of last tree), and sets the next tree length to half the previous. So frac 5 63 16 calls frac 4 31 8 which calls frac 3 15 4 ...

    Yes, this can all be done iteratively, but I was just too lazy to refactor it for such a small n. The nice thing about this approach is that all the constants are easily adjustable to make it work on any size board with any length trees and any number of branches even.

    When the table is printed at the end, just remeber to leave off the 64th starting base row and you're good.

    declare -A tab
    
    for r in {1..64}; do
        for c in {1..100}; do
            tab["$r,$c"]="_"
        done
    done
    
    tab["64,50"]="1"
    
    function prtab {
        for r in {1..63}; do
            for c in {1..100}; do
                echo -n ${tab["$r,$c"]}
            done
        echo
        done
    }
    
    function tree {
        line=$1
        len=$2
        base=$(($line + 1))
        for i in $(seq 0  $(($len - 1))); do
            trunkcur=$(($line - $i))
            branchcur=$(($line - $len - $i))
            for c in {1..100}; do
                # trunk
                if test "1" = ${tab["$base,$c"]-_}; then
                    tab["$trunkcur,$c"]="1"
                fi
                # left branch
                right=$(($c + $i + 1))
                if test "1" = ${tab["$base,$right"]-_}; then
                    tab["$branchcur,$c"]="1"
                fi
                # right branch
                left=$(($c - $i - 1))
                if test "1" = ${tab["$base,$left"]-_}; then
                    tab["$branchcur,$c"]="1"
                fi
            done
        done
    }
    
    function frac {
        iter=$1
        start=$2
        len=$3
        
        if [ $iter -eq 0 ]; then
            return
        fi
    
        tree $start $len
        frac $((iter - 1)) $((start - len * 2)) $((len / 2))
    }
    
    read n
    frac $n 63 16
    
    prtab