Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rotating lists clockwise

100 views
Skip to first unread message

ashneerson

unread,
Jul 29, 2010, 1:52:21 AM7/29/10
to
hi, have a puzzle with rotating a list like below

{{ht a3 pr2} {ht a2 pr1} {lt a1 pr2} {lt a3 pr4} {ht a2 pr2}}

into a list like this one:

{{ht ht ht lt lt} {a2 a2 a1 a3} {pr1 pr2 pr2 pr2 pr4}}

so that to rotate the columns to rows and retain original
correspondence between the list elements.

can someone please help me figure out the trick?
-a.

Harald Oehlmann

unread,
Jul 29, 2010, 2:23:42 AM7/29/10
to
On 29 Jul., 07:52, ashneerson <ashneer...@gmail.com> wrote:
> hi, have a puzzle with rotating a list like below
>
> {{ht a3 pr2} {ht a2 pr1} {lt a1 pr2} {lt a3 pr4} {ht a2 pr2}}
>
> into a list like this one:
>
> {{ht ht ht lt lt}  {a2 a2 a1 a3}  {pr1 pr2 pr2 pr2 pr4}}
>
> so that to rotate the columns to rows and retain original
> correspondence between the list elements.

Sorry, I did not get what you mean. Could you write it with indexes ?

ashneerson

unread,
Jul 29, 2010, 2:37:37 AM7/29/10
to
ok. What I want to do is convert columns to rows as follows:

{
{0 1 2}
{0 1 3}
{0 2 1}
{1 1 2}
{1 2 3}

}

converted to :

{
{0 0 0 1 1}
{1 1 2 1 2}
{2 3 1 2 3}
}

# initial code
proc rotate_list { list } {
set lWidth [llength $list]
set lHeight [llength [lindex $list 0]]

set w $lHeight
set h $lWidth

set list {}

for {set i 0} {$i < h} {incr i} {
for {set j 0} {$j < w} {incr j} {
list [i][j] = list[w - j -1] [i]
}
}
return list
}

what I am stuck at is this line:

list [i][j] = list[w - j -1] [i]

thanks!
-a.

ashneerson

unread,
Jul 29, 2010, 3:06:47 AM7/29/10
to

I modified the code a bit:

# code

proc rotate_list { list } {
set lWidth [llength $list]
set lHeight [llength [lindex $list 0]]

set w $lHeight
set h $lWidth

set lst {}

for {set i 0} {$i < $h} {incr i} {
set case {}
for {set j 0} {$j < $w} {incr j} {
#list [i][j] = list[w - j -1] [i]
#lappend lst [expr {$w - $j -1} * $i]
lappend case [expr {$w - $j -1} * $i]
}
lappend lst $case
}
set lst
}

it does the rotation but i can't figure out why it returns indices
instead of letters now.

% set m {{ht a2 pr2} {ht a2 pr1} {lt a1 pr2} {ht a3 pr2} {lt a3 pr4}}

{ht a2 pvt2} {ht a2 pvt1} {lt a1 pvt2} {ht a3 pvt2} {lt a3 pvt4}

% rotate_list $m

{3 2 1} {2 1 0} {1 0 -1} {0 -1 -2} {-1 -2 -3}

can someone please help with this?

Uwe Klein

unread,
Jul 29, 2010, 4:09:30 AM7/29/10
to
ashneerson wrote:
> can someone please help with this?

#!/usr/bin/tclsh
proc prettyprintlist list {
puts \{
foreach line $list {
puts -nonewline \t\{\
foreach item $line {
puts -nonewline [ format %10s $item ]
}
puts \t\}\
}
puts \}
}
proc listrot list {
set columns {}
set col 0
foreach line $list {
if {!$col} {
foreach item $line {
lappend columns c:$col
incr col
}
}
set col 0
foreach item $line {
lappend c(c:$col) $item
incr col
}
}
foreach tok $columns {
lappend ret $c($tok)
}
return $ret
}
set ilist {


{0 1 2}
{0 1 3}
{0 2 1}
{1 1 2}
{1 2 3}
}

