combining the elements of several lists - tcl

I want to take an arbitrary number of lists and return list of combinations of elements, but only combining one element from each list. All I have is sudo code because I don't know where to start.
I did find the solution to this program in the question of Combining the elements of 2 lists but I don't understand that scala code. I'm writing my program in Tcl but if you're able to help me feel free to write your answer in anything like java or python or pseudo code or whatever. Can anyone help me bring the following pseudo code to life?
for example:
# example: {a b} {c} {d e}
# returns: {a c d} {a c e} {b c d} {b c e}
# how?
# example: {a b} {c} {d e}
# iters: 0 0 0
# 0 0 1
# 1 0 0
# 1 0 1
#
#
# set done false
#
# while {!done} {
#
# list append combination_of_list due to iteration counts
#
# foreach list $lists {
# increment the correct count (specifically {0->1} {0->0} {0->1}) }
# reset the approapraite counts to 0
# }
#
# if all the counts in all the lists are at or above their max {
# set done true
# }
# }

Various Tcl solutions are discussed on this page: Cartesian product of a list of lists
Donal Fellows presents this variation at the end of the page:
proc product args {
set xs {{}}
foreach ys $args {
set result {}
foreach x $xs {
foreach y $ys {
lappend result [list {*}$x $y]
}
}
set xs $result
}
return $xs
}
Running that like this gives you the result:
% product {a b} {c} {d e}
{a c d} {a c e} {b c d} {b c e}
Documentation:
foreach,
lappend,
list,
proc,
return,
set,
{*} (syntax)

Here is a pseudocode describing an algorithm that generates all the combinations:
list_of_lists = {{a b}{c}{d e}}
def copy(list):
copy = {}
for element in list:
copy.add(element)
return copy;
def combine(list1, list2):
combinations = {}
for item1 in list1:
for item2 in list2:
combination = copy(item1)
combination.add(item2)
combinations.add(combination)
return combinations
results = {{}}
while list_of_lists.length>0:
results = combine(results, list_of_lists[0])
list_of_lists.remove(0)
It starts by combining {{}} with {a b c}
which produces {{a} {b}} which will be combined with {c} to generate {{a c} {b c}} on the next iteration etc.
Update:
Javascript version:
var list_of_lists = [["a", "b"],["c"],["d", "e"]];
function copy(list) {
var copy = [];
for (element of list) {
copy.push(element);
}
return copy;
}
function combine(list1, list2) {
var combinations = [];
for (let item1 of list1) {
var combination = copy(item1);
for (let item2 of list2){
combination.push(item2);
combinations.push(combination);
}
}
return combinations;
}
results = [[]]
while (list_of_lists.length>0) {
results = combine(results, list_of_lists[0]);
list_of_lists.splice(0,1);
}
console.log(results);

Related

Does TCL containg built in functions of type get_bits and set_bits?

The get_bits will return specific bits of a value and set_bits will set specific bits of a value to a specified value. Does TCL contain such functions built in or should they be written by the user?
The binary scan command does come close to the get_bits function but is not the same thing.
There's no specific function for getting or setting a particular bit. We can make them.
proc get_bit {value bit} {
expr {($value & (1 << $bit)) != 0}
}
proc set_bit {varName bit {value 1}} {
upvar 1 $varName var
if {$value} {
set var [expr {$var | (1 << $bit)}]
} else {
set var [expr {$var & ~(1 << $bit)}]
}
}
Those will work with integer values of any width; you're not restricted to 32 bits or 64 bits.
# Lots of bits!
set x 123456789012345678901234567890
# Fetch a particular bit
puts [get_bit $x 17]
# Set a bit to 1
set_bit x 78
puts "x = $x"
# Set a bit to 0
set_bit x 75 0
puts "x = $x"

finding difference between list elements in Tcl

