Inserting at random positions in a block
This might be a very simple question but I'm having a very hard time trying to solve it. I am trying to insert a character at random inside a block. I know that each block has a position marker, that I can move with instructions like: tail, head, next, skip and so on. Say I have the block >> blk: [7 10 2 8 1] the instruction at should set the index of the block at the designated item in the block, so >> at blk 3 should set the index at the number 2. Of course, I will want the number used with at to be generated randomly, but let's leave that for another day. Now, the instruction insert should add a new element at the current position, so: >> insert blk * should look like: [7 10 * 2 8 1] instead I get == [7 10 2 8 1] but if I probe blk I get: == [* 7 10 2 8 1] showing that the instruction inserted the * at the head, moved the index one position and returned the block, so if I ask: >>head blk we get == [* 7 10 2 8 1] I get a similar experience with skip: >> skip blk 3 >> insert blk $ gives me not [* 7 $ 10 2 8 1] but == [* 7 10 2 8 1] >> head blk == [$ * 7 $ 10 2 8 1] The use of refinements is not being kinder with me: >> insert/part blk # 5 == [# $ * 7 10 2 8 1] The first glimmer of hope comes with: >> blk: [7 10 2 8 1] >> blk: at blk 3 insert blk * == [2 8 1] >> head blk == [7 10 * 2 8 1] I would appreciate any insight on as how to properly insert elements at random access positions, why I am getting this behavior and how does the final example work. Thanks in advance...
posted by: Brother Damian 26-Feb-2016/15:38:39-8:00
(Those stupid curly quotes should be abondoned from all charsets in this world. ;-) ) >> blk: [7 10 2 8 1] >> blk: at blk 3 this sets blk to be positioned at position 3. The two positions before that are still part of the series but the index is now pointing at the third element. >>insert blk "*" This now inserts before the indexed position. >> head blk most of the time I use this as blk: head blk to set the index back to the head position, or in our terms of understanding, the first one. Getting any clearer?
posted by: iArnold 26-Feb-2016/16:04:38-8:00
> Of course, I will want the number used with at to be generated randomly, but let's leave that for another day. Here's one way to do that: blk: at head blk random/secure length? blk Now you can do the insert, and (per iArnold's short tutorial) see the full block again: insert blk "*" probe head blk
posted by: Sunanda 27-Feb-2016/1:55:27-8:00
Thanks iArnold for describing what's happening in the algorithm that seems to work. I would like to understand better the syntax: I though that >> at blk 3 would have been enough to set the pointer in blk, like it seems to happen with >> head blk but no, it doesn't. Instead I have to do some kind of assignment with the colon operator: >> blk: at blk 3 Why is this? However, this solution is not really working. That or my reasoning is flawed. In order to insert at random my item into the block I tried this but had the following unexpected result: blk: copy [] blk: [19 20 9 3 17] item: * n: random 6 prin "n= " print n blk: at blk n insert blk item head blk probe blk and got the following: n= 4 ["*" 3 17] ; (now, this does not happen all the time, but I do run the same code all the time!) That was unexpected, so I tried >> head blk == [19 20 9 "*" 3 17] Aha! But did the head instruction change the index? >> index? blk == 4 Apparently not. Following Sunanda's very smart code, it seems that, again one needs to assign the index position with the colon: >> blk: head blk However, this gave me: >> index? Blk == 4 with the consequence that if I request >> print blk/1 == * which means that I was able to insert the item in my block but now I don't know how to use the entire block, including the first items. Is this assignment correct? Is this a proper way for inserting an item in a block or am I bending the purpose of code? Why am I getting inconsistent results? Is there an alternative way to do this? Could this be an entry for the Beginner's Gotchas Tutorial? I got some consistent results with: blk: [19 20 9 3 17] n: random 5 item: * forall blk [ if n = index? blk [ insert blk item ]] which would not be so offensive with a small block like in the example but would not work in other contexts as it requires block traversal. So, to sum up: is this assignment, as in: >> blk: at blk 3 >> blk: head blk the proper syntax and the proper solution for the problem at hand? And if so, why is the index not updated? Also, what if I use another block for the assignment, as in: >> blk: at other-blk 3 (just in case, I am using REBOL/View 2.7.8.3.1 1-Jan-2011) Thanks again for your help.
posted by: Brother Damian 27-Feb-2016/11:03:52-8:00
I think you may be missing a neat concept about blocks: A block is not just a aeries of items; it is also an "internal pointer" to the "current" item - think of it like a cursor if that terminology works for you. These examples attempt to show what happens when you change the internal pointer in various ways: blk: [1 2 3 4 5 6] probe blk ; shows original block probe next blk ; shows block from 2nd item probe at blk 4 ; shows block from 4th item probe blk ; shows original block -- internal pointer has not changed blk: next blk ; change internal pointer to 2nd item probe blk ; shows block from 2nd item probe head blk ; shows original block probe at blk 4 ; shows block from 5th item blk: head blk ; reset internal pointer to start of block probe blk ; what do you expect to see?
posted by: Sunanda 27-Feb-2016/18:27:54-8:00
Dear Sunanda: I would expect to see the block from the first item forth, but as the transcription of the little experiment in my previous post shows, this didn't happen. I am aware of the pointer in blocks, which is the basis of my code; but I am not finding a correlation between what I expect to see from what actually happens. This could be because of improper syntax or because there is some conceptual element I am missing. In any event, I want to insert an item at random into a block (hopefully with out having to traverse it) and believe that the "internal pointer" is the right way to do it but my implementations are not working. But I am not really asking for just a solution, I would appreciate an explanation that would help me understand the hows and whys that can help me make better predictions (and code) later. Thanks for any help.
posted by: Brother Damian 1-Mar-2016/8:57:35-8:00
>the instruction at should set the index of the block It's more like creating a new pointer to the block. Skip and head works the same way. Sorry if this already was clear. >> blk: [7 10 2 8 1] == [7 10 2 8 1] >> insert at blk 3 "*" == [2 8 1] ;pos after insert >> blk == [7 10 "*" 2 8 1]
posted by: Gorf 1-Mar-2016/21:02:25-8:00
As Gorf suggests, an approach to the mental model is to think of the "name" of the block as being both the variable name AND the current position: B: copy [1 2 3 4] ;defines a block called B positioned at its head at B 3 ; displays what is at position 3 of the block without changing the "implicit" pointer B: at B 3 ;; changes the implicit pointer to be at position 3 of the block print B ;; now prints from position 3 without changing the implicit pointer print head B ;; prints from the start of B without changing the implicit pointer B: head B ;; resets the pointer to the start of the block A: at B 3 ;; creates another pointer .... b/3 = a/1 ;; Yes it does! insert a 99 ;; is the same as insert at B 3 99
posted by: Sunanda 4-Mar-2016/7:02:20-8:00
Brother Damian: 1) a block! models the comp sci concept of an array 2) a block! can have 0 to n values 3) an index into a block! is an integer representing "the address" of interest 4) a block! start at index 1 Key Idea #1: the RVC stores a value at virtual memory location of the index >> b: [7 10 2 8 1] == [7 10 2 8 1] like this in p-code and many languages: b[1] = 7; b[2] = 10; b[3] = 2; b[4] = 8; b[5] = 1 Carl designed REBOL to be syntax sparse / free so you don't access block!(s), aka arrays, like you would in syntax heavy languages. Key Idea #2: Whatever C representation the RVC uses to model a block! structure, it must have a "slot" that keeps an integer to track "the view," i.e., from the current index to the tail. It must have a slot for the current view name. The RVC keeps the entire block! regardless of its view name. Key Idea #3: Whenever you or your "code" (in REBOL, it's really all data, ask Carl), introduce an expression, which the RVC can evaluate to a value, it keeps that on it's memory system (however Carl designed it heap, stack, whatever). So, if you do this: >> [7 10 2 8 1] == [7 10 2 8 1] It's there in memory. However, you have no obvious handle to access it. The RVC keeps the entire block! regardless of its view name. Key Idea #4: any block! has a head item, a last item, a head position and n other positions and a tail position. The nth position of n positions is the last item position. >> e: [] == [] >> head? e == true >> tail? e == true >> equal? head? e tail? e == true >> same? head? e tail? e == true >> attempt [last e] ;; there is nothing there >> attempt [last e] == none >> attempt [first e] == none Key Idea #5: >> b: [7 10 2 8 1] == [7 10 2 8 1] You can ask the RVC to look anywhere without tagging the view with a name ;; change the view but not the view name ;; get it? >> tail? tail b == true >> head? b == true >> b == [7 10 2 8 1] Key Idea #6: You can ask the RVC to tag any view of the block! it has (Key Idea #) regardless of what it once was named. ;; move the view and the view name >> b: tail b == [] >> length? b == 0 >> tail? b == true >> head? b == false >> b: head b == [7 10 2 8 1] >> head? b == true > b: [7 10 2 8 1] == [7 10 2 8 1] Key Idea #7 You can have handles tag the same block! in memory when such a block! has a name >> c: :b == [7 10 2 8 1] >> b: tail b == [] >> c == [7 10 2 8 1] Key Idea #8 If you ask the RVC to change the view (Key Idea #5) and tag that view (Key Idea #6), it still has the entire block! as it was first defined (Key Idea #3). The view names no long name the same view. ;; names are tagging different bits (views) of memory >> same? b c == false ;; names are tagging different bits (views) of memory >> equal? b c == false Reset to the same view. ;; names are tagging same bits (views) of memory >> b: head b == [7 10 2 8 1] >> same? b c == true Key Idea #9 Because the RVC indexes block!(s) by integers, you can tell the RVC to "iterate" over any block! ;; FOR 'word start end bump body for j 1 length? b 1 [ print b/:j ] Key Idea #10: The RVC has slicker, "REBOL-ISH" ways to do the same: forall b [print b/1] foreach j b [print join "b " j ] ;; dumb for skip = 1 but works forskip b 1 [print b/1] That is part of blockology. Discover the secrets of REBOL by reading my work: The RVC, REBOL and Red Enlightenment through RVC Zen at timeserieslord.github.io/rvc/
posted by: Time Series Lord 29-Sep-2016/17:15:44-7:00
|