Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

"It is easier to fight for principles than to live up to them." -- Alfred Adler


devel / comp.lang.tcl / Re: element-wise union of lists

Re: element-wise union of lists

<f3a63010-5636-471b-b852-f7738e95ba52n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=22808&group=comp.lang.tcl#22808

  copy link   Newsgroups: comp.lang.tcl
X-Received: by 2002:a05:6214:1790:b0:66d:17f:4dd2 with SMTP id ct16-20020a056214179000b0066d017f4dd2mr33791qvb.2.1697715360368;
Thu, 19 Oct 2023 04:36:00 -0700 (PDT)
X-Received: by 2002:a05:6870:e248:b0:1e9:b0fa:de72 with SMTP id
d8-20020a056870e24800b001e9b0fade72mr931629oac.9.1697715360145; Thu, 19 Oct
2023 04:36:00 -0700 (PDT)
Path: i2pn2.org!i2pn.org!paganini.bofh.team!2.eu.feeder.erje.net!feeder.erje.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer02.ams4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.tcl
Date: Thu, 19 Oct 2023 04:35:59 -0700 (PDT)
In-Reply-To: <c3961810-33a3-437e-bf85-0a837f689e93n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=91.217.55.78; posting-account=Od2xOAoAAACEyRX3Iu5rYt4oevuoeYUG
NNTP-Posting-Host: 91.217.55.78
References: <cea64616-b039-4268-b0a7-23bf314a49b6n@googlegroups.com>
<ugbmrn$38akq$1@dont-email.me> <33e00fa0-dc2f-4a2f-aa5e-eb7eee40566dn@googlegroups.com>
<49361f12-9d6d-4a5a-84cf-3ddcf735fe9en@googlegroups.com> <86b8aa4c-76cc-4392-a557-59245c952affn@googlegroups.com>
<26c2dbaf-5bf2-4f19-acbe-644bb2d2ac44n@googlegroups.com> <c3961810-33a3-437e-bf85-0a837f689e93n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <f3a63010-5636-471b-b852-f7738e95ba52n@googlegroups.com>
Subject: Re: element-wise union of lists
From: martin.heinrich@frequentis.com (heinrichmartin)
Injection-Date: Thu, 19 Oct 2023 11:36:00 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 11598
 by: heinrichmartin - Thu, 19 Oct 2023 11:35 UTC