I am a beginner in using Tcl. I am using it as VMD (molecular visualization) software uses it as a scripting language.
I have a list of co-ordinates of atom positions for a protein like: {{1 2 3} {7 9 13}, ...} I have a separate list of the same length with different positions say: {{3 5 2} {7 3 8}, ...}.
VMD has an inbuilt vecsub function which can subtract {1 2 3} and {3 5 2} to give {-2 -3 1}. I have written a foreach loop to iterate on the entire list and calculate vecsub.
My code is as follows:\
set sel1 [atomselect 0 "protein"] # selecting protein1
set sel2 [atomselect 1 "protein"] # selecting protein2
# create a list of same length as protein to store values
# $sel1 get index returns length of protein
foreach i [$sel1 get index] {
lappend x 0
}
# veclength2 returns square of vector length
# $sel1 get {x y z} returns a position list as described earlier
foreach i [$sel1 get index] {
lset x $i [expr [veclength2 [vecsub [lindex [$sel1 get {x y z}] $i] [lindex [$sel2 get {x y z}] $i]]]]
}
Is there another way to do this in Tcl? Similar to python array subtraction perhaps?
I would try this, but it's just a guess
set x [lmap p1 [$sel1 get {x y z}] p2 [$sel2 get {x y z}] {
expr [veclength2 [vecsub $p1 $p2]]
}]
With this, there's no need to pre-declare $x

How do I enforce fully bytecode compiling?

