How to implement stacks in Tcl without using lists? - data-structures

I know implementing stacks and queues with lists is very easy. But how would I implement a stack without using lists and list-manipulation functions such as lappend and lindex?
Actuallt I am using Tcl in Synopsys, so all the item in a stack are a part of circuit, like cells, ports, nets... which are collections in synopsys and cannot be processed directly through list function.

The right data structure is a list. However, you can make one by using an array. Here are the classic operations:
init to set an empty stack up
push to add a value to the stack
size to report the number of elements on the stack
top to peek the top-most value on the stack
pop to remove and return the top-most value on the stack
proc init {stackVar} {
upvar 1 $stackVar stk
unset -nocomplain stk
set stk(top) -1
}
proc push {stackVar value} {
upvar 1 $stackVar stk
set stk([incr stk(top)]) $value
return
}
proc size {stackVar} {
upvar 1 $stackVar stk
return [expr {$stk(top) + 1}]
}
proc top {stackVar} {
upvar 1 $stackVar stk
return $stk($stk(top))
}
proc pop {stackVar} {
upvar 1 $stackVar stk
set val $stk($stk(top))
unset stk($stk(top))
incr stk(top) -1
return $val
}
No lists used. But it is a lot more heavyweight than a good list-based implementation needs to be.

There is struct::stack in the Tcl standard library. Of course, that package is implemented using lists.
One could also store the stack content in a delimited string and add to / chop off the end of the string.
Or, I think, encode the stack content as integers and use multiplication, division, and module operations to push and pop (the value span needs to be smaller than the smallest item, though). Um, no. Turns out integer multiplication is commutative, who knew?

Related

Returning the last return values of an iterator without storing a vararg in a table

Writing a function that takes a generic for loop iterator consisting of the iterator function, the invariant state & the loop control variable to return the value the control variable has in the last iteration is straightforward:
function iterator_last_value(iterator, state, control_var)
local last
for value in iterator, state, control_var do
last = value
end
return last
end
print(iterator_last_value(("hello world"):gmatch"%a+")) -- world
This could be easily extended to support arbitrary constant numbers of arguments up to Lua's local register limit. We can also add vararg iterator return value support by always storing the last vararg in a table; this requires us to get rid of Lua's for loop syntactic sugar:
function iterator_last(iterator, state, control_var)
local last = {}
local last_n = 0
local function iter(...)
local control_var = ...
if control_var == nil then
return table.unpack(last, 1, last_n)
end
last = {...}
last_n = select("#", ...)
return iter(iterator(state, control_var))
end
return iter(iterator(state, control_var))
end
print(iterator_last(ipairs{"a", "b", "c"})) -- 3, c
which works well but creates a garbage table every iteration. If we replace
last = {...}
last_n = select("#", ...)
with
last_n = select("#", ...)
for i = 1, last_n do
last[i] = select(i, ...)
end
we can get away with reusing one table - presumably at the cost of manually filling the table using select being less efficient than {...}, but creating significantly fewer garbage tables (only one garbage table per call to iterator_last).
Is it possible to implement a variadic return value iterator_last without storing a vararg with significant overhead using a table, coroutine or the like, leaving it on the stack and only passing the varargs around through function calls? I conjure that this is not possible, but have been unable to prove or disprove it.

Recursion transformation without stack frames code repetitions