On Thursday, October 19, 2023 at 2:58:34 AM UTC+2, briang wrote:
> On Tuesday, October 17, 2023 at 9:04:18 PM UTC-7, briang wrote:
> > On Sunday, October 15, 2023 at 7:28:04 AM UTC-7, Mole Cool wrote:
> > > Sorry Helmut, your result was unfair :-) , because you may have worked with one index only. And if you have no idea what data you get, this may dangerous. List creation is now out, done in 'Task', only with call by values, and sorry dict is not the fastest :-), but it is very fast for few indicies. And you did it in one proc, this was not fair either :-)
> > >
> > > And as mentioned it seems to be 30% slower
> > >
> > > Now the start scenario is the same for each test, I hope :-)
> > >
> > > time1 {10133.08 microseconds per iteration}
> > > time2 {10808.5 microseconds per iteration}
> > > time3 {10865.56 microseconds per iteration}
> > > time4 {13078.14 microseconds per iteration}
> > > time5 {20947.82 microseconds per iteration}
> > > time6 {20225.42 microseconds per iteration}
> > > time7 {13771.64 microseconds per iteration}
> > > proc Task {} {
> > > set n 100000
> > > set t 50
> > > # L1 has now uniquid indicines
> > > set L1 [Get_List1 $n ]
> > > set L2 [Get_List2 $n ]
> > > set time0 [time {ZIP_Main0 $L1 $L2} $t]
> > > set time1 [time {ZIP_Main1 $L1 $L2} $t]
> > > set time2 [time {ZIP_Main2 $L1 $L2} $t]
> > > set time3 [time {ZIP_Main3 $L1 $L2} $t]
> > > set time4 [time {ZIP_Main4 $L1 $L2} $t]
> > > set time5 [time {ZIP_Main5 $L1 $L2} $t]
> > > set time6 [time {ZIP_Main6 $L1 $L2} $t]
> > > set time7 [time {ZIP_Main7 $L1 $L2} $t]
> > > }
> > >
> > > # std call by value
> > > proc ZIP_Main0 {L1 L2} {
> > > set LR [ZIP_Action0 $L1 $L2]
> > > }
> > >
> > > proc ZIP_Action0 {L1 L2} {
> > > foreach I1 $L1 I2 $L2 {
> > > lappend LR $I1 $I2
> > > }
> > > return $LR
> > > }
> > > # in args by ref
> > > proc ZIP_Main1 {L1 L2} {
> > > set LR [ZIP_Action1 L1 L2]
> > > }
> > >
> > >
> > > proc ZIP_Action1 {cbrL1 cbrL2} {
> > > upvar $cbrL1 L1
> > > upvar $cbrL2 L2
> > > foreach I1 $L1 I2 $L2 {
> > > lappend LR $I1 $I2
> > > }
> > > return $LR
> > > }
> > >
> > > # all by ref
> > > proc ZIP_Main2 {L1 L2} {
> > > set LR [list]
> > > ZIP_Action2 L1 L2 LR
> > > }
> > >
> > > proc ZIP_Action2 {cbrL1 cbrL2 cbrRes} {
> > > upvar $cbrL1 L1
> > > upvar $cbrL2 L2
> > > upvar $cbrRes LR
> > > foreach I1 $L1 I2 $L2 {
> > > lappend LR $I1 $I2
> > > }
> > > }
> > > # result by ref
> > > proc ZIP_Main3 {L1 L2} {
> > > set LR [list]
> > > ZIP_Action3 $L1 $L2 LR
> > > }
> > >
> > >
> > > proc ZIP_Action3 {L1 L2 cbrRes} {
> > > upvar $cbrRes LR
> > > foreach I1 $L1 I2 $L2 {
> > > lappend LR $I1 $I2
> > > }
> > > }
> > > # # by ref and index
> > > proc ZIP_Main4 {L1 L2} {
> > > set LR [list]
> > > ZIP_Action4 L1 L2 LR
> > > }
> > >
> > > proc ZIP_Action4 {cbrL1 cbrL2 cbrRes} {
> > > upvar $cbrL1 L1
> > > upvar $cbrL2 L2
> > > upvar $cbrRes LR
> > > set LR [list]
> > > set n [llength $L1]
> > > for {set i 0} {$i < $n} {incr i} {
> > > lappend LR [lindex $L1 $i] [lindex $L2 $i]
> > > }
> > > return $LR
> > > }
> > > # use lmap by val
> > > proc ZIP_Main5 {L1 L2} {
> > > set LR [ZIP_Action5 $L1 $L2]
> > > }
> > >
> > > proc ZIP_Action5 {L1 L2} {
> > > return [lmap a $L1 b $L2 {list $a $b}]
> > > }
> > > # use lmap by ref
> > > proc ZIP_Main6 {L1 L2} {
> > > set LR [ZIP_Action6 L1 L2]
> > > }
> > >
> > > proc ZIP_Action6 {cbrL1 cbrL2} {
> > > upvar $cbrL1 L1
> > > upvar $cbrL2 L2
> > > return [lmap a $L1 b $L2 {list $a $b}]
> > > }
> > > # use dict with unique ID's in L1
> > > # use lmap by ref
> > > proc ZIP_Main7 {L1 L2} {
> > > set LR [ZIP_Action7 $L1 $L2]
> > > }
> > >
> > > proc ZIP_Action7 {L1 L2} {
> > > set d [dict create]
> > > foreach I1 $L1 I2 $L2 {
> > > dict set d $I1 $I2
> > > }
> > > return [set d]
> > > }
> > >
> > > proc Get_List1 {n} {
> > > set bl [list]
> > > for {set i 0} {$i < $n} {incr i} {
> > > lappend bl $i
> > > }
> > > return $bl
> > > }
> > >
> > > proc Get_List2 {n} {
> > > return [lrepeat $n {A B C d e F} ]
> > > }
> > I've implemented "ZIP" as an abstract list. It is implemented as the command [lweave] which takes 1 or more lists as arguments and returns the zippered (or weaved) list.
> >
> > Added the following test procs:
> >
> > package require lweave
> > # use lweave
> > proc ZIP_Main8 {L1 L2} {
> > set LR [ZIP_Action8 $L1 $L2]
> > }
> >
> > proc ZIP_Action8 {L1 L2} {
> > lweave $L1 $L2
> > }
> >
> > proc ZipCheck {0 1 zip} {
> > set i 0
> > set errors 0
> > foreach a $0 b $1 {
> > if {$a ne [lindex $zip $i]} {
> > puts "Mismatch($i) $a ne [lindex $zip $i]"
> > incr errors
> > }
> > incr i
> > if {$b ne [lindex $zip $i]} {
> > puts "Mismatch($i) $b ne [lindex $zip $i]"
> > incr errors
> > }
> > incr i
> > }
> > puts "Errors=$errors"
> > }
> >
> > And here are the results. (Note: I'm using a virtual machine running on an older laptop, so the times are about double+ those reported above.)
> >
> > $ tclsh9.0 weave_test.tcl
> > Start Task
> > Errors=0
> > Errors=0
> > timeL1->19785 microseconds per iteration
> > timeL2->1034 microseconds per iteration
> > time0->31293.82 microseconds per iteration
> > time1->32768.96 microseconds per iteration
> > time2->31919.48 microseconds per iteration
> > time3->31927.18 microseconds per iteration
> > time4->40238.34 microseconds per iteration
> > time5->34435.24 microseconds per iteration
> > time6->34532.44 microseconds per iteration
> > time7->52551.18 microseconds per iteration
> > time8->2.88 microseconds per iteration
> >
> > I will check in the implementation to github in the next couple days, then post a link here.
> > -Brian
> The implementation of "lweave" can be found here:
> https://github.com/bgriffinfortytwo/abstractlist-toys/commit/94b0f4addc05e8f777833629847e5dcb685375ca
>
> Here is the comparative results of lweave. Note that although the create time for the weaved (Zipped) list is significantly faster, iterating over the list is about 4x slower. The memory footprint should be smaller though. Also note that string creation is expensive for such large lists.
>
> tclsh9.0 weave_test.tcl
> Start Task
> timeL1->21252 microseconds per iteration
> timeL2->961 microseconds per iteration
> time8->2.96 microseconds per iteration
> Z8-representation->value is a lweave with a refcount of 2, object pointer at 0x55ad8d4ee960, internal representation 0x55ad8cfbc200:0x55ad8d4ee7b0, no string representation
> dict-keys->169024 microseconds per iteration
> After-dict->value is a dict with a refcount of 2, object pointer at 0x55ad8d4ee960, internal representation 0x55ad8d02e720:0x0, string representation "0 {A B C d e ..."
> time0->32575.44 microseconds per iteration
> time1->32297.28 microseconds per iteration
> time2->32364.22 microseconds per iteration
> time3->32841.46 microseconds per iteration
> time4->41252.14 microseconds per iteration
> time5->35948.38 microseconds per iteration
> time6->35133.78 microseconds per iteration
> time7->55273.42 microseconds per iteration
> Errors=0
> Z0-check->34604 microseconds per iteration
> Errors=0
> Z8-check->142120 microseconds per iteration
> 21075 microseconds per iteration
>
> See weave_test.tcl in the abstractlist-toys project to replay the above results.
>
> This implementation will only work in Tcl 9.0.
>
> -Brian

Cool things happen in Tcl 9.0. Looking at the code without any experience with abstract lists, I wonder:

* If "NULL) /* in operation */"[1] is the hook for the "in" operator, then implementing it might be useful (true if "in any list" instead of iterating over the woven list).

* Is there no "iterator" for abstract lists? I.e. would foreach call ObjIndex up to ObjLength times? But I guess taking this further would bloat the interface quite a bit: thinking of the Fibonacci example, the coroutine/iterator approach seems much more efficient than repeatedly calculating items.

* Nested/multiple indices are not supported for the time being[2]. I guess that was a design decision to get work done faster - the semantics and implementation would otherwise look quite clear, aren't they?

* I guess I know why lreverse is not implemented (the simple implementation does not account for ribbons of different sizes -> pad with empty strings before reversing?), but the same "error" seems present in lset[3]. Without possibility to test, I assume from the code: set w [lweave [list 0 2 4] [list 1]]; lset w 5 5; puts $w; # 0 1 2 5 4 "", but expected 0 1 2 "" 4 5

[1] https://github.com/bgriffinfortytwo/abstractlist-toys/commit/94b0f4addc05e8f777833629847e5dcb685375ca#diff-49da01101cfbbe312c2e416d26cf05d2e8cf8168af8c8f98e31079a2801d4160R67
[2] https://github.com/bgriffinfortytwo/abstractlist-toys/commit/94b0f4addc05e8f777833629847e5dcb685375ca#diff-49da01101cfbbe312c2e416d26cf05d2e8cf8168af8c8f98e31079a2801d4160R267
[3] https://github.com/bgriffinfortytwo/abstractlist-toys/commit/94b0f4addc05e8f777833629847e5dcb685375ca#diff-49da01101cfbbe312c2e416d26cf05d2e8cf8168af8c8f98e31079a2801d4160R306

SubjectRepliesAuthor
o element-wise union of lists

By: Eduard Zozulya on Fri, 13 Oct 2023

15Eduard Zozulya
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor