Binary Tree in G'MIC (A code I made, but not sure if there's interest)

Ended up being bored, and then got the idea to do something unique.

What I did was made a G’MIC command that has it own DSL, and then generates a binary tree image off it:

#@cli rep_str2bin_struct:'string',vector_size
#@cli : The following chars do the following action when building a binary tree structure.
#@cli : '^' = Move up the tree
#@cli : '<' = Create node (if needed) and go to left child of binary branch
#@cli : '>' = Create node (if needed) and go to right child of binary branch
#@cli : '.' = Create 2 child nodes, but do not go to either. Does not overwrite values. If one or two exist, they're not created.
#@cli : '~' = Create a sibling branch, if one does not exist, then create one. After, switch to sibling branch.
#@cli : '{' = Insert vec_num at current position.'}' signify end. Anything in between is calculated.
#@cli : '*' = Go to the highest branch with same direction.
#@cli : '+' = Go to the root of binary tree
#@cli :
#@cli : Image structure per channel:
#@cli : 0 = parent
#@cli : 1 = left child
#@cli : 2 = right child
#@cli : 3+ = values
#@cli : $ rep_str2bin_struct "><*{5}",1 split c append y
+rep_str2bin_struct:
check isint(${2=1},1)

('"$1"')  => str
cursor,L,C,size_of_creation:=0,{[w,$!,3+$2]} # C is used for image construction later
$size_of_creation,1,1,1,nan => B

current_branch=B

do
	if i[#$str,$cursor]==32
		cursor+=1
	elif i[#$str,$cursor]==_'^'
		if !same('$current_branch','B')
			current_branch={`resize('$current_branch',size('$current_branch')-1,-1)`}
		fi

		cursor+=1
	elif i[#$str,$cursor]==_'<'
		temp_branch=${current_branch}L

		if !narg(${$temp_branch})
			$size_of_creation,1,1,1,nan => $temp_branch
			set[${$current_branch}] {${$temp_branch}-$C},1
			set[${$temp_branch}]    {${$current_branch}-$C},0
		fi

		current_branch=$temp_branch

		cursor+=1
	elif i[#$str,$cursor]==_'>'
		temp_branch=${current_branch}R

		if !narg(${$temp_branch})
			$size_of_creation,1,1,1,nan => $temp_branch
			set[${$current_branch}] {${$temp_branch}-$C},2
			set[${$temp_branch}]    {${$current_branch}-$C},0
		fi

		current_branch=$temp_branch

		cursor+=1
	elif i[#$str,$cursor]==_'.'
		temp_branch_L=${current_branch}L
		temp_branch_R=${current_branch}R

		if !narg(${$temp_branch_L})
			$size_of_creation,1,1,1,nan => $temp_branch_L
			set[${$current_branch}] {${$temp_branch_L}-$C},1
			set[${$temp_branch_L}]  {${$current_branch}-$C},0
		fi

		if !narg(${$temp_branch_R})
			$size_of_creation,1,1,1,nan => $temp_branch_R
			set[${$current_branch}] {${$temp_branch_R}-$C},2
			set[${$temp_branch_R}]  {${$current_branch}-$C},0
		fi

		cursor+=1
	elif i[#$str,$cursor]==_'~'
		if !same('$current_branch','B')
			current_direction={V='$current_branch';V[size(V)-1]==_'R'}
			root_branch={`resize('$current_branch',size('$current_branch')-1,-1)`}

			if $current_direction
				temp_branch=${root_branch}L
			else
				temp_branch=${root_branch}R
			fi

			if !narg(${$temp_branch})
				$size_of_creation,1,1,1,nan => $temp_branch
				set[${$root_branch}] {${$temp_branch}-$C},{1+!$current_direction}
				set[${$temp_branch}] {${$root_branch}-$C},0
			fi

			current_branch=$temp_branch
		fi

		cursor+=1
	elif i[#$str,$cursor]==_'{' # } { Ignore this comment
		next_cursor={find(#$str,_'\}',$cursor+1,1)}
		if $next_cursor==-1 error missing_end_char_@ fi
		length={$next_cursor-$cursor-1}
		values={[{`crop(#$str,$cursor+1,0,0,0,$length,1,1,1,0)`}]}
		values={vector(#$2,$values)}
		eval values=[$values];copy(i[#${$current_branch},3],values);
		cursor={$next_cursor+1}
	elif i[#$str,$cursor]==_'*'
		if !same('$current_branch','B')
			eval "
				current_branch='"$current_branch"';
				char_pos=size(current_branch)-1;
				last_char=current_branch[char_pos];
				while(char_pos--,
					if(current_branch[char_pos]!=last_char,break(););
				);
				char_pos+1;
			"
			current_branch={`('$current_branch')[0,${}]`}
		fi

		cursor+=1
	elif i[#$str,$cursor]==_'+'
		current_branch=B
		cursor+=1
	else
		error inval_char
	fi

while $cursor<$L

a[$C--1] c
rm..

If you’re interested in this. Let me know. Though, this was just a fun exercise for me. I don’t see applications here.

Also, a example use:

C:\Windows\System32>gmic v - rep_str2bin_struct \"{1}<{2}>{9}^<{3}>{5}^<{4}+>{2}<{3}^>{4}<{5}^>{6}>{7}<{8}^>{9}\",1 s c repeat $! e {crop(#"$>")} done rm
nan,1,6,1
0,3,2,2
1,nan,nan,9
1,5,4,3
3,nan,nan,5
3,nan,nan,4
0,7,8,2
6,nan,nan,3
6,9,10,4
8,nan,nan,5
8,nan,11,6
10,12,13,7
11,nan,nan,8
11,nan,nan,9

This match:

                    1
                  /   \
                 2     2
                / \   / \
               3   9 3   4
              / \       / \
             4   5     5   6
                           \
                           7
                          / \
                         8   9
1 Like

Admittedly I’m not likely to need this, but it’s fascinating that you’re writing interpreters inside g’mic. (Also good to see you creating new stuff!)

Yeah, the new stuff are rarely happening just because there’s still a huge roadblock problem: “Create N new colors that represent the farthest distance away from all the previous color in bounded box of s(spectrum) dimension in which all length is 256 in optimal way (voronoi among other things)”. Once that happen, I can finish up my new color selection helper command used for GUI script and immediately improve every of my GUI filter.

That being said, the only coding interpreter I did was brainfuck and this one. Closest one in gmic-community is roman2int series. This one was made to try to solve the Phylogeny generation problem, but I think it’s better to do bottom-up randomly, and this one can be used to solve top down generation with user input.