I have the following pseudo-code:
function X(data, limit, level = 0)
{
result = [];
foreach (Y(data, level) as entity) {
if (level < limit) {
result = result + X(entity, limit, level + 1);
} else {
//trivial recursion case:
result = result + Z(entity);
}
}
return result;
}
which I need to turn into a plain (e.g. without recursive calls). So far I'm out of ideas regarding how to do that elegantly. Following this answer I see that I must construct the entire stack frames which are basically the code repetitions (i.e. I will place same code again and again with different return addresses).
Or I tried stuff like these suggestions - where there is a phrase
Find a recursive call that’s not a tail call.
Identify what work is being done between that call and its return statement.
But I do not understand how can the "work" be identified in the case when it is happening from within internal loop.
So, my problem is that all examples above are providing cases when the "work can be easily identified" because there are no control instructions from within the function. I understand the concept behind recursion on a compilation level, but what I want to avoid is code repetition. So,
My question: how to approach transformation of the pseudo-code above which does not mean code repetitions for simulating stack frames?
It looks like an algorithm to descend a nested data structure (lists of lists) and flatten it out into a single list. It would have been good to have a simple description like that in the question.
To do that, you need to keep track of multiple indices / iterators / cursors, one at each level that you've descended through. A recursive implementation does that by using the call stack. A non-recursive implementation will need a manually-implemented stack data structure where you can push/pop stuff.
Since you don't have to save context (registers) and a return address on the call stack, just the actual iterator (e.g. array index), this can be a lot more space efficient.
When you're looping over the result of Y and need to call X or Z, push the current state onto the stack. Branch back to the beginning of the foreach, and call Y on the new entity. When you get to the end of a loop, pop the old state if there is any, and pick up in the middle of that loop.

How to 'array push' a string into a list in TI-Nspire?

As homework, I must swap letters in a given string. I already figured out how to do this, but not how to display them at once. it involves a for loop. so if I include disp x in the for loop, it displays them between parentheses and a space, but I want them all together, so instead of
"a"
"b"
"c"
I want "abc". Is there a way to do this? Should I push the variable into an array and then display the array after the for loop? How to push variables in to an array?
This is in TI-Nspire CX Cas btw.
To add an element x to an array A use augment(A, {x}).
For your specific case, I would use a string variable (call it string) to which I concatenate the next letter at each iteration of the for loop. So if the next letter to be added is in the variable letter, you would put the following line of code at the end of your for loop: string := string & letter.
here is also way:
Local array
array[dim(array)+1] := value
I would answer you by an example covering your scenario. Let's say we are aiming to have a array listing the elements of binaries when we construct an integer into the base2 (binary).
Define LibPub develope(a,b)=
Func
Local mi,m,q
mi:=mod(a,b)
q:=((a-mi)/(b))
Disp mi
While q≥b
a:=q
m:=mod(a,b)
q:=((a-m)/(b))
Disp m
EndWhile
EndFunc
The above small program develops an integer in decimal base into the binary base; however each binary is shown in a separate line as you mentioned:
ex:
develope(222,2)
0
1
1
1
1
0
1
enter image description here
but this is not what you want, you want is in a single line. IMPORTANCE IS THAT YOU SHOULD LIKELIHOOD WANT EACH ELEMENT BE ACCESSIBLE AS A SEPARATE INTEGER, RIGHT? LIKE AS AN ELEMENT IN A ARRAY LIST, THAT'S WHAT YOU LOOKING FOR RIGHT?
There we Go:
Define LibPub develope(n,b)=
Func
Local q,k,seti,set,valid
valid:=b
If valid>1 Then
q:=n
k:=0
set:={}
While q≠0
seti:=mod(q,b)
q:=int(((q)/(b)))
k:=k+1
seti→set[k]
EndWhile
Else
Disp "Erreur, La base doit être plus grand que 1."
EndIf
Return set
EndFunc
Basically, because we do not know how many elements are going to be added in the array list, the set:={} declares an array with an undefined dim (typically length) in order that dynamically be augmented.
The command seti→set[k] will add the value of the seti whatever it is, into the k position of the array list.
and the return set simply returns the array.
if you need to get access to a specific element, you know how to to that: elementNumber5:=set[5]
I wish it helps.

Having a hard time understanding & implementing some Ruby code

myitem.inject({}) {|a,b| a[b.one] = b.two; a}
Where:
myitem is a class which holds an array or pair objects (pair objects have two fields in them one and two)
I am not sure what the above code is supposed to do?
Starting with an empty map, set its value for the b.one key to b.two.
In other words, for every item in the "myitem" collection, create a map entry. The key will be an item's "one" value. That map entry's value will be the item's "two" value.
The block given to "inject" receives two parameters. The first is the "accumulator". It's initial value in this case is the empty map passed to "inject". The second parameter is the current item in the collection. In this case, each item in the collection.
The block must return whatever will be used as the next accumulator value, in this case, the map. We want to keep using the same map, so when we're done, the "inject" method will return the map with all the key/value pairs.
Without saving the results of the inject it's a bit worthless.
It's a pedantic way of writing
h = {}
myitem.each { |b| h[b.one] = b.two }
or to be closer to your original code
a = {}
mytem.each { |b| a[b.one] = b.two }
(I personnaly hate this pattern (and people who use it) as it needs the ; a at the end, losing all the functional aspect of inject. (Using a side-effect function inside a 'functional pattern', and then realizing that the later function (a[..]) doesn't return the expecting object is just wrong, IMO).
Inject is normal use to 'fold' a list into a result like
[1,2,3].inject(0) { |sum, x| sum+x }
=> 6 # (0+1+2+3)
here sum is the result of the last call to the block, x is each value on the list and 0 is the initial value of sum.
[2,3].inject(10) { |p,x| p*x }
=> 60 # 10*2*3
etc ...
Hash[my_item.map {|object| [object.one, object.two]}]
is another way to do it.

Scala: Mutable vs. Immutable Object Performance - OutOfMemoryError

I wanted to compare the performance characteristics of immutable.Map and mutable.Map in Scala for a similar operation (namely, merging many maps into a single one. See this question). I have what appear to be similar implementations for both mutable and immutable maps (see below).
As a test, I generated a List containing 1,000,000 single-item Map[Int, Int] and passed this list into the functions I was testing. With sufficient memory, the results were unsurprising: ~1200ms for mutable.Map, ~1800ms for immutable.Map, and ~750ms for an imperative implementation using mutable.Map -- not sure what accounts for the huge difference there, but feel free to comment on that, too.
What did surprise me a bit, perhaps because I'm being a bit thick, is that with the default run configuration in IntelliJ 8.1, both mutable implementations hit an OutOfMemoryError, but the immutable collection did not. The immutable test did run to completion, but it did so very slowly -- it takes about 28 seconds. When I increased the max JVM memory (to about 200MB, not sure where the threshold is), I got the results above.
Anyway, here's what I really want to know:
Why do the mutable implementations run out of memory, but the immutable implementation does not? I suspect that the immutable version allows the garbage collector to run and free up memory before the mutable implementations do -- and all of those garbage collections explain the slowness of the immutable low-memory run -- but I'd like a more detailed explanation than that.
Implementations below. (Note: I don't claim that these are the best implementations possible. Feel free to suggest improvements.)
def mergeMaps[A,B](func: (B,B) => B)(listOfMaps: List[Map[A,B]]): Map[A,B] =
(Map[A,B]() /: (for (m <- listOfMaps; kv <-m) yield kv)) { (acc, kv) =>
acc + (if (acc.contains(kv._1)) kv._1 -> func(acc(kv._1), kv._2) else kv)
}
def mergeMutableMaps[A,B](func: (B,B) => B)(listOfMaps: List[mutable.Map[A,B]]): mutable.Map[A,B] =
(mutable.Map[A,B]() /: (for (m <- listOfMaps; kv <- m) yield kv)) { (acc, kv) =>
acc + (if (acc.contains(kv._1)) kv._1 -> func(acc(kv._1), kv._2) else kv)
}
def mergeMutableImperative[A,B](func: (B,B) => B)(listOfMaps: List[mutable.Map[A,B]]): mutable.Map[A,B] = {
val toReturn = mutable.Map[A,B]()
for (m <- listOfMaps; kv <- m) {
if (toReturn contains kv._1) {
toReturn(kv._1) = func(toReturn(kv._1), kv._2)
} else {
toReturn(kv._1) = kv._2
}
}
toReturn
}
Well, it really depends on what the actual type of Map you are using. Probably HashMap. Now, mutable structures like that gain performance by pre-allocating memory it expects to use. You are joining one million maps, so the final map is bound to be somewhat big. Let's see how these key/values get added:
protected def addEntry(e: Entry) {
val h = index(elemHashCode(e.key))
e.next = table(h).asInstanceOf[Entry]
table(h) = e
tableSize = tableSize + 1
if (tableSize > threshold)
resize(2 * table.length)
}
See the 2 * in the resize line? The mutable HashMap grows by doubling each time it runs out of space, while the immutable one is pretty conservative in memory usage (though existing keys will usually occupy twice the space when updated).
Now, as for other performance problems, you are creating a list of keys and values in the first two versions. That means that, before you join any maps, you already have each Tuple2 (the key/value pairs) in memory twice! Plus the overhead of List, which is small, but we are talking about more than one million elements times the overhead.
You may want to use a projection, which avoids that. Unfortunately, projection is based on Stream, which isn't very reliable for our purposes on Scala 2.7.x. Still, try this instead:
for (m <- listOfMaps.projection; kv <- m) yield kv
A Stream doesn't compute a value until it is needed. The garbage collector ought to collect the unused elements as well, as long as you don't keep a reference to the Stream's head, which seems to be the case in your algorithm.
EDIT
Complementing, a for/yield comprehension takes one or more collections and return a new collection. As often as it makes sense, the returning collection is of the same type as the original collection. So, for example, in the following code, the for-comprehension creates a new list, which is then stored inside l2. It is not val l2 = which creates the new list, but the for-comprehension.
val l = List(1,2,3)
val l2 = for (e <- l) yield e*2
Now, let's look at the code being used in the first two algorithms (minus the mutable keyword):
(Map[A,B]() /: (for (m <- listOfMaps; kv <-m) yield kv))
The foldLeft operator, here written with its /: synonymous, will be invoked on the object returned by the for-comprehension. Remember that a : at the end of an operator inverts the order of the object and the parameters.
Now, let's consider what object is this, on which foldLeft is being called. The first generator in this for-comprehension is m <- listOfMaps. We know that listOfMaps is a collection of type List[X], where X isn't really relevant here. The result of a for-comprehension on a List is always another List. The other generators aren't relevant.
So, you take this List, get all the key/values inside each Map which is a component of this List, and make a new List with all of that. That's why you are duplicating everything you have.
(in fact, it's even worse than that, because each generator creates a new collection; the collections created by the second generator are just the size of each element of listOfMaps though, and are immediately discarded after use)
The next question -- actually, the first one, but it was easier to invert the answer -- is how the use of projection helps.
When you call projection on a List, it returns new object, of type Stream (on Scala 2.7.x). At first you may think this will only make things worse, because you'll now have three copies of the List, instead of a single one. But a Stream is not pre-computed. It is lazily computed.
What that means is that the resulting object, the Stream, isn't a copy of the List, but, rather, a function that can be used to compute the Stream when required. Once computed, the result will be kept so that it doesn't need to be computed again.
Also, map, flatMap and filter of a Stream all return a new Stream, which means you can chain them all together without making a single copy of the List which created them. Since for-comprehensions with yield use these very functions, the use of Stream inside the prevent unnecessary copies of data.
Now, suppose you wrote something like this:
val kvs = for (m <- listOfMaps.projection; kv <-m) yield kv
(Map[A,B]() /: kvs) { ... }
In this case you aren't gaining anything. After assigning the Stream to kvs, the data hasn't been copied yet. Once the second line is executed, though, kvs will have computed each of its elements, and, therefore, will hold a complete copy of the data.
Now consider the original form::
(Map[A,B]() /: (for (m <- listOfMaps.projection; kv <-m) yield kv))
In this case, the Stream is used at the same time it is computed. Let's briefly look at how foldLeft for a Stream is defined:
override final def foldLeft[B](z: B)(f: (B, A) => B): B = {
if (isEmpty) z
else tail.foldLeft(f(z, head))(f)
}
If the Stream is empty, just return the accumulator. Otherwise, compute a new accumulator (f(z, head)) and then pass it and the function to the tail of the Stream.
Once f(z, head) has executed, though, there will be no remaining reference to the head. Or, in other words, nothing anywhere in the program will be pointing to the head of the Stream, and that means the garbage collector can collect it, thus freeing memory.
The end result is that each element produced by the for-comprehension will exist just briefly, while you use it to compute the accumulator. And this is how you save keeping a copy of your whole data.
Finally, there is the question of why the third algorithm does not benefit from it. Well, the third algorithm does not use yield, so no copy of any data whatsoever is being made. In this case, using projection only adds an indirection layer.

Resources