|
Yes, but on Linux (LMDE). Email, casual Internet on one. Virtual machines, usually 3 open for programming on another. ESXi server on the third. If I want to do disk things, like backup and such, I open another. Same for my website tinkering on a Pi, just for learning. Once you get used to switching, it is second nature. Even this old dog learned a couple of new tricks a few years ago.
>64
If you can keep your head while those about you are losing theirs, perhaps you don't understand the situation.
|
|
|
|
|
mm.. do you have multiple screens though?
I think it might reduce the need for multiple desktop...
come to think of it, I should try them on my little tablet!
|
|
|
|
|
True. Worked that way back in the day. No, how I have one 34" monitor. I put multiple windows on each desktop.
I have 2 monitors (28 and 22") that are gathering dust (plus a 7" on my Pi). Like my current way with the large monitor best. Next one will be a large 4K TV.
Happy New Year.
>64
If you can keep your head while those about you are losing theirs, perhaps you don't understand the situation.
|
|
|
|
|
This is not a programming question. I will figure this out, and I don't really need help with it, although if an idea is burning a hole in your brain, go ahead and let me know.
I have the following structures:
struct FATransition : IComparable<FATransition> {
public int Min;
public int Max;
public FA To;
public FATransition(int min,int max,FA to) {
Min = min;
Max = max;
To = to;
}
public FATransition(FA to) {
Min = Max = -1;
To = to;
}
public int CompareTo([AllowNull] FATransition other) {
var c = Min.CompareTo(other.Min);
if (c != 0) return c;
return Max.CompareTo(other.Max);
}
}
...
class FA {
...
public bool IsDeterministic { get; private set; } = true;
List<FATransition> _transitions = new List<FATransition>();
public IList<FATransition> Transitions { get { return _transitions.AsReadOnly(); } }
...
}
The upshot is _transitions contains a list of range+state pairs.
The list should be sorted at all times, meaning inserts should be sorted. There will not be a way to remove FATransition items, except for clearing the list altogether, I think? I'm not sure yet. If I can avoid it I will.
There's a wrinkle. The ranges should not overlap for FATransitions where the To state is the same. On insert, they need to be merged into one transition if they overlap.
If there ever ends up a situation where more than one range or part of a range points to more than one To state I mark the IsDeterministic property false.
It's not that I don't know how to do this - it's just that there's no clean way to do it that is also efficient.
If I simply collated and merged over the entire list and rebuilt the list on each insert, that wouldn't be much code.
But to do it inline, only messing with the parts of the list that need messed with is corner case city.
I hate corner cases.
A) It broadens the test matrix
B) It is often *hard* to get full code coverage the more corner cases you have
C) It's harder to write
D) Ergo it's harder to read
E) 9 times out of 10 it's due to an anti-pattern
In this case, it's not an anti-pattern, or at least not one I can readily identify. It's just complicated. Dealing with sorted inserts is not a problem, but dealing with sorted range inserts gets tricky. The naive way to do it is to "expand" the ranges into individual items so 0-9 would be 10 entries, and then work with that, recombining when done, but that's not efficient.
By itself, that's not terrible. But when you add the rules about the ranges being able to overlap as long as their destination (To) states are different it gets weird fast.
I hate code like this. I hate writing it, and I hate that I want to put it off so badly that I write posts like this.
I only hope getting this out there inspires me to somehow come up with a better way to skin this particular cat. Sometimes just writing out my frustration brings me answers.
Real programmers use butterflies
|
|
|
|
|
I really appreciate your articles, and also your over all contribution to the forum. But sorry, for my feeling you are misusing your status and post programming questions (even you don't count this as such) here in the lounge.
Only my 2 cents.
|
|
|
|
|
Sorry, honey(only going by your username).
Wish I could help. But I am not even gonna use C# in my life. I'm just gonna be using HTML, Java, Python, and C++.
|
|
|
|
|
Having just seen an episode of the Simpsons, you almost lost me with the first "fat ran". I can almost imagine Homer saying "I have to run too?"
I do not know C# but maybe you are trying to do too much on a single list. Try looking at your problem from a different perspective. Instead of looking at the problem bottom-up try top-down, sideways, mad scientist user or... you know... like Homer
I have a custom list implemented (over the default list) in Java that, because it must be ordered, it does not use only a default list. It uses a default list to keep track of the order of the data, but the actual data is stored in a map of lists.
In your case data could be stored in the map indexed by "To" (your almost non-overlapping property) where each position of the map has a list with the actual data.
Good luck and try not to start the new year frustrated
|
|
|
|
|
Yeah, they could be indexed by To states. I actually do that in some of my previous code. I'd consider it here, but it means rewriting some very complicated code that acts on that FATransition list.
Real programmers use butterflies
|
|
|
|
|
I do not know what is possible to do in C# but, when a default data structure does not directly implement everything I need, I always try to make my data storage classes independent of the underlying storage type (data structure) by using templates and abstract classes.
Let us say that I want to store ClassA instances ordered by something that is a combination of some of its fields. I would probably make it ClassAStorage implements ClassStorageBase<actualstorageclass> where ClassStorageBase<t> implements the methods I need to make ClassStorage easier to work with including some abstract methods that will depend on ClassAStorage to be implemented and will be used in other methods of ClassStorageBase.
This also helps reusing code for, say, a ClassB that can be easily implemented as a ClassBStorage implements ClassStorageBase<anotherstorageclass>.
Simple snippet using my custom list:
- My storage class
public abstract class IndexedSet<TYPE_KEY extends Object,TYPE_DATA extends Object> {
private HashMap<TYPE_KEY,TYPE_DATA > cells;
}
- My ordered storage class
public abstract class IndexedSequence<TYPE_KEY extends Object,TYPE_DATA extends Object> extends IndexedSet<TYPE_KEY,TYPE_DATA>{
private ArrayList<TYPE_KEY> cellsOrder;
public Entry<TYPE_KEY, TYPE_DATA> get(int pos) {
TYPE_KEY k=cellsOrder.get(pos);
return new Pair<TYPE_KEY, TYPE_DATA>(k,internal().get(k));
}
}
- My base storage table (indexed rows that have indexed columns)
public abstract class TableCore<TYPE_KEY extends Object,TYPE_DATA extends Object>{
protected abstract TYPE_KEY getKey(TYPE_ROW r);
}
- finally, my class
public class TableBasic<TYPE_DATA extends Object> extends TableCore<Integer, TYPE_DATA>{
@Override
protected Integer getKey(TYPE_DATA r) {
return r.hashCode();
}
}
- and my other class
public class Table extends TableCore<UUID, TYPE_DATA extends MyData>{
@Override
protected UUID getKey(TYPE_DATA r) {
return r.id();
}
}
And, yes, it is a lot of work.
|
|
|
|
|
Yeah, I mean, I already do something like that in another part of my code, but it's not really appropriate here. It would add maintenance, but since it's only used by one thing, it doesn't need to be heavily abstracted.
Real programmers use butterflies
|
|
|
|
|
I don't quite see the problem here?
I mean, at the risk of being silly and obvious, I will state you should do a binary search when inserting (start an N/2, then N/4 or 3N/4 and so on...) for a quick match and then insert or merge. Elementary my dear Watson... or not?
FA being an ICollection<FATransition> , isn't it?
|
|
|
|
|
Normally, yes, but, I have to check the entry prior, to see if its range overlaps the one I just inserted, and I also have to check the entries after until I get one whose max value is less than or equal to the new max. Basically I need to combine overlapping ranges into one range.
This is further complicated because that only applies to ranges where the To entry is the same.
FA contains a list of FATransitions in addition to other data.
Real programmers use butterflies
|
|
|
|
|
ok, untested code (sorry) but I think it should work, in principle...
public struct FATransition : IComparable<FATransition>
{
public int Min;
public int Max;
public FA To;
public FATransition(int min, int max, FA to)
{
if (max < min)
throw new ArgumentOutOfRangeException(nameof(max));
Min = min;
Max = max;
To = to;
}
public FATransition(FA to)
{
Min = Max = -1;
To = to;
}
public int CompareTo(FATransition other)
{
var c = Min.CompareTo(other.Min);
if (c != 0) return c;
return Max.CompareTo(other.Max);
}
}
public class FA : ICollection<FATransition>
{
List<FATransition> _transitions = new List<FATransition>();
public bool IsDeterministic { get; private set; } = true;
int FindIndex(int min)
{
int iMin = 0, iMax = _transitions.Count;
while (iMin + 1 < iMax)
{
int i = (iMin + iMax) / 2;
var t = _transitions[i];
if (t.Min >= min)
iMax = i;
else
iMin = i;
}
return iMin;
}
public void Add(FATransition item)
{
int start = FindIndex(item.Min);
for (int i = _transitions.Count - 1; i >= start; i--)
{
var t = _transitions[i];
if (t.To == item.To && t.Min <= item.Max)
{
item.Max = t.Max;
_transitions.RemoveAt(i);
}
else if (t.To != item.To && t.Min <= item.Max && t.Max > item.Min)
{
IsDeterministic = false;
}
}
_transitions.Insert(start, item);
}
bool ICollection<FATransition>.Remove(FATransition item)
=> throw new NotSupportedException();
public int Count => _transitions.Count;
bool ICollection<FATransition>.IsReadOnly => false;
public void Clear()
{
_transitions.Clear();
IsDeterministic = true;
}
public bool Contains(FATransition item) => _transitions.Contains(item);
public void CopyTo(FATransition[] array, int arrayIndex)
=> _transitions.CopyTo(array, arrayIndex);
public IEnumerator<FATransition> GetEnumerator() => _transitions.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
modified 30-Dec-21 16:27pm.
|
|
|
|
|
Nope, that just does a sorted insert. That's simple, but not what I need.
What do you do when a range overlaps?
You've done nothing in that case. You just insert the range. You aren't merging overlapping ranges that have the same To.
Edit: I see. never mind, I missed it the first time. sorry.
Real programmers use butterflies
|
|
|
|
|
your answer confuses me, it looks like you haven't read the code (lack of sleep perhaps?), or I misunderstand the question (lack of sleep on my part perhaps).
Because the code quite obviously merge overlap range on insert so... could you be more clear on what's wrong?
For clarity I paste the add method again below with added comment
public void Add(FATransition item)
{
int start = FindIndex(item.Min);
for (int i = _transitions.Count - 1; i >= start; i--)
{
var t = _transitions[i];
if (t.To == item.To && t.Min <= item.Max)
{
item.Max = t.Max;
_transitions.RemoveAt(i);
}
else if (t.To != item.To && t.Min <= item.Max && t.Max > item.Min)
{
IsDeterministic = false;
}
}
_transitions.Insert(start, item);
}
|
|
|
|
|
It was my fault - i had since edited my comment accordingly - I missed it the first time through.
Real programmers use butterflies
|
|
|
|
|
I guess brain ache doesn't help!
No worries!
|
|
|
|
|
just amended the Add() method
for (int i = _transitions.Count - 1; i >= start; i--)
obviously count down to start , not 0!
|
|
|
|
|
That is basically what the map does on my post above.
Unless we are misunderstanding something.
Best regards
|
|
|
|
|
I rarely load "ranges" since they rarely make sense as specified; e.g. 100-200; 200-300; etc.
I just load the max values for each range.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Well I think? I see what you're saying, but in this case I need the minimums too.
In this case the ranges are Unicode Codepoints, and those are often laid out in runs of related characters, so you wind up, with for example, whitespace being, instead of a hundred individual characters, a series of i don't know, like 3 or 4 ranges.
If it were simply that, I'd store a marker id for each type of range (whitespace, digit, letter, etc), but ranges can and must be added to, removed from and intersected with other ranges.
I have to preserve the entire set of data, not just the maximums.
Real programmers use butterflies
|
|
|
|
|
|
Umm, you dramatically misunderstand the problem.
Unicode categories are not the only ranges I need.
Forget they exist, as they will only confuse things.
Let me put it this way.
ASCII has 127 characters.
UTF32 has 0x10FFFF (however many that is)
If I didn't use ranges, I would have to store each character transition individually.
That is not realistic for unicode. Period.
The way to make it realistic is to use ranges.
Not to use unicode categories, because that wouldn't make sense.
Real programmers use butterflies
|
|
|
|
|
Code Points, Code Points
|
|
|
|
|
yeah yeah, codepoints. point is there are a lot of them.
Real programmers use butterflies
|
|
|
|
|