prettyprintlist $ilist
set olist [ listrot $ilist ]
prettyprintlist $olist
#end

hae

unread,
Jul 29, 2010, 5:35:12 AM7/29/10
to
On 29 Jul., 10:09, Uwe Klein <uwe_klein_habertw...@t-online.de> wrote:
> ashneerson wrote:
> > can someone please help with this?
>
> #!/usr/bin/tclsh
> proc prettyprintlist list {
>          puts \{
>          foreach line $list {
>                  puts -nonewline \t\{
>                  foreach item $line {
>                          puts -nonewline [ format %10s $item ]
>                  }
>                  puts \t\}
>          }
>          puts \}}
>

Hi,

here a version of prettyprintlist that works.

hae

unread,
Jul 29, 2010, 5:37:45 AM7/29/10
to
On 29 Jul., 07:52, ashneerson <ashneer...@gmail.com> wrote:

Hi,

this looks like you want to transpose a matrix. You could use
struct::matrix from tcllib. It already provides this functionality.

http://tcllib.sourceforge.net/doc/matrix.html

Rüdiger

hrachyag

unread,
Jul 29, 2010, 6:55:52 AM7/29/10
to

thanks, Rüdiger! that helped. i wrote my own implementation for
transposing the list based on what they had there. thanks!

hrachyag

unread,
Jul 29, 2010, 6:56:55 AM7/29/10
to
On Jul 29, 1:09 pm, Uwe Klein <uwe_klein_habertw...@t-online.de>
wrote:

thanks Uwe for your help!

Uwe Klein

unread,
Jul 29, 2010, 6:56:49 AM7/29/10
to
hae wrote:
> here a version of prettyprintlist that works.
so where is your improvement ( except partly
fixing the issues some(your?) MUA inserted )?

uwe

Ruchir

unread,
Jul 29, 2010, 8:19:20 AM7/29/10
to

> can someone please help with this?

#!/usr/bin/tclsh

set ilist {


{0 1 2}
{0 1 3}
{0 2 1}
{1 1 2}
{1 2 3}
}

# assume size of each row to be same
set num_col [llength [lindex $ilist 0]]
set i 0
set nlist {}
foreach r $ilist {
puts "$i -> $r"
set j 0
foreach c $r {
if {$i == 0} {
lappend nlist [list $c]
} else {
set l [lindex $nlist $j]
lappend l $c
lset nlist $j $l
}
incr j
}
incr i
}
puts "\ntransposed list --->"
set i 0
foreach ele $nlist {
puts "$i -> $ele"
incr i
}

tomk

unread,
Jul 29, 2010, 11:52:23 AM7/29/10
to

For the case given you could do the following (assuming the first list
is in a variable named alist).

foreach a b c d e {*}${alist} {
lappend result [list $a $b $c $d $e]
}

The result isn't exactly the same result suggested because it appears
the elements is the suggested result appear to have been sorted while
my example is a rotation.

tomk

tomk

unread,
Jul 29, 2010, 12:31:43 PM7/29/10
to

OOPS,
The above code doesn't work. This is what it should have been.

set alist [list {ht a3 pr2} {ht a2 pr1} {lt a1 pr2} {lt a3 pr4} {ht a2
pr2}]
set i 0
foreach a ${alist} {
lappend args a${i} ${a}
incr i
}
set res ""
foreach {a b} ${args} {
append res " \$${a}"
}
foreach {*}${args} {
lappend result [eval list $res]
}
puts $result

And you will get the following.
{ht ht lt lt ht} {a3 a2 a1 a3 a2} {pr2 pr1 pr2 pr4 pr2}

Regards,
tomk

hae

unread,
Jul 29, 2010, 2:54:14 PM7/29/10
to

Your version had a trailing \ with some puts that did not work for me.
For example
Compare 'puts -nonewline \t\{\'
with 'puts -nonewline \t\{'

That is the change.

Rüdiger

Uwe Klein

