olcott <No...@NoWhere.com> writes:
> On 5/12/2022 7:06 PM, Ben wrote:
>> olcott <No...@NoWhere.com> writes:
>> I've removed the philosophy group and comp.lang.c as this is C++.
>>
>>> C/C++ people please critique this as the basis for an improvement to
>>> std::deque.
>> You will get critiques of the code on whatever basis people feel
>> inclined to comment! You can't limit the comments to some particular
>> context.
>>
>>> It seems to have the key functionality of std::deque and
>>> does it much more simply while saving time and space.
>> It does not have any of the functionality of std::deque.
>
> That is a ridiculously stupid thing to say. It has the key most
> important functionality of a std:deque
Generally, when you think I am saying something absurd, you should
re-consider.
A deque has (at least) these operations:
front
back
pop_front
push_front
pop_back
push_back
Your Tape_Type has none of these. Even internally it does not maintain
the right data to be able to provide them.
> Double ended queue
> deque (usually pronounced like "deck") is an irregular acronym of
> double-ended queue. Double-ended queues are sequence containers with
> dynamic sizes that can be expanded or contracted on both ends (either
> its front or its back).
>
> All of the rest of the functionality of std::deque can be added as
> needed.
You mean you could implement a deque using two arrays if you chose to?
So what? All I am saying is that you haven't got a deque.
>> There is a
>> commonly used (though not particularly efficient) way to implement a
>> deque using two arrays, but this is not it.
>>
>>> #define tape_element unsigned char
>> Use a typedef or using declaration. Also, I'd put the typedef in the
>> class as the type belongs to the class (as least that appears to be the
>> case from the name you've chosen).
>>
>>> class Tape_Type
>>> {
>>> private:
>>> int Tape_Head = 0; // Can be negative
>>> std::vector<tape_element> Left; // Stores left expansion
>>> std::vector<tape_element> Right; // Stores right expansion
>>> tape_element & operator[](int index);
>>>
>>> public:
>>> void move_left(); // Tape_Head--; Left.push_back(0); as needed
>>> void move_right(); // Tape_Head++; Left.push_back(0); as needed
>> The comments are wrong since you push_back('_').
>>
>>> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>>> tape_element Read() { return this->operator[](Tape_Head); };
>> I'd write (*this)[Tape_Head] but I suppose that's just a matter of style.
>>
>>> Tape_Type(){ Right.push_back('_'); } // constructor
>> The constructor leaves a Tape_Type object in an unusable state, but
>> that's due to a bug in operator[]. Did you test?
>
> Yes I tested so I don't see what you mean.
Testing should have caught the bug in operator[].
There is none. I just said the constructor leaves the tape unusable
because of the bug in operator[].
> I like mixed case because it is easier to read, mine not be consistent.
>
> Here they are implemented.
>
> //
> // Tape_Type implements a two-way Turing machine tape.
> // Right contains Tape_Head >= 0 values (right expansion)
> // Left contains Tape_Head < 0 values (left expansion)
> //
> // Tape_Type has functionality very similar to std::deque
This comment is not correct.
> // yet implements this functionality much more simply.
> // This saves time and space.
> //
> class Tape_Type
> {
> typedef unsigned char tape_element;
You probably want that to be a public typedef. And now that it's in the
class, the name can be sorter. The usual convention is _t for types:
typedef unsigned char element_t;
I plugged your tape class into my C++ TM interpreter and it made it
slightly slower for the "big" BB(5) test compared with my naive tape
that just uses a single string.
Note: this is not a comment on the design of your tape. There's nothing
wrong with it (except a little inconvenience, see below). The speed
will be determined almost entirely by how std::string and std::vector
are implemented. You might see completely different timings just by
linking with a different library.
Mind you, I prefer using a string to all the other methods I've tried
because it's so convenient. You can set up the TM with an input simply
by writing
tape = input
and you can debug by printing the tape any time you like. And I use a
string_view to get the non-blank "result" out of the TM and the end of a
run. All easy to get round with a couple of functions, but still, since
it's fast I see no reason t change.