Is there a data structure like stream, but weak? - list

Weak as in weak references. Basically, I need a sequence of numbers where some of them can be unallocated when they aren't needed anymore.

scalaz.EphemeralStream is what you want.

Views provide you with a lazy collection, where each value is computed as it is needed.

One thing you could do is create an Iterable instead of a Stream. Your Iterable needs to provide an iterator method, which returns an iterator with hasNext and next methods.
When you loop over the Iterable, hasNext and next will be called to generate the elements as they are needed, but they are not stored anywhere (like a Stream does).
Simple example:
class Numbers extends Iterable[Int] {
def iterator = new Iterator[Int] {
private var num = -1
def hasNext = num < 99
def next = { num += 1; num }
}
}

Related

How do I add unique elements to a List?

In flutter/dart, how can I add elements to a list whilst ensuring that every new entry is unique (i.e. no duplicates).
So we know how to add elements to a list:
List myList = [];
then
myList.add(...);
but I'd like to know how to make sure that whatever has been added has not been added before.
Many thanks,
You should consider using a set. A set is an unordered collection of unique items.
var mySet = <String>{};
mySet.add('something');
Optionally, you may use the Dart´s Extensions function
extension ListExtension<E> on List<E> {
void addAllUnique(Iterable<E> iterable) {
for (var element in iterable) {
if (!contains(element)) {
add(element);
}
}
}
}
Use a Map for the initial adding, Maps will not let duplicates then convert from Map to list.
Maps are Name Value pairs so if these are strings just set the name and value the same, if it is an object set the "uniqueID" as the name and the object as the value...
Then you can take the Name set or usually Value set and turn that into a list for iteration and looping.
https://www.tutorialspoint.com/dart_programming/dart_programming_map.htm

a pushBack() function, as opposite to popFront()