unread,
Jul 29, 2010, 3:06:52 PM7/29/10
to
hae wrote:
> Your version had a trailing \ with some puts that did not work for me.
> For example
> Compare 'puts -nonewline \t\{\'
> with 'puts -nonewline \t\{'
>
> That is the change.
>
> Rüdiger

what I posted was 'puts -nonewline \t\{\<space>'
"\t\{ " would have been equivalent for the payload

Not quite sure who had the <space> for dinner.

uwe

mark anthony

unread,
Jul 30, 2010, 4:17:32 PM7/30/10
to
i wanted to see how my matrix lib performs in comparison to your
suggestions... anyway let me share my timings. either i'm to stupid
to use struct::matrix or its awfully slow for this operation (or since
struct::matrix does it in place, we actually flip the same matrix so
this could be the cause but shouldn't).

anyway, your suggestions used only half the time of struct::matrix.
also i wonder why my code is so much faster....


timing results:
tomk 2078.416 microseconds per iteration
ruchir 2002.312 microseconds per iteration
uwe 1921.835 microseconds per iteration
kob 1043.529 microseconds per iteration
::struct::matrix 4082.555 microseconds per iteration

for your convenience find the script used for testing bellow

cheers,
mark

p.s. feedback is appreciated

--- code follows ---
#!/usr/bin/tclsh
::puts "transpose \nUsage:"
::puts "transpose ?--time?"

::set mi 20
::set mj 50

::package require struct::matrix

::set clist {


{0 1 2 }
{0 1 3 }
{0 2 1 }
{1 1 2 }
{1 2 3 }
}

::struct::matrix mycmatrix
mycmatrix deserialize [::list 5 3 $clist]

## prepare the test data
::puts "init"
::proc getnum {} {
::return [::expr {100000*rand()}]
}

::struct::matrix mymatrix
::set mymatrixlist [::list]
::for {::set i 0 } {$i < $mi } {::incr i } {
::set row [::list]
::for {::set j 0 } {$j < $mj } {::incr j } {
::lappend row [getnum]
}
::lappend mymatrixlist $row
}
mymatrix deserialize [::list $mi $mj $mymatrixlist]
## procs

## tcllib
proc transpose { } {
mymatrix transpose
}
::proc tomk { alist } {


set i 0
foreach a ${alist} {
lappend args a${i} ${a}
incr i
}

set res ""
foreach {a b} ${args} {
append res " \$${a}"
}

foreach {*}${args} {
lappend result [eval list $res]
}

return $result

}
::proc ttranspose {} {
tomk $::mymatrixlist
}

## ashneerson
::proc rotate_list { list } {
::set W [::llength $list]
::set H [::llength [::lindex $list 0]]

::set w $H
::set h $W

::set lst [::list ]

::for {::set i 0 } {$i < $h} {incr i} {
::set case [::list ]

::for {::set j 0} {$j < $w} {incr j} {
::lappend case [::lindex $list [::expr {($w-$j
-1)}] $i]
}
::lappend lst $case
}
::return $lst
}
::proc arotate { } {
::rotate_list $::mymatrixlist
}
## uwe
::proc listrot list {


::set columns {}
::set col 0
::foreach line $list {
::if {!$col} {
::foreach item $line {
::lappend columns c::$col
::incr col
}
}
::set col 0
::foreach item $line {
::lappend c(c::$col) $item
::incr col
}
}
::foreach tok $columns {
::lappend ret $c($tok)
}
::return $ret
}

::proc utranspose {} {
listrot $::mymatrixlist
}


## kob
## taken from my matrix namespace
::proc dim { A } {
::set i [::llength $A ]
::set j [::llength [::lindex $A 0] ]
::return [::list $i $j ]
}
::proc Mat { dai x daj } {
::for {::set i 0} {$i<$daj } {::incr i} {
::lappend list 0
}
::for {::set i 0} {$i<$dai} {::incr i} {
::lappend C $list
}
::return $C
}
::proc T { A } {
::foreach [::list dai daj ] [dim $A] ::break
::set B [Mat $daj x $dai]
::set i 0
::foreach a $A {
::set j 0
::foreach aij $a {
::lset B $j $i $aij
::incr j
}
::incr i
}
::return $B
}

##
::proc ktranspose { } {
T $::mymatrixlist
}
## ruchir
::proc ruchir { A } {
::set i 0
::set nlist [::list ]
::foreach r $A {
::set j 0


::foreach c $r {
::if {$i == 0 } {
::lappend nlist [::list $c]
} else {
::set l [::lindex $nlist $j]
::lappend l $c
::lset nlist $j $l
}
::incr j
}
::incr i
}

::return $nlist
}
::proc rtranspose {} {
ruchir $::mymatrixlist
}

::if {[::lsearch $argv --time]>=0} {
## cache
::puts "prepare bytecode"
rtranspose
utranspose
ktranspose
ttranspose
transpose

## time
::puts "timing results:"
::puts -nonewline "tomk "
::puts [::time {
ttranspose
} 1000]


::puts -nonewline "ruchir "
::puts [::time {
rtranspose
} 1000]

::puts -nonewline "uwe "
::puts [::time {
utranspose
} 1000]
::puts -nonewline "kob "
::puts [::time {
ktranspose
} 1000]
::puts -nonewline "::struct::matrix "
::puts [::time {
transpose
} 1000]
}
::puts "correctness"
::puts -nonewline "solution: "
::puts [::list {0 0 0 1 1} {1 1 2 1 2} {2 3 1 2 3} ]
::puts -nonewline "tomk "
::puts [tomk $clist]
::puts -nonewline "ruchir "
::puts [ruchir $clist]
::puts -nonewline "uwe "
::puts [listrot $clist]
::puts -nonewline "kob "
::puts [T $clist]
::puts -nonewline "struct::matrix "
mycmatrix transpose
::puts [::lindex [mycmatrix serialize ] 2]

tom.rmadilo

unread,
Jul 31, 2010, 2:57:48 AM7/31/10
to

I wrote a proc for this, for some reason called it matrix:


proc ::resource::matrix { inList outList cols } {

# procedure creates new list from input list
# cols is the result set cols == input rows
# cols is an artificial dimension, which along
# with the length of the list determines the
# dims of the matrix. The list is filled
# with {} until the matrix is complete:
# 1 2 3 4 1 5 9
# 5 6 7 8 - cols = 3 -> 2 6 10
# 9 10 11 {} 3 7 11
# 4 8 {}
#
upvar $inList IL
upvar $outList OL

set rows [expr round(ceil([llength $IL].0/$cols))]
# make matrix
set Index [expr ($rows * $cols)]
set OL [list]

for {set i 0} {$i < $Index} {incr i} {
set x [expr $i/$cols ]
set y [expr $i % $cols]
# flip x y
lappend OL [lindex $IL [expr $y * $rows + $x] ]
}

}

Link to original source:
http://junom.com/gitweb/gitweb.perl?p=tnt.git;a=blob;f=packages/resource/tcl/resource-procs.tcl;h=45752;hb=HEAD#l100

Of course I assume you should agree that matrix dimensions are
imaginary projections of a simple list...but why choose a complex
structure and then try to manipulate it into a different form? This
choice could require a mapping for each matrix element.

tom.rmadilo

unread,
Jul 31, 2010, 3:17:50 AM7/31/10
to
> Link to original source:http://junom.com/gitweb/gitweb.perl?p=tnt.git;a=blob;f=packages/resou...

>
> Of course I assume you should agree that matrix dimensions are
> imaginary projections of a simple list...but why choose a complex
> structure and then try to manipulate it into a different form? This
> choice could require a mapping for each matrix element.

Maybe I should clarify: in Tcl there is no way to identify the
dimensions of a matrix, in Tcl every matrix has one row and the number
of columns is equal to the number of list elements. If you think
otherwise you are bound to fail. In Tcl multi-dimensional arrays or
matrices are a construction of the program's interpretation of the
data. So basically you can't transpose a matrix in Tcl unless you
specify the matrix dimensions (you can't just point to the matrix).

Maybe tcllib's matrix command is the best option.

0 new messages