I am using TCL8.6.8.
Here is my experiment:
>cat ~/tmp/1.tcl
proc p {} {
foreach i {a b c} {
if {$i == "b"} {
break
}
puts $i
}
}
Now I come into tclsh:
% proc disa {file_name} {
set f [open $file_name r]
set data [read -nonewline $f]
close $f
tcl::unsupported::disassemble script $data
}
% disa ~/tmp/1.tcl
ByteCode 0x0x55cabfc393b0, refCt 1, epoch 17, interp 0x0x55cabfbdd990 (epoch 17)
Source "proc p {} {\nforeach i {a b c} {\n if {$i == \"b\"} ..."
Cmds 1, src 175, inst 11, litObjs 4, aux 0, stkDepth 4, code/src 1.26
Code 220 = header 168+inst 11+litObj 32+exc 0+aux 0+cmdMap 4
Commands 1:
1: pc 0-9, src 0-87
Command 1: "proc p {} {\nforeach i {a b c} {\n if {$i == \"b\"} ..."
(0) push1 0 # "proc"
(2) push1 1 # "p"
(4) push1 2 # ""
(6) push1 3 # "\nforeach i {a b c} {\n if {$i == \"b..."
(8) invokeStk1 4
(10) done
You can see that it is not fully compiled to bytecode in that the nesting script of foreach is taken as literal string.
Now I use tcl::unsupported::disassemble proc instead of tcl::unsupported::disassemble script, I can get a fully bytecode compiled version:
% source ~/tmp/1.tcl
% tcl::unsupported::disassemble proc p
ByteCode 0x0x55cabfc393b0, refCt 1, epoch 17, interp 0x0x55cabfbdd990 (epoch 17)
Source "\nforeach i {a b c} {\n if {$i == \"b\"} {\n ..."
File "/home/jibin/tmp/1.tcl" Line 1
Cmds 4, src 76, inst 54, litObjs 4, aux 1, stkDepth 5, code/src 4.21
Code 320 = header 168+inst 54+litObj 32+exc 28+aux 16+cmdMap 16
Proc 0x0x55cabfc72820, refCt 1, args 0, compiled locals 1
slot 0, scalar, "i"
Exception ranges 1, depth 1:
0: level 0, loop, pc 7-47, continue 49, break 50
Commands 4:
1: pc 0-52, src 1-74 2: pc 7-41, src 25-60
3: pc 23-36, src 50-54 4: pc 42-47, src 66-72
Command 1: "foreach i {a b c} {\n if {$i == \"b\"} {\n br..."
(0) push1 0 # "a b c"
(2) foreach_start 0
[jumpOffset=-42, vars=[%v0]]
Command 2: "if {$i == \"b\"} {\n break\n ..."
(7) startCommand +34 1 # next cmd at pc 41, 1 cmds start here
(16) loadScalar1 %v0 # var "i"
(18) push1 1 # "b"
(20) eq
(21) jumpFalse1 +18 # pc 39
Command 3: "break..."
(23) startCommand +14 1 # next cmd at pc 37, 1 cmds start here
(32) jump4 +18 # pc 50
(37) jump1 +4 # pc 41
(39) push1 2 # ""
(41) pop
Command 4: "puts $i..."
(42) push1 3 # "puts"
(44) loadScalar1 %v0 # var "i"
(46) invokeStk1 2
(48) pop
(49) foreach_step
(50) foreach_end
(51) push1 2 # ""
(53) done
Here is my question: Why doesn't tcl::unsupported::disassemble script fully compile the script? foreach command is inside a proc, I'd imagine that the compiling function of proc invokes the compiling function of each command, so the compiling function of foreach command is invoked regardless.
Tcl postpones the compilation of a script or procedure until the first time the bytecoded version of the script/procedure is needed. Compilation is fairly fast (and cached carefully, where that makes sense) and the optimizer in 8.6 is lightweight (just killing some of the stupider code sequences that used to be generated), so this isn't typically a big problem. The degree of compilation done for a particular command varies a lot: expr is almost always deeply compiled (if possible!) and proc itself is never compiled; what you're seeing in the disassembly is generic command call compilation (push the words on the stack, call a generic command with that many words, job done). This makes sense because most calls of proc happen once only and only really set things up for interesting things to happen later. The chances of us changing proc itself to gain deep compilation (as opposed to the procedures it creates) are zero, at least for 8.7/9.0 and probably well ahead there. There's just no win possible to justify the work it would take.
However, if you want to trigger procedure compilation early, you can. All it takes is a little triggering…
trace add execution proc leave {apply {{cmdArgs code result op} {
if {$code == 0} {
# proc succeeded; it must have been called as: proc name args body
set procedureName [lindex $cmdArgs 1]
# Make sure we resolve the procedure name in the right namespace!
set compTime [lindex [time {
uplevel 1 [list tcl::unsupported::getbytecode proc $procedureName]
}] 0]
# We're done now! Totally optional print of how long it took…
puts stderr "Compiled $procedure in $compTime µs"
}
}}}
I think that getbytecode is a little faster than disassemble (it's doing the same general thing but produces machine-readable output) but I might be wrong. You'll need to use disassemble if the code is to be used in 8.5.

efficient grid lookup by coordinate in Tcl

I'm trying to implement a simple grid lookup in Tcl. You can think of the grid items as boxes within a grid. Something like the following.
I have the x and y coordinates of the boundaries (left, right , top bottom) of each of the blue boxes within the coordinate space shown in a dictionary called boxcoordinates
given an arbitrary X and Y point, what is the most efficient way to identify which (if any) of the blue boxes are intercepted by the X,Y pair?
I'm currently doing a check for each box, on the conditions where Left < X < Right and Bottom < Y < Top to see which box satisfies those conditions.
Something like
foreach boxid [dict keys boxcoordinates] {
if {([dict get $boxcoordinates $boxid LEFT] < $x) && ([dict get $boxcoordinates $boxid RIGHT] > $x) && ([dict get $boxcoordinates $boxid BOTTOM] < $y) && ([dict get $boxcoordinates $boxid TOP] > $y)} {
set selected $boxid
break
}
}
But that seems very inefficient since there are a lot of boxes to scan through. Is there a more efficient way to do this?
If you sort the coordinate list in a regular fashion, you can do a binary search to find the coordinates you are looking for. The example below only has 9 entries, but should give you the idea. The coordinates used in this exampled are ordered as x1, x2, y1, y2.
global vars
proc init { } {
global vars
set vars(d) {
0 {1 4 1 4}
1 {1 4 6 8}
2 {1 4 10 12}
3 {6 8 1 4}
4 {6 8 6 8}
5 {6 8 10 12}
6 {10 12 1 4}
7 {10 12 6 8}
8 {10 12 10 12}
}
}
proc lCompare { a b } {
lassign $a ax1 ax2 ay1 ay2
lassign $b bx1 bx2 by1 by2
if { $bx1 < $ax1 } {
return -1
} elseif { $bx2 > $ax2 } {
return 1
} elseif { $by1 < $ay1 } {
return -1
} elseif { $by2 > $ay2 } {
return 1
}
return 0
}
proc bsearch { mx my } {
global vars
set target [list $mx $mx $my $my]
set low 0
set high [expr {[dict size $vars(d)]-1}]
while { $low <= $high } {
set mid [expr {($low+$high)/2}] ; # integer division
set lrc [lCompare [dict get $vars(d) $mid] $target]
if { $lrc > 0 } {
set low [expr {$mid+1}]
} elseif { $lrc < 0 } {
set high [expr {$mid-1}]
} else {
return $mid
}
}
return -1
}
init
set idx [bsearch 3 10]
puts "A:$idx"
set idx [bsearch 10 10]
puts "B:$idx"
set idx [bsearch 3 3]
puts "C:$idx"
set idx [bsearch 5 9]
puts "D:$idx"
Output:
bll-tecra:bll$ tclsh z.tcl
A:2
B:8
C:0
D:-1
References: wikipedia: Binary Search Algorithm

Converting this algorithm in TCL

I need help in converting this algorithm into tcl for my work, I am not so good in tcl language.
Inputs: STA−1, STA−2, STA−3, ..., STA−n
//requests from various stations for channel access
Shared Variables:
for every i, 1 ≤ i ≤ n
counter[i] ∈ { / 0, 1, 2,..., N}, initially 0, updated by stations
Sequence Number, K ∈ { / 0, 1, 2,..., N}, initially 0, will be set to a positive integer
Procedure:
//Initialization
Set sequence number K = m; //based on the action selected
for (i = 1 to n)
counter[i] = 0;
for (i = 1 to n)
{
while (channel access[i])
if (counter[i]! = K)
{
if (channel == idle)
{
if (counter[i]<min(counter[i+1], counter[i+2], ..., counter[i + n]))
access channel;
else
defer access;
}
counter[i]+ +;
}
else
defer access;
}
This is for CPS devices to access internet using a WSN in between..basic network is done but need help with adding this algo to it..
Can someone help me code that algo in tcl?
Your question isn't clear enough.
For syntax, I'd recommend referring TCL online help.
Some quick snippets:
# Inputs: STA−1, STA−2, STA−3, ..., STA−n
set stations [list "STA−1" "STA−2" "STA−3"]
# Shared Variables:
# for every i, 1 ≤ i ≤ n
# counter[i] ∈ { / 0, 1, 2,..., N}, initially 0, updated by stations
array set counter {}
set n 10
set i 0
while {$i < $n} {
set counter($i) 0
incr i
}
The core of your method is converted to this, assuming that counter is converted to an (associative) array, and that channel identifiers are stored in the channel array:
variable K 0
for {set i 1} {$i <= $n} {incr i} {
set counter($i) 0
}
for {set i 1} {$i <= $n} {incr i} {
while {[channelAccess $channel($i)]} {
if {$counter($i) != $K} {
if {[channelIdle $channel($i)]} {
set minimum [getMinimum [expr {$i + 1}] [expr {$i + $n}]]
if {$counter($i) < $minimum} {
accessChannel $channel($i)
} else {
deferAccess $channel($i)
}
}
incr counter($i)
} else {
deferAccess $channel($i)
}
}
}
You'll also need this procedure:
proc getMinimum {from to} {
upvar 1 counter counter
set minVal $counter($from)
for {set i $from} {$i <= $to} {incr i} {
set minVal [expr {min($minVal, $counter($i))}]
}
return $minVal
}
And you'll need to define channelAccess, channelIdle, accessChannel and deferAccess; they're things that your algorithm doesn't specify. There's also nothing to say what various variable are actually updated by. But that's the algorithm converted.
Note the patterns for using for; those are idiomatic Tcl for this sort of thing. Also note the brace positioning; your life will be easiest in Tcl if you use that style.