Can I use popFront() and then eventually push back what was poped? The number of calls to popFront() might be more than one (but not much greater than it, say < 10, if does matter). This is also the number of calls which the imaginary pushBack() function will be called too.
for example:
string s = "Hello, World!";
int n = 5;
foreach(i; 0 .. n) {
// do something with s.front
s.popFront();
}
if(some_condition) {
foreach(i; 0 .. n) {
s.pushBack();
}
}
writeln(s); // should output "Hello, World!" since number of poped is same as pushed back.
I think popFront() does use .ptr but I'm not sure if it in D does makes any difference and can help anyway to reach my goal easily (i.e, in D's way and not write my own with a Circular buffer or so).
A completely different approach to reach it is very welcome too.
A range is either generative (e.g. if it's a list of random numbers), or it's a view into a container. In neither case does it make sense to push anything onto it. As you call popFront, you're iterating through the list and shrinking your view of the container. If you think of a range being like two C++ iterators for a moment, and you have something like
struct IterRange(T)
{
#property bool empty() { return iter == end; }
#property T front() { return *iter; }
void popFront() { ++iter; }
private Iterator iter;
private Iterator end;
}
then it will be easier to understand. If you called popFront, it would move the iterator forward by one, thereby changing which element you're looking at, but you can't add elements in front of it. That would require doing something like an insertion on the container itself, and maybe the iterator or range could be used to tell the container where you want an alement inserted, but the iterator or range can't do that itself. The same goes if you have a generative range like
struct IncRange(T)
{
#property bool empty() { value == T.max; }
#property T front() { return value; }
void popFront() { ++value; }
private T value;
}
It keeps incrementing the value, and there is no container backing it. So, it doesn't even have anywhere that you could push a value onto.
Arrays are a little bit funny because they're ranges but they're also containers (sort of). They have range semantics when popping elements off of them or slicing them, but they don't own their own memory, and once you append to them, you can get a completely different chunk of memory with the same values. So, it is sort of a range that you can add and remove elements from - but you can't do it using the range API. So, you could do something like
str = newChar ~ str;
but that's not terribly efficient. You could make it more efficient by creating a new array at the target size and then filling in its elements rather than concatenating repeatedly, but regardless, pushing something on the the front of an array is not a particularly idiomatic or efficient thing to be doing.
Now, if what you're looking to do is just reset the range so that it once again refers to the elements that were popped off rather than really push elements onto it - that is, open up the window again so that it shows what it showed before - that's a bit different. It's still not supported by the range API at all (you can never unpop anything that was popped off). However, if the range that you're dealing with is a forward range (and arrays are), then you can save the range before you pop off the elements and then use that to restore the previous state. e.g.
string s = "Hello, World!";
int n = 5;
auto saved = s.save;
foreach(i; 0 .. n)
s.popFront();
if(some_condition)
s = saved;
So, you have to explicitly store the previous state yourself in order to restore it instead of having something like unpopFront, but having the range store that itself (as would be required for unpopFront) would be very inefficient in most cases (much is it might work in the iterator case if the range kept track of where the beginning of the container was).
No, there is no standard way to "unpop" a range or a string.
If you were to pass a slice of a string to a function:
fun(s[5..10]);
You'd expect that that function would only be able to see those 5 characters. If there was a way to "unpop" the slice, the function would be able to see the entire string.
Now, D is a system programming language, so expanding a slice is possible using pointer arithmetic and GC queries. But there is nothing in the standard library to do this for you.

Returning elements of a row in a list using Scala

I need to write a method that will return the contents of a particular row (index of it is inputted as method parameter). I have to use recursion and no loops.
So far I have attempted this uncompleted code (and I have no idea how to continue it):
class Sudoku(val grid: List[List[Int]]) {
def r(r: Int): Set[Int] = {
if (grid.isEmpty) Set()
else
}
}
I also do not know how Set works. Any help would be really appreciated. PS: I am not asking for complete code, an algorithm explanation would be more than enough!
This is the answer to the literal interpretation of the question:
class Sudoku(val grid: List[List[Int]]) {
def row(n: Int): List[Int] =
if (grid.size > n) grid(n) else Nil
}
The apply method on List, here applied on the value grid, which can be written either grid apply n, or simply grid(n) returns the n'th element of the list. If that element does not exist (e.g. grid(1000000)), it throws an exception, therefore we check the size of the list first.
I have no idea why you should return a Set, but you could simple call .toSet on the result. A Set is a collection with distinct elements (each element only occurs once) with no guarantee of ordering.
I also don't know why you would need recursion for this, so I reckon the question is part of a larger problem.

c++: use map as value of another map

I just wonder if I can use a "complicated" map as the value of another map. I have self-defined several structs as follow:
typedef std::vector<std::string> pattern;
typedef std::map<int, std::vector<pattern>> dimPatternsMap;
typedef std::map<int, dimPatternsMap> supportDimMapMap;
OK let me explain these things...pattern is a vector of strings. For the "smaller" map dimPatternsMap, the key is an integer which is the dimension of pattern (the size of that vector containing strings) and the value is vector containing patterns (which is a vector of vectors...).
The "bigger" map supportDimMapMap also use an integer as the key value, but use dimPatternsMap as its value. The key means "support count".
Now I begin to construct this "complicated" map:
supportDimMapMap currReverseMap;
pattern p = getItFromSomePlace(); //I just omit the process I got pattern and its support
int support = getItFromSomePlaceToo();
if(currReverseMap.find(support) == currReverseMap.end()) {
dimPatternsMap newDpm;
std::vector<pattern> newPatterns;
newPatterns.push_back(currPattern);
newDpm[dim] = newPatterns;
currReverseMap[support] = newDpm;
} else{
dimPatternsMap currDpm = currReverseMap[support];
if(currDpm.find(dim) == currDpm.end()) {
std::vector<pattern> currDimPatterns;
currDimPatterns.push_back(currPattern);
currDpm[dim] = currDimPatterns;
} else {
currDpm[dim].push_back(currPattern);
}
}
Forgive me the code is really a mass...
But then as I want to traverse the map like:
for(supportDimMapMap::iterator iter = currReverseMap.begin(); iter != currReverseMap.end(); ++iter) {
int support = iter->first;
dimPatternsMap dpm = iter->second;
for(dimPatternsMap::iterator ittt = dpm.begin(); ittt != dpm.end(); ++ittt) {
int dim = ittt->first;
std::vector<pattern> patterns = ittt->second;
int s = patterns.size();
}
}
I found the value s is always 1, which means that for each unique support value and for each dimension of that support value, there is only one pattern! But as I debug my code in the map constructing process, I indeed found that the size is not 1 - I actually added the new patterns into the map successfully...But when it comes to traversing, all the sizes become 1 and I don't know why...
Any suggestions or explanations will be greatly appreciated! Thanks!!
dimPatternsMap currDpm = currReverseMap[support];
currDpm is a copy of currReverseMap[support]. It is not the same object. So then when you make changes to currDpm, nothing within currReverseMap changes.
On the other hand, if you use a reference:
dimPatternsMap& currDpm = currReverseMap[support];
then currDpm and currReverseMap[support] really are the same object, so later statements using currDpm will really be changing a value within currReverseMap.
There are a few other places where your code could benefit from references too.
My guess: you should use a reference in your else:
dimPatternsMap& currDpm = currReverseMap[support];
Your current code creates a copy instead of using the original map.
Your problem is this line:
dimPatternsMap currDpm = currReverseMap[support];
Based on the code following it, it wants to read like this:
dimPatternsMap& currDpm = currReverseMap[support];
Without the & you modify a copy of the entry rather than the existing entry.
Your code is making several copies of the objects underneath, try using more references and iterators (find() already gives you an element if it was found, for example).
For example, dimPatternsMap currDpm = currReverseMap[support]; actually makes a copy of a map in your structure and adds an element to it (not to the original). Try using a reference instead.

Erase in multiset

I'm new with STL containers, and right now i'm having some problems working with Multiset.
The problem is with the following two collections:
vector<DataReference*> referenceCol;
multiset<DataCount, DataCountSortingCriterion> orderedCol;
orderedCol mantains some data elements that have two public integer fields: id and count. I'm ordering that structure by the count elements. I may need to increment and decrement the count field from that elements, so, in order to maintain the ordering, i'm using a second collection (referenceCol) which is indexed by the id field and holds a reference (iterator) to the orderedCol collection, so every moment i need to refresh the count i can erase the element from orderedCol quickly (by refering to it in referenceCol), refresh it, and insert it again in its proper place according to the ordering.
The referenceCol is created in the constructor of my class, and has two fields: validReference (bool) that indicates whether the iterator reference is valid or not, and the multiset<....>::iterator variable.
The following methods handle the increment and decrement operations that affect these two collections:
void SomeClass::decrementCount(int index)
{
multiset<DataCount, DataCountSortingCriterion>::iterator it = referenceCol[index]->it;
DataCount dop = *it;
orderedCol.erase(it);
dop.count--;
if (dop.count > 0) {
it = orderedCol.insert(dop);
referenceCol[index]->it = it;
}
else {
referenceCol[index]->validRef = false;
}
}
void SomeClass::incrementCount(int index)
{
DataCount dop;
multiset<DataCount, DataCountSortingCriterion>::iterator it;
if (referenceCol[index]->validRef) {
it = referenceCol[index]->it;
dop = *it;
orderedCol.erase(it); <--------- BOOM!
dop.count++;
}
else {
dop.id = index;
dop.count = 1;
referenceCol[index]->validRef = true;
}
it = orderedCol.insert(dop);
referenceCol[index]->it = it;
}
The problem is that i'm having an error when i try to erase the iterator in the increment operation (look at the BOOM comment from the code).
The error i'm having is this:
"map/set erase iterator outside range"
The only thing that occurs to me is that maybe when erasing elements i may be invalidating other iterators, so those references doesn't hold any more, but i googled it and i found that for multiset, the erase operation only invalidate the erasing elements but no others...
I also checked that in my running example i'm not erasing the element with the problematic index.
Please help! And sorry for my bad english!
Oh, and i'm open to suggestions about better strategies to accomplish the "refresh" of elements in order :)
Thanks in advance!
With only the code you've given us to debug I cannot be certain, but I suspect that you are calling decrementCount(index) such that referenceCol[index]->validRef is false. When this happens your decrementCount method simply calls erase on the iterator without checking validity.
If this were to happen on a formerly invalidated iterator you might see the behavior you're seeing.
As an aside here it appears that you should be using a multimap not a multiset. But again without understanding all of your code I can't say that